#[inline]
pub unsafe fn read_i16(ptr: *const u8) -> i16 {
read_u16(ptr) as i16
}
#[inline]
pub unsafe fn read_u16(ptr: *const u8) -> u16 {
u16::from_be_bytes(unsafe { ptr.cast::<[u8; 2]>().read() })
}
#[cfg(test)]
pub mod test {
use crate::opcode;
use anyhow::Result;
use primitives::U256;
use rand::Rng;
pub fn build_memory_input_opcodes(start_offset: U256, input: &[u8]) -> Result<Vec<u8>> {
let mut opcodes = vec![];
let mut current_offset = start_offset;
let offset_step = U256::from(32);
for bytes in input.chunks(32) {
build_push_bytes(bytes, &mut opcodes);
build_push_u256(current_offset, &mut opcodes);
opcodes.push(opcode::MSTORE);
current_offset += offset_step;
}
Ok(opcodes)
}
fn build_push_u256(value: U256, opcodes: &mut Vec<u8>) {
let bytes = value.to_be_bytes_trimmed_vec();
build_push_bytes(&bytes, opcodes);
}
fn build_push_bytes(bytes: &[u8], opcodes: &mut Vec<u8>) {
let len = bytes.len();
assert!(len <= 32);
let push_opcode = opcode::PUSH0 + len as u8;
opcodes.push(push_opcode);
opcodes.extend_from_slice(bytes);
}
#[test]
fn test_build_memory_input_opcodes() {
let mut rng = rand::rng();
let start_offset = rng.random_range(0x0100_0000..=(u32::MAX - 100));
let mut current_offset = start_offset;
let mut all_inputs = vec![];
let mut expected_opcodes = vec![];
let input_arr: [[u8; 32]; 3] = rng.random();
for input in input_arr {
all_inputs.extend(input);
expected_opcodes.push(opcode::PUSH32);
expected_opcodes.extend(input);
expected_opcodes.push(opcode::PUSH4);
expected_opcodes.extend(current_offset.to_be_bytes());
expected_opcodes.push(opcode::MSTORE);
current_offset += 32;
}
let last_input: [u8; 15] = rng.random();
{
all_inputs.extend(last_input);
expected_opcodes.push(opcode::PUSH15);
expected_opcodes.extend(last_input);
expected_opcodes.push(opcode::PUSH4);
expected_opcodes.extend(current_offset.to_be_bytes());
expected_opcodes.push(opcode::MSTORE);
}
let opcodes = build_memory_input_opcodes(U256::from(start_offset), &all_inputs).unwrap();
assert_eq!(opcodes, expected_opcodes);
}
}