1mod error;
8
9use core::mem::MaybeUninit;
10use core::ptr::copy_nonoverlapping;
11
12pub use self::error::EncodeError;
13
14use crate::{CopyOptimization, Wire};
15
16pub unsafe trait Encode<W: Wire, E: ?Sized>: Sized {
22 const COPY_OPTIMIZATION: CopyOptimization<Self, W> = CopyOptimization::disable();
27
28 fn encode(
30 self,
31 encoder: &mut E,
32 out: &mut MaybeUninit<W>,
33 constraint: W::Constraint,
34 ) -> Result<(), EncodeError>;
35}
36
37pub unsafe trait EncodeOption<W: Wire, E: ?Sized>: Sized {
43 fn encode_option(
45 this: Option<Self>,
46 encoder: &mut E,
47 out: &mut MaybeUninit<W>,
48 constraint: W::Constraint,
49 ) -> Result<(), EncodeError>;
50}
51
52unsafe impl<W, E, T> Encode<W, E> for Box<T>
54where
55 W: Wire,
56 E: ?Sized,
57 T: Encode<W, E>,
58{
59 fn encode(
60 self,
61 encoder: &mut E,
62 out: &mut MaybeUninit<W>,
63 constraint: W::Constraint,
64 ) -> Result<(), EncodeError> {
65 T::encode(*self, encoder, out, constraint)
66 }
67}
68
69unsafe impl<'a, W, E, T> Encode<W, E> for &'a Box<T>
71where
72 W: Wire,
73 E: ?Sized,
74 &'a T: Encode<W, E>,
75{
76 fn encode(
77 self,
78 encoder: &mut E,
79 out: &mut MaybeUninit<W>,
80 constraint: W::Constraint,
81 ) -> Result<(), EncodeError> {
82 <&'a T>::encode(self, encoder, out, constraint)
83 }
84}
85
86unsafe impl<W, E, T> EncodeOption<W, E> for Box<T>
88where
89 W: Wire,
90 E: ?Sized,
91 T: EncodeOption<W, E>,
92{
93 fn encode_option(
94 this: Option<Self>,
95 encoder: &mut E,
96 out: &mut MaybeUninit<W>,
97 constraint: W::Constraint,
98 ) -> Result<(), EncodeError> {
99 T::encode_option(this.map(|value| *value), encoder, out, constraint)
100 }
101}
102
103unsafe impl<'a, W, E, T> EncodeOption<W, E> for &'a Box<T>
105where
106 W: Wire,
107 E: ?Sized,
108 &'a T: EncodeOption<W, E>,
109{
110 fn encode_option(
111 this: Option<Self>,
112 encoder: &mut E,
113 out: &mut MaybeUninit<W>,
114 constraint: W::Constraint,
115 ) -> Result<(), EncodeError> {
116 <&'a T>::encode_option(this.map(|value| &**value), encoder, out, constraint)
117 }
118}
119
120fn encode_to_array<A, W, E, T, const N: usize>(
121 value: A,
122 encoder: &mut E,
123 out: &mut MaybeUninit<[W; N]>,
124 constraint: W::Constraint,
125) -> Result<(), EncodeError>
126where
127 A: AsRef<[T]> + IntoIterator,
128 A::Item: Encode<W, E>,
129 W: Wire,
130 E: ?Sized,
131 T: Encode<W, E>,
132{
133 if T::COPY_OPTIMIZATION.is_enabled() {
134 unsafe {
136 copy_nonoverlapping(value.as_ref().as_ptr().cast(), out.as_mut_ptr(), 1);
137 }
138 } else {
139 for (i, item) in value.into_iter().enumerate() {
140 let out_i = unsafe { &mut *out.as_mut_ptr().cast::<MaybeUninit<W>>().add(i) };
150 item.encode(encoder, out_i, constraint)?;
151 }
152 }
153 Ok(())
154}
155
156unsafe impl<W, E, T, const N: usize> Encode<[W; N], E> for [T; N]
158where
159 W: Wire,
160 E: ?Sized,
161 T: Encode<W, E>,
162{
163 const COPY_OPTIMIZATION: CopyOptimization<Self, [W; N]> = T::COPY_OPTIMIZATION.infer_array();
164
165 fn encode(
166 self,
167 encoder: &mut E,
168 out: &mut MaybeUninit<[W; N]>,
169 constraint: W::Constraint,
170 ) -> Result<(), EncodeError> {
171 encode_to_array(self, encoder, out, constraint)
172 }
173}
174
175unsafe impl<'a, W, E, T, const N: usize> Encode<[W; N], E> for &'a [T; N]
177where
178 W: Wire,
179 E: ?Sized,
180 T: Encode<W, E>,
181 &'a T: Encode<W, E>,
182{
183 fn encode(
184 self,
185 encoder: &mut E,
186 out: &mut MaybeUninit<[W; N]>,
187 constraint: W::Constraint,
188 ) -> Result<(), EncodeError> {
189 encode_to_array(self, encoder, out, constraint)
190 }
191}
192
193unsafe impl<W, E, T> Encode<W, E> for Option<T>
195where
196 W: Wire,
197 E: ?Sized,
198 T: EncodeOption<W, E>,
199{
200 fn encode(
201 self,
202 encoder: &mut E,
203 out: &mut MaybeUninit<W>,
204 constraint: W::Constraint,
205 ) -> Result<(), EncodeError> {
206 T::encode_option(self, encoder, out, constraint)
207 }
208}
209
210unsafe impl<'a, W, E, T> Encode<W, E> for &'a Option<T>
212where
213 W: Wire,
214 E: ?Sized,
215 Option<&'a T>: Encode<W, E>,
216{
217 fn encode(
218 self,
219 encoder: &mut E,
220 out: &mut MaybeUninit<W>,
221 constraint: W::Constraint,
222 ) -> Result<(), EncodeError> {
223 self.as_ref().encode(encoder, out, constraint)
224 }
225}