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}