1use crate::{Deserializable, Serializable, Tagged};
15#[cfg(feature = "proptest")]
16use proptest::strategy::ValueTree;
17#[cfg(feature = "proptest")]
18use proptest::{
19 strategy::{NewTree, Strategy},
20 test_runner::TestRunner,
21};
22#[cfg(feature = "proptest")]
23use rand::Rng;
24#[cfg(feature = "proptest")]
25use rand::distributions::{Distribution, Standard};
26#[cfg(feature = "proptest")]
27use std::fmt::Debug;
28use std::io::{BufWriter, Read};
29#[cfg(feature = "proptest")]
30use std::marker::PhantomData;
31
32pub trait VecExt {
33 fn with_bounded_capacity(n: usize) -> Self;
34}
35
36impl<T> VecExt for Vec<T> {
37 fn with_bounded_capacity(n: usize) -> Self {
38 const MEMORY_LIMIT: usize = 1 << 25; let alloc_limit = MEMORY_LIMIT.checked_div(std::mem::size_of::<T>()).unwrap_or(n);
40 Self::with_capacity(usize::min(alloc_limit, n))
41 }
42}
43
44pub trait ReadExt: Read {
45 fn read_exact_to_vec(&mut self, n: usize) -> std::io::Result<Vec<u8>> {
46 const CHUNK_SIZE: usize = 4096;
47 let mut res = Vec::with_capacity(CHUNK_SIZE);
48 let mut len = 0;
49 while n > len {
50 let new_len = usize::min(n, len + CHUNK_SIZE);
51 res.resize(new_len, 0);
52 self.read_exact(&mut res[len..])?;
53 len = new_len;
54 }
55 Ok(res)
56 }
57}
58
59impl<R: Read> ReadExt for R {}
60
61impl Serializable for () {
62 fn serialize(&self, _writer: &mut impl std::io::Write) -> std::io::Result<()> {
63 Ok(())
64 }
65 fn serialized_size(&self) -> usize {
66 0
67 }
68}
69
70impl Deserializable for () {
71 fn deserialize(_reader: &mut impl Read, _recursion_depth: u32) -> std::io::Result<Self> {
72 Ok(())
73 }
74}
75
76impl Tagged for () {
77 fn tag() -> std::borrow::Cow<'static, str> {
78 std::borrow::Cow::Borrowed("()")
79 }
80 fn tag_unique_factor() -> String {
81 "()".into()
82 }
83}
84
85impl Serializable for bool {
86 fn serialize(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> {
87 writer.write_all(&[*self as u8])
88 }
89 fn serialized_size(&self) -> usize {
90 1
91 }
92}
93
94impl Deserializable for bool {
95 fn deserialize(reader: &mut impl Read, _recursion_depth: u32) -> std::io::Result<Self> {
96 let mut buf = [0u8];
97 reader.read_exact(&mut buf[..])?;
98 match buf[0] {
99 0 => Ok(false),
100 1 => Ok(true),
101 v => Err(std::io::Error::new(
102 std::io::ErrorKind::InvalidData,
103 format!("cannot deserialize {v} as bool"),
104 )),
105 }
106 }
107}
108
109impl Tagged for bool {
110 fn tag() -> std::borrow::Cow<'static, str> {
111 std::borrow::Cow::Borrowed("bool")
112 }
113 fn tag_unique_factor() -> String {
114 "bool".into()
115 }
116}
117
118macro_rules! via_le_bytes {
119 ($ty:ty, $len:expr_2021) => {
120 impl Serializable for $ty {
121 fn serialize(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> {
122 writer.write_all(&self.to_le_bytes()[..])
123 }
124 fn serialized_size(&self) -> usize {
125 $len
126 }
127 }
128
129 impl Deserializable for $ty {
130 fn deserialize(reader: &mut impl Read, _recursion_depth: u32) -> std::io::Result<Self> {
131 let mut buf = [0u8; $len];
132 reader.read_exact(&mut buf[..])?;
133 Ok(<$ty>::from_le_bytes(buf))
134 }
135 }
136
137 impl Tagged for $ty {
138 fn tag() -> std::borrow::Cow<'static, str> {
139 std::borrow::Cow::Borrowed(stringify!($ty))
140 }
141 fn tag_unique_factor() -> String {
142 stringify!($ty).into()
143 }
144 }
145 };
146}
147
148macro_rules! via_scale {
149 ($ty:ty, $n:expr_2021) => {
150 impl Serializable for $ty {
151 fn serialize(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> {
152 ScaleBigInt::from(*self).serialize(writer)
153 }
154 fn serialized_size(&self) -> usize {
155 ScaleBigInt::from(*self).serialized_size()
156 }
157 }
158
159 impl Deserializable for $ty {
160 fn deserialize(reader: &mut impl Read, recursion_depth: u32) -> std::io::Result<Self> {
161 <$ty>::try_from(ScaleBigInt::deserialize(reader, recursion_depth)?)
162 }
163 }
164
165 impl From<$ty> for ScaleBigInt {
166 fn from(val: $ty) -> ScaleBigInt {
167 let mut res = ScaleBigInt([0u8; SCALE_MAX_BYTES]);
168 let le_bytes = val.to_le_bytes();
169 res.0[..$n].copy_from_slice(&le_bytes[..]);
170 res
171 }
172 }
173
174 impl TryFrom<ScaleBigInt> for $ty {
175 type Error = std::io::Error;
176 fn try_from(val: ScaleBigInt) -> std::io::Result<$ty> {
177 if val.0[$n..].iter().any(|b| *b != 0) {
178 return Err(std::io::Error::new(
179 std::io::ErrorKind::InvalidData,
180 concat!("out of range for ", stringify!($ty)),
181 ));
182 }
183 Ok(<$ty>::from_le_bytes(
184 val.0[..$n]
185 .try_into()
186 .expect("slice of known size must coerce to array"),
187 ))
188 }
189 }
190
191 impl Tagged for $ty {
192 fn tag() -> std::borrow::Cow<'static, str> {
193 std::borrow::Cow::Borrowed(stringify!($ty))
194 }
195 fn tag_unique_factor() -> String {
196 stringify!($ty).into()
197 }
198 }
199 };
200}
201
202via_le_bytes!(u8, 1);
203via_le_bytes!(u16, 2);
204via_le_bytes!(i8, 1);
205via_le_bytes!(i16, 2);
206via_le_bytes!(i32, 4);
207via_le_bytes!(i64, 8);
208via_le_bytes!(i128, 16);
209via_scale!(u32, 4);
210via_scale!(u64, 8);
211via_scale!(u128, 16);
212
213const SCALE_MAX_BYTES: usize = 67;
214pub struct ScaleBigInt(pub [u8; SCALE_MAX_BYTES]);
215
216impl Default for ScaleBigInt {
217 fn default() -> Self {
218 ScaleBigInt([0u8; SCALE_MAX_BYTES])
219 }
220}
221
222const SCALE_ONE_BYTE_MARKER: u8 = 0b00;
223const SCALE_TWO_BYTE_MARKER: u8 = 0b01;
224const SCALE_FOUR_BYTE_MARKER: u8 = 0b10;
225const SCALE_N_BYTE_MARKER: u8 = 0b11;
226
227impl Serializable for ScaleBigInt {
228 fn serialize(&self, writer: &mut impl std::io::Write) -> std::io::Result<()> {
229 let top2bits = |b| (b & 0b1100_0000) >> 6;
230 let bot6bits = |b| (b & 0b0011_1111) << 2;
231 match self.serialized_size() {
232 1 => writer.write_all(&[bot6bits(self.0[0]) | SCALE_ONE_BYTE_MARKER]),
233 2 => {
234 let b0 = bot6bits(self.0[0]) | SCALE_TWO_BYTE_MARKER;
235 let b1 = top2bits(self.0[0]) | bot6bits(self.0[1]);
236 writer.write_all(&[b0, b1])
237 }
238 4 => {
239 let b0 = bot6bits(self.0[0]) | SCALE_FOUR_BYTE_MARKER;
240 let b1 = top2bits(self.0[0]) | bot6bits(self.0[1]);
241 let b2 = top2bits(self.0[1]) | bot6bits(self.0[2]);
242 let b3 = top2bits(self.0[2]) | bot6bits(self.0[3]);
243 writer.write_all(&[b0, b1, b2, b3])
244 }
245 n => {
246 writer.write_all(&[(n as u8 - 5) << 2 | SCALE_N_BYTE_MARKER])?;
247 writer.write_all(&self.0[..n - 1])
248 }
249 }
250 }
251 fn serialized_size(&self) -> usize {
252 let trailing_zeros = self.0.iter().rev().take_while(|x| **x == 0).count();
253 let occupied = SCALE_MAX_BYTES - trailing_zeros;
254 let can_squeeze = self.0[occupied.saturating_sub(1)] < 64;
255 match (occupied, can_squeeze) {
256 (0, _) | (1, true) => 1,
257 (1, false) | (2, true) => 2,
258 (2, false) | (3, _) | (4, true) => 4,
259 (n, _) => n + 1,
260 }
261 }
262}
263
264impl Deserializable for ScaleBigInt {
265 fn deserialize(reader: &mut impl Read, recursion_depth: u32) -> std::io::Result<Self> {
266 let first = u8::deserialize(reader, recursion_depth)?;
267 let mut res = ScaleBigInt([0u8; SCALE_MAX_BYTES]);
268 let top6bits = |b| (b & 0b1111_1100) >> 2;
269 let bot2bits = |b| (b & 0b0000_0011) << 6;
270 match first & 0b11 {
271 SCALE_ONE_BYTE_MARKER => res.0[0] = top6bits(first),
272 SCALE_TWO_BYTE_MARKER => {
273 let second = u8::deserialize(reader, recursion_depth)?;
274 if second == 0 {
275 return Err(std::io::Error::new(
276 std::io::ErrorKind::InvalidData,
277 "non-canonical scale encoding",
278 ));
279 }
280 res.0[0] = top6bits(first) | bot2bits(second);
281 res.0[1] = top6bits(second);
282 }
283 SCALE_FOUR_BYTE_MARKER => {
284 let second = u8::deserialize(reader, recursion_depth)?;
285 let third = u8::deserialize(reader, recursion_depth)?;
286 let fourth = u8::deserialize(reader, recursion_depth)?;
287 if third == 0 && fourth == 0 {
288 return Err(std::io::Error::new(
289 std::io::ErrorKind::InvalidData,
290 "non-canonical scale encoding",
291 ));
292 }
293 res.0[0] = top6bits(first) | bot2bits(second);
294 res.0[1] = top6bits(second) | bot2bits(third);
295 res.0[2] = top6bits(third) | bot2bits(fourth);
296 res.0[3] = top6bits(fourth);
297 }
298 SCALE_N_BYTE_MARKER => {
299 let n = top6bits(first) as usize + 4;
300 reader.read_exact(&mut res.0[..n])?;
301 if res.0[n - 1] == 0 || (n == 4 && res.0[3] < 64) {
305 return Err(std::io::Error::new(
306 std::io::ErrorKind::InvalidData,
307 "non-canonical scale encoding",
308 ));
309 }
310 }
311 _ => unreachable!(),
312 }
313 Ok(res)
314 }
315}
316
317macro_rules! tuple_serializable {
318 (($a:tt, $aidx: tt)$(, ($as:tt, $asidx: tt))*) => {
319 impl<$a: Serializable,$($as: Serializable,)*> Serializable for ($a,$($as,)*) {
320 fn serialize(
321 &self,
322 writer: &mut impl std::io::Write,
323 ) -> std::io::Result<()> {
324 <$a as Serializable>::serialize(&(self.$aidx), writer)?;
325 $(<$as as Serializable>::serialize(&(self.$asidx), writer)?;)*
326 Ok(())
327 }
328
329 fn serialized_size(&self) -> usize {
330 <$a as Serializable>::serialized_size(&(self.$aidx)) $(+ <$as as Serializable>::serialized_size(&(self.$asidx)))*
331 }
332 }
333
334 impl<$a: Deserializable,$($as: Deserializable,)*> Deserializable for ($a,$($as,)*) {
335 fn deserialize(reader: &mut impl std::io::Read, mut recursion_depth: u32) -> std::io::Result<Self> {
336 <Self as Deserializable>::check_rec(&mut recursion_depth)?;
337 Ok((
338 <$a as Deserializable>::deserialize(reader, recursion_depth)?,
339 $(<$as as Deserializable>::deserialize(reader, recursion_depth)?,)*
340 ))
341 }
342 }
343
344 impl<$a: Tagged,$($as: Tagged,)*> Tagged for ($a, $($as,)*) {
345 fn tag() -> std::borrow::Cow<'static, str> {
346 let mut res = String::new();
347 res.push_str("(");
348 res.push_str(&$a::tag());
349 $(
350 res.push_str(",");
351 res.push_str(&$as::tag());
352 )*
353 res.push_str(")");
354 std::borrow::Cow::Owned(res)
355 }
356 fn tag_unique_factor() -> String {
357 let mut res = String::new();
358 res.push_str("(");
359 res.push_str(&$a::tag_unique_factor());
360 $(
361 res.push_str(",");
362 res.push_str(&$as::tag_unique_factor());
363 )*
364 res.push_str(")");
365 res
366 }
367 }
368 }
369}
370
371tuple_serializable!((A, 0));
372tuple_serializable!((A, 0), (B, 1));
373tuple_serializable!((A, 0), (B, 1), (C, 2));
374tuple_serializable!((A, 0), (B, 1), (C, 2), (D, 3));
375tuple_serializable!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4));
376tuple_serializable!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5));
377tuple_serializable!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5), (G, 6));
378tuple_serializable!(
379 (A, 0),
380 (B, 1),
381 (C, 2),
382 (D, 3),
383 (E, 4),
384 (F, 5),
385 (G, 6),
386 (H, 7)
387);
388tuple_serializable!(
389 (A, 0),
390 (B, 1),
391 (C, 2),
392 (D, 3),
393 (E, 4),
394 (F, 5),
395 (G, 6),
396 (H, 7),
397 (I, 8)
398);
399tuple_serializable!(
400 (A, 0),
401 (B, 1),
402 (C, 2),
403 (D, 3),
404 (E, 4),
405 (F, 5),
406 (G, 6),
407 (H, 7),
408 (I, 8),
409 (J, 9)
410);
411tuple_serializable!(
412 (A, 0),
413 (B, 1),
414 (C, 2),
415 (D, 3),
416 (E, 4),
417 (F, 5),
418 (G, 6),
419 (H, 7),
420 (I, 8),
421 (J, 9),
422 (K, 10)
423);
424tuple_serializable!(
425 (A, 0),
426 (B, 1),
427 (C, 2),
428 (D, 3),
429 (E, 4),
430 (F, 5),
431 (G, 6),
432 (H, 7),
433 (I, 8),
434 (J, 9),
435 (K, 10),
436 (L, 11)
437);
438tuple_serializable!(
439 (A, 0),
440 (B, 1),
441 (C, 2),
442 (D, 3),
443 (E, 4),
444 (F, 5),
445 (G, 6),
446 (H, 7),
447 (I, 8),
448 (J, 9),
449 (K, 10),
450 (L, 11),
451 (M, 12)
452);
453tuple_serializable!(
454 (A, 0),
455 (B, 1),
456 (C, 2),
457 (D, 3),
458 (E, 4),
459 (F, 5),
460 (G, 6),
461 (H, 7),
462 (I, 8),
463 (J, 9),
464 (K, 10),
465 (L, 11),
466 (M, 12),
467 (N, 13)
468);
469tuple_serializable!(
470 (A, 0),
471 (B, 1),
472 (C, 2),
473 (D, 3),
474 (E, 4),
475 (F, 5),
476 (G, 6),
477 (H, 7),
478 (I, 8),
479 (J, 9),
480 (K, 10),
481 (L, 11),
482 (M, 12),
483 (N, 13),
484 (O, 14)
485);
486tuple_serializable!(
487 (A, 0),
488 (B, 1),
489 (C, 2),
490 (D, 3),
491 (E, 4),
492 (F, 5),
493 (G, 6),
494 (H, 7),
495 (I, 8),
496 (J, 9),
497 (K, 10),
498 (L, 11),
499 (M, 12),
500 (N, 13),
501 (O, 14),
502 (P, 15)
503);
504
505impl Deserializable for String {
506 fn deserialize(reader: &mut impl Read, recursion_depth: u32) -> std::io::Result<Self> {
507 let vec = <Vec<u8>>::deserialize(reader, recursion_depth)?;
508 String::from_utf8(vec).map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
509 }
510}
511
512impl Tagged for String {
513 fn tag() -> std::borrow::Cow<'static, str> {
514 std::borrow::Cow::Borrowed("string")
515 }
516 fn tag_unique_factor() -> String {
517 "string".into()
518 }
519}
520
521impl Tagged for str {
522 fn tag() -> std::borrow::Cow<'static, str> {
523 std::borrow::Cow::Borrowed("string")
524 }
525 fn tag_unique_factor() -> String {
526 "string".into()
527 }
528}
529
530pub fn gen_static_serialize_file<T: Serializable + Tagged>(
531 value: &T,
532) -> Result<(), std::io::Error> {
533 let mut file = BufWriter::new(std::fs::File::create(format!("{}.bin", T::tag(),))?);
534 crate::tagged_serialize(&value, &mut file)
535}
536
537pub fn test_file_deserialize<T: Deserializable + Tagged>(
538 path: std::path::PathBuf,
539) -> Result<T, std::io::Error> {
540 let bytes = std::fs::read(path)?;
541 crate::tagged_deserialize(&mut bytes.as_slice())
542}
543
544#[cfg(feature = "proptest")]
545pub struct NoSearch<T>(T);
546
547#[cfg(feature = "proptest")]
548impl<T: Debug + Clone> ValueTree for NoSearch<T> {
549 type Value = T;
550
551 fn current(&self) -> T {
552 self.0.clone()
553 }
554
555 fn simplify(&mut self) -> bool {
556 false
557 }
558
559 fn complicate(&mut self) -> bool {
560 false
561 }
562}
563
564#[derive(Debug)]
565#[cfg(feature = "proptest")]
566pub struct NoStrategy<T>(pub PhantomData<T>);
567
568#[cfg(feature = "proptest")]
569impl<T: Debug + Clone> Strategy for NoStrategy<T>
570where
571 Standard: Distribution<T>,
572{
573 type Tree = NoSearch<T>;
574 type Value = T;
575
576 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
577 Ok(NoSearch(runner.rng().r#gen()))
578 }
579}
580
581#[macro_export]
582macro_rules! tag_enforcement_test {
583 ($type:ident) => {
584 serialize::tag_enforcement_test!($type < >);
585 };
586 ($type:ident < $($targ:ty),* >) => {
587 #[cfg(test)]
588 ::pastey::paste! {
589 #[allow(non_snake_case)]
590 #[test]
591 fn [<tag_enforcement_test_ $type>]() {
592 let tag = <$type<$($targ),*> as serialize::Tagged>::tag();
593 println!("{tag}");
594 let unique_factor = <$type<$($targ),*> as serialize::Tagged>::tag_unique_factor();
595 let mut dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
596 dir.pop();
597 dir.push(".tag-decompositions");
598 ::std::fs::create_dir_all(&dir).unwrap();
599 let fpath = dir.join(tag.as_ref());
600 if ::std::fs::exists(&fpath).unwrap() {
601 let read_factor = ::std::fs::read_to_string(&fpath).unwrap();
602 assert_eq!(read_factor, unique_factor);
603 } else {
604 ::std::fs::write(&fpath, unique_factor).unwrap();
605 }
606 }
607 }
608 };
609}
610
611#[macro_export]
612#[cfg(feature = "proptest")]
613macro_rules! randomised_tagged_serialization_test {
614 ($type:ident) => {
615 serialize::randomised_tagged_serialization_test!($type < >);
616 };
617 ($type:ident < $($targ:ty),* >) => {
618 #[cfg(test)]
619 ::pastey::paste! {
620 #[allow(non_snake_case)]
621 #[test]
622 fn [<proptest_deserialize_tagged_ $type>]() where $type<$($targ),*>: proptest::prelude::Arbitrary {
623 let mut runner = proptest::test_runner::TestRunner::default();
624
625 runner.run(&<$type<$($targ),*> as proptest::prelude::Arbitrary>::arbitrary(), |v| {
626 let mut bytes: Vec<u8> = Vec::new();
627 serialize::tagged_serialize(&v, &mut bytes).unwrap();
628 let des_result: $type<$($targ),*> = serialize::tagged_deserialize(&mut bytes.as_slice()).unwrap();
629 assert_eq!(des_result, v);
630
631 Ok(())
632 }).unwrap();
633 }
634 serialize::randomised_serialization_test!($type<$($targ),*>);
635 }
636 }
637}
638
639#[macro_export]
640#[cfg(feature = "proptest")]
641macro_rules! randomised_serialization_test {
642 ($type:ident) => {
643 serialize::randomised_serialization_test!($type < >);
644 };
645 ($type:ident < $($targ:ty),* >) => {
646 #[cfg(test)]
647 ::pastey::paste! {
648 #[allow(non_snake_case)]
649 #[test]
650 fn [<proptest_deserialize_ $type>]() where $type<$($targ),*>: proptest::prelude::Arbitrary {
651 let mut runner = proptest::test_runner::TestRunner::default();
652
653 runner.run(&<$type<$($targ),*> as proptest::prelude::Arbitrary>::arbitrary(), |v| {
654 let mut bytes: Vec<u8> = Vec::new();
655 <$type<$($targ),*> as serialize::Serializable>::serialize(&v, &mut bytes).unwrap();
656 let des_result: $type<$($targ),*> = <$type<$($targ),*> as serialize::Deserializable>::deserialize(&mut bytes.as_slice(), 0).unwrap();
657 assert_eq!(des_result, v);
658
659 Ok(())
660 }).unwrap();
661 }
662
663 #[allow(non_snake_case)]
664 #[test]
665 fn [<proptest_serialized_size_ $type>]() where $type<$($targ),*>: proptest::prelude::Arbitrary {
666 let mut runner = proptest::test_runner::TestRunner::default();
667
668 runner.run(&<$type<$($targ),*> as proptest::prelude::Arbitrary>::arbitrary(), |v| {
669 let mut bytes: Vec<u8> = Vec::new();
670 <$type<$($targ),*> as serialize::Serializable>::serialize(&v, &mut bytes).unwrap();
671 assert_eq!(bytes.len(), <$type<$($targ),*> as serialize::Serializable>::serialized_size(&v));
672
673 Ok(())
674 }).unwrap();
675 }
676
677 #[allow(non_snake_case)]
678 #[test]
679 fn [<proptest_random_data_deserialize_ $type>]() {
680 use rand::Rng;
681 let mut rng = rand::thread_rng();
682
683 for _ in 0..100 {
684 let size: u8 = rng.r#gen();
685 let mut bytes: Vec<u8> = Vec::new();
686 for _i in 0..size {
687 bytes.push(rng.r#gen())
688 }
689 let _ = <$type<$($targ),*> as serialize::Deserializable>::deserialize(&mut bytes.as_slice(), 0);
690 }
691 }
692 }
693 };
694}
695
696#[macro_export]
698#[cfg(feature = "proptest")]
699macro_rules! simple_arbitrary {
700 ($type:ty) => {
701 impl Arbitrary for $type {
702 type Parameters = ();
703 type Strategy = NoStrategy<$type>;
704
705 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
706 NoStrategy(PhantomData)
707 }
708 }
709 };
710}
711
712#[cfg(feature = "proptest")]
713#[allow(unused)]
714use crate as serialize;
715
716#[cfg(feature = "proptest")]
717randomised_serialization_test!(String);