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, original_len
67 );
68 }
69
70 if bytecode.is_empty() {
71 panic!("bytecode cannot be empty");
72 }
73
74 if bytecode.last() != Some(&opcode::STOP) {
75 panic!("last bytecode byte should be STOP (0x00)");
76 }
77
78 Self {
79 bytecode,
80 original_len,
81 jump_table,
82 }
83 }
84
85 pub fn bytecode(&self) -> &Bytes {
89 &self.bytecode
90 }
91
92 pub fn original_len(&self) -> usize {
94 self.original_len
95 }
96
97 pub fn original_bytes(&self) -> Bytes {
99 self.bytecode.slice(..self.original_len)
100 }
101
102 pub fn original_byte_slice(&self) -> &[u8] {
104 &self.bytecode[..self.original_len]
105 }
106
107 pub fn jump_table(&self) -> &JumpTable {
109 &self.jump_table
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116 use crate::{opcode, LegacyRawBytecode};
117 use bitvec::{bitvec, order::Lsb0};
118
119 #[test]
120 fn test_bytecode_new() {
121 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
122 let bytecode = LegacyRawBytecode(bytecode).into_analyzed();
123 let _ = LegacyAnalyzedBytecode::new(
124 bytecode.bytecode,
125 bytecode.original_len,
126 bytecode.jump_table,
127 );
128 }
129
130 #[test]
131 #[should_panic(expected = "original_len is greater than bytecode length")]
132 fn test_panic_on_large_original_len() {
133 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
134 let bytecode = LegacyRawBytecode(bytecode).into_analyzed();
135 let _ = LegacyAnalyzedBytecode::new(bytecode.bytecode, 100, bytecode.jump_table);
136 }
137
138 #[test]
139 #[should_panic(expected = "jump table length 1 is less than original length 2")]
140 fn test_panic_on_short_jump_table() {
141 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
142 let bytecode = LegacyRawBytecode(bytecode).into_analyzed();
143 let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 1]);
144 let _ = LegacyAnalyzedBytecode::new(bytecode.bytecode, bytecode.original_len, jump_table);
145 }
146
147 #[test]
148 #[should_panic(expected = "last bytecode byte should be STOP (0x00)")]
149 fn test_panic_on_non_stop_bytecode() {
150 let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]);
151 let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 2]);
152 let _ = LegacyAnalyzedBytecode::new(bytecode, 2, jump_table);
153 }
154
155 #[test]
156 #[should_panic(expected = "bytecode cannot be empty")]
157 fn test_panic_on_empty_bytecode() {
158 let bytecode = Bytes::from_static(&[]);
159 let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 0]);
160 let _ = LegacyAnalyzedBytecode::new(bytecode, 0, jump_table);
161 }
162}