1use std::cmp::Ordering;
2use std::error::Error;
3use std::fmt::Debug;
4use std::fmt::Display;
5use std::marker::PhantomData;
6use std::slice::Iter;
7
8pub use bfieldcodec_derive::BFieldCodec;
11use num_traits::ConstOne;
12use num_traits::ConstZero;
13use thiserror::Error;
14
15use super::b_field_element::BFieldElement;
16use super::polynomial::Polynomial;
17use super::traits::FiniteField;
18use crate::bfe;
19use crate::bfe_vec;
20
21pub trait BFieldCodec {
31 type Error: Into<Box<dyn Error + Send + Sync>> + Debug + Display;
32
33 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error>;
34 fn encode(&self) -> Vec<BFieldElement>;
35
36 fn static_length() -> Option<usize>;
39}
40
41#[derive(Debug, Error)]
42#[non_exhaustive]
43pub enum BFieldCodecError {
44 #[error("empty sequence")]
45 EmptySequence,
46
47 #[error("sequence too short")]
48 SequenceTooShort,
49
50 #[error("sequence too long")]
51 SequenceTooLong,
52
53 #[error("element out of range")]
54 ElementOutOfRange,
55
56 #[error("missing length indicator")]
57 MissingLengthIndicator,
58
59 #[error("invalid length indicator")]
60 InvalidLengthIndicator,
61
62 #[error(transparent)]
63 TryFromIntError(#[from] std::num::TryFromIntError),
64
65 #[error("inner decoding error: {0}")]
66 InnerDecodingFailure(#[from] Box<dyn Error + Send + Sync>),
67}
68
69impl BFieldCodec for BFieldElement {
74 type Error = BFieldCodecError;
75
76 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
77 if sequence.is_empty() {
78 return Err(Self::Error::EmptySequence);
79 }
80 if sequence.len() > 1 {
81 return Err(Self::Error::SequenceTooLong);
82 }
83 Ok(Box::new(sequence[0]))
84 }
85
86 fn encode(&self) -> Vec<BFieldElement> {
87 [*self].to_vec()
88 }
89
90 fn static_length() -> Option<usize> {
91 Some(1)
92 }
93}
94
95macro_rules! impl_bfield_codec_for_big_primitive_uint {
96 ($ty:ty, $size:literal) => {
97 impl BFieldCodec for $ty {
98 type Error = BFieldCodecError;
99
100 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
101 if sequence.is_empty() {
102 return Err(Self::Error::EmptySequence);
103 }
104 if sequence.len() < $size {
105 return Err(Self::Error::SequenceTooShort);
106 }
107 if sequence.len() > $size {
108 return Err(Self::Error::SequenceTooLong);
109 }
110 if sequence.iter().any(|s| s.value() > u32::MAX.into()) {
111 return Err(Self::Error::ElementOutOfRange);
112 }
113
114 let element = sequence
115 .iter()
116 .enumerate()
117 .map(|(i, s)| Self::from(s) << (i * 32))
118 .sum();
119 Ok(Box::new(element))
120 }
121
122 fn encode(&self) -> Vec<BFieldElement> {
123 const LOW_BIT_MASK: $ty = u32::MAX as $ty;
124
125 (0..$size)
126 .map(|i| bfe!((*self >> (i * 32)) & LOW_BIT_MASK))
127 .collect()
128 }
129
130 fn static_length() -> Option<usize> {
131 Some($size)
132 }
133 }
134 };
135}
136
137impl_bfield_codec_for_big_primitive_uint!(u64, 2);
138impl_bfield_codec_for_big_primitive_uint!(u128, 4);
139
140macro_rules! impl_bfield_codec_for_signed_int {
141 ($iint:ty, using $uint:ty) => {
142 impl BFieldCodec for $iint {
143 type Error = <$uint as BFieldCodec>::Error;
144
145 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
146 <$uint>::decode(sequence).map(|v| Box::new(*v as Self))
147 }
148
149 fn encode(&self) -> Vec<BFieldElement> {
150 (*self as $uint).encode()
151 }
152
153 fn static_length() -> Option<usize> {
154 <$uint>::static_length()
155 }
156 }
157 };
158}
159
160impl_bfield_codec_for_signed_int!(i8, using u8);
161impl_bfield_codec_for_signed_int!(i16, using u16);
162impl_bfield_codec_for_signed_int!(i32, using u32);
163impl_bfield_codec_for_signed_int!(i64, using u64);
164impl_bfield_codec_for_signed_int!(i128, using u128);
165
166impl BFieldCodec for bool {
167 type Error = BFieldCodecError;
168
169 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
170 if sequence.is_empty() {
171 return Err(Self::Error::EmptySequence);
172 }
173 if sequence.len() > 1 {
174 return Err(Self::Error::SequenceTooLong);
175 }
176
177 let element = match sequence[0].value() {
178 0 => false,
179 1 => true,
180 _ => return Err(Self::Error::ElementOutOfRange),
181 };
182 Ok(Box::new(element))
183 }
184
185 fn encode(&self) -> Vec<BFieldElement> {
186 vec![BFieldElement::new(*self as u64)]
187 }
188
189 fn static_length() -> Option<usize> {
190 Some(1)
191 }
192}
193
194macro_rules! impl_bfield_codec_for_small_primitive_uint {
195 ($($t:ident),+ $(,)?) => {$(
196 impl BFieldCodec for $t {
197 type Error = BFieldCodecError;
198
199 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
200 if sequence.is_empty() {
201 return Err(Self::Error::EmptySequence);
202 }
203 let [first] = sequence[..] else {
204 return Err(Self::Error::SequenceTooLong);
205 };
206 let element = $t::try_from(first.value())
207 .map_err(|_| Self::Error::ElementOutOfRange)?;
208
209 Ok(Box::new(element))
210 }
211
212 fn encode(&self) -> Vec<BFieldElement> {
213 bfe_vec![*self]
214 }
215
216 fn static_length() -> Option<usize> {
217 Some(1)
218 }
219 }
220 )+};
221}
222
223impl_bfield_codec_for_small_primitive_uint!(u8, u16, u32);
224
225impl<T: BFieldCodec> BFieldCodec for Box<T> {
226 type Error = T::Error;
227
228 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
229 T::decode(sequence).map(Box::new)
230 }
231
232 fn encode(&self) -> Vec<BFieldElement> {
233 self.as_ref().encode()
234 }
235
236 fn static_length() -> Option<usize> {
237 T::static_length()
238 }
239}
240
241macro_rules! impl_bfield_codec_for_tuple {
242 ($($forward:ident),+) => {
244 impl_bfield_codec_for_tuple!(@>@ $($forward)+ @rev@);
245 };
246
247 ($($a:ident)* @>@ $b:ident $($c:ident)* @rev@ $($reverse:ident)*) => {
249 impl_bfield_codec_for_tuple!($($a)* $b @>@ $($c)* @rev@ $b $($reverse)*);
250 };
251
252 ($($f:ident)+ @>@ @rev@ $($r:ident)+) => {
267 impl <$($f),+> BFieldCodec for ($($f),+ ,)
268 where $($f: BFieldCodec),+
269 {
270 type Error = BFieldCodecError;
271
272 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
273 $(
274 if $r::static_length().is_none() && sequence.first().is_none() {
275 return Err(Self::Error::MissingLengthIndicator);
276 }
277 let (length, sequence) = $r::static_length()
278 .map(|length| (Ok(length), sequence))
279 .unwrap_or_else(|| (sequence[0].try_into(), &sequence[1..]));
280 let length = length?;
281 if sequence.len() < length {
282 return Err(Self::Error::SequenceTooShort);
283 }
284 let (sequence_for_ty, sequence) = sequence.split_at(length);
285 #[allow(non_snake_case)]
286 let $r = *$r::decode(sequence_for_ty).map_err(|err| err.into())?;
287 )+
288
289 if !sequence.is_empty() {
290 return Err(Self::Error::SequenceTooLong);
291 }
292 Ok(Box::new(($($f),+ ,)))
293 }
294
295 fn encode(&self) -> Vec<BFieldElement> {
296 #[allow(non_snake_case)]
297 let ($($f),+ ,) = self;
298 let mut sequence = vec![];
299
300 $(
301 let encoding = $r.encode();
302 if $r::static_length().is_none() {
303 sequence.push(encoding.len().into());
304 }
305 sequence.extend(encoding);
306 )+
307
308 sequence
309 }
310
311 fn static_length() -> Option<usize> {
312 Some($($f::static_length()? +)+ 0)
315 }
316 }
317 };
318}
319
320impl_bfield_codec_for_tuple!(A);
321impl_bfield_codec_for_tuple!(A, B);
322impl_bfield_codec_for_tuple!(A, B, C);
323impl_bfield_codec_for_tuple!(A, B, C, D);
324impl_bfield_codec_for_tuple!(A, B, C, D, E);
325impl_bfield_codec_for_tuple!(A, B, C, D, E, F);
326impl_bfield_codec_for_tuple!(A, B, C, D, E, F, G);
327impl_bfield_codec_for_tuple!(A, B, C, D, E, F, G, H);
328impl_bfield_codec_for_tuple!(A, B, C, D, E, F, G, H, I);
329impl_bfield_codec_for_tuple!(A, B, C, D, E, F, G, H, I, J);
330impl_bfield_codec_for_tuple!(A, B, C, D, E, F, G, H, I, J, K);
331impl_bfield_codec_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
332
333impl<T: BFieldCodec> BFieldCodec for Option<T> {
334 type Error = BFieldCodecError;
335
336 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
337 if sequence.is_empty() {
338 return Err(Self::Error::EmptySequence);
339 }
340 let is_some = *bool::decode(&sequence[0..1])?;
341 let sequence = &sequence[1..];
342 let maybe_result = is_some.then(|| T::decode(sequence).map_err(|e| e.into()));
343 let element = maybe_result.transpose()?.map(|boxed_self| *boxed_self);
344
345 if !is_some && !sequence.is_empty() {
346 return Err(Self::Error::SequenceTooLong);
347 }
348 Ok(Box::new(element))
349 }
350
351 fn encode(&self) -> Vec<BFieldElement> {
352 match self {
353 None => vec![BFieldElement::ZERO],
354 Some(t) => [vec![BFieldElement::ONE], t.encode()].concat(),
355 }
356 }
357
358 fn static_length() -> Option<usize> {
359 None
360 }
361}
362
363impl<T: BFieldCodec, const N: usize> BFieldCodec for [T; N] {
364 type Error = BFieldCodecError;
365
366 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
367 if N > 0 && sequence.is_empty() {
368 return Err(Self::Error::EmptySequence);
369 }
370
371 let vec_t = bfield_codec_decode_list(N, sequence)?;
372 let array = vec_t.try_into().map_err(|_| {
373 Self::Error::InnerDecodingFailure(format!("cannot convert Vec<T> into [T; {N}]").into())
374 })?;
375 Ok(Box::new(array))
376 }
377
378 fn encode(&self) -> Vec<BFieldElement> {
379 bfield_codec_encode_list(self.iter())
380 }
381
382 fn static_length() -> Option<usize> {
383 T::static_length().map(|len| len * N)
384 }
385}
386
387impl<T: BFieldCodec> BFieldCodec for Vec<T> {
388 type Error = BFieldCodecError;
389
390 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
391 if sequence.is_empty() {
392 return Err(Self::Error::EmptySequence);
393 }
394
395 let vec_length = sequence[0].try_into()?;
396 let vec = bfield_codec_decode_list(vec_length, &sequence[1..])?;
397 Ok(Box::new(vec))
398 }
399
400 fn encode(&self) -> Vec<BFieldElement> {
401 let mut encoding = bfe_vec![self.len()];
402 encoding.extend(bfield_codec_encode_list(self.iter()));
403 encoding
404 }
405
406 fn static_length() -> Option<usize> {
407 None
408 }
409}
410
411#[derive(Debug, Error)]
412pub enum PolynomialBFieldCodecError {
413 #[error("trailing zeros in polynomial-encoding")]
422 TrailingZerosInPolynomialEncoding,
423
424 #[error(transparent)]
425 Other(#[from] BFieldCodecError),
426}
427
428impl<T> BFieldCodec for Polynomial<'_, T>
429where
430 T: BFieldCodec + FiniteField + 'static,
431{
432 type Error = PolynomialBFieldCodecError;
433
434 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
435 if sequence.is_empty() {
436 return Err(Self::Error::Other(BFieldCodecError::EmptySequence));
437 }
438
439 let coefficients_field_length_indicator: Result<usize, _> = sequence[0].value().try_into();
440 let Ok(coefficients_field_length_indicator) = coefficients_field_length_indicator else {
441 return Err(Self::Error::Other(BFieldCodecError::InvalidLengthIndicator));
442 };
443
444 let indicated_sequence_length = coefficients_field_length_indicator + 1;
446 let decoded_vec = match sequence.len().cmp(&indicated_sequence_length) {
447 Ordering::Equal => Vec::<T>::decode(&sequence[1..]),
448 Ordering::Less => Err(BFieldCodecError::SequenceTooShort),
449 Ordering::Greater => Err(BFieldCodecError::SequenceTooLong),
450 }?;
451
452 let encoding_contains_trailing_zeros = decoded_vec
453 .last()
454 .is_some_and(|last_coeff| last_coeff.is_zero());
455 if encoding_contains_trailing_zeros {
456 return Err(PolynomialBFieldCodecError::TrailingZerosInPolynomialEncoding);
457 }
458
459 Ok(Box::new(Polynomial::new(*decoded_vec)))
460 }
461
462 fn encode(&self) -> Vec<BFieldElement> {
463 let coefficients_encoded = self.coefficients().to_owned().encode();
466 [bfe_vec!(coefficients_encoded.len()), coefficients_encoded].concat()
467 }
468
469 fn static_length() -> Option<usize> {
470 None
471 }
472}
473
474fn bfield_codec_decode_list<T: BFieldCodec>(
477 indicated_num_items: usize,
478 sequence: &[BFieldElement],
479) -> Result<Vec<T>, BFieldCodecError> {
480 let vec = if T::static_length().is_some() {
481 bfield_codec_decode_list_with_statically_sized_items(indicated_num_items, sequence)?
482 } else {
483 bfield_codec_decode_list_with_dynamically_sized_items(indicated_num_items, sequence)?
484 };
485 Ok(vec)
486}
487
488fn bfield_codec_decode_list_with_statically_sized_items<T: BFieldCodec>(
489 num_items: usize,
490 sequence: &[BFieldElement],
491) -> Result<Vec<T>, BFieldCodecError> {
492 let mut vec = vec![];
494
495 let item_length = T::static_length().unwrap();
496 let maybe_vector_size = num_items.checked_mul(item_length);
497 let Some(vector_size) = maybe_vector_size else {
498 return Err(BFieldCodecError::InvalidLengthIndicator);
499 };
500 if sequence.len() < vector_size {
501 return Err(BFieldCodecError::SequenceTooShort);
502 }
503 if sequence.len() > vector_size {
504 return Err(BFieldCodecError::SequenceTooLong);
505 }
506
507 for raw_item in sequence.chunks_exact(item_length) {
508 let item = *T::decode(raw_item).map_err(|e| e.into())?;
509 vec.push(item);
510 }
511 Ok(vec)
512}
513
514fn bfield_codec_decode_list_with_dynamically_sized_items<T: BFieldCodec>(
515 num_items: usize,
516 sequence: &[BFieldElement],
517) -> Result<Vec<T>, BFieldCodecError> {
518 let mut vec = vec![];
520 let mut sequence_index = 0;
521 for _ in 0..num_items {
522 let item_length = sequence
523 .get(sequence_index)
524 .ok_or(BFieldCodecError::MissingLengthIndicator)?;
525 let item_length = usize::try_from(item_length)?;
526 sequence_index += 1;
527 if sequence.len() < sequence_index + item_length {
528 return Err(BFieldCodecError::SequenceTooShort);
529 }
530 let item = *T::decode(&sequence[sequence_index..sequence_index + item_length])
531 .map_err(|e| e.into())?;
532 sequence_index += item_length;
533 vec.push(item);
534 }
535 if sequence.len() != sequence_index {
536 return Err(BFieldCodecError::SequenceTooLong);
537 }
538 Ok(vec)
539}
540
541fn bfield_codec_encode_list<T: BFieldCodec>(elements: Iter<T>) -> Vec<BFieldElement> {
544 if T::static_length().is_some() {
545 return elements.flat_map(|elem| elem.encode()).collect();
546 }
547
548 let mut encoding = vec![];
549 for element in elements {
550 let element_encoded = element.encode();
551 encoding.push(element_encoded.len().into());
552 encoding.extend(element_encoded);
553 }
554 encoding
555}
556
557impl BFieldCodec for () {
558 type Error = BFieldCodecError;
559
560 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
561 sequence
562 .is_empty()
563 .then(|| Box::new(()))
564 .ok_or_else(|| BFieldCodecError::SequenceTooLong)
565 }
566
567 fn encode(&self) -> Vec<BFieldElement> {
568 Vec::new()
569 }
570
571 fn static_length() -> Option<usize> {
572 Some(0)
573 }
574}
575
576impl<T> BFieldCodec for PhantomData<T> {
577 type Error = BFieldCodecError;
578
579 fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>, Self::Error> {
580 sequence
581 .is_empty()
582 .then(|| Box::new(PhantomData))
583 .ok_or_else(|| BFieldCodecError::SequenceTooLong)
584 }
585
586 fn encode(&self) -> Vec<BFieldElement> {
587 Vec::new()
588 }
589
590 fn static_length() -> Option<usize> {
591 Some(0)
592 }
593}
594
595#[cfg(test)]
596#[cfg_attr(coverage_nightly, coverage(off))]
597mod tests {
598 use num_traits::ConstZero;
599 use num_traits::Zero;
600 use proptest::collection::size_range;
601 use proptest::collection::vec;
602 use proptest::prelude::*;
603 use proptest::test_runner::TestCaseResult;
604
605 use super::*;
606 use crate::prelude::*;
607 use crate::proptest_arbitrary_interop::arb;
608 use crate::tests::proptest;
609 use crate::tests::test;
610
611 #[derive(Debug, PartialEq, Eq, test_strategy::Arbitrary)]
612 struct BFieldCodecPropertyTestData<T>
613 where
614 T: 'static + BFieldCodec + Eq + Debug + Clone + for<'a> arbitrary::Arbitrary<'a>,
615 {
616 #[strategy(arb())]
617 value: T,
618
619 #[strategy(Just(#value.encode()))]
620 encoding: Vec<BFieldElement>,
621
622 #[strategy(vec(arb(), #encoding.len()))]
623 #[filter(#encoding.iter().zip(#random_encoding.iter()).all(|(a, b)| a != b))]
624 random_encoding: Vec<BFieldElement>,
625
626 #[any(size_range(1..128).lift())]
627 encoding_lengthener: Vec<BFieldElement>,
628
629 #[strategy(0..=#encoding.len())]
630 length_of_too_short_sequence: usize,
631 }
632
633 impl<T> BFieldCodecPropertyTestData<T>
634 where
635 T: 'static + BFieldCodec + Eq + Debug + Clone + for<'a> arbitrary::Arbitrary<'a>,
636 {
637 fn assert_bfield_codec_properties(&self) -> TestCaseResult {
638 self.assert_static_length_is_equal_to_encoded_length()?;
639 self.assert_decoded_encoding_is_self()?;
640 self.assert_decoding_too_long_encoding_fails()?;
641 self.assert_decoding_too_short_encoding_fails()?;
642 self.modify_each_element_and_assert_decoding_failure()?;
643 self.assert_decoding_random_too_short_encoding_fails_gracefully()?;
644 Ok(())
645 }
646
647 fn assert_static_length_is_equal_to_encoded_length(&self) -> TestCaseResult {
648 if let Some(static_len) = T::static_length() {
649 prop_assert_eq!(static_len, self.encoding.len());
650 }
651 Ok(())
652 }
653
654 fn assert_decoded_encoding_is_self(&self) -> TestCaseResult {
655 let Ok(decoding) = T::decode(&self.encoding) else {
656 let err = TestCaseError::Fail("decoding canonical encoding must not fail".into());
657 return Err(err);
658 };
659 prop_assert_eq!(&self.value, &*decoding);
660 Ok(())
661 }
662
663 fn assert_decoding_too_long_encoding_fails(&self) -> TestCaseResult {
664 let mut too_long_encoding = self.encoding.to_owned();
665 too_long_encoding.extend(self.encoding_lengthener.to_owned());
666 prop_assert!(T::decode(&too_long_encoding).is_err());
667 Ok(())
668 }
669
670 fn assert_decoding_too_short_encoding_fails(&self) -> TestCaseResult {
671 if self.failure_assertions_for_decoding_too_short_sequence_is_not_meaningful() {
672 return Ok(());
673 }
674 let mut encoded = self.encoding.to_owned();
675 encoded.pop();
676 prop_assert!(T::decode(&encoded).is_err());
677 Ok(())
678 }
679
680 fn modify_each_element_and_assert_decoding_failure(&self) -> TestCaseResult {
681 let mut encoding = self.encoding.to_owned();
682 for i in 0..encoding.len() {
683 let original_value = encoding[i];
684 encoding[i] = self.random_encoding[i];
685 let decoding = T::decode(&encoding);
686 if decoding.is_ok_and(|d| *d == self.value) {
687 return Err(TestCaseError::Fail(format!("failing index: {i}").into()));
688 }
689 encoding[i] = original_value;
690 }
691 Ok(())
692 }
693
694 fn assert_decoding_random_too_short_encoding_fails_gracefully(&self) -> TestCaseResult {
695 if self.failure_assertions_for_decoding_too_short_sequence_is_not_meaningful() {
696 return Ok(());
697 }
698
699 let random_encoding =
700 self.random_encoding[..self.length_of_too_short_sequence].to_vec();
701 let decoding_result = T::decode(&random_encoding);
702 if decoding_result.is_ok_and(|d| *d == self.value) {
703 return Err(TestCaseError::Fail("randomness mustn't be `self`".into()));
704 }
705 Ok(())
706 }
707
708 fn failure_assertions_for_decoding_too_short_sequence_is_not_meaningful(&self) -> bool {
709 self.encoding.is_empty()
710 }
711 }
712
713 macro_rules! test_case {
714 (fn $fn_name:ident for $t:ty: $static_len:expr) => {
715 #[macro_rules_attr::apply(proptest)]
716 fn $fn_name(test_data: BFieldCodecPropertyTestData<$t>) {
717 prop_assert_eq!($static_len, <$t as BFieldCodec>::static_length());
718 test_data.assert_bfield_codec_properties()?;
719 }
720 };
721 }
722
723 macro_rules! neg_test_case {
724 (fn $fn_name:ident for $t:ty) => {
725 #[macro_rules_attr::apply(proptest)]
726 fn $fn_name(random_encoding: Vec<BFieldElement>) {
727 let decoding = <$t as BFieldCodec>::decode(&random_encoding);
728 prop_assert!(decoding.is_err());
729 }
730 };
731 }
732
733 test_case! { fn test_u8 for u8: Some(1) }
734 test_case! { fn test_i8 for i8: Some(1) }
735 test_case! { fn test_u16 for u16: Some(1) }
736 test_case! { fn test_i16 for i16: Some(1) }
737 test_case! { fn test_u32 for u32: Some(1) }
738 test_case! { fn test_i32 for i32: Some(1) }
739 test_case! { fn test_u64 for u64: Some(2) }
740 test_case! { fn test_i64 for i64: Some(2) }
741 test_case! { fn test_u128 for u128: Some(4) }
742 test_case! { fn test_i128 for i128: Some(4) }
743 test_case! { fn bfieldelement for BFieldElement: Some(1) }
744 test_case! { fn xfieldelement for XFieldElement: Some(3) }
745 test_case! { fn digest for Digest: Some(5) }
746 test_case! { fn vec_of_bfieldelement for Vec<BFieldElement>: None }
747 test_case! { fn vec_of_xfieldelement for Vec<XFieldElement>: None }
748 test_case! { fn vec_of_digest for Vec<Digest>: None }
749 test_case! { fn vec_of_vec_of_bfieldelement for Vec<Vec<BFieldElement>>: None }
750 test_case! { fn vec_of_vec_of_xfieldelement for Vec<Vec<XFieldElement>>: None }
751 test_case! { fn vec_of_vec_of_digest for Vec<Vec<Digest>>: None }
752 test_case! { fn poly_bfe for Polynomial<'static, BFieldElement>: None }
753 test_case! { fn poly_xfe for Polynomial<'static, XFieldElement>: None }
754 test_case! { fn tuples_static_static_size_0 for (Digest, u128): Some(9) }
755 test_case! { fn tuples_static_static_size_1 for (Digest, u64): Some(7) }
756 test_case! { fn tuples_static_static_size_2 for (BFieldElement, BFieldElement): Some(2) }
757 test_case! { fn tuples_static_static_size_3 for (BFieldElement, XFieldElement): Some(4) }
758 test_case! { fn tuples_static_static_size_4 for (XFieldElement, BFieldElement): Some(4) }
759 test_case! { fn tuples_static_static_size_5 for (XFieldElement, Digest): Some(8) }
760 test_case! { fn tuples_static_static_size_6 for (u8, u16, u32, u64): Some(5) }
761 test_case! { fn tuples_static_static_size_7 for (u8,): Some(1) }
762 test_case! { fn tuples_static_dynamic_size_0 for (u32, Vec<u32>): None }
763 test_case! { fn tuples_static_dynamic_size_1 for (u32, Vec<u64>): None }
764 test_case! { fn tuples_static_dynamic_size_2 for (Digest, Vec<BFieldElement>): None }
765 test_case! { fn tuples_static_dynamic_size_3 for (Vec<BFieldElement>,): None }
766 test_case! { fn tuples_dynamic_static_size for (Vec<XFieldElement>, Digest): None }
767 test_case! { fn tuples_dynamic_dynamic_size for (Vec<XFieldElement>, Vec<Digest>): None }
768 test_case! { fn unit for (): Some(0) }
769 test_case! { fn phantom_data for PhantomData<Tip5>: Some(0) }
770 test_case! { fn boxed_u32s for Box<u32>: Some(1) }
771 test_case! { fn tuple_with_boxed_bfe for (u64, Box<BFieldElement>): Some(3) }
772 test_case! { fn tuple_with_boxed_digest for (u128, Box<Digest>): Some(9) }
773 test_case! { fn vec_of_boxed_tuple_of_u128_and_bfe for Vec<(u128, Box<BFieldElement>)>: None }
774 test_case! { fn vec_option_xfieldelement for Vec<Option<XFieldElement>>: None }
775 test_case! { fn array_with_static_element_size for [u64; 14]: Some(28) }
776 test_case! { fn array_with_dynamic_element_size for [Vec<Digest>; 19]: None }
777
778 neg_test_case! { fn vec_of_bfield_element_neg for Vec<BFieldElement> }
779 neg_test_case! { fn vec_of_xfield_elements_neg for Vec<XFieldElement> }
780 neg_test_case! { fn vec_of_digests_neg for Vec<Digest> }
781 neg_test_case! { fn vec_of_vec_of_bfield_elements_neg for Vec<Vec<BFieldElement>> }
782 neg_test_case! { fn vec_of_vec_of_xfield_elements_neg for Vec<Vec<XFieldElement>> }
783 neg_test_case! { fn poly_of_bfe_neg for Polynomial<BFieldElement> }
784 neg_test_case! { fn poly_of_xfe_neg for Polynomial<XFieldElement> }
785
786 #[macro_rules_attr::apply(test)]
787 fn encoding_tuple_puts_fields_in_expected_order() {
788 let encoding = (1_u8, 2_u16, 3_u32, 4_u64, true).encode();
789 let expected = bfe_vec![1, 4, 0, 3, 2, 1];
790 assert_eq!(expected, encoding);
791 }
792
793 #[macro_rules_attr::apply(test)]
794 fn leading_zero_coefficient_have_no_effect_on_encoding_empty_poly_bfe() {
795 let empty_poly = Polynomial::<BFieldElement>::new(vec![]);
796 assert_eq!(empty_poly.encode(), Polynomial::new(bfe_vec![0]).encode());
797 }
798
799 #[macro_rules_attr::apply(test)]
800 fn leading_zero_coefficients_have_no_effect_on_encoding_empty_poly_xfe() {
801 let empty_poly = Polynomial::<XFieldElement>::new(vec![]);
802 assert_eq!(empty_poly.encode(), Polynomial::new(xfe_vec![0]).encode());
803 }
804
805 #[macro_rules_attr::apply(proptest)]
806 fn leading_zero_coefficients_have_no_effect_on_encoding_poly_bfe_pbt(
807 polynomial: Polynomial<'static, BFieldElement>,
808 #[strategy(0usize..30)] num_leading_zeros: usize,
809 ) {
810 let encoded = polynomial.encode();
811
812 let mut coefficients = polynomial.into_coefficients();
813 coefficients.extend(vec![BFieldElement::ZERO; num_leading_zeros]);
814 let poly_w_leading_zeros = Polynomial::new(coefficients);
815
816 prop_assert_eq!(encoded, poly_w_leading_zeros.encode());
817 }
818
819 #[macro_rules_attr::apply(proptest)]
820 fn leading_zero_coefficients_have_no_effect_on_encoding_poly_xfe_pbt(
821 polynomial: Polynomial<'static, XFieldElement>,
822 #[strategy(0usize..30)] num_leading_zeros: usize,
823 ) {
824 let encoded = polynomial.encode();
825
826 let mut coefficients = polynomial.into_coefficients();
827 coefficients.extend(vec![XFieldElement::ZERO; num_leading_zeros]);
828 let poly_w_leading_zeros = Polynomial::new(coefficients);
829
830 prop_assert_eq!(encoded, poly_w_leading_zeros.encode());
831 }
832
833 fn disallow_trailing_zeros_in_poly_encoding_prop<FF>(
834 polynomial: Polynomial<FF>,
835 leading_coefficient: FF,
836 num_leading_zeros: usize,
837 ) -> TestCaseResult
838 where
839 FF: FiniteField + BFieldCodec + 'static,
840 {
841 let mut polynomial_coefficients = polynomial.into_coefficients();
842 polynomial_coefficients.push(leading_coefficient);
843 let actual_polynomial = Polynomial::new(polynomial_coefficients.clone());
844 let vec_encoding = actual_polynomial.coefficients().to_vec().encode();
845 let poly_encoding = actual_polynomial.encode();
846 prop_assert_eq!(
847 [bfe_vec!(vec_encoding.len()), vec_encoding].concat(),
848 poly_encoding,
849 "This test expects similarity of Vec and Polynomial encoding"
850 );
851
852 polynomial_coefficients.extend(vec![FF::ZERO; num_leading_zeros]);
853 let coefficient_encoding = polynomial_coefficients.encode();
854 let poly_encoding_with_leading_zeros =
855 [bfe_vec!(coefficient_encoding.len()), coefficient_encoding].concat();
856 let decoding_result = Polynomial::<FF>::decode(&poly_encoding_with_leading_zeros);
857 prop_assert!(matches!(
858 decoding_result.unwrap_err(),
859 PolynomialBFieldCodecError::TrailingZerosInPolynomialEncoding
860 ));
861
862 Ok(())
863 }
864
865 #[macro_rules_attr::apply(proptest)]
866 fn disallow_trailing_zeros_in_poly_encoding_bfe(
867 polynomial: Polynomial<'static, BFieldElement>,
868 #[filter(!#leading_coefficient.is_zero())] leading_coefficient: BFieldElement,
869 #[strategy(1usize..30)] num_leading_zeros: usize,
870 ) {
871 disallow_trailing_zeros_in_poly_encoding_prop(
872 polynomial,
873 leading_coefficient,
874 num_leading_zeros,
875 )?
876 }
877
878 #[macro_rules_attr::apply(proptest)]
879 fn disallow_trailing_zeros_in_poly_encoding_xfe(
880 polynomial: Polynomial<'static, XFieldElement>,
881 #[filter(!#leading_coefficient.is_zero())] leading_coefficient: XFieldElement,
882 #[strategy(1usize..30)] num_leading_zeros: usize,
883 ) {
884 disallow_trailing_zeros_in_poly_encoding_prop(
885 polynomial,
886 leading_coefficient,
887 num_leading_zeros,
888 )?
889 }
890
891 pub mod derive {
900 use arbitrary::Arbitrary;
901 use num_traits::Zero;
902
903 use super::*;
904 use crate::math::x_field_element::XFieldElement;
905 use crate::tests::proptest;
906 use crate::tests::test;
907 use crate::tip5::Digest;
908 use crate::tip5::Tip5;
909 use crate::util_types::mmr::mmr_accumulator::MmrAccumulator;
910 use crate::util_types::mmr::mmr_membership_proof::MmrMembershipProof;
911
912 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
913 struct UnitStruct;
914
915 test_case! { fn unit_struct for UnitStruct: Some(0) }
916
917 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
918 struct StructWithUnitStruct {
919 a: UnitStruct,
920 }
921
922 test_case! { fn struct_with_unit_struct for StructWithUnitStruct: Some(0) }
923
924 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
925 enum EnumWithUnitStruct {
926 A(UnitStruct),
927 B,
928 }
929
930 test_case! { fn enum_with_unit_struct for EnumWithUnitStruct: Some(1) }
931
932 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
933 struct DeriveTestStructA {
934 field_a: u64,
935 field_b: u64,
936 field_c: u64,
937 }
938
939 test_case! { fn struct_a for DeriveTestStructA: Some(6) }
940
941 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
942 struct DeriveTestStructB(u128);
943
944 test_case! { fn struct_b for DeriveTestStructB: Some(4) }
945
946 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
947 struct DeriveTestStructC(u128, u64, u32);
948
949 test_case! { fn struct_c for DeriveTestStructC: Some(7) }
950
951 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
953 struct DeriveTestStructD(Vec<u128>);
954
955 test_case! { fn struct_d for DeriveTestStructD: None }
956
957 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
959 struct DeriveTestStructWithBfePolynomialField(Polynomial<'static, BFieldElement>);
960
961 test_case! {
962 fn struct_with_bfe_poly_field for DeriveTestStructWithBfePolynomialField: None
963 }
964
965 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
966 struct DeriveTestStructWithXfePolynomialField(Polynomial<'static, XFieldElement>);
967
968 test_case! {
969 fn struct_with_xfe_poly_field for DeriveTestStructWithXfePolynomialField: None
970 }
971
972 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
973 enum EnumWithVariantWithPolyField {
974 Bee,
975 BooBoo(Polynomial<'static, BFieldElement>),
976 Bop(Polynomial<'static, XFieldElement>),
977 }
978
979 test_case! { fn enum_with_variant_with_poly_field for EnumWithVariantWithPolyField: None }
980 neg_test_case! { fn enum_with_variant_with_poly_field_neg for EnumWithVariantWithPolyField }
981
982 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
983 struct DeriveTestStructE(Vec<u128>, u128, u64, Vec<bool>, u32, Vec<u128>);
984
985 test_case! { fn struct_e for DeriveTestStructE: None }
986
987 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
988 struct DeriveTestStructF {
989 field_a: Vec<u64>,
990 field_b: bool,
991 field_c: u32,
992 field_d: Vec<bool>,
993 field_e: Vec<BFieldElement>,
994 field_f: Vec<BFieldElement>,
995 }
996
997 test_case! { fn struct_f for DeriveTestStructF: None }
998
999 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1000 struct WithPhantomData<FF: FiniteField> {
1001 a_field: u128,
1002 #[bfield_codec(ignore)]
1003 _phantom_data: PhantomData<FF>,
1004 another_field: Vec<u64>,
1005 }
1006
1007 test_case! { fn with_phantom_data for WithPhantomData<BFieldElement>: None }
1008
1009 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1010 struct WithNestedPhantomData<FF: FiniteField> {
1011 a_field: u128,
1012 #[bfield_codec(ignore)]
1013 _phantom_data: PhantomData<FF>,
1014 another_field: Vec<u64>,
1015 a_third_field: Vec<WithPhantomData<FF>>,
1016 a_fourth_field: WithPhantomData<BFieldElement>,
1017 }
1018
1019 test_case! { fn with_nested_phantom_data for WithNestedPhantomData<XFieldElement>: None }
1020
1021 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1022 struct WithNestedVec {
1023 a_field: Vec<Vec<u64>>,
1024 }
1025
1026 test_case! { fn with_nested_vec for WithNestedVec: None }
1027
1028 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1029 struct EmptyStruct {}
1030
1031 test_case! { fn empty_struct for EmptyStruct: Some(0) }
1032
1033 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1034 struct StructWithEmptyStruct {
1035 a: EmptyStruct,
1036 }
1037
1038 test_case! { fn struct_with_empty_struct for StructWithEmptyStruct: Some(0) }
1039
1040 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1041 struct StructWithTwoEmptyStructs {
1042 a: EmptyStruct,
1043 b: EmptyStruct,
1044 }
1045
1046 test_case! { fn struct_with_two_empty_structs for StructWithTwoEmptyStructs: Some(0) }
1047
1048 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1049 struct BigStructWithEmptyStructs {
1050 a: EmptyStruct,
1051 b: EmptyStruct,
1052 c: StructWithTwoEmptyStructs,
1053 d: StructWithEmptyStruct,
1054 e: EmptyStruct,
1055 }
1056
1057 test_case! { fn big_struct_with_empty_structs for BigStructWithEmptyStructs: Some(0) }
1058
1059 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1060 enum EnumWithEmptyStruct {
1061 A(EmptyStruct),
1062 B,
1063 C(EmptyStruct),
1064 }
1065
1066 test_case! { fn enum_with_empty_struct for EnumWithEmptyStruct: Some(1) }
1067
1068 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1069 struct MuchNesting {
1070 a: Vec<Vec<Vec<Vec<BFieldElement>>>>,
1071 #[bfield_codec(ignore)]
1072 b: PhantomData<Tip5>,
1073 #[bfield_codec(ignore)]
1074 c: PhantomData<Tip5>,
1075 }
1076
1077 test_case! { fn much_nesting for MuchNesting: None }
1078
1079 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1080 struct SmallArrayStructUnnamedFields([u128; 1]);
1081
1082 test_case! {
1083 fn small_array_struct_unnamed_fields for SmallArrayStructUnnamedFields: Some(4)
1084 }
1085
1086 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1087 struct SmallArrayStructNamedFields {
1088 a: [u128; 1],
1089 }
1090
1091 test_case! { fn small_array_struct_named_fields for SmallArrayStructNamedFields: Some(4) }
1092
1093 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1094 struct BigArrayStructUnnamedFields([u128; 150]);
1095
1096 test_case! {
1097 fn big_array_struct_unnamed_fields for BigArrayStructUnnamedFields: Some(4 * 150)
1098 }
1099
1100 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1101 struct BigArrayStructNamedFields {
1102 a: [XFieldElement; 150],
1103 b: XFieldElement,
1104 c: u64,
1105 }
1106
1107 test_case! {
1108 fn big_array_struct_named_fields for BigArrayStructNamedFields: Some(3 * 150 + 3 + 2)
1109 }
1110
1111 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1112 struct ArrayStructDynamicallySizedElementsUnnamedFields([Vec<u128>; 7]);
1113
1114 test_case! {
1115 fn array_struct_dyn_sized_elements_unnamed_fields
1116 for ArrayStructDynamicallySizedElementsUnnamedFields: None
1117 }
1118
1119 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1120 struct ArrayStructDynamicallySizedElementsNamedFields {
1121 a: [Vec<u128>; 7],
1122 }
1123
1124 test_case! {
1125 fn array_struct_dyn_sized_elements_named_fields
1126 for ArrayStructDynamicallySizedElementsNamedFields: None
1127 }
1128
1129 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1130 struct StructWithTupleField {
1131 a: (Digest, Vec<Digest>),
1132 }
1133
1134 test_case! { fn struct_with_tuple_field for StructWithTupleField: None }
1135
1136 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1137 struct StructWithTupleFieldTwoElements {
1138 a: ([Digest; 2], XFieldElement),
1139 }
1140
1141 test_case! {
1142 fn struct_with_tuple_field_two_elements for StructWithTupleFieldTwoElements: Some(13)
1143 }
1144
1145 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1146 struct StructWithNestedTupleField {
1147 a: (([Digest; 2], Vec<XFieldElement>), (XFieldElement, u64)),
1148 }
1149
1150 test_case! { fn struct_with_nested_tuple_field for StructWithNestedTupleField: None }
1151
1152 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1153 struct MsMembershipProof {
1154 sender_randomness: Digest,
1155 receiver_preimage: Digest,
1156 auth_path_aocl: MmrMembershipProof,
1157 }
1158
1159 test_case! { fn ms_membership_proof for MsMembershipProof: None }
1160 test_case! { fn mmr_accumulator for MmrAccumulator: None }
1161
1162 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1163 struct UnsupportedFields {
1164 a: u64,
1165 #[bfield_codec(ignore)]
1166 b: usize,
1167 }
1168
1169 #[macro_rules_attr::apply(proptest)]
1170 fn unsupported_fields_can_be_ignored_test(#[strategy(arb())] my_struct: UnsupportedFields) {
1171 let encoded = my_struct.encode();
1172 let decoded = UnsupportedFields::decode(&encoded).unwrap();
1173 prop_assert_eq!(my_struct.a, decoded.a);
1174 prop_assert_eq!(usize::default(), decoded.b);
1175 }
1176
1177 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1178 struct OneFixedLenField {
1179 some_digest: Digest,
1180 }
1181
1182 test_case! { fn one_fixed_len_field for OneFixedLenField: Some(5) }
1183
1184 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1185 pub struct TwoFixedLenFields {
1186 pub some_digest: Digest,
1187 pub some_u64: u64,
1188 }
1189
1190 test_case! { fn two_fixed_len_fields for TwoFixedLenFields: Some(7) }
1191
1192 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1193 pub struct TwoFixedLenUnnamedFields(Digest, u64);
1194
1195 test_case! { fn two_fixed_len_unnamed_fields for TwoFixedLenUnnamedFields: Some(7) }
1196
1197 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1198 pub struct FixAndVarLenFields {
1199 pub some_digest: Digest,
1200 pub some_vec: Vec<u64>,
1201 }
1202
1203 test_case! { fn fix_and_var_len_fields for FixAndVarLenFields: None }
1204
1205 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1206 struct FixAndVarLenUnnamedFields(Digest, Vec<u64>);
1207
1208 test_case! { fn fix_and_var_len_unnamed_fields for FixAndVarLenUnnamedFields: None }
1209
1210 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1211 struct QuiteAFewFixAndVarLenFields {
1212 some_digest: Digest,
1213 some_vec: Vec<u64>,
1214 some_u64: u64,
1215 other_vec: Vec<u32>,
1216 other_digest: Digest,
1217 yet_another_vec: Vec<u32>,
1218 and_another_vec: Vec<u64>,
1219 more_fixed_len: u64,
1220 even_more_fixed_len: u64,
1221 }
1222
1223 test_case! { fn quite_a_few_fix_and_var_len_fields for QuiteAFewFixAndVarLenFields: None }
1224
1225 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1226 struct SimpleStructA {
1227 a: BFieldElement,
1228 b: XFieldElement,
1229 }
1230
1231 test_case! { fn simple_struct_a for SimpleStructA: Some(4) }
1232
1233 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1234 struct SimpleStructB(u32, u64);
1235
1236 test_case! { fn simple_struct_b for SimpleStructB: Some(3) }
1237
1238 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1239 struct StructWithBox {
1240 a: Box<u64>,
1241 }
1242
1243 test_case! { fn struct_with_box for StructWithBox: Some(2) }
1244
1245 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1246 struct TupleStructWithBox(Box<u64>);
1247
1248 test_case! { fn tuple_struct_with_box for TupleStructWithBox: Some(2) }
1249
1250 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1251 struct StructWithBoxContainingStructWithBox {
1252 a: Box<StructWithBox>,
1253 b: Box<TupleStructWithBox>,
1254 }
1255
1256 test_case! {
1257 fn struct_with_box_containing_struct_with_box
1258 for StructWithBoxContainingStructWithBox: Some(4)
1259 }
1260
1261 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1262 enum SimpleEnum {
1263 A,
1264 B(u32),
1265 C(BFieldElement, u32, u32),
1266 }
1267
1268 test_case! { fn simple_enum for SimpleEnum: None }
1269
1270 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1271 enum ComplexEnum {
1272 A,
1273 B(u32),
1274 C(BFieldElement, XFieldElement, u32),
1275 D(Vec<BFieldElement>, Digest),
1276 E(Option<bool>),
1277 }
1278
1279 test_case! { fn complex_enum for ComplexEnum: None }
1280
1281 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1282 enum EnumWithUniformDataSize {
1283 A(Digest),
1284 B(Digest),
1285 C(Digest),
1286 }
1287
1288 test_case! { fn enum_with_uniform_data_size for EnumWithUniformDataSize: Some(6) }
1289
1290 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1291 enum EnumWithIrregularDataSize {
1292 A(u32),
1293 B,
1294 C(Digest),
1295 D(Vec<XFieldElement>),
1296 }
1297
1298 test_case! { fn enum_with_irregular_data_size for EnumWithIrregularDataSize: None }
1299
1300 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1301 enum EnumWithGenerics<I: Into<u64>> {
1302 A(I),
1303 B(I, I),
1304 }
1305
1306 test_case! { fn enum_with_generics for EnumWithGenerics<u32>: None }
1307
1308 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1309 enum EnumWithGenericsAndWhereClause<I: Into<u64>>
1310 where
1311 I: Debug + Copy + Eq,
1312 {
1313 A,
1314 B(I),
1315 C(I, I),
1316 }
1317
1318 test_case! {
1319 fn enum_with_generics_and_where_clause for EnumWithGenericsAndWhereClause<u32>: None
1320 }
1321
1322 #[macro_rules_attr::apply(test)]
1323 fn enums_bfield_codec_discriminant_can_be_accessed() {
1324 let a = EnumWithGenericsAndWhereClause::<u32>::A;
1325 let b = EnumWithGenericsAndWhereClause::<u32>::B(1);
1326 let c = EnumWithGenericsAndWhereClause::<u32>::C(1, 2);
1327 assert_eq!(0, a.bfield_codec_discriminant());
1328 assert_eq!(1, b.bfield_codec_discriminant());
1329 assert_eq!(2, c.bfield_codec_discriminant());
1330 }
1331
1332 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1333 enum EnumWithBoxedVariant {
1334 A(Box<u64>),
1335 B(Box<u64>, Box<u64>),
1336 }
1337
1338 test_case! { fn enum_with_boxed_variant for EnumWithBoxedVariant: None }
1339
1340 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1341 enum EnumWithBoxedVariantAndBoxedStruct {
1342 A(Box<StructWithBox>),
1343 B(Box<StructWithBox>, Box<TupleStructWithBox>),
1344 }
1345
1346 test_case! {
1347 fn enum_with_boxed_variant_and_boxed_struct for EnumWithBoxedVariantAndBoxedStruct: None
1348 }
1349
1350 #[derive(Debug, Clone, PartialEq, Eq, BFieldCodec, Arbitrary)]
1351 struct DummyPolynomial<T: FiniteField + BFieldCodec> {
1352 coefficients: Vec<T>,
1353 }
1354
1355 #[macro_rules_attr::apply(proptest)]
1356 fn manual_poly_encoding_implementation_is_consistent_with_derived_bfe(
1357 #[strategy(arb())] coefficients: Vec<BFieldElement>,
1358 ) {
1359 manual_poly_encoding_implementation_is_consistent_with_derived(coefficients)?;
1360 }
1361
1362 #[macro_rules_attr::apply(proptest)]
1363 fn manual_poly_encoding_implementation_is_consistent_with_derived_xfe(
1364 #[strategy(arb())] coefficients: Vec<XFieldElement>,
1365 ) {
1366 manual_poly_encoding_implementation_is_consistent_with_derived(coefficients)?;
1367 }
1368
1369 fn manual_poly_encoding_implementation_is_consistent_with_derived<FF>(
1370 coefficients: Vec<FF>,
1371 ) -> TestCaseResult
1372 where
1373 FF: FiniteField + BFieldCodec + 'static,
1374 {
1375 if coefficients.last().is_some_and(Zero::is_zero) {
1376 let rsn = "`DummyPolynomial::encode` only works for non-zero leading coefficients";
1377 return Err(TestCaseError::Reject(rsn.into()));
1378 }
1379
1380 let polynomial = Polynomial::new(coefficients.clone());
1381 let dummy_polynomial = DummyPolynomial { coefficients };
1382 prop_assert_eq!(dummy_polynomial.encode(), polynomial.encode());
1383 Ok(())
1384 }
1385 }
1386}