fidl_next_codec/decode/
mod.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Provides decoding for FIDL types.
6
7mod error;
8
9pub use self::error::*;
10
11use crate::{Slot, WireF32, WireF64, WireI16, WireI32, WireI64, WireU16, WireU32, WireU64};
12
13/// Decodes a value from the given slot.
14///
15/// # Safety
16///
17/// If `decode` returns `Ok`, then the provided `slot` must now contain a valid
18/// value of the implementing type.
19pub unsafe trait Decode<D: ?Sized> {
20    /// Decodes a value into a slot using a decoder.
21    ///
22    /// If decoding succeeds, `slot` will contain a valid value. If decoding fails, an error will be
23    /// returned.
24    fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError>;
25}
26
27macro_rules! impl_primitive {
28    ($ty:ty) => {
29        unsafe impl<D: ?Sized> Decode<D> for $ty {
30            #[inline]
31            fn decode(_: Slot<'_, Self>, _: &mut D) -> Result<(), DecodeError> {
32                Ok(())
33            }
34        }
35    };
36}
37
38macro_rules! impl_primitives {
39    ($($ty:ty),* $(,)?) => {
40        $(
41            impl_primitive!($ty);
42        )*
43    }
44}
45
46impl_primitives! {
47    i8,
48    WireI16,
49    WireI32,
50    WireI64,
51
52    u8,
53    WireU16,
54    WireU32,
55    WireU64,
56
57    WireF32,
58    WireF64,
59}
60
61unsafe impl<D: ?Sized> Decode<D> for bool {
62    #[inline]
63    fn decode(slot: Slot<'_, Self>, _: &mut D) -> Result<(), DecodeError> {
64        let value = unsafe { slot.as_ptr().cast::<u8>().read() };
65        match value {
66            0 | 1 => (),
67            invalid => return Err(DecodeError::InvalidBool(invalid)),
68        }
69        Ok(())
70    }
71}
72
73unsafe impl<D: ?Sized, T: Decode<D>, const N: usize> Decode<D> for [T; N] {
74    fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
75        for i in 0..N {
76            T::decode(slot.index(i), decoder)?;
77        }
78        Ok(())
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use crate::{chunks, WireF32, WireF64, WireI16, WireI32, WireI64, WireU16, WireU32, WireU64};
85
86    use crate::testing::assert_decoded;
87    use crate::wire::{WireBox, WireString, WireVector};
88    use crate::{WireOptionalString, WireOptionalVector};
89
90    #[test]
91    fn decode_bool() {
92        assert_decoded::<bool>(&mut chunks![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], |x| {
93            assert!(*x)
94        });
95        assert_decoded::<bool>(&mut chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], |x| {
96            assert!(!*x)
97        });
98    }
99
100    #[test]
101    fn decode_ints() {
102        assert_decoded::<u8>(&mut chunks![0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], |x| {
103            assert_eq!(*x, 0xa3u8)
104        });
105        assert_decoded::<i8>(&mut chunks![0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], |x| {
106            assert_eq!(*x, -0x45i8)
107        });
108
109        assert_decoded::<WireU16>(
110            &mut chunks![0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
111            |x| assert_eq!(*x, 0x1234u16),
112        );
113        assert_decoded::<WireI16>(
114            &mut chunks![0xcc, 0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
115            |x| assert_eq!(*x, -0x1234i16),
116        );
117
118        assert_decoded::<WireU32>(
119            &mut chunks![0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00],
120            |x| assert_eq!(*x, 0x12345678u32),
121        );
122        assert_decoded::<WireI32>(
123            &mut chunks![0x88, 0xa9, 0xcb, 0xed, 0x00, 0x00, 0x00, 0x00],
124            |x| assert_eq!(*x, -0x12345678i32),
125        );
126
127        assert_decoded::<WireU64>(
128            &mut chunks![0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12],
129            |x| assert_eq!(*x, 0x123456789abcdef0u64),
130        );
131        assert_decoded::<WireI64>(
132            &mut chunks![0x10, 0x21, 0x43, 0x65, 0x87, 0xa9, 0xcb, 0xed],
133            |x| assert_eq!(*x, -0x123456789abcdef0i64),
134        );
135    }
136
137    #[test]
138    fn decode_floats() {
139        assert_decoded::<WireF32>(
140            &mut chunks![0xdb, 0x0f, 0x49, 0x40, 0x00, 0x00, 0x00, 0x00],
141            |x| assert_eq!(*x, ::core::f32::consts::PI),
142        );
143        assert_decoded::<WireF64>(
144            &mut chunks![0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40],
145            |x| assert_eq!(*x, ::core::f64::consts::PI),
146        );
147    }
148
149    #[test]
150    fn decode_box() {
151        assert_decoded::<WireBox<WireU64>>(
152            &mut chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
153            |x| assert_eq!(x.as_ref(), None),
154        );
155        assert_decoded::<WireBox<WireU64>>(
156            &mut chunks![
157                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
158                0x34, 0x12,
159            ],
160            |x| assert_eq!(*x.as_ref().unwrap(), 0x123456789abcdef0u64),
161        );
162    }
163
164    #[test]
165    fn decode_vec() {
166        assert_decoded::<WireOptionalVector<WireU32>>(
167            &mut chunks![
168                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169                0x00, 0x00,
170            ],
171            |x| assert!(x.as_ref().is_none()),
172        );
173        assert_decoded::<WireVector<WireU32>>(
174            &mut chunks![
175                0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
176                0xff, 0xff, 0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a,
177            ],
178            |x| assert_eq!(x.as_slice(), [0x12345678, 0x9abcdef0].as_slice(),),
179        );
180        assert_decoded::<WireVector<WireU32>>(
181            &mut chunks![
182                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
183                0xff, 0xff,
184            ],
185            |x| assert_eq!(x.len(), 0),
186        );
187    }
188
189    #[test]
190    fn decode_string() {
191        assert_decoded::<WireOptionalString>(
192            &mut chunks![
193                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194                0x00, 0x00,
195            ],
196            |x| assert!(x.is_none()),
197        );
198        assert_decoded::<WireString>(
199            &mut chunks![
200                0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
201                0xff, 0xff, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00,
202            ],
203            |x| assert_eq!(x.as_str(), "0123"),
204        );
205        assert_decoded::<WireString>(
206            &mut chunks![
207                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
208                0xff, 0xff,
209            ],
210            |x| assert_eq!(x.len(), 0),
211        );
212    }
213}