revm_bytecode/legacy/
analyzed.rs1use super::JumpTable;
2use crate::opcode;
3use primitives::Bytes;
4
5#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub struct LegacyAnalyzedBytecode {
32 bytecode: Bytes,
34 original_len: usize,
36 jump_table: JumpTable,
38}
39
40impl Default for LegacyAnalyzedBytecode {
41 #[inline]
42 fn default() -> Self {
43 Self {
44 bytecode: Bytes::from_static(&[0]),
45 original_len: 0,
46 jump_table: JumpTable::default(),
47 }
48 }
49}
50
51impl LegacyAnalyzedBytecode {
52 pub fn new(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
60 if original_len > bytecode.len() {
61 panic!("original_len is greater than bytecode length");
62 }
63 if original_len > jump_table.len() {
64 panic!(
65 "jump table length {} is less than original length {}",
66 jump_table.len(),
67 original_len
68 );
69 }
70
71 if bytecode.is_empty() {
72 panic!("bytecode cannot be empty");
73 }
74
75 if bytecode.last() != Some(&opcode::STOP) {
76 panic!("last bytecode byte should be STOP (0x00)");
77 }
78
79 Self {
80 bytecode,
81 original_len,
82 jump_table,
83 }
84 }
85
86 pub fn bytecode(&self) -> &Bytes {
90 &self.bytecode
91 }
92
93 pub fn original_len(&self) -> usize {
95 self.original_len
96 }
97
98 pub fn original_bytes(&self) -> Bytes {
100 self.bytecode.slice(..self.original_len)
101 }
102
103 pub fn original_byte_slice(&self) -> &[u8] {
105 &self.bytecode[..self.original_len]
106 }
107
108 pub fn jump_table(&self) -> &JumpTable {
110 &self.jump_table
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117 use crate::{opcode, LegacyRawBytecode};
118 use bitvec::{bitvec, order::Lsb0};
119
120 #[test]
121 fn test_bytecode_new() {
122 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
123 let bytecode = LegacyRawBytecode(bytecode).into_analyzed();
124 let _ = LegacyAnalyzedBytecode::new(
125 bytecode.bytecode,
126 bytecode.original_len,
127 bytecode.jump_table,
128 );
129 }
130
131 #[test]
132 #[should_panic(expected = "original_len is greater than bytecode length")]
133 fn test_panic_on_large_original_len() {
134 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
135 let bytecode = LegacyRawBytecode(bytecode).into_analyzed();
136 let _ = LegacyAnalyzedBytecode::new(bytecode.bytecode, 100, bytecode.jump_table);
137 }
138
139 #[test]
140 #[should_panic(expected = "jump table length 1 is less than original length 2")]
141 fn test_panic_on_short_jump_table() {
142 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
143 let bytecode = LegacyRawBytecode(bytecode).into_analyzed();
144 let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 1]);
145 let _ = LegacyAnalyzedBytecode::new(bytecode.bytecode, bytecode.original_len, jump_table);
146 }
147
148 #[test]
149 #[should_panic(expected = "last bytecode byte should be STOP (0x00)")]
150 fn test_panic_on_non_stop_bytecode() {
151 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
152 let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 2]);
153 let _ = LegacyAnalyzedBytecode::new(bytecode, 2, jump_table);
154 }
155
156 #[test]
157 #[should_panic(expected = "bytecode cannot be empty")]
158 fn test_panic_on_empty_bytecode() {
159 let bytecode = Bytes::from_static(&[]);
160 let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 0]);
161 let _ = LegacyAnalyzedBytecode::new(bytecode, 0, jump_table);
162 }
163}