solana_bytes_reader/
reader.rs

1use solana_program_error::ProgramError;
2use super::{
3    utils::*,
4    traits::*
5};
6
7
8#[derive(Debug, Clone, Copy)]
9/// # Safety
10/// The caller is responsible for ensuring that the bytes slice is valid.
11/// 
12/// # Examples
13/// ```
14/// use core::array;
15/// use solana_bytes_reader::{Reader, ReadBytes};
16/// 
17/// fn main() -> Result<(), Box<dyn std::error::Error>> {
18///     let bytes: [u8; 32] = array::from_fn(|i| if i % 4 == 0 { i as u8 } else { 0u8 });
19///     
20///     let mut reader: Reader = Reader::new(&bytes);
21///     let first_u32: u32 = reader.read_u32()?;
22///     let second_u32: u32 = reader.read_u32()?;
23///     let third_u32: u32 = reader.read_u32()?;
24/// 
25///     assert_eq!(first_u32, 0u32);
26///     assert_eq!(second_u32, 4u32);
27///     assert_eq!(third_u32, 8u32);
28///     
29///     Ok(())
30/// }
31/// ```
32///
33/// It's recommended to initialize `Reader` and use it's methods if there are more than 2 method calls.
34/// 
35/// Otherwise there's no need in this struct and functions can be used instead.
36pub struct Reader<'a> {
37    bytes: &'a [u8],
38    offset: usize
39}
40
41impl<'a> Reader<'a> {
42    /// # Panics
43    /// if bytes slice is empty.
44    #[inline]
45    pub fn new(bytes: &'a [u8]) -> Self {
46        assert!(bytes.len() > 0);
47        Self { bytes, offset: 0 }
48    }
49
50    /// # Panics 
51    /// if `offset` equals/greater than bytes slice OR if bytes slice is empty.
52    #[inline]
53    pub fn new_with_offset(bytes: &'a [u8], offset: usize) -> Self {
54        let len: usize = bytes.len();
55        assert!(len > offset && len > 0);
56        Self { bytes, offset }
57    }
58
59    #[inline]
60    pub fn bytes(&self) -> &'a [u8] {
61        self.bytes
62    }
63
64    #[inline]
65    pub fn offset(&self) -> usize {
66        self.offset
67    }
68
69    #[inline]
70    /// Returns remaining bytes.
71    pub fn remaining(&self) -> usize {
72        self.bytes.len().saturating_sub(self.offset)
73    }
74
75    /// # Panics 
76    /// if `new_offset` equals/greater than bytes slice.
77    #[inline]
78    pub fn set_offset(&mut self, new_offset: usize) -> () {
79        assert!(self.bytes.len() > new_offset);
80        self.offset = new_offset;
81    }
82
83    fn read<T, F>(&mut self, read_method: F) -> Result<T, ProgramError> 
84    where
85        T: Sized,
86        F: Fn(&[u8], usize) -> Result<T, ProgramError>
87    {
88        let val: T = read_method(self.bytes, self.offset)?;
89        self.offset += std::mem::size_of::<T>();
90        Ok(val)
91    }
92}
93
94impl ReadBytes for Reader<'_> {
95    type Error = ProgramError;
96
97    fn read_u64(&mut self) -> Result<u64, Self::Error> {
98        self.read(read_u64_slice)
99    }
100
101    fn read_i64(&mut self) -> Result<i64, Self::Error> {
102        self.read(read_i64_slice)
103    }
104
105    fn read_u32(&mut self) -> Result<u32, Self::Error> {
106        self.read(read_u32_slice)
107    }
108
109    fn read_i32(&mut self) -> Result<i32, Self::Error> {
110        self.read(read_i32_slice)
111    }
112
113    fn read_u16(&mut self) -> Result<u16, Self::Error> {
114        self.read(read_u16_slice)
115    }
116
117    fn read_i16(&mut self) -> Result<i16, Self::Error> {
118        self.read(read_i16_slice)
119    }
120
121    fn read_bool(&mut self) -> Result<bool, Self::Error> {
122        self.read(read_bool_slice)
123    }
124
125    fn read_u8(&mut self) -> Result<u8, Self::Error> {
126        self.read(read_u8_slice)
127    }
128
129    fn read_i8(&mut self) -> Result<i8, Self::Error> {
130        self.read(read_i8_slice)
131    }
132
133    fn read_bytes<const N: usize>(&mut self) -> Result<[u8; N], Self::Error> {
134        self.read(read_bytes_slice)
135    }
136
137    fn skip(&mut self, bytes_to_skip: usize) {
138        self.offset += bytes_to_skip;
139    }
140}
141
142impl PeekIntoBytes for Reader<'_> {
143    type Error = ProgramError;
144
145    fn peek_u64(&self) -> Result<u64, Self::Error> {
146        read_u64_slice(self.bytes, self.offset)
147    }
148
149    fn peek_i64(&self) -> Result<i64, Self::Error> {
150        read_i64_slice(self.bytes, self.offset)
151    }
152
153    fn peek_u32(&self) -> Result<u32, Self::Error> {
154        read_u32_slice(self.bytes, self.offset)
155    }
156
157    fn peek_i32(&self) -> Result<i32, Self::Error> {
158        read_i32_slice(self.bytes, self.offset)
159    }
160
161    fn peek_u16(&self) -> Result<u16, Self::Error> {
162        read_u16_slice(self.bytes, self.offset)
163    }
164
165    fn peek_i16(&self) -> Result<i16, Self::Error> {
166        read_i16_slice(self.bytes, self.offset)
167    }
168
169    fn peek_bool(&self) -> Result<bool, ProgramError> {
170        read_bool_slice(self.bytes, self.offset)
171    }
172
173    fn peek_u8(&self) -> Result<u8, Self::Error> {
174        read_u8_slice(self.bytes, self.offset)
175    }
176
177    fn peek_i8(&self) -> Result<i8, Self::Error> {
178        read_i8_slice(self.bytes, self.offset)
179    }
180
181    fn peek_bytes<const N: usize>(&self) -> Result<[u8; N], Self::Error> {
182        read_bytes_slice::<N>(self.bytes, self.offset)
183    }
184}