hopper_core/account/
cursor.rs1use hopper_runtime::error::ProgramError;
4
5pub struct SliceCursor<'a> {
10 data: &'a [u8],
11 pos: usize,
12}
13
14impl<'a> SliceCursor<'a> {
15 #[inline(always)]
17 pub const fn new(data: &'a [u8]) -> Self {
18 Self { data, pos: 0 }
19 }
20
21 #[inline(always)]
23 pub fn from_instruction(data: &'a [u8], min_len: usize) -> Result<Self, ProgramError> {
24 if data.len() < min_len {
25 return Err(ProgramError::InvalidInstructionData);
26 }
27 Ok(Self::new(data))
28 }
29
30 #[inline(always)]
32 pub const fn position(&self) -> usize {
33 self.pos
34 }
35
36 #[inline(always)]
38 pub const fn remaining(&self) -> usize {
39 self.data.len() - self.pos
40 }
41
42 #[inline(always)]
44 pub fn data_from_position(&self) -> &'a [u8] {
45 &self.data[self.pos..]
46 }
47
48 #[inline(always)]
50 pub fn skip(&mut self, n: usize) -> Result<(), ProgramError> {
51 if self.remaining() < n {
52 return Err(ProgramError::InvalidAccountData);
53 }
54 self.pos += n;
55 Ok(())
56 }
57
58 #[inline(always)]
60 pub fn read_u8(&mut self) -> Result<u8, ProgramError> {
61 if self.remaining() < 1 {
62 return Err(ProgramError::InvalidAccountData);
63 }
64 let v = self.data[self.pos];
65 self.pos += 1;
66 Ok(v)
67 }
68
69 #[inline(always)]
71 pub fn read_u16(&mut self) -> Result<u16, ProgramError> {
72 if self.remaining() < 2 {
73 return Err(ProgramError::InvalidAccountData);
74 }
75 let v = u16::from_le_bytes([self.data[self.pos], self.data[self.pos + 1]]);
76 self.pos += 2;
77 Ok(v)
78 }
79
80 #[inline(always)]
82 pub fn read_u32(&mut self) -> Result<u32, ProgramError> {
83 if self.remaining() < 4 {
84 return Err(ProgramError::InvalidAccountData);
85 }
86 let v = u32::from_le_bytes([
87 self.data[self.pos],
88 self.data[self.pos + 1],
89 self.data[self.pos + 2],
90 self.data[self.pos + 3],
91 ]);
92 self.pos += 4;
93 Ok(v)
94 }
95
96 #[inline(always)]
98 pub fn read_u64(&mut self) -> Result<u64, ProgramError> {
99 if self.remaining() < 8 {
100 return Err(ProgramError::InvalidAccountData);
101 }
102 let v = u64::from_le_bytes([
103 self.data[self.pos],
104 self.data[self.pos + 1],
105 self.data[self.pos + 2],
106 self.data[self.pos + 3],
107 self.data[self.pos + 4],
108 self.data[self.pos + 5],
109 self.data[self.pos + 6],
110 self.data[self.pos + 7],
111 ]);
112 self.pos += 8;
113 Ok(v)
114 }
115
116 #[inline(always)]
118 pub fn read_i64(&mut self) -> Result<i64, ProgramError> {
119 self.read_u64().map(|v| v as i64)
120 }
121
122 #[inline(always)]
124 pub fn read_bool(&mut self) -> Result<bool, ProgramError> {
125 self.read_u8().map(|v| v != 0)
126 }
127
128 #[inline(always)]
130 pub fn read_address(&mut self) -> Result<&'a [u8; 32], ProgramError> {
131 if self.remaining() < 32 {
132 return Err(ProgramError::InvalidAccountData);
133 }
134 let addr = unsafe { &*(self.data.as_ptr().add(self.pos) as *const [u8; 32]) };
136 self.pos += 32;
137 Ok(addr)
138 }
139
140 #[inline(always)]
142 pub fn read_bytes(&mut self, len: usize) -> Result<&'a [u8], ProgramError> {
143 if self.remaining() < len {
144 return Err(ProgramError::InvalidAccountData);
145 }
146 let slice = &self.data[self.pos..self.pos + len];
147 self.pos += len;
148 Ok(slice)
149 }
150}
151
152pub struct DataWriter<'a> {
154 data: &'a mut [u8],
155 pos: usize,
156}
157
158impl<'a> DataWriter<'a> {
159 #[inline(always)]
161 pub fn new(data: &'a mut [u8]) -> Self {
162 Self { data, pos: 0 }
163 }
164
165 #[inline(always)]
167 pub const fn written(&self) -> usize {
168 self.pos
169 }
170
171 #[inline(always)]
173 pub const fn remaining(&self) -> usize {
174 self.data.len() - self.pos
175 }
176
177 #[inline(always)]
179 pub fn write_u8(&mut self, v: u8) -> Result<(), ProgramError> {
180 if self.remaining() < 1 {
181 return Err(ProgramError::AccountDataTooSmall);
182 }
183 self.data[self.pos] = v;
184 self.pos += 1;
185 Ok(())
186 }
187
188 #[inline(always)]
190 pub fn write_u16(&mut self, v: u16) -> Result<(), ProgramError> {
191 if self.remaining() < 2 {
192 return Err(ProgramError::AccountDataTooSmall);
193 }
194 let bytes = v.to_le_bytes();
195 self.data[self.pos] = bytes[0];
196 self.data[self.pos + 1] = bytes[1];
197 self.pos += 2;
198 Ok(())
199 }
200
201 #[inline(always)]
203 pub fn write_u32(&mut self, v: u32) -> Result<(), ProgramError> {
204 if self.remaining() < 4 {
205 return Err(ProgramError::AccountDataTooSmall);
206 }
207 let bytes = v.to_le_bytes();
208 self.data[self.pos..self.pos + 4].copy_from_slice(&bytes);
209 self.pos += 4;
210 Ok(())
211 }
212
213 #[inline(always)]
215 pub fn write_u64(&mut self, v: u64) -> Result<(), ProgramError> {
216 if self.remaining() < 8 {
217 return Err(ProgramError::AccountDataTooSmall);
218 }
219 let bytes = v.to_le_bytes();
220 self.data[self.pos..self.pos + 8].copy_from_slice(&bytes);
221 self.pos += 8;
222 Ok(())
223 }
224
225 #[inline(always)]
227 pub fn write_bool(&mut self, v: bool) -> Result<(), ProgramError> {
228 self.write_u8(v as u8)
229 }
230
231 #[inline(always)]
233 pub fn write_address(&mut self, addr: &[u8; 32]) -> Result<(), ProgramError> {
234 if self.remaining() < 32 {
235 return Err(ProgramError::AccountDataTooSmall);
236 }
237 self.data[self.pos..self.pos + 32].copy_from_slice(addr);
238 self.pos += 32;
239 Ok(())
240 }
241
242 #[inline(always)]
244 pub fn write_bytes(&mut self, src: &[u8]) -> Result<(), ProgramError> {
245 if self.remaining() < src.len() {
246 return Err(ProgramError::AccountDataTooSmall);
247 }
248 self.data[self.pos..self.pos + src.len()].copy_from_slice(src);
249 self.pos += src.len();
250 Ok(())
251 }
252}