fidl_next_codec/
decoder.rs1use core::mem::take;
8use core::ptr::NonNull;
9use core::slice;
10
11use crate::{Chunk, Decode, DecodeError, Decoded, Slot, CHUNK_SIZE};
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>>(
120 self: &mut &'de mut Self,
121 ) -> Result<T::Decoded<'de>, DecodeError>;
122
123 fn decode<T>(self) -> Result<Decoded<T, Self>, DecodeError>
128 where
129 T: Decode<Self>,
130 Self: Sized;
131}
132
133impl<D: Decoder + ?Sized> DecoderExt for D {
134 fn take_chunks<'de>(
135 self: &mut &'de mut Self,
136 count: usize,
137 ) -> Result<&'de mut [Chunk], DecodeError> {
138 self.take_chunks_raw(count).map(|p| unsafe { slice::from_raw_parts_mut(p.as_ptr(), count) })
139 }
140
141 fn take_slot<'de, T>(self: &mut &'de mut Self) -> Result<Slot<'de, T>, DecodeError> {
142 assert!(
145 align_of::<T>() <= CHUNK_SIZE,
146 "attempted to take a slot for a type with an alignment higher \
147 than {CHUNK_SIZE}",
148 );
149
150 let count = size_of::<T>().div_ceil(CHUNK_SIZE);
151 let chunks = self.take_chunks(count)?;
152 unsafe { Ok(Slot::new_unchecked(chunks.as_mut_ptr().cast())) }
155 }
156
157 fn take_slice_slot<'de, T>(
158 self: &mut &'de mut Self,
159 len: usize,
160 ) -> Result<Slot<'de, [T]>, DecodeError> {
161 assert!(
162 align_of::<T>() <= CHUNK_SIZE,
163 "attempted to take a slice slot for a type with an alignment \
164 higher than {CHUNK_SIZE}",
165 );
166
167 let count = (size_of::<T>() * len).div_ceil(CHUNK_SIZE);
168 let chunks = self.take_chunks(count)?;
169 unsafe { Ok(Slot::new_slice_unchecked(chunks.as_mut_ptr().cast(), len)) }
172 }
173
174 fn decode_owned<'de, T: Decode<Self>>(
175 self: &mut &'de mut Self,
176 ) -> Result<T::Decoded<'de>, DecodeError> {
177 let mut slot = self.take_slot::<T>()?;
178 T::decode(slot.as_mut(), self)?;
179 self.commit();
180 unsafe { Ok(slot.as_mut_ptr().cast::<T::Decoded<'de>>().read()) }
183 }
184
185 fn decode<T>(mut self) -> Result<Decoded<T, Self>, DecodeError>
186 where
187 T: Decode<Self>,
188 Self: Sized,
189 {
190 let mut decoder = &mut self;
191 let mut slot = decoder.take_slot::<T>()?;
192 T::decode(slot.as_mut(), decoder)?;
193 decoder.commit();
194 unsafe { Ok(Decoded::new_unchecked(slot.as_mut_ptr(), self)) }
197 }
198}