revm_bytecode/legacy/
analyzed.rs1use super::JumpTable;
2use primitives::Bytes;
3
4#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30pub struct LegacyAnalyzedBytecode {
31 bytecode: Bytes,
33 original_len: usize,
35 jump_table: JumpTable,
37}
38
39impl Default for LegacyAnalyzedBytecode {
40 #[inline]
41 fn default() -> Self {
42 Self {
43 bytecode: Bytes::from_static(&[0]),
44 original_len: 0,
45 jump_table: JumpTable::default(),
46 }
47 }
48}
49
50impl LegacyAnalyzedBytecode {
51 pub fn analyze(bytecode: Bytes) -> Self {
55 let original_len = bytecode.len();
56 let (jump_table, padded_bytecode) = super::analysis::analyze_legacy(bytecode);
57 Self::new(padded_bytecode, original_len, jump_table)
58 }
59
60 pub fn new(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
70 assert!(
71 original_len <= bytecode.len(),
72 "original_len is greater than bytecode length"
73 );
74 assert!(
75 original_len <= jump_table.len(),
76 "jump table length is less than original length"
77 );
78 assert!(!bytecode.is_empty(), "bytecode cannot be empty");
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 is less than original length")]
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 = "bytecode cannot be empty")]
150 fn test_panic_on_empty_bytecode() {
151 let bytecode = Bytes::from_static(&[]);
152 let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 0]);
153 let _ = LegacyAnalyzedBytecode::new(bytecode, 0, jump_table);
154 }
155}