bitcode/derive/
mod.rs

1use crate::coder::{Buffer, Decoder, Encoder, View};
2use crate::consume::expect_eof;
3use crate::Error;
4use alloc::vec::Vec;
5use core::num::NonZeroUsize;
6
7mod array;
8mod atomic;
9pub(crate) mod convert;
10mod duration;
11mod empty;
12mod impls;
13// TODO: When ip_in_core has been stable (https://github.com/rust-lang/rust/issues/108443)
14// for long enough, remove feature check.
15#[cfg(feature = "std")]
16mod ip_addr;
17mod map;
18mod option;
19mod result;
20mod smart_ptr;
21mod variant;
22pub(crate) mod vec;
23
24// For derive macro.
25#[cfg(feature = "derive")]
26#[doc(hidden)]
27pub mod __private {
28    extern crate alloc;
29    pub use crate::coder::{uninit_field, Buffer, Decoder, Encoder, Result, View};
30    pub use crate::derive::variant::{VariantDecoder, VariantEncoder};
31    pub use crate::derive::{Decode, Encode};
32    pub fn invalid_enum_variant<T>() -> Result<T> {
33        crate::error::err("invalid enum variant")
34    }
35    pub use alloc::vec::Vec;
36}
37
38/// A type which can be encoded to bytes with [`encode`].
39///
40/// Use `#[derive(Encode)]` to implement.
41pub trait Encode {
42    #[doc(hidden)]
43    type Encoder: Encoder<Self>;
44}
45
46/// A type which can be decoded from bytes with [`decode`].
47///
48/// Use `#[derive(Decode)]` to implement.
49pub trait Decode<'a>: Sized {
50    #[doc(hidden)]
51    type Decoder: Decoder<'a, Self>;
52}
53
54/// A type which can be decoded without borrowing any bytes from the input.
55///
56/// This type is a shorter version of `for<'de> Decode<'de>`.
57pub trait DecodeOwned: for<'de> Decode<'de> {}
58impl<T> DecodeOwned for T where T: for<'de> Decode<'de> {}
59
60// Stop #[inline(always)] of Encoder::encode/Decoder::decode since 90% of the time is spent in these
61// functions, and we don't want extra code interfering with optimizations.
62#[inline(never)]
63fn encode_inline_never<T: Encode + ?Sized>(encoder: &mut T::Encoder, t: &T) {
64    encoder.encode(t);
65}
66#[inline(never)]
67fn decode_inline_never<'a, T: Decode<'a>>(decoder: &mut T::Decoder) -> T {
68    decoder.decode()
69}
70
71/// Encodes a `T:` [`Encode`] into a [`Vec<u8>`].
72///
73/// **Warning:** The format is subject to change between major versions.
74pub fn encode<T: Encode + ?Sized>(t: &T) -> Vec<u8> {
75    let mut encoder = T::Encoder::default();
76    encoder.reserve(NonZeroUsize::new(1).unwrap());
77    encode_inline_never(&mut encoder, t);
78    encoder.collect()
79}
80
81/// Decodes a [`&[u8]`][`prim@slice`] into an instance of `T:` [`Decode`].
82///
83/// **Warning:** The format is subject to change between major versions.
84pub fn decode<'a, T: Decode<'a>>(mut bytes: &'a [u8]) -> Result<T, Error> {
85    let mut decoder = T::Decoder::default();
86    decoder.populate(&mut bytes, 1)?;
87    expect_eof(bytes)?;
88    Ok(decode_inline_never(&mut decoder))
89}
90
91impl crate::buffer::Buffer {
92    /// Like [`encode`], but saves allocations between calls.
93    pub fn encode<'a, T: Encode + ?Sized>(&'a mut self, t: &T) -> &'a [u8] {
94        // Safety: Encoders don't have any lifetimes (they don't contain T either).
95        let encoder = unsafe { self.registry.get_non_static::<T::Encoder>() };
96        encoder.reserve(NonZeroUsize::new(1).unwrap());
97        encode_inline_never(encoder, t);
98        self.out.clear();
99        encoder.collect_into(&mut self.out);
100        self.out.as_slice()
101    }
102
103    /// Like [`decode`], but saves allocations between calls.
104    pub fn decode<'a, T: Decode<'a>>(&mut self, mut bytes: &'a [u8]) -> Result<T, Error> {
105        // Safety: Decoders have dangling pointers to `bytes` from previous calls which haven't been
106        // cleared. This isn't an issue in practice because they remain as pointers in FastSlice and
107        // aren't dereferenced. If we wanted to be safer we could clear all the decoders but this
108        // would result in lots of extra code to maintain and a performance/binary size hit.
109        // To detect misuse we run miri tests/cargo fuzz where bytes goes out of scope between calls.
110        let decoder = unsafe { self.registry.get_non_static::<T::Decoder>() };
111        decoder.populate(&mut bytes, 1)?;
112        expect_eof(bytes)?;
113        Ok(decode_inline_never(decoder))
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    use crate::{Decode, Encode};
120    use alloc::vec::Vec;
121
122    #[test]
123    fn decode() {
124        macro_rules! test {
125            ($v:expr, $t:ty) => {
126                let v = $v;
127                let encoded = super::encode::<$t>(&v);
128                #[cfg(feature = "std")]
129                println!("{:<24} {encoded:?}", stringify!($t));
130                assert_eq!(v, super::decode::<$t>(&encoded).unwrap());
131            };
132        }
133
134        test!(("abc", "123"), (&str, &str));
135        test!(Vec::<Option<i16>>::new(), Vec<Option<i16>>);
136        test!(vec![None, Some(1), None], Vec<Option<i16>>);
137        test!((0, 1), (usize, isize));
138        test!(vec![true; 255], Vec<bool>);
139        test!([0, 1], [u8; 2]);
140        test!([0, 1, 2], [u8; 3]);
141        test!([0, -1, 0, -1, 0, -1, 0], [i8; 7]);
142        test!([], [u8; 0]);
143    }
144
145    #[derive(Encode, Decode)]
146    enum Never {}
147
148    #[derive(Encode, Decode)]
149    enum One {
150        A(u8),
151    }
152
153    // cargo expand --lib --tests | grep -A15 Two
154    #[derive(Encode, Decode)]
155    enum Two {
156        A(u8),
157        B(i8),
158    }
159
160    #[derive(Encode, Decode)]
161    struct TupleStruct(u8, i8);
162
163    #[derive(Encode, Decode)]
164    struct Generic<T>(T);
165
166    #[derive(Encode, Decode)]
167    struct GenericManual<T>(#[bitcode(bound_type = "T")] T);
168
169    #[derive(Encode, Decode)]
170    struct GenericWhere<A, B>(A, B)
171    where
172        A: From<B>;
173
174    #[derive(Encode, Decode)]
175    struct Lifetime<'a>(&'a str);
176
177    #[derive(Encode, Decode)]
178    struct LifetimeWhere<'a, 'b>(&'a str, &'b str)
179    where
180        'a: 'b;
181
182    #[derive(Encode, Decode)]
183    struct ConstGeneric<const N: usize>([u8; N]);
184
185    #[derive(Encode, Decode)]
186    struct Empty;
187
188    #[derive(Encode, Decode)]
189    struct AssociatedConst([u8; Self::N]);
190    impl AssociatedConst {
191        const N: usize = 1;
192    }
193
194    #[derive(Encode, Decode)]
195    struct AssociatedConstTrait([u8; <Self as Trait>::N]);
196    trait Trait {
197        const N: usize;
198    }
199    impl Trait for AssociatedConstTrait {
200        const N: usize = 1;
201    }
202
203    #[test]
204    fn skipped_fields() {
205        macro_rules! test_skip {
206            ($a:expr, $b:expr, $t:ty) => {
207                let v = $a;
208                let encoded = super::encode::<$t>(&v);
209                #[cfg(feature = "std")]
210                println!("{:<24} {encoded:?}", stringify!($t));
211                assert_eq!($b, super::decode::<$t>(&encoded).unwrap());
212            };
213        }
214
215        #[derive(Encode, Decode, Debug, PartialEq)]
216        struct LifetimeSkipped<'a>(#[bitcode(skip)] &'a str);
217
218        let skipped_string = alloc::string::String::from("I'm skipped!");
219        let lifetime = LifetimeSkipped(&skipped_string);
220        test_skip!(lifetime, LifetimeSkipped(""), LifetimeSkipped);
221
222        #[derive(Encode, Decode, Debug, PartialEq)]
223        struct SkipStruct {
224            pub a: u32,
225            #[bitcode(skip)]
226            pub b: u32,
227        }
228
229        #[derive(Encode, Decode, Debug, PartialEq)]
230        struct SkipTuple(bool, #[bitcode(skip)] u32, u8, #[bitcode(skip)] u8, i32);
231
232        #[derive(Encode, Decode, Debug, PartialEq)]
233        enum SkipEnumTuple {
234            A(u8, u32),
235            B(bool, #[bitcode(skip)] u32, u8, #[bitcode(skip)] u8, i32),
236        }
237
238        #[derive(Default, Debug, PartialEq)]
239        struct Skipped(u32);
240
241        #[derive(Encode, Decode, Debug, PartialEq)]
242        enum SkipEnumStruct {
243            A {
244                a: u8,
245                #[bitcode(skip)]
246                b: Skipped,
247                c: u8,
248                #[bitcode(skip)]
249                d: u8,
250                e: u8,
251            },
252            B,
253        }
254
255        #[derive(Encode, Decode, Debug, PartialEq)]
256        struct SkipGeneric<A, B> {
257            present: A,
258            #[bitcode(skip)]
259            skipped: B,
260        }
261
262        #[derive(Encode, Decode, Debug, PartialEq)]
263        struct PartialSkipGeneric<A, B> {
264            present: A,
265            also_present: B,
266            #[bitcode(skip)]
267            skipped: B,
268        }
269
270        #[derive(Encode, Decode, Debug, PartialEq)]
271        struct SkipAll {
272            #[bitcode(skip)]
273            skipped: u8,
274        }
275
276        #[derive(Encode, Decode, Debug, PartialEq)]
277        struct SkipAllGeneric<A> {
278            #[bitcode(skip)]
279            skipped: A,
280        }
281
282        #[derive(Default, Debug, PartialEq)]
283        struct Indirect<A> {
284            field: A,
285        }
286
287        #[derive(Encode, Decode, Debug, PartialEq)]
288        struct SkipIndirectGeneric<A> {
289            #[bitcode(skip)]
290            skipped: Indirect<A>,
291        }
292
293        test_skip!(
294            SkipStruct { a: 231, b: 9696 },
295            SkipStruct { a: 231, b: 0 },
296            SkipStruct
297        );
298        test_skip!(
299            SkipTuple(true, 23, 231, 42, -13),
300            SkipTuple(true, 0, 231, 0, -13),
301            SkipTuple
302        );
303        test_skip!(
304            SkipEnumTuple::B(true, 23, 231, 42, -42),
305            SkipEnumTuple::B(true, 0, 231, 0, -42),
306            SkipEnumTuple
307        );
308        test_skip!(
309            SkipEnumStruct::A {
310                a: 1,
311                b: Skipped(2),
312                c: 3,
313                d: 4,
314                e: 5
315            },
316            SkipEnumStruct::A {
317                a: 1,
318                b: Skipped(0),
319                c: 3,
320                d: 0,
321                e: 5
322            },
323            SkipEnumStruct
324        );
325        test_skip! {
326            SkipAll {
327                skipped: 42u8,
328            },
329            SkipAll {
330                skipped: 0u8,
331            },
332            SkipAll
333        }
334        assert_eq!(bitcode::encode(&SkipAll { skipped: 42u8 }).len(), 0);
335        test_skip!(
336            SkipGeneric {
337                present: 42u8,
338                skipped: Skipped(231),
339            },
340            SkipGeneric {
341                present: 42u8,
342                skipped: Skipped(0),
343            },
344            SkipGeneric<u8, Skipped>
345        );
346        test_skip!(
347            PartialSkipGeneric {
348                present: 42u8,
349                also_present: 231i32,
350                skipped: 77i32,
351            },
352            PartialSkipGeneric {
353                present: 42u8,
354                also_present: 231i32,
355                skipped: 0i32,
356            },
357            PartialSkipGeneric<u8, i32>
358        );
359        test_skip! {
360            SkipAllGeneric {
361                skipped: 42i32,
362            },
363            SkipAllGeneric {
364                skipped: 0i32,
365            },
366            SkipAllGeneric<i32>
367        }
368        test_skip! {
369            SkipIndirectGeneric {
370                skipped: Indirect{ field: 42i32 },
371            },
372            SkipIndirectGeneric {
373                skipped: Indirect{ field: 0i32 },
374            },
375            SkipIndirectGeneric<i32>
376        }
377        assert_eq!(bitcode::encode(&SkipAllGeneric { skipped: 42u8 }).len(), 0);
378    }
379
380    #[test]
381    fn skipped_fields_regression() {
382        #[derive(Encode, Decode, Default, Debug, PartialEq)]
383        pub struct Indirect<A>(A);
384        #[derive(Encode, Decode, Debug, PartialEq)]
385        struct SkipGeneric<A> {
386            #[bitcode(bound_type = "Indirect<A>")]
387            present: Indirect<A>,
388        }
389    }
390}