snarkvm_utilities/serialize/
impls.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use std::io::{Read, Write};
17
18use crate::{FromBytes, SerializationError, ToBytes, serialize::traits::*};
19
20use bincode::Options;
21
22use std::{borrow::Cow, collections::BTreeMap, marker::PhantomData, rc::Rc, sync::Arc};
23
24impl Valid for bool {
25    fn check(&self) -> Result<(), SerializationError> {
26        Ok(())
27    }
28}
29
30impl CanonicalSerialize for bool {
31    #[inline]
32    fn serialize_with_mode<W: Write>(&self, mut writer: W, _compress: Compress) -> Result<(), SerializationError> {
33        Ok(self.write_le(&mut writer)?)
34    }
35
36    #[inline]
37    fn serialized_size(&self, _compress: Compress) -> usize {
38        1
39    }
40}
41
42impl CanonicalDeserialize for bool {
43    #[inline]
44    fn deserialize_with_mode<R: Read>(
45        reader: R,
46        _compress: Compress,
47        _validate: Validate,
48    ) -> Result<Self, SerializationError> {
49        Ok(bool::read_le(reader)?)
50    }
51}
52
53impl CanonicalSerialize for String {
54    #[inline]
55    fn serialize_with_mode<W: Write>(&self, mut writer: W, _compress: Compress) -> Result<(), SerializationError> {
56        Ok(bincode::serialize_into(&mut writer, self)?)
57    }
58
59    #[inline]
60    fn serialized_size(&self, _compress: Compress) -> usize {
61        self.len() + 8
62    }
63}
64
65impl Valid for String {
66    #[inline]
67    fn check(&self) -> Result<(), SerializationError> {
68        Ok(())
69    }
70
71    #[inline]
72    fn batch_check<'a>(_batch: impl Iterator<Item = &'a Self>) -> Result<(), SerializationError>
73    where
74        Self: 'a,
75    {
76        Ok(())
77    }
78}
79
80impl CanonicalDeserialize for String {
81    #[inline]
82    fn deserialize_with_mode<R: Read>(
83        reader: R,
84        _compress: Compress,
85        _validate: Validate,
86    ) -> Result<Self, SerializationError> {
87        Ok(bincode::DefaultOptions::new()
88            .with_fixint_encoding() // this option is for compatibility with the defaults
89            .allow_trailing_bytes() // so is this
90            .with_limit(10 * 1024)  // a limit to guard against OOMs
91            .deserialize_from(reader)?)
92    }
93}
94
95macro_rules! impl_canonical_serialization_uint {
96    ($type:ty) => {
97        impl CanonicalSerialize for $type {
98            #[inline]
99            fn serialize_with_mode<W: Write>(
100                &self,
101                mut writer: W,
102                _compress: Compress,
103            ) -> Result<(), SerializationError> {
104                Ok(writer.write_all(&self.to_le_bytes())?)
105            }
106
107            #[inline]
108            fn serialized_size(&self, _compress: Compress) -> usize {
109                std::mem::size_of::<$type>()
110            }
111        }
112        impl Valid for $type {
113            #[inline]
114            fn check(&self) -> Result<(), SerializationError> {
115                Ok(())
116            }
117
118            #[inline]
119            fn batch_check<'a>(_batch: impl Iterator<Item = &'a Self>) -> Result<(), SerializationError>
120            where
121                Self: 'a,
122            {
123                Ok(())
124            }
125        }
126
127        impl CanonicalDeserialize for $type {
128            #[inline]
129            fn deserialize_with_mode<R: Read>(
130                mut reader: R,
131                _compress: Compress,
132                _validate: Validate,
133            ) -> Result<Self, SerializationError> {
134                let mut bytes = [0u8; std::mem::size_of::<$type>()];
135                reader.read_exact(&mut bytes)?;
136                Ok(<$type>::from_le_bytes(bytes))
137            }
138        }
139    };
140}
141
142impl_canonical_serialization_uint!(u8);
143impl_canonical_serialization_uint!(u16);
144impl_canonical_serialization_uint!(u32);
145impl_canonical_serialization_uint!(u64);
146
147impl CanonicalSerialize for usize {
148    #[inline]
149    fn serialize_with_mode<W: Write>(&self, mut writer: W, _compress: Compress) -> Result<(), SerializationError> {
150        let u64_value = u64::try_from(*self).map_err(|_| SerializationError::IncompatibleTarget)?;
151        Ok(writer.write_all(&u64_value.to_le_bytes())?)
152    }
153
154    #[inline]
155    fn serialized_size(&self, _compress: Compress) -> usize {
156        8
157    }
158}
159
160impl Valid for usize {
161    #[inline]
162    fn check(&self) -> Result<(), SerializationError> {
163        Ok(())
164    }
165
166    #[inline]
167    fn batch_check<'a>(_batch: impl Iterator<Item = &'a Self>) -> Result<(), SerializationError>
168    where
169        Self: 'a,
170    {
171        Ok(())
172    }
173}
174
175impl CanonicalDeserialize for usize {
176    #[inline]
177    fn deserialize_with_mode<R: Read>(
178        mut reader: R,
179        _compress: Compress,
180        _validate: Validate,
181    ) -> Result<Self, SerializationError> {
182        let u64_value = u64::deserialize_compressed(&mut reader)?;
183        usize::try_from(u64_value).map_err(|_| SerializationError::IncompatibleTarget)
184    }
185}
186
187impl<T: CanonicalSerialize> CanonicalSerialize for Option<T> {
188    #[inline]
189    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
190        self.is_some().serialize_with_mode(&mut writer, compress)?;
191        if let Some(item) = self {
192            item.serialize_with_mode(&mut writer, compress)?;
193        }
194
195        Ok(())
196    }
197
198    #[inline]
199    fn serialized_size(&self, compress: Compress) -> usize {
200        8 + self.as_ref().map(|s| s.serialized_size(compress)).unwrap_or(0)
201    }
202}
203
204impl<T: Valid> Valid for Option<T> {
205    #[inline]
206    fn check(&self) -> Result<(), SerializationError> {
207        match self {
208            Some(v) => v.check(),
209            None => Ok(()),
210        }
211    }
212
213    #[inline]
214    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
215    where
216        Self: 'a,
217    {
218        T::batch_check(batch.map(Option::as_ref).filter(Option::is_some).flatten())
219    }
220}
221
222impl<T: CanonicalDeserialize> CanonicalDeserialize for Option<T> {
223    #[inline]
224    fn deserialize_with_mode<R: Read>(
225        mut reader: R,
226        compress: Compress,
227        validate: Validate,
228    ) -> Result<Self, SerializationError> {
229        let is_some = bool::deserialize_with_mode(&mut reader, compress, validate)?;
230        let data = if is_some { Some(T::deserialize_with_mode(&mut reader, compress, validate)?) } else { None };
231
232        Ok(data)
233    }
234}
235
236// No-op
237impl<T> CanonicalSerialize for std::marker::PhantomData<T> {
238    #[inline]
239    fn serialize_with_mode<W: Write>(&self, _writer: W, _compress: Compress) -> Result<(), SerializationError> {
240        Ok(())
241    }
242
243    #[inline]
244    fn serialized_size(&self, _compress: Compress) -> usize {
245        0
246    }
247}
248
249impl<T: Sync> Valid for PhantomData<T> {
250    #[inline]
251    fn check(&self) -> Result<(), SerializationError> {
252        Ok(())
253    }
254}
255
256impl<T: Send + Sync> CanonicalDeserialize for std::marker::PhantomData<T> {
257    #[inline]
258    fn deserialize_with_mode<R: Read>(
259        _reader: R,
260        _compress: Compress,
261        _validate: Validate,
262    ) -> Result<Self, SerializationError> {
263        Ok(std::marker::PhantomData)
264    }
265}
266
267impl<T: CanonicalSerialize + ToOwned> CanonicalSerialize for Rc<T> {
268    #[inline]
269    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
270        self.as_ref().serialize_with_mode(&mut writer, compress)
271    }
272
273    #[inline]
274    fn serialized_size(&self, compress: Compress) -> usize {
275        self.as_ref().serialized_size(compress)
276    }
277}
278
279// impl<T: Valid> Valid for Rc<T> {
280//     #[inline]
281//     fn check(&self) -> Result<(), SerializationError> {
282//         self.as_ref().check()
283//     }
284
285//     #[inline]
286
287//     fn batch_check<'a>(batch: impl Iterator<Item = &'a Self>) -> Result<(), SerializationError>
288//     where
289//         Self: 'a,
290//     {
291//         T::batch_check(batch.map(|v| v.as_ref()))
292//     }
293// }
294
295// impl<T: CanonicalDeserialize + ToOwned> CanonicalDeserialize for Rc<T> {
296//     #[inline]
297//     fn deserialize_with_mode<R: Read>(
298//         reader: R,
299//         compress: Compress,
300//         validate: Validate,
301//     ) -> Result<Self, SerializationError> {
302//         Ok(Rc::new(T::deserialize_with_mode(reader, compress, validate)?))
303//     }
304// }
305
306impl<T: CanonicalSerialize> CanonicalSerialize for Arc<T> {
307    #[inline]
308    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
309        self.as_ref().serialize_with_mode(&mut writer, compress)
310    }
311
312    #[inline]
313    fn serialized_size(&self, compress: Compress) -> usize {
314        self.as_ref().serialized_size(compress)
315    }
316}
317
318impl<T: Valid + Sync + Send> Valid for Arc<T> {
319    #[inline]
320    fn check(&self) -> Result<(), SerializationError> {
321        self.as_ref().check()
322    }
323
324    #[inline]
325    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
326    where
327        Self: 'a,
328    {
329        T::batch_check(batch.map(|v| v.as_ref()))
330    }
331}
332
333impl<T: CanonicalDeserialize + Sync + Send> CanonicalDeserialize for Arc<T> {
334    #[inline]
335    fn deserialize_with_mode<R: Read>(
336        reader: R,
337        compress: Compress,
338        validate: Validate,
339    ) -> Result<Self, SerializationError> {
340        Ok(Arc::new(T::deserialize_with_mode(reader, compress, validate)?))
341    }
342}
343
344impl<T: CanonicalSerialize + ToOwned> CanonicalSerialize for Cow<'_, T> {
345    #[inline]
346    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
347        self.as_ref().serialize_with_mode(&mut writer, compress)
348    }
349
350    #[inline]
351    fn serialized_size(&self, compress: Compress) -> usize {
352        self.as_ref().serialized_size(compress)
353    }
354}
355
356// impl<'b, T> Valid for Cow<'b, T>
357// where
358//     T: ToOwned + Sync + Valid + Send,
359//     <T as ToOwned>::Owned: CanonicalDeserialize + Send + Valid,
360// {
361//     #[inline]
362//     fn check(&self) -> Result<(), SerializationError> {
363//         <<T as ToOwned>::Owned>::check(self.as_ref().borrow())
364//     }
365
366//     #[inline]
367
368//     fn batch_check<'a>(batch: impl Iterator<Item = &'a Self>) -> Result<(), SerializationError>
369//     where
370//         Self: 'a
371//     {
372//         <<T as ToOwned>::Owned>::batch_check(batch.map(|v| v.as_ref()))
373//     }
374// }
375
376// impl<'a, T> CanonicalDeserialize for Cow<'a, T>
377// where
378//     T: ToOwned + Valid + Valid + Sync + Send,
379//     <T as ToOwned>::Owned: CanonicalDeserialize + Valid + Send,
380// {
381//     #[inline]
382//     fn deserialize_with_mode<R: Read>(reader: R, compress: Compress, validate: Validate) -> Result<Self, SerializationError> {
383//         Ok(Cow::Owned(<T as ToOwned>::Owned::deserialize_with_mode(reader, compress, validate)?))
384//     }
385// }
386
387impl<T: CanonicalSerialize> CanonicalSerialize for Vec<T> {
388    #[inline]
389    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
390        self.as_slice().serialize_with_mode(&mut writer, compress)
391    }
392
393    #[inline]
394    fn serialized_size(&self, compress: Compress) -> usize {
395        self.as_slice().serialized_size(compress)
396    }
397}
398
399impl<T: Valid> Valid for Vec<T> {
400    #[inline]
401    fn check(&self) -> Result<(), SerializationError> {
402        T::batch_check(self.iter())
403    }
404
405    #[inline]
406    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
407    where
408        Self: 'a,
409    {
410        T::batch_check(batch.flatten())
411    }
412}
413
414impl<T: CanonicalDeserialize> CanonicalDeserialize for Vec<T> {
415    #[inline]
416    fn deserialize_with_mode<R: Read>(
417        mut reader: R,
418        compress: Compress,
419        validate: Validate,
420    ) -> Result<Self, SerializationError> {
421        let len = u64::deserialize_with_mode(&mut reader, compress, validate)?;
422        let mut values = Vec::new();
423        let _ = values.try_reserve(len as usize);
424        for _ in 0..len {
425            values.push(T::deserialize_with_mode(&mut reader, compress, Validate::No)?);
426        }
427
428        if let Validate::Yes = validate {
429            T::batch_check(values.iter())?
430        }
431        Ok(values)
432    }
433}
434
435impl<T: CanonicalDeserialize + std::fmt::Debug> CanonicalDeserialize for [T; 32] {
436    #[inline]
437    fn deserialize_with_mode<R: Read>(
438        mut reader: R,
439        compress: Compress,
440        validate: Validate,
441    ) -> Result<Self, SerializationError> {
442        let values = [(); 32].map(|_| T::deserialize_with_mode(&mut reader, compress, Validate::No));
443
444        // check that each value is error free
445        if values.iter().any(|value| value.is_err()) {
446            return Err(SerializationError::InvalidData);
447        }
448
449        let values = values.map(|r| r.unwrap());
450
451        if let Validate::Yes = validate {
452            T::batch_check(values.iter())?
453        }
454
455        Ok(values)
456    }
457}
458
459impl<T: Valid> Valid for [T; 32] {
460    #[inline]
461    fn check(&self) -> Result<(), SerializationError> {
462        T::batch_check(self.iter())
463    }
464
465    #[inline]
466    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
467    where
468        Self: 'a,
469    {
470        T::batch_check(batch.flatten())
471    }
472}
473
474impl<T: CanonicalSerialize> CanonicalSerialize for [T] {
475    #[inline]
476    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
477        let len = self.len() as u64;
478        len.serialize_with_mode(&mut writer, compress)?;
479        for item in self.iter() {
480            item.serialize_with_mode(&mut writer, compress)?;
481        }
482        Ok(())
483    }
484
485    #[inline]
486    fn serialized_size(&self, compress: Compress) -> usize {
487        8 + self.iter().map(|item| item.serialized_size(compress)).sum::<usize>()
488    }
489}
490
491impl<T: CanonicalSerialize> CanonicalSerialize for [T; 32] {
492    #[inline]
493    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
494        for item in self.iter() {
495            item.serialize_with_mode(&mut writer, compress)?;
496        }
497        Ok(())
498    }
499
500    #[inline]
501    fn serialized_size(&self, compress: Compress) -> usize {
502        8 + self.iter().map(|item| item.serialized_size(compress)).sum::<usize>()
503    }
504}
505
506impl<T: CanonicalSerialize> CanonicalSerialize for &'_ [T] {
507    #[inline]
508    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
509        (*self).serialize_with_mode(&mut writer, compress)
510    }
511
512    #[inline]
513    fn serialized_size(&self, compress: Compress) -> usize {
514        (*self).serialized_size(compress)
515    }
516}
517
518// Implement Serialization for tuples
519macro_rules! impl_tuple {
520    ($( $ty: ident : $no: tt, )+) => {
521        impl<$($ty, )+> Valid for ($($ty,)+) where
522            $($ty: Valid,)+
523        {
524            #[inline]
525            fn check(&self) -> Result<(), SerializationError> {
526                $(self.$no.check()?;)*
527                Ok(())
528            }
529        }
530
531        impl<$($ty, )+> CanonicalSerialize for ($($ty,)+) where
532            $($ty: CanonicalSerialize,)+
533        {
534            #[inline]
535            fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
536                $(self.$no.serialize_with_mode(&mut writer, compress)?;)*
537                Ok(())
538            }
539
540            #[inline]
541            fn serialized_size(&self, compress: Compress) -> usize {
542                [$(
543                    self.$no.serialized_size(compress),
544                )*].iter().sum()
545            }
546        }
547
548        impl<$($ty, )+> CanonicalDeserialize for ($($ty,)+) where
549            $($ty: CanonicalDeserialize,)+
550        {
551            #[inline]
552            fn deserialize_with_mode<R: Read>(mut reader: R, compress: Compress, validate: Validate) -> Result<Self, SerializationError> {
553                Ok(($(
554                    $ty::deserialize_with_mode(&mut reader, compress, validate)?,
555                )+))
556            }
557        }
558    }
559}
560
561impl_tuple!(A:0, B:1,);
562impl_tuple!(A:0, B:1, C:2,);
563impl_tuple!(A:0, B:1, C:2, D:3,);
564
565impl<K, V> CanonicalSerialize for BTreeMap<K, V>
566where
567    K: CanonicalSerialize,
568    V: CanonicalSerialize,
569{
570    /// Serializes a `BTreeMap` as `len(map) || key 1 || value 1 || ... || key n || value n`.
571    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
572        let len = self.len() as u64;
573        len.serialize_with_mode(&mut writer, compress)?;
574        for (k, v) in self.iter() {
575            k.serialize_with_mode(&mut writer, compress)?;
576            v.serialize_with_mode(&mut writer, compress)?;
577        }
578        Ok(())
579    }
580
581    fn serialized_size(&self, compress: Compress) -> usize {
582        8 + self.iter().map(|(k, v)| k.serialized_size(compress) + v.serialized_size(compress)).sum::<usize>()
583    }
584}
585
586impl<K: Valid, V: Valid> Valid for BTreeMap<K, V> {
587    #[inline]
588    fn check(&self) -> Result<(), SerializationError> {
589        K::batch_check(self.keys())?;
590        V::batch_check(self.values())
591    }
592
593    #[inline]
594    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self>) -> Result<(), SerializationError>
595    where
596        Self: 'a,
597    {
598        let (keys, values): (Vec<_>, Vec<_>) = batch.map(|b| (b.keys(), b.values())).unzip();
599        K::batch_check(keys.into_iter().flatten())?;
600        V::batch_check(values.into_iter().flatten())
601    }
602}
603
604impl<K, V> CanonicalDeserialize for BTreeMap<K, V>
605where
606    K: Ord + CanonicalDeserialize,
607    V: CanonicalDeserialize,
608{
609    /// Deserializes a `BTreeMap` from `len(map) || key 1 || value 1 || ... || key n || value n`.
610    fn deserialize_with_mode<R: Read>(
611        mut reader: R,
612        compress: Compress,
613        validate: Validate,
614    ) -> Result<Self, SerializationError> {
615        let len = u64::deserialize_with_mode(&mut reader, compress, validate)?;
616        let mut map = BTreeMap::new();
617        for _ in 0..len {
618            map.insert(
619                K::deserialize_with_mode(&mut reader, compress, validate)?,
620                V::deserialize_with_mode(&mut reader, compress, validate)?,
621            );
622        }
623        Ok(map)
624    }
625}
626
627#[cfg(test)]
628mod test {
629    use super::*;
630    use crate::{deserialize_vec_without_len, serialize_vec_without_len, serialized_vec_size_without_len};
631
632    fn test_serialize<T: PartialEq + std::fmt::Debug + CanonicalSerialize + CanonicalDeserialize>(data: T) {
633        let combinations = [
634            (Compress::No, Validate::No),
635            (Compress::Yes, Validate::No),
636            (Compress::No, Validate::Yes),
637            (Compress::Yes, Validate::Yes),
638        ];
639        for (compress, validate) in combinations {
640            let mut serialized = vec![0; data.serialized_size(compress)];
641            data.serialize_with_mode(&mut serialized[..], compress).unwrap();
642            let de = T::deserialize_with_mode(&serialized[..], compress, validate).unwrap();
643            assert_eq!(data, de);
644        }
645    }
646
647    fn test_serialize_without_len<T: PartialEq + std::fmt::Debug + CanonicalSerialize + CanonicalDeserialize>(
648        data: Vec<T>,
649    ) {
650        let combinations = [
651            (Compress::No, Validate::No),
652            (Compress::Yes, Validate::No),
653            (Compress::No, Validate::Yes),
654            (Compress::Yes, Validate::Yes),
655        ];
656        for (compress, validate) in combinations {
657            let len = serialized_vec_size_without_len(&data, compress);
658            let mut serialized = vec![0; len];
659            serialize_vec_without_len(data.iter(), serialized.as_mut_slice(), compress).unwrap();
660            let elements = if len > 0 { len / CanonicalSerialize::serialized_size(&data[0], compress) } else { 0 };
661            let de = deserialize_vec_without_len(serialized.as_slice(), compress, validate, elements).unwrap();
662            assert_eq!(data, de);
663        }
664    }
665
666    #[test]
667    fn test_bool() {
668        test_serialize(true);
669        test_serialize(false);
670    }
671
672    #[test]
673    fn test_uint() {
674        test_serialize(192830918usize);
675        test_serialize(192830918u64);
676        test_serialize(192830918u32);
677        test_serialize(22313u16);
678        test_serialize(123u8);
679    }
680
681    #[test]
682    fn test_string() {
683        test_serialize("asdf".to_owned());
684    }
685
686    #[test]
687    fn test_vec() {
688        test_serialize(vec![1u64, 2, 3, 4, 5]);
689        test_serialize(Vec::<u64>::new());
690    }
691
692    #[test]
693    fn test_vec_without_len() {
694        test_serialize_without_len(vec![1u64, 2, 3, 4, 5]);
695        test_serialize_without_len(Vec::<u64>::new());
696    }
697
698    #[test]
699    fn test_tuple() {
700        test_serialize((123u64, 234u32, 999u16));
701    }
702
703    #[test]
704    fn test_tuple_vec() {
705        test_serialize(vec![(123u64, 234u32, 999u16), (123u64, 234u32, 999u16), (123u64, 234u32, 999u16)]);
706    }
707
708    #[test]
709    fn test_option() {
710        test_serialize(Some(3u32));
711        test_serialize(None::<u32>);
712    }
713
714    #[test]
715    fn test_phantomdata() {
716        test_serialize(std::marker::PhantomData::<u64>);
717    }
718}