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 / std::mem::size_of::<T>();
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 {
302 return Err(std::io::Error::new(
303 std::io::ErrorKind::InvalidData,
304 "non-canonical scale encoding",
305 ));
306 }
307 }
308 _ => unreachable!(),
309 }
310 Ok(res)
311 }
312}
313
314macro_rules! tuple_serializable {
315 (($a:tt, $aidx: tt)$(, ($as:tt, $asidx: tt))*) => {
316 impl<$a: Serializable,$($as: Serializable,)*> Serializable for ($a,$($as,)*) {
317 fn serialize(
318 &self,
319 writer: &mut impl std::io::Write,
320 ) -> std::io::Result<()> {
321 <$a as Serializable>::serialize(&(self.$aidx), writer)?;
322 $(<$as as Serializable>::serialize(&(self.$asidx), writer)?;)*
323 Ok(())
324 }
325
326 fn serialized_size(&self) -> usize {
327 <$a as Serializable>::serialized_size(&(self.$aidx)) $(+ <$as as Serializable>::serialized_size(&(self.$asidx)))*
328 }
329 }
330
331 impl<$a: Deserializable,$($as: Deserializable,)*> Deserializable for ($a,$($as,)*) {
332 fn deserialize(reader: &mut impl std::io::Read, mut recursion_depth: u32) -> std::io::Result<Self> {
333 <Self as Deserializable>::check_rec(&mut recursion_depth)?;
334 Ok((
335 <$a as Deserializable>::deserialize(reader, recursion_depth)?,
336 $(<$as as Deserializable>::deserialize(reader, recursion_depth)?,)*
337 ))
338 }
339 }
340
341 impl<$a: Tagged,$($as: Tagged,)*> Tagged for ($a, $($as,)*) {
342 fn tag() -> std::borrow::Cow<'static, str> {
343 let mut res = String::new();
344 res.push_str("(");
345 res.push_str(&$a::tag());
346 $(
347 res.push_str(",");
348 res.push_str(&$as::tag());
349 )*
350 res.push_str(")");
351 std::borrow::Cow::Owned(res)
352 }
353 fn tag_unique_factor() -> String {
354 let mut res = String::new();
355 res.push_str("(");
356 res.push_str(&$a::tag_unique_factor());
357 $(
358 res.push_str(",");
359 res.push_str(&$as::tag_unique_factor());
360 )*
361 res.push_str(")");
362 res
363 }
364 }
365 }
366}
367
368tuple_serializable!((A, 0));
369tuple_serializable!((A, 0), (B, 1));
370tuple_serializable!((A, 0), (B, 1), (C, 2));
371tuple_serializable!((A, 0), (B, 1), (C, 2), (D, 3));
372tuple_serializable!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4));
373tuple_serializable!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5));
374tuple_serializable!((A, 0), (B, 1), (C, 2), (D, 3), (E, 4), (F, 5), (G, 6));
375tuple_serializable!(
376 (A, 0),
377 (B, 1),
378 (C, 2),
379 (D, 3),
380 (E, 4),
381 (F, 5),
382 (G, 6),
383 (H, 7)
384);
385tuple_serializable!(
386 (A, 0),
387 (B, 1),
388 (C, 2),
389 (D, 3),
390 (E, 4),
391 (F, 5),
392 (G, 6),
393 (H, 7),
394 (I, 8)
395);
396tuple_serializable!(
397 (A, 0),
398 (B, 1),
399 (C, 2),
400 (D, 3),
401 (E, 4),
402 (F, 5),
403 (G, 6),
404 (H, 7),
405 (I, 8),
406 (J, 9)
407);
408tuple_serializable!(
409 (A, 0),
410 (B, 1),
411 (C, 2),
412 (D, 3),
413 (E, 4),
414 (F, 5),
415 (G, 6),
416 (H, 7),
417 (I, 8),
418 (J, 9),
419 (K, 10)
420);
421tuple_serializable!(
422 (A, 0),
423 (B, 1),
424 (C, 2),
425 (D, 3),
426 (E, 4),
427 (F, 5),
428 (G, 6),
429 (H, 7),
430 (I, 8),
431 (J, 9),
432 (K, 10),
433 (L, 11)
434);
435tuple_serializable!(
436 (A, 0),
437 (B, 1),
438 (C, 2),
439 (D, 3),
440 (E, 4),
441 (F, 5),
442 (G, 6),
443 (H, 7),
444 (I, 8),
445 (J, 9),
446 (K, 10),
447 (L, 11),
448 (M, 12)
449);
450tuple_serializable!(
451 (A, 0),
452 (B, 1),
453 (C, 2),
454 (D, 3),
455 (E, 4),
456 (F, 5),
457 (G, 6),
458 (H, 7),
459 (I, 8),
460 (J, 9),
461 (K, 10),
462 (L, 11),
463 (M, 12),
464 (N, 13)
465);
466tuple_serializable!(
467 (A, 0),
468 (B, 1),
469 (C, 2),
470 (D, 3),
471 (E, 4),
472 (F, 5),
473 (G, 6),
474 (H, 7),
475 (I, 8),
476 (J, 9),
477 (K, 10),
478 (L, 11),
479 (M, 12),
480 (N, 13),
481 (O, 14)
482);
483tuple_serializable!(
484 (A, 0),
485 (B, 1),
486 (C, 2),
487 (D, 3),
488 (E, 4),
489 (F, 5),
490 (G, 6),
491 (H, 7),
492 (I, 8),
493 (J, 9),
494 (K, 10),
495 (L, 11),
496 (M, 12),
497 (N, 13),
498 (O, 14),
499 (P, 15)
500);
501
502impl Deserializable for String {
503 fn deserialize(reader: &mut impl Read, recursion_depth: u32) -> std::io::Result<Self> {
504 let vec = <Vec<u8>>::deserialize(reader, recursion_depth)?;
505 String::from_utf8(vec).map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
506 }
507}
508
509impl Tagged for String {
510 fn tag() -> std::borrow::Cow<'static, str> {
511 std::borrow::Cow::Borrowed("string")
512 }
513 fn tag_unique_factor() -> String {
514 "string".into()
515 }
516}
517
518impl Tagged for str {
519 fn tag() -> std::borrow::Cow<'static, str> {
520 std::borrow::Cow::Borrowed("string")
521 }
522 fn tag_unique_factor() -> String {
523 "string".into()
524 }
525}
526
527pub fn gen_static_serialize_file<T: Serializable + Tagged>(
528 value: &T,
529) -> Result<(), std::io::Error> {
530 let mut file = BufWriter::new(std::fs::File::create(format!("{}.bin", T::tag(),))?);
531 crate::tagged_serialize(&value, &mut file)
532}
533
534pub fn test_file_deserialize<T: Deserializable + Tagged>(
535 path: std::path::PathBuf,
536) -> Result<T, std::io::Error> {
537 let bytes = std::fs::read(path)?;
538 crate::tagged_deserialize(&mut bytes.as_slice())
539}
540
541#[cfg(feature = "proptest")]
542pub struct NoSearch<T>(T);
543
544#[cfg(feature = "proptest")]
545impl<T: Debug + Clone> ValueTree for NoSearch<T> {
546 type Value = T;
547
548 fn current(&self) -> T {
549 self.0.clone()
550 }
551
552 fn simplify(&mut self) -> bool {
553 false
554 }
555
556 fn complicate(&mut self) -> bool {
557 false
558 }
559}
560
561#[derive(Debug)]
562#[cfg(feature = "proptest")]
563pub struct NoStrategy<T>(pub PhantomData<T>);
564
565#[cfg(feature = "proptest")]
566impl<T: Debug + Clone> Strategy for NoStrategy<T>
567where
568 Standard: Distribution<T>,
569{
570 type Tree = NoSearch<T>;
571 type Value = T;
572
573 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
574 Ok(NoSearch(runner.rng().r#gen()))
575 }
576}
577
578#[macro_export]
579macro_rules! tag_enforcement_test {
580 ($type:ident) => {
581 serialize::tag_enforcement_test!($type < >);
582 };
583 ($type:ident < $($targ:ty),* >) => {
584 #[cfg(test)]
585 ::pastey::paste! {
586 #[allow(non_snake_case)]
587 #[test]
588 fn [<tag_enforcement_test_ $type>]() {
589 let tag = <$type<$($targ),*> as serialize::Tagged>::tag();
590 println!("{tag}");
591 let unique_factor = <$type<$($targ),*> as serialize::Tagged>::tag_unique_factor();
592 let mut dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
593 dir.pop();
594 dir.push(".tag-decompositions");
595 ::std::fs::create_dir_all(&dir).unwrap();
596 let fpath = dir.join(tag.as_ref());
597 if ::std::fs::exists(&fpath).unwrap() {
598 let read_factor = ::std::fs::read_to_string(&fpath).unwrap();
599 assert_eq!(read_factor, unique_factor);
600 } else {
601 ::std::fs::write(&fpath, unique_factor).unwrap();
602 }
603 }
604 }
605 };
606}
607
608#[macro_export]
609#[cfg(feature = "proptest")]
610macro_rules! randomised_tagged_serialization_test {
611 ($type:ident) => {
612 serialize::randomised_tagged_serialization_test!($type < >);
613 };
614 ($type:ident < $($targ:ty),* >) => {
615 #[cfg(test)]
616 ::pastey::paste! {
617 #[allow(non_snake_case)]
618 #[test]
619 fn [<proptest_deserialize_tagged_ $type>]() where $type<$($targ),*>: proptest::prelude::Arbitrary {
620 let mut runner = proptest::test_runner::TestRunner::default();
621
622 runner.run(&<$type<$($targ),*> as proptest::prelude::Arbitrary>::arbitrary(), |v| {
623 let mut bytes: Vec<u8> = Vec::new();
624 serialize::tagged_serialize(&v, &mut bytes).unwrap();
625 let des_result: $type<$($targ),*> = serialize::tagged_deserialize(&mut bytes.as_slice()).unwrap();
626 assert_eq!(des_result, v);
627
628 Ok(())
629 }).unwrap();
630 }
631 serialize::randomised_serialization_test!($type<$($targ),*>);
632 }
633 }
634}
635
636#[macro_export]
637#[cfg(feature = "proptest")]
638macro_rules! randomised_serialization_test {
639 ($type:ident) => {
640 serialize::randomised_serialization_test!($type < >);
641 };
642 ($type:ident < $($targ:ty),* >) => {
643 #[cfg(test)]
644 ::pastey::paste! {
645 #[allow(non_snake_case)]
646 #[test]
647 fn [<proptest_deserialize_ $type>]() where $type<$($targ),*>: proptest::prelude::Arbitrary {
648 let mut runner = proptest::test_runner::TestRunner::default();
649
650 runner.run(&<$type<$($targ),*> as proptest::prelude::Arbitrary>::arbitrary(), |v| {
651 let mut bytes: Vec<u8> = Vec::new();
652 <$type<$($targ),*> as serialize::Serializable>::serialize(&v, &mut bytes).unwrap();
653 let des_result: $type<$($targ),*> = <$type<$($targ),*> as serialize::Deserializable>::deserialize(&mut bytes.as_slice(), 0).unwrap();
654 assert_eq!(des_result, v);
655
656 Ok(())
657 }).unwrap();
658 }
659
660 #[allow(non_snake_case)]
661 #[test]
662 fn [<proptest_serialized_size_ $type>]() where $type<$($targ),*>: proptest::prelude::Arbitrary {
663 let mut runner = proptest::test_runner::TestRunner::default();
664
665 runner.run(&<$type<$($targ),*> as proptest::prelude::Arbitrary>::arbitrary(), |v| {
666 let mut bytes: Vec<u8> = Vec::new();
667 <$type<$($targ),*> as serialize::Serializable>::serialize(&v, &mut bytes).unwrap();
668 assert_eq!(bytes.len(), <$type<$($targ),*> as serialize::Serializable>::serialized_size(&v));
669
670 Ok(())
671 }).unwrap();
672 }
673
674 #[allow(non_snake_case)]
675 #[test]
676 fn [<proptest_random_data_deserialize_ $type>]() {
677 use rand::Rng;
678 let mut rng = rand::thread_rng();
679
680 for _ in 0..100 {
681 let size: u8 = rng.r#gen();
682 let mut bytes: Vec<u8> = Vec::new();
683 for _i in 0..size {
684 bytes.push(rng.r#gen())
685 }
686 let _ = <$type<$($targ),*> as serialize::Deserializable>::deserialize(&mut bytes.as_slice(), 0);
687 }
688 }
689 }
690 };
691}
692
693#[macro_export]
695#[cfg(feature = "proptest")]
696macro_rules! simple_arbitrary {
697 ($type:ty) => {
698 impl Arbitrary for $type {
699 type Parameters = ();
700 type Strategy = NoStrategy<$type>;
701
702 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
703 NoStrategy(PhantomData)
704 }
705 }
706 };
707}
708
709#[cfg(feature = "proptest")]
710#[allow(unused)]
711use crate as serialize;
712
713#[cfg(feature = "proptest")]
714randomised_serialization_test!(String);