1use core::marker::PhantomData;
8use core::mem::MaybeUninit;
9use core::slice::from_raw_parts;
10
11use crate::wire::Uint64;
12use crate::{CHUNK_SIZE, Chunk, Encode, EncodeError, Slot, Wire};
13
14pub trait InternalHandleEncoder {
16 #[doc(hidden)]
21 fn __internal_handle_count(&self) -> usize;
22}
23
24pub trait Encoder: InternalHandleEncoder {
26 fn bytes_written(&self) -> usize;
28
29 fn write_zeroes(&mut self, len: usize);
33
34 fn write(&mut self, bytes: &[u8]);
38
39 fn rewrite(&mut self, pos: usize, bytes: &[u8]);
41}
42
43impl InternalHandleEncoder for Vec<Chunk> {
44 #[inline]
45 fn __internal_handle_count(&self) -> usize {
46 0
47 }
48}
49
50impl Encoder for Vec<Chunk> {
51 #[inline]
52 fn bytes_written(&self) -> usize {
53 self.len() * CHUNK_SIZE
54 }
55
56 #[inline]
57 fn write_zeroes(&mut self, len: usize) {
58 let count = len.div_ceil(CHUNK_SIZE);
59 self.reserve(count);
60 let ptr = unsafe { self.as_mut_ptr().add(self.len()) };
63 unsafe {
66 ptr.write_bytes(0, count);
67 }
68 unsafe {
70 self.set_len(self.len() + count);
71 }
72 }
73
74 #[inline]
75 fn write(&mut self, bytes: &[u8]) {
76 if bytes.is_empty() {
77 return;
78 }
79
80 let count = bytes.len().div_ceil(CHUNK_SIZE);
81 self.reserve(count);
82
83 unsafe {
86 self.as_mut_ptr().add(self.len() + count - 1).write(Uint64(0));
87 }
88 let ptr = unsafe { self.as_mut_ptr().add(self.len()).cast::<u8>() };
90
91 unsafe {
95 ptr.copy_from_nonoverlapping(bytes.as_ptr(), bytes.len());
96 }
97
98 unsafe {
101 self.set_len(self.len() + count);
102 }
103 }
104
105 #[inline]
106 fn rewrite(&mut self, pos: usize, bytes: &[u8]) {
107 assert!(pos + bytes.len() <= self.bytes_written());
108
109 let ptr = unsafe { self.as_mut_ptr().cast::<u8>().add(pos) };
111 unsafe {
114 ptr.copy_from_nonoverlapping(bytes.as_ptr(), bytes.len());
115 }
116 }
117}
118
119pub trait EncoderExt {
121 fn preallocate<T>(&mut self, len: usize) -> Preallocated<'_, Self, T>;
123
124 fn encode_next_iter<W, T>(
128 &mut self,
129 values: impl ExactSizeIterator<Item = T>,
130 ) -> Result<(), EncodeError>
131 where
132 W: Wire<Constraint = ()>,
133 T: Encode<W, Self>;
134
135 fn encode_next_iter_with_constraint<W, T>(
139 &mut self,
140 values: impl ExactSizeIterator<Item = T>,
141 constraint: W::Constraint,
142 ) -> Result<(), EncodeError>
143 where
144 W: Wire,
145 T: Encode<W, Self>;
146
147 fn encode_next<W, T>(&mut self, value: T) -> Result<(), EncodeError>
151 where
152 W: Wire<Constraint = ()>,
153 T: Encode<W, Self>;
154
155 fn encode_next_with_constraint<W: Wire, T: Encode<W, Self>>(
159 &mut self,
160 value: T,
161 constraint: W::Constraint,
162 ) -> Result<(), EncodeError>;
163
164 fn encode<W, T>(value: T) -> Result<Self, EncodeError>
168 where
169 Self: Default,
170 W: Wire<Constraint = ()>,
171 T: Encode<W, Self>;
172
173 fn encode_with_constraint<W, T>(
177 value: T,
178 constraint: W::Constraint,
179 ) -> Result<Self, EncodeError>
180 where
181 Self: Default,
182 W: Wire,
183 T: Encode<W, Self>;
184}
185
186impl<E: Encoder + ?Sized> EncoderExt for E {
187 fn preallocate<T>(&mut self, len: usize) -> Preallocated<'_, Self, T> {
188 let pos = self.bytes_written();
189
190 self.write_zeroes(len * size_of::<T>());
192
193 Preallocated {
194 encoder: self,
195 pos,
196 #[cfg(debug_assertions)]
197 remaining: len,
198 _phantom: PhantomData,
199 }
200 }
201
202 fn encode_next_iter<W, T>(
203 &mut self,
204 values: impl ExactSizeIterator<Item = T>,
205 ) -> Result<(), EncodeError>
206 where
207 W: Wire<Constraint = ()>,
208 T: Encode<W, Self>,
209 {
210 self.encode_next_iter_with_constraint(values, ())
211 }
212
213 fn encode_next_iter_with_constraint<W, T>(
214 &mut self,
215 values: impl ExactSizeIterator<Item = T>,
216 constraint: W::Constraint,
217 ) -> Result<(), EncodeError>
218 where
219 W: Wire,
220 T: Encode<W, Self>,
221 {
222 let mut outputs = self.preallocate::<W>(values.len());
223
224 let mut out = MaybeUninit::<W>::uninit();
225 <W as Wire>::zero_padding(&mut out);
226 for value in values {
227 value.encode(outputs.encoder, &mut out, constraint)?;
228 W::validate(unsafe { Slot::new_unchecked_from_maybe_uninit(&mut out) }, constraint)
230 .map_err(EncodeError::Validation)?;
231 unsafe {
233 outputs.write_next(out.assume_init_ref());
234 }
235 }
236
237 Ok(())
238 }
239
240 fn encode_next<W, T>(&mut self, value: T) -> Result<(), EncodeError>
241 where
242 W: Wire<Constraint = ()>,
243 T: Encode<W, Self>,
244 {
245 self.encode_next_with_constraint(value, ())
246 }
247
248 fn encode_next_with_constraint<W, T>(
249 &mut self,
250 value: T,
251 constraint: W::Constraint,
252 ) -> Result<(), EncodeError>
253 where
254 W: Wire,
255 T: Encode<W, Self>,
256 {
257 self.encode_next_iter_with_constraint(core::iter::once(value), constraint)
258 }
259
260 fn encode<W, T>(value: T) -> Result<Self, EncodeError>
261 where
262 Self: Default,
263 W: Wire<Constraint = ()>,
264 T: Encode<W, Self>,
265 {
266 Self::encode_with_constraint(value, ())
267 }
268
269 fn encode_with_constraint<W, T>(
270 value: T,
271 constraint: W::Constraint,
272 ) -> Result<Self, EncodeError>
273 where
274 Self: Default,
275 W: Wire,
276 T: Encode<W, Self>,
277 {
278 let mut result = Self::default();
279 result.encode_next_with_constraint(value, constraint)?;
280 Ok(result)
281 }
282}
283
284pub struct Preallocated<'a, E: ?Sized, T> {
286 pub encoder: &'a mut E,
288 pos: usize,
289 #[cfg(debug_assertions)]
290 remaining: usize,
291 _phantom: PhantomData<T>,
292}
293
294impl<E: Encoder + ?Sized, T> Preallocated<'_, E, T> {
295 pub unsafe fn write_next(&mut self, value: &T) {
301 #[cfg(debug_assertions)]
302 {
303 assert!(self.remaining > 0, "attemped to write more slots than preallocated");
304 self.remaining -= 1;
305 }
306
307 let bytes_ptr = (value as *const T).cast::<u8>();
308 let bytes = unsafe { from_raw_parts(bytes_ptr, size_of::<T>()) };
311 self.encoder.rewrite(self.pos, bytes);
312 self.pos += size_of::<T>();
313 }
314}