1#![no_std]
7#![deny(warnings)]
8
9extern crate alloc;
10
11use alloc::vec::Vec;
12
13pub use miden_field::Felt;
14pub use miden_field_repr_derive::DeriveFromFeltRepr as FromFeltRepr;
16pub use miden_field_repr_derive::DeriveToFeltRepr as ToFeltRepr;
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21#[non_exhaustive]
22pub enum FeltReprError {
23 UnexpectedEof {
25 pos: usize,
27 len: usize,
29 },
30 ValueOutOfRange {
32 pos: usize,
34 len: usize,
36 ty: &'static str,
38 value: u64,
40 max: u64,
42 },
43 InvalidOptionTag {
45 pos: usize,
47 len: usize,
49 tag: u64,
51 },
52 InvalidBool {
54 pos: usize,
56 len: usize,
58 value: u64,
60 },
61 UnknownEnumTag {
63 pos: usize,
65 len: usize,
67 ty: &'static str,
69 tag: u32,
71 },
72 TrailingData {
74 pos: usize,
76 len: usize,
78 },
79 Custom(&'static str),
81}
82
83impl core::fmt::Display for FeltReprError {
84 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
85 match self {
86 Self::UnexpectedEof { pos, len } => {
87 write!(f, "unexpected end of input at felt {pos} of {len}")
88 }
89 Self::ValueOutOfRange {
90 pos,
91 len,
92 ty,
93 value,
94 max,
95 } => {
96 write!(f, "value {value} out of range for {ty} at felt {pos} of {len} (max {max})")
97 }
98 Self::InvalidOptionTag { pos, len, tag } => {
99 write!(f, "invalid Option tag at felt {pos} of {len}: {tag}")
100 }
101 Self::InvalidBool { pos, len, value } => {
102 write!(f, "invalid bool value at felt {pos} of {len}: {value}")
103 }
104 Self::UnknownEnumTag { pos, len, ty, tag } => {
105 write!(f, "unknown enum tag for {ty} at felt {pos} of {len}: {tag}")
106 }
107 Self::TrailingData { pos, len } => {
108 write!(f, "trailing data starting at felt {pos} of {len}")
109 }
110 Self::Custom(msg) => f.write_str(msg),
111 }
112 }
113}
114
115pub type FeltReprResult<T> = core::result::Result<T, FeltReprError>;
117
118pub struct FeltReader<'a> {
120 data: &'a [Felt],
121 pos: usize,
122}
123
124impl<'a> FeltReader<'a> {
125 #[inline(always)]
127 pub fn new(data: &'a [Felt]) -> Self {
128 Self { data, pos: 0 }
129 }
130
131 #[inline(always)]
133 pub fn pos(&self) -> usize {
134 self.pos
135 }
136
137 #[inline(always)]
139 pub fn len(&self) -> usize {
140 self.data.len()
141 }
142
143 #[inline(always)]
145 pub fn is_empty(&self) -> bool {
146 self.data.is_empty()
147 }
148
149 #[inline(always)]
151 pub fn remaining(&self) -> usize {
152 self.data.len().saturating_sub(self.pos)
153 }
154
155 #[inline(always)]
157 pub fn ensure_eof(&self) -> FeltReprResult<()> {
158 if self.remaining() != 0 {
159 return Err(FeltReprError::TrailingData {
160 pos: self.pos,
161 len: self.data.len(),
162 });
163 }
164 Ok(())
165 }
166
167 #[inline(always)]
169 pub fn read(&mut self) -> FeltReprResult<Felt> {
170 if self.pos >= self.data.len() {
171 return Err(FeltReprError::UnexpectedEof {
172 pos: self.pos,
173 len: self.data.len(),
174 });
175 }
176
177 let felt = self.data[self.pos];
178 self.pos += 1;
179 Ok(felt)
180 }
181
182 #[inline(always)]
184 pub fn read_u32(&mut self) -> FeltReprResult<u32> {
185 let pos = self.pos;
186 let len = self.data.len();
187 let value = self.read()?.as_canonical_u64();
188 if value > u32::MAX as u64 {
189 return Err(FeltReprError::ValueOutOfRange {
190 pos,
191 len,
192 ty: "u32",
193 value,
194 max: u32::MAX as u64,
195 });
196 }
197 Ok(value as u32)
198 }
199
200 #[inline(always)]
202 pub fn read_u8(&mut self) -> FeltReprResult<u8> {
203 let pos = self.pos;
204 let len = self.data.len();
205 let value = self.read()?.as_canonical_u64();
206 if value > u8::MAX as u64 {
207 return Err(FeltReprError::ValueOutOfRange {
208 pos,
209 len,
210 ty: "u8",
211 value,
212 max: u8::MAX as u64,
213 });
214 }
215 Ok(value as u8)
216 }
217
218 #[inline(always)]
222 pub fn read_bool(&mut self) -> FeltReprResult<bool> {
223 let pos = self.pos;
224 let len = self.data.len();
225 match self.read()?.as_canonical_u64() {
226 0 => Ok(false),
227 1 => Ok(true),
228 value => Err(FeltReprError::InvalidBool { pos, len, value }),
229 }
230 }
231
232 #[inline(always)]
236 pub fn read_len_u32(&mut self) -> FeltReprResult<usize> {
237 Ok(self.read_u32()? as usize)
238 }
239}
240
241pub struct FeltWriter<'a> {
243 data: &'a mut Vec<Felt>,
244}
245
246impl<'a> FeltWriter<'a> {
247 #[inline(always)]
249 pub fn new(data: &'a mut Vec<Felt>) -> Self {
250 Self { data }
251 }
252
253 #[inline(always)]
255 pub fn write(&mut self, felt: Felt) {
256 self.data.push(felt);
257 }
258}
259
260pub trait FromFeltRepr: Sized {
262 fn from_felt_repr(reader: &mut FeltReader<'_>) -> FeltReprResult<Self>;
264}
265
266impl FromFeltRepr for Felt {
267 #[inline(always)]
268 fn from_felt_repr(reader: &mut FeltReader<'_>) -> FeltReprResult<Self> {
269 reader.read()
270 }
271}
272
273impl FromFeltRepr for u64 {
274 #[inline(always)]
275 fn from_felt_repr(reader: &mut FeltReader<'_>) -> FeltReprResult<Self> {
276 let lo = reader.read_u32()? as u64;
278 let hi = reader.read_u32()? as u64;
279 Ok((hi << 32) | lo)
280 }
281}
282
283impl FromFeltRepr for u32 {
284 #[inline(always)]
285 fn from_felt_repr(reader: &mut FeltReader<'_>) -> FeltReprResult<Self> {
286 reader.read_u32()
287 }
288}
289
290impl FromFeltRepr for u8 {
291 #[inline(always)]
292 fn from_felt_repr(reader: &mut FeltReader<'_>) -> FeltReprResult<Self> {
293 reader.read_u8()
294 }
295}
296
297impl FromFeltRepr for bool {
298 #[inline(always)]
299 fn from_felt_repr(reader: &mut FeltReader<'_>) -> FeltReprResult<Self> {
300 reader.read_bool()
301 }
302}
303
304impl<T> FromFeltRepr for Option<T>
310where
311 T: FromFeltRepr,
312{
313 #[inline(always)]
314 fn from_felt_repr(reader: &mut FeltReader<'_>) -> FeltReprResult<Self> {
315 let pos = reader.pos();
316 let len = reader.len();
317 match reader.read()?.as_canonical_u64() {
318 0 => Ok(None),
319 1 => Ok(Some(T::from_felt_repr(reader)?)),
320 tag => Err(FeltReprError::InvalidOptionTag { pos, len, tag }),
321 }
322 }
323}
324
325impl<T> FromFeltRepr for Vec<T>
329where
330 T: FromFeltRepr,
331{
332 #[inline(always)]
333 fn from_felt_repr(reader: &mut FeltReader<'_>) -> FeltReprResult<Self> {
334 let len = reader.read_len_u32()?;
335
336 let mut result = Vec::with_capacity(len);
337
338 let mut i = 0usize;
339 while i < len {
340 result.push(T::from_felt_repr(reader)?);
341 i += 1;
342 }
343 Ok(result)
344 }
345}
346
347pub trait ToFeltRepr {
349 fn write_felt_repr(&self, writer: &mut FeltWriter<'_>);
351
352 fn to_felt_repr(&self) -> Vec<Felt> {
354 let mut data = Vec::with_capacity(256);
356 self.write_felt_repr(&mut FeltWriter::new(&mut data));
357 data
358 }
359}
360
361impl ToFeltRepr for Felt {
362 #[inline(always)]
363 fn write_felt_repr(&self, writer: &mut FeltWriter<'_>) {
364 writer.write(*self);
365 }
366}
367
368impl ToFeltRepr for u64 {
369 #[inline(always)]
370 fn write_felt_repr(&self, writer: &mut FeltWriter<'_>) {
371 let lo = (*self & 0xffff_ffff) as u32;
372 let hi = (*self >> 32) as u32;
373 writer.write(Felt::new(lo as u64).unwrap());
374 writer.write(Felt::new(hi as u64).unwrap());
375 }
376}
377
378impl ToFeltRepr for u32 {
379 #[inline(always)]
380 fn write_felt_repr(&self, writer: &mut FeltWriter<'_>) {
381 writer.write(Felt::new(*self as u64).unwrap());
382 }
383}
384
385impl ToFeltRepr for u8 {
386 #[inline(always)]
387 fn write_felt_repr(&self, writer: &mut FeltWriter<'_>) {
388 writer.write(Felt::new(*self as u64).unwrap());
389 }
390}
391
392impl ToFeltRepr for bool {
393 #[inline(always)]
394 fn write_felt_repr(&self, writer: &mut FeltWriter<'_>) {
395 writer.write(Felt::new(*self as u64).unwrap());
396 }
397}
398
399impl<T> ToFeltRepr for Option<T>
405where
406 T: ToFeltRepr,
407{
408 #[inline(always)]
409 fn write_felt_repr(&self, writer: &mut FeltWriter<'_>) {
410 match self {
411 None => writer.write(Felt::new(0).unwrap()),
412 Some(value) => {
413 writer.write(Felt::new(1).unwrap());
414 value.write_felt_repr(writer);
415 }
416 }
417 }
418}
419
420impl<T> ToFeltRepr for Vec<T>
424where
425 T: ToFeltRepr,
426{
427 #[inline(always)]
428 fn write_felt_repr(&self, writer: &mut FeltWriter<'_>) {
429 let len = self.len();
430 assert!(len <= u32::MAX as usize, "Vec: length out of range");
431 writer.write(Felt::new(len as u64).unwrap());
432
433 let mut i = 0usize;
434 while i < len {
435 self[i].write_felt_repr(writer);
436 i += 1;
437 }
438 }
439}