use core::option::OptionTrait; use core::array::ArrayTrait; use core::keccak::cairo_keccak; use core::integer::u128_byte_reverse; use core::fmt::{Debug, Formatter}; use pyth::util::{UNEXPECTED_OVERFLOW, UNEXPECTED_ZERO, one_shift_left_bytes_u128}; use super::byte_buffer::{ByteBuffer, ByteBufferImpl}; #[derive(Drop, Copy, Debug, PartialEq, Serde, Hash)] pub enum Error { UnexpectedEndOfInput, } impl ErrorIntoFelt252 of Into { fn into(self: Error) -> felt252 { match self { Error::UnexpectedEndOfInput => 'unexpected end of input', } } } /// Allows to read data from a byte array as big endian integers. /// All methods return `EOF` error if attempted to /// read more bytes than is available. #[derive(Drop, Clone, Debug, PartialEq, Serde)] pub struct Reader { // Input array. array: ByteBuffer, // Current value to read from (in big endian). current: u128, // Number of remaining bytes in `self.current`. num_current_bytes: u8, // Next value to read from (in big endian). This is needed because // `array.pop_front()` returns up to 31 bytes which require two u128 to store. next: Option, } impl DefaultReader of Default { fn default() -> Reader { ReaderImpl::new(Default::default()) } } #[generate_trait] pub impl ReaderImpl of ReaderTrait { fn new(array: ByteBuffer) -> Reader { Reader { array, current: 0, num_current_bytes: 0, next: Option::None } } /// Reads the specified number of bytes (up to 16) as a big endian unsigned integer. fn read_num_bytes(ref self: Reader, num_bytes: u8) -> u128 { assert!(num_bytes <= 16, "Reader::read_num_bytes: num_bytes is too large"); if num_bytes <= self.num_current_bytes { return self.read_from_current(num_bytes); } let num_low_bytes = num_bytes - self.num_current_bytes; let high = self.current; self.fetch_next(); let low = self.read_num_bytes(num_low_bytes); if num_low_bytes == 16 { low } else { high * one_shift_left_bytes_u128(num_low_bytes) + low } } fn read_u256(ref self: Reader) -> u256 { let high = self.read_num_bytes(16); let low = self.read_num_bytes(16); let value = u256 { high, low }; value } fn read_u160(ref self: Reader) -> u256 { let high = self.read_num_bytes(4); let low = self.read_num_bytes(16); u256 { high, low } } fn read_u128(ref self: Reader) -> u128 { self.read_num_bytes(16) } fn read_u64(ref self: Reader) -> u64 { self.read_num_bytes(8).try_into().expect(UNEXPECTED_OVERFLOW) } fn read_u32(ref self: Reader) -> u32 { self.read_num_bytes(4).try_into().expect(UNEXPECTED_OVERFLOW) } fn read_u16(ref self: Reader) -> u16 { self.read_num_bytes(2).try_into().expect(UNEXPECTED_OVERFLOW) } fn read_u8(ref self: Reader) -> u8 { self.read_num_bytes(1).try_into().expect(UNEXPECTED_OVERFLOW) } // TODO: skip without calculating values fn skip(ref self: Reader, mut num_bytes: usize) { while num_bytes > 0 { if num_bytes > 16 { self.read_num_bytes(16); num_bytes -= 16; } else { // num_bytes <= 16 so it shouldn't overflow. self.read_num_bytes(num_bytes.try_into().expect(UNEXPECTED_OVERFLOW)); break; } } } /// Reads the specified number of bytes as a new byte array. fn read_byte_array(ref self: Reader, num_bytes: usize) -> ByteBuffer { let mut array: Array = array![]; let mut num_last_bytes = 0; let mut num_remaining_bytes = num_bytes; loop { let (num_read, eof) = self.read_bytes_iteration(num_remaining_bytes, ref array); num_remaining_bytes -= num_read; if eof { num_last_bytes = num_read; break; } }; // num_last_bytes < 31 let num_last_bytes = num_last_bytes.try_into().expect(UNEXPECTED_OVERFLOW); ByteBufferImpl::new(array, num_last_bytes) } /// Returns number of remaining bytes to read. fn len(ref self: Reader) -> usize { let num_next_bytes = if self.next.is_some() { 16 } else { 0 }; self.num_current_bytes.into() + num_next_bytes + self.array.len() } } #[generate_trait] impl ReaderPrivateImpl of ReaderPrivateTrait { /// Reads the specified number of bytes from `self.current`. /// Panics if attempted to read more than `self.num_current_bytes`. fn read_from_current(ref self: Reader, num_bytes: u8) -> u128 { let num_remaining_bytes = self.num_current_bytes - num_bytes; let divisor = one_shift_left_bytes_u128(num_remaining_bytes) .try_into() .expect(UNEXPECTED_ZERO); let (high, low) = DivRem::div_rem(self.current, divisor); self.current = low; self.num_current_bytes = num_remaining_bytes; high } /// Replenishes `self.current` and `self.num_current_bytes`. /// This should only be called when all bytes from `self.current` has been read. /// Returns `EOF` error if no more data is available. fn fetch_next(ref self: Reader) { match self.next { Option::Some(next) => { self.next = Option::None; self.current = next; self.num_current_bytes = 16; }, Option::None => { let (value, bytes) = self .array .pop_front() .expect(Error::UnexpectedEndOfInput.into()); let value: u256 = value.into(); if bytes > 16 { self.current = value.high; self.next = Option::Some(value.low); self.num_current_bytes = bytes - 16; } else { self.current = value.low; self.num_current_bytes = bytes; } }, } } // Moved out from `read_bytes` because we cannot use `return` or `?` within a loop. fn read_bytes_iteration( ref self: Reader, num_bytes: usize, ref array: Array ) -> (usize, bool) { if num_bytes >= 31 { let high = self.read_num_bytes(15); let low = self.read_num_bytes(16); let value: felt252 = u256 { high, low }.try_into().expect(UNEXPECTED_OVERFLOW); array.append(value); (31, false) } else if num_bytes > 16 { // num_bytes < 31 let high = self.read_num_bytes((num_bytes - 16).try_into().expect(UNEXPECTED_OVERFLOW)); let low = self.read_num_bytes(16); let value: felt252 = u256 { high, low }.try_into().expect(UNEXPECTED_OVERFLOW); array.append(value); (num_bytes, true) } else { // bytes < 16 let low = self.read_num_bytes(num_bytes.try_into().expect(UNEXPECTED_OVERFLOW)); let value: felt252 = low.try_into().expect(UNEXPECTED_OVERFLOW); array.append(value); (num_bytes, true) } } }