fidl_next_codec/
decoder.rs1use core::mem::take;
8use core::ptr::NonNull;
9use core::slice;
10
11use crate::{CHUNK_SIZE, Chunk, Constrained, Decode, DecodeError, Decoded, Slot};
12
13pub trait InternalHandleDecoder {
15    #[doc(hidden)]
20    fn __internal_take_handles(&mut self, count: usize) -> Result<(), DecodeError>;
21
22    #[doc(hidden)]
27    fn __internal_handles_remaining(&self) -> usize;
28}
29
30pub unsafe trait Decoder: InternalHandleDecoder {
42    fn take_chunks_raw(&mut self, count: usize) -> Result<NonNull<Chunk>, DecodeError>;
46
47    fn commit(&mut self);
54
55    fn finish(&self) -> Result<(), DecodeError>;
57}
58
59impl InternalHandleDecoder for &mut [Chunk] {
60    #[inline]
61    fn __internal_take_handles(&mut self, _: usize) -> Result<(), DecodeError> {
62        Err(DecodeError::InsufficientHandles)
63    }
64
65    #[inline]
66    fn __internal_handles_remaining(&self) -> usize {
67        0
68    }
69}
70
71unsafe impl Decoder for &mut [Chunk] {
72    #[inline]
73    fn take_chunks_raw(&mut self, count: usize) -> Result<NonNull<Chunk>, DecodeError> {
74        if count > self.len() {
75            return Err(DecodeError::InsufficientData);
76        }
77
78        let chunks = take(self);
79        let (prefix, suffix) = unsafe { chunks.split_at_mut_unchecked(count) };
80        *self = suffix;
81        unsafe { Ok(NonNull::new_unchecked(prefix.as_mut_ptr())) }
82    }
83
84    #[inline]
85    fn commit(&mut self) {
86        }
88
89    #[inline]
90    fn finish(&self) -> Result<(), DecodeError> {
91        if !self.is_empty() {
92            return Err(DecodeError::ExtraBytes { num_extra: self.len() * CHUNK_SIZE });
93        }
94
95        Ok(())
96    }
97}
98
99pub trait DecoderExt {
101    fn take_chunks<'de>(
103        self: &mut &'de mut Self,
104        count: usize,
105    ) -> Result<&'de mut [Chunk], DecodeError>;
106
107    fn take_slot<'de, T>(self: &mut &'de mut Self) -> Result<Slot<'de, T>, DecodeError>;
109
110    fn take_slice_slot<'de, T>(
112        self: &mut &'de mut Self,
113        len: usize,
114    ) -> Result<Slot<'de, [T]>, DecodeError>;
115
116    fn decode_owned<'de, T: Decode<Self> + Constrained<Constraint = ()>>(
120        self: &mut &'de mut Self,
121    ) -> Result<T::Owned<'de>, DecodeError>;
122
123    fn decode<T>(self) -> Result<Decoded<T, Self>, DecodeError>
128    where
129        T: Decode<Self> + Constrained<Constraint = ()>,
130        Self: Sized;
131
132    fn decode_with_constraint<T>(
137        self,
138        constraint: <T as Constrained>::Constraint,
139    ) -> Result<Decoded<T, Self>, DecodeError>
140    where
141        T: Decode<Self>,
142        Self: Sized;
143}
144
145impl<D: Decoder + ?Sized> DecoderExt for D {
146    fn take_chunks<'de>(
147        self: &mut &'de mut Self,
148        count: usize,
149    ) -> Result<&'de mut [Chunk], DecodeError> {
150        self.take_chunks_raw(count).map(|p| unsafe { slice::from_raw_parts_mut(p.as_ptr(), count) })
151    }
152
153    fn take_slot<'de, T>(self: &mut &'de mut Self) -> Result<Slot<'de, T>, DecodeError> {
154        assert!(
157            align_of::<T>() <= CHUNK_SIZE,
158            "attempted to take a slot for a type with an alignment higher \
159             than {CHUNK_SIZE}",
160        );
161
162        let count = size_of::<T>().div_ceil(CHUNK_SIZE);
163        let chunks = self.take_chunks(count)?;
164        unsafe { Ok(Slot::new_unchecked(chunks.as_mut_ptr().cast())) }
167    }
168
169    fn take_slice_slot<'de, T>(
170        self: &mut &'de mut Self,
171        len: usize,
172    ) -> Result<Slot<'de, [T]>, DecodeError> {
173        assert!(
174            align_of::<T>() <= CHUNK_SIZE,
175            "attempted to take a slice slot for a type with an alignment \
176             higher than {CHUNK_SIZE}",
177        );
178
179        let slice_byte_length = size_of::<T>() * len;
180        let chunk_count = slice_byte_length.div_ceil(CHUNK_SIZE);
181        let chunk_length = CHUNK_SIZE * chunk_count;
182        let padding_length = chunk_length - slice_byte_length;
183        let chunks_ptr = self.take_chunks(chunk_count)?.as_mut_ptr();
184        let padding: &[u8] = unsafe {
185            core::slice::from_raw_parts(
186                chunks_ptr.cast::<u8>().add(slice_byte_length),
187                padding_length,
188            )
189        };
190        if padding.iter().any(|byte| *byte != 0) {
191            return Err(DecodeError::InvalidPadding);
192        }
193
194        unsafe { Ok(Slot::new_slice_unchecked(chunks_ptr.cast(), len)) }
197    }
198
199    fn decode_owned<'de, T: Decode<Self> + Constrained<Constraint = ()>>(
200        self: &mut &'de mut Self,
201    ) -> Result<T::Owned<'de>, DecodeError> {
202        let mut slot = self.take_slot::<T>()?;
203        T::decode(slot.as_mut(), self, ())?;
204        self.commit();
205        unsafe { Ok(slot.as_mut_ptr().cast::<T::Owned<'de>>().read()) }
208    }
209
210    fn decode<T>(self) -> Result<Decoded<T, Self>, DecodeError>
211    where
212        T: Decode<Self> + Constrained<Constraint = ()>,
213        Self: Sized,
214    {
215        self.decode_with_constraint(())
216    }
217
218    fn decode_with_constraint<T>(
219        mut self,
220        constraint: <T as Constrained>::Constraint,
221    ) -> Result<Decoded<T, Self>, DecodeError>
222    where
223        T: Decode<Self>,
224        Self: Sized,
225    {
226        let mut decoder = &mut self;
227        let mut slot = decoder.take_slot::<T>()?;
228        T::decode(slot.as_mut(), decoder, constraint)?;
229        decoder.commit();
230        decoder.finish()?;
231        unsafe { Ok(Decoded::new_unchecked(slot.as_mut_ptr(), self)) }
234    }
235}