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        bool::serialized_size(&self.is_some(), compress)
201            + self.as_ref().map(|s| s.serialized_size(compress)).unwrap_or(0)
202    }
203}
204
205impl<T: Valid> Valid for Option<T> {
206    #[inline]
207    fn check(&self) -> Result<(), SerializationError> {
208        match self {
209            Some(v) => v.check(),
210            None => Ok(()),
211        }
212    }
213
214    #[inline]
215    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
216    where
217        Self: 'a,
218    {
219        T::batch_check(batch.map(Option::as_ref).filter(Option::is_some).flatten())
220    }
221}
222
223impl<T: CanonicalDeserialize> CanonicalDeserialize for Option<T> {
224    #[inline]
225    fn deserialize_with_mode<R: Read>(
226        mut reader: R,
227        compress: Compress,
228        validate: Validate,
229    ) -> Result<Self, SerializationError> {
230        let is_some = bool::deserialize_with_mode(&mut reader, compress, validate)?;
231        let data = if is_some { Some(T::deserialize_with_mode(&mut reader, compress, validate)?) } else { None };
232
233        Ok(data)
234    }
235}
236
237// No-op
238impl<T> CanonicalSerialize for std::marker::PhantomData<T> {
239    #[inline]
240    fn serialize_with_mode<W: Write>(&self, _writer: W, _compress: Compress) -> Result<(), SerializationError> {
241        Ok(())
242    }
243
244    #[inline]
245    fn serialized_size(&self, _compress: Compress) -> usize {
246        0
247    }
248}
249
250impl<T: Sync> Valid for PhantomData<T> {
251    #[inline]
252    fn check(&self) -> Result<(), SerializationError> {
253        Ok(())
254    }
255}
256
257impl<T: Send + Sync> CanonicalDeserialize for std::marker::PhantomData<T> {
258    #[inline]
259    fn deserialize_with_mode<R: Read>(
260        _reader: R,
261        _compress: Compress,
262        _validate: Validate,
263    ) -> Result<Self, SerializationError> {
264        Ok(std::marker::PhantomData)
265    }
266}
267
268impl<T: CanonicalSerialize + ToOwned> CanonicalSerialize for Rc<T> {
269    #[inline]
270    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
271        self.as_ref().serialize_with_mode(&mut writer, compress)
272    }
273
274    #[inline]
275    fn serialized_size(&self, compress: Compress) -> usize {
276        self.as_ref().serialized_size(compress)
277    }
278}
279
280// impl<T: Valid> Valid for Rc<T> {
281//     #[inline]
282//     fn check(&self) -> Result<(), SerializationError> {
283//         self.as_ref().check()
284//     }
285
286//     #[inline]
287
288//     fn batch_check<'a>(batch: impl Iterator<Item = &'a Self>) -> Result<(), SerializationError>
289//     where
290//         Self: 'a,
291//     {
292//         T::batch_check(batch.map(|v| v.as_ref()))
293//     }
294// }
295
296// impl<T: CanonicalDeserialize + ToOwned> CanonicalDeserialize for Rc<T> {
297//     #[inline]
298//     fn deserialize_with_mode<R: Read>(
299//         reader: R,
300//         compress: Compress,
301//         validate: Validate,
302//     ) -> Result<Self, SerializationError> {
303//         Ok(Rc::new(T::deserialize_with_mode(reader, compress, validate)?))
304//     }
305// }
306
307impl<T: CanonicalSerialize> CanonicalSerialize for Arc<T> {
308    #[inline]
309    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
310        self.as_ref().serialize_with_mode(&mut writer, compress)
311    }
312
313    #[inline]
314    fn serialized_size(&self, compress: Compress) -> usize {
315        self.as_ref().serialized_size(compress)
316    }
317}
318
319impl<T: Valid + Sync + Send> Valid for Arc<T> {
320    #[inline]
321    fn check(&self) -> Result<(), SerializationError> {
322        self.as_ref().check()
323    }
324
325    #[inline]
326    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
327    where
328        Self: 'a,
329    {
330        T::batch_check(batch.map(|v| v.as_ref()))
331    }
332}
333
334impl<T: CanonicalDeserialize + Sync + Send> CanonicalDeserialize for Arc<T> {
335    #[inline]
336    fn deserialize_with_mode<R: Read>(
337        reader: R,
338        compress: Compress,
339        validate: Validate,
340    ) -> Result<Self, SerializationError> {
341        Ok(Arc::new(T::deserialize_with_mode(reader, compress, validate)?))
342    }
343}
344
345impl<T: CanonicalSerialize + ToOwned> CanonicalSerialize for Cow<'_, T> {
346    #[inline]
347    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
348        self.as_ref().serialize_with_mode(&mut writer, compress)
349    }
350
351    #[inline]
352    fn serialized_size(&self, compress: Compress) -> usize {
353        self.as_ref().serialized_size(compress)
354    }
355}
356
357// impl<'b, T> Valid for Cow<'b, T>
358// where
359//     T: ToOwned + Sync + Valid + Send,
360//     <T as ToOwned>::Owned: CanonicalDeserialize + Send + Valid,
361// {
362//     #[inline]
363//     fn check(&self) -> Result<(), SerializationError> {
364//         <<T as ToOwned>::Owned>::check(self.as_ref().borrow())
365//     }
366
367//     #[inline]
368
369//     fn batch_check<'a>(batch: impl Iterator<Item = &'a Self>) -> Result<(), SerializationError>
370//     where
371//         Self: 'a
372//     {
373//         <<T as ToOwned>::Owned>::batch_check(batch.map(|v| v.as_ref()))
374//     }
375// }
376
377// impl<'a, T> CanonicalDeserialize for Cow<'a, T>
378// where
379//     T: ToOwned + Valid + Valid + Sync + Send,
380//     <T as ToOwned>::Owned: CanonicalDeserialize + Valid + Send,
381// {
382//     #[inline]
383//     fn deserialize_with_mode<R: Read>(reader: R, compress: Compress, validate: Validate) -> Result<Self, SerializationError> {
384//         Ok(Cow::Owned(<T as ToOwned>::Owned::deserialize_with_mode(reader, compress, validate)?))
385//     }
386// }
387
388impl<T: CanonicalSerialize> CanonicalSerialize for Vec<T> {
389    #[inline]
390    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
391        self.as_slice().serialize_with_mode(&mut writer, compress)
392    }
393
394    #[inline]
395    fn serialized_size(&self, compress: Compress) -> usize {
396        self.as_slice().serialized_size(compress)
397    }
398}
399
400impl<T: Valid> Valid for Vec<T> {
401    #[inline]
402    fn check(&self) -> Result<(), SerializationError> {
403        T::batch_check(self.iter())
404    }
405
406    #[inline]
407    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
408    where
409        Self: 'a,
410    {
411        T::batch_check(batch.flatten())
412    }
413}
414
415impl<T: CanonicalDeserialize> CanonicalDeserialize for Vec<T> {
416    #[inline]
417    fn deserialize_with_mode<R: Read>(
418        mut reader: R,
419        compress: Compress,
420        validate: Validate,
421    ) -> Result<Self, SerializationError> {
422        let len = u64::deserialize_with_mode(&mut reader, compress, validate)?;
423        let mut values = Vec::new();
424        let _ = values.try_reserve(len as usize);
425        for _ in 0..len {
426            values.push(T::deserialize_with_mode(&mut reader, compress, Validate::No)?);
427        }
428
429        if let Validate::Yes = validate {
430            T::batch_check(values.iter())?
431        }
432        Ok(values)
433    }
434}
435
436impl<T: CanonicalDeserialize + std::fmt::Debug> CanonicalDeserialize for [T; 32] {
437    #[inline]
438    fn deserialize_with_mode<R: Read>(
439        mut reader: R,
440        compress: Compress,
441        validate: Validate,
442    ) -> Result<Self, SerializationError> {
443        let values = [(); 32].map(|_| T::deserialize_with_mode(&mut reader, compress, Validate::No));
444
445        // check that each value is error free
446        if values.iter().any(|value| value.is_err()) {
447            return Err(SerializationError::InvalidData);
448        }
449
450        let values = values.map(|r| r.unwrap());
451
452        if let Validate::Yes = validate {
453            T::batch_check(values.iter())?
454        }
455
456        Ok(values)
457    }
458}
459
460impl<T: Valid> Valid for [T; 32] {
461    #[inline]
462    fn check(&self) -> Result<(), SerializationError> {
463        T::batch_check(self.iter())
464    }
465
466    #[inline]
467    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self> + Send) -> Result<(), SerializationError>
468    where
469        Self: 'a,
470    {
471        T::batch_check(batch.flatten())
472    }
473}
474
475impl<T: CanonicalSerialize> CanonicalSerialize for [T] {
476    #[inline]
477    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
478        let len = self.len() as u64;
479        len.serialize_with_mode(&mut writer, compress)?;
480        for item in self.iter() {
481            item.serialize_with_mode(&mut writer, compress)?;
482        }
483        Ok(())
484    }
485
486    #[inline]
487    fn serialized_size(&self, compress: Compress) -> usize {
488        8 + self.iter().map(|item| item.serialized_size(compress)).sum::<usize>()
489    }
490}
491
492impl<T: CanonicalSerialize> CanonicalSerialize for [T; 32] {
493    #[inline]
494    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
495        for item in self.iter() {
496            item.serialize_with_mode(&mut writer, compress)?;
497        }
498        Ok(())
499    }
500
501    #[inline]
502    fn serialized_size(&self, compress: Compress) -> usize {
503        8 + self.iter().map(|item| item.serialized_size(compress)).sum::<usize>()
504    }
505}
506
507impl<T: CanonicalSerialize> CanonicalSerialize for &'_ [T] {
508    #[inline]
509    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
510        (*self).serialize_with_mode(&mut writer, compress)
511    }
512
513    #[inline]
514    fn serialized_size(&self, compress: Compress) -> usize {
515        (*self).serialized_size(compress)
516    }
517}
518
519// Implement Serialization for tuples
520macro_rules! impl_tuple {
521    ($( $ty: ident : $no: tt, )+) => {
522        impl<$($ty, )+> Valid for ($($ty,)+) where
523            $($ty: Valid,)+
524        {
525            #[inline]
526            fn check(&self) -> Result<(), SerializationError> {
527                $(self.$no.check()?;)*
528                Ok(())
529            }
530        }
531
532        impl<$($ty, )+> CanonicalSerialize for ($($ty,)+) where
533            $($ty: CanonicalSerialize,)+
534        {
535            #[inline]
536            fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
537                $(self.$no.serialize_with_mode(&mut writer, compress)?;)*
538                Ok(())
539            }
540
541            #[inline]
542            fn serialized_size(&self, compress: Compress) -> usize {
543                [$(
544                    self.$no.serialized_size(compress),
545                )*].iter().sum()
546            }
547        }
548
549        impl<$($ty, )+> CanonicalDeserialize for ($($ty,)+) where
550            $($ty: CanonicalDeserialize,)+
551        {
552            #[inline]
553            fn deserialize_with_mode<R: Read>(mut reader: R, compress: Compress, validate: Validate) -> Result<Self, SerializationError> {
554                Ok(($(
555                    $ty::deserialize_with_mode(&mut reader, compress, validate)?,
556                )+))
557            }
558        }
559    }
560}
561
562impl_tuple!(A:0, B:1,);
563impl_tuple!(A:0, B:1, C:2,);
564impl_tuple!(A:0, B:1, C:2, D:3,);
565
566impl<K, V> CanonicalSerialize for BTreeMap<K, V>
567where
568    K: CanonicalSerialize,
569    V: CanonicalSerialize,
570{
571    /// Serializes a `BTreeMap` as `len(map) || key 1 || value 1 || ... || key n || value n`.
572    fn serialize_with_mode<W: Write>(&self, mut writer: W, compress: Compress) -> Result<(), SerializationError> {
573        let len = self.len() as u64;
574        len.serialize_with_mode(&mut writer, compress)?;
575        for (k, v) in self.iter() {
576            k.serialize_with_mode(&mut writer, compress)?;
577            v.serialize_with_mode(&mut writer, compress)?;
578        }
579        Ok(())
580    }
581
582    fn serialized_size(&self, compress: Compress) -> usize {
583        8 + self.iter().map(|(k, v)| k.serialized_size(compress) + v.serialized_size(compress)).sum::<usize>()
584    }
585}
586
587impl<K: Valid, V: Valid> Valid for BTreeMap<K, V> {
588    #[inline]
589    fn check(&self) -> Result<(), SerializationError> {
590        K::batch_check(self.keys())?;
591        V::batch_check(self.values())
592    }
593
594    #[inline]
595    fn batch_check<'a>(batch: impl Iterator<Item = &'a Self>) -> Result<(), SerializationError>
596    where
597        Self: 'a,
598    {
599        let (keys, values): (Vec<_>, Vec<_>) = batch.map(|b| (b.keys(), b.values())).unzip();
600        K::batch_check(keys.into_iter().flatten())?;
601        V::batch_check(values.into_iter().flatten())
602    }
603}
604
605impl<K, V> CanonicalDeserialize for BTreeMap<K, V>
606where
607    K: Ord + CanonicalDeserialize,
608    V: CanonicalDeserialize,
609{
610    /// Deserializes a `BTreeMap` from `len(map) || key 1 || value 1 || ... || key n || value n`.
611    fn deserialize_with_mode<R: Read>(
612        mut reader: R,
613        compress: Compress,
614        validate: Validate,
615    ) -> Result<Self, SerializationError> {
616        let len = u64::deserialize_with_mode(&mut reader, compress, validate)?;
617        let mut map = BTreeMap::new();
618        for _ in 0..len {
619            map.insert(
620                K::deserialize_with_mode(&mut reader, compress, validate)?,
621                V::deserialize_with_mode(&mut reader, compress, validate)?,
622            );
623        }
624        Ok(map)
625    }
626}
627
628#[cfg(test)]
629mod test {
630    use super::*;
631    use crate::{deserialize_vec_without_len, serialize_vec_without_len, serialized_vec_size_without_len};
632
633    fn test_serialize<T: PartialEq + std::fmt::Debug + CanonicalSerialize + CanonicalDeserialize>(data: T) {
634        let combinations = [
635            (Compress::No, Validate::No),
636            (Compress::Yes, Validate::No),
637            (Compress::No, Validate::Yes),
638            (Compress::Yes, Validate::Yes),
639        ];
640        for (compress, validate) in combinations {
641            let mut serialized = vec![];
642            data.serialize_with_mode(&mut serialized, compress).unwrap();
643            let de = T::deserialize_with_mode(&serialized[..], compress, validate).unwrap();
644            assert_eq!(data, de);
645
646            assert_eq!(data.serialized_size(compress), serialized.len());
647        }
648    }
649
650    fn test_serialize_without_len<T: PartialEq + std::fmt::Debug + CanonicalSerialize + CanonicalDeserialize>(
651        data: Vec<T>,
652    ) {
653        let combinations = [
654            (Compress::No, Validate::No),
655            (Compress::Yes, Validate::No),
656            (Compress::No, Validate::Yes),
657            (Compress::Yes, Validate::Yes),
658        ];
659        for (compress, validate) in combinations {
660            let len = serialized_vec_size_without_len(&data, compress);
661            let mut serialized = vec![0; len];
662            serialize_vec_without_len(data.iter(), serialized.as_mut_slice(), compress).unwrap();
663            let elements = if len > 0 { len / CanonicalSerialize::serialized_size(&data[0], compress) } else { 0 };
664            let de = deserialize_vec_without_len(serialized.as_slice(), compress, validate, elements).unwrap();
665            assert_eq!(data, de);
666        }
667    }
668
669    #[test]
670    fn test_bool() {
671        test_serialize(true);
672        test_serialize(false);
673    }
674
675    #[test]
676    fn test_uint() {
677        test_serialize(192830918usize);
678        test_serialize(192830918u64);
679        test_serialize(192830918u32);
680        test_serialize(22313u16);
681        test_serialize(123u8);
682    }
683
684    #[test]
685    fn test_string() {
686        test_serialize("asdf".to_owned());
687    }
688
689    #[test]
690    fn test_vec() {
691        test_serialize(vec![1u64, 2, 3, 4, 5]);
692        test_serialize(Vec::<u64>::new());
693    }
694
695    #[test]
696    fn test_vec_without_len() {
697        test_serialize_without_len(vec![1u64, 2, 3, 4, 5]);
698        test_serialize_without_len(Vec::<u64>::new());
699    }
700
701    #[test]
702    fn test_tuple() {
703        test_serialize((123u64, 234u32, 999u16));
704    }
705
706    #[test]
707    fn test_tuple_vec() {
708        test_serialize(vec![(123u64, 234u32, 999u16), (123u64, 234u32, 999u16), (123u64, 234u32, 999u16)]);
709    }
710
711    #[test]
712    fn test_option() {
713        test_serialize(Some(3u32));
714        test_serialize(None::<u32>);
715    }
716
717    #[test]
718    fn test_phantomdata() {
719        test_serialize(std::marker::PhantomData::<u64>);
720    }
721}