Skip to main content

agglayer_bincode/
lib.rs

1pub use bincode::{Error, ErrorKind, Options, Result};
2
3/// Bincode configuration. Deliberately inaccessible from the outside.
4mod options {
5    use bincode::config::{
6        AllowTrailing, BigEndian, Bounded, DefaultOptions as BincodeDefaultOptions, FixintEncoding,
7        Options as _, WithOtherEndian, WithOtherIntEncoding, WithOtherLimit, WithOtherTrailing,
8    };
9
10    pub type Default =
11        WithOtherIntEncoding<WithOtherEndian<BincodeDefaultOptions, BigEndian>, FixintEncoding>;
12
13    #[inline]
14    pub fn default() -> Default {
15        bincode::options().with_big_endian().with_fixint_encoding()
16    }
17
18    pub type SP1Compatible = WithOtherTrailing<
19        WithOtherIntEncoding<BincodeDefaultOptions, FixintEncoding>,
20        AllowTrailing,
21    >;
22
23    #[inline]
24    pub fn sp1_compatible() -> SP1Compatible {
25        bincode::options()
26            .with_fixint_encoding()
27            .allow_trailing_bytes()
28    }
29
30    pub type Limited<T> = WithOtherLimit<T, Bounded>;
31}
32
33/// Bincode codec with opinionated settings.
34#[derive(Clone, Debug)]
35pub struct Codec<Opts>(Opts);
36
37/// Create a bincode codec with default agglayer settings.
38#[inline]
39pub fn default() -> Codec<options::Default> {
40    Codec(options::default())
41}
42
43/// Create a bincode codec with settings compatible with SP1 payload encoding.
44#[inline]
45pub fn sp1_compatible() -> Codec<options::SP1Compatible> {
46    Codec(options::sp1_compatible())
47}
48
49/// Create a bincode codec with settings used by `sp1`.
50#[deprecated(note = "use sp1_compatible()")]
51#[inline]
52pub fn sp1v4() -> Codec<options::SP1Compatible> {
53    sp1_compatible()
54}
55
56/// Create a bincode coded with settings used by smart contract verifiers.
57///
58/// This happens to be the same as [default] but with a more accurate name.
59#[inline]
60pub fn contracts() -> Codec<options::Default> {
61    default()
62}
63
64impl<Opts: Options> Codec<Opts> {
65    /// Impose a limit on encoding / decoding size.
66    #[inline]
67    pub fn with_limit(self, max: u64) -> Codec<options::Limited<Opts>> {
68        Codec(self.0.with_limit(max))
69    }
70
71    /// Encode an object into a byte vector.
72    #[inline]
73    pub fn serialize<T>(self, item: &T) -> Result<Vec<u8>>
74    where
75        T: ?Sized + serde::Serialize,
76    {
77        self.0.serialize(item)
78    }
79
80    /// Encode an object into a writer.
81    #[inline]
82    pub fn serialize_into<W, T>(self, writer: W, item: &T) -> Result<()>
83    where
84        W: std::io::Write,
85        T: ?Sized + serde::Serialize,
86    {
87        self.0.serialize_into(writer, item)
88    }
89
90    /// Decode an object from a slice.
91    #[inline]
92    pub fn deserialize<'a, T>(self, bytes: &'a [u8]) -> Result<T>
93    where
94        T: serde::Deserialize<'a>,
95    {
96        self.0.deserialize(bytes)
97    }
98
99    /// Decode an object from a reader.
100    #[inline]
101    pub fn deserialize_from<T, R>(self, reader: R) -> Result<T>
102    where
103        T: serde::de::DeserializeOwned,
104        R: std::io::Read,
105    {
106        self.0.deserialize_from(reader)
107    }
108}
109
110#[cfg(test)]
111mod test {
112    #[test]
113    fn sp1_endians() {
114        type NetworkId = u32;
115
116        let network_id: NetworkId = 0x00112233;
117        let network_id_enc = super::sp1_compatible().serialize(&network_id).unwrap();
118
119        let mut stdin0 = sp1_sdk::SP1Stdin::new();
120        stdin0.write_slice(&network_id_enc);
121
122        let mut stdin1 = sp1_sdk::SP1Stdin::new();
123        stdin1.write(&network_id);
124
125        assert_eq!(&stdin1.buffer[0], &[0x33, 0x22, 0x11, 0x00]);
126        assert_eq!(stdin0.buffer, stdin1.buffer);
127        assert_eq!(stdin0.read::<NetworkId>(), stdin1.read::<NetworkId>());
128    }
129
130    #[test]
131    fn sp1_compatible_round_trips_network_id() {
132        type NetworkId = u32;
133
134        let bytes = vec![0x33, 0x22, 0x11, 0x00];
135
136        let decoded: NetworkId = super::sp1_compatible().deserialize(&bytes).unwrap();
137
138        assert_eq!(decoded, 0x00112233);
139    }
140}