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>
53where
54 W: Wire,
55 E: ?Sized,
56 T: Encode<W, E>,
57{
58 fn encode(
59 self,
60 encoder: &mut E,
61 out: &mut MaybeUninit<W>,
62 constraint: W::Constraint,
63 ) -> Result<(), EncodeError> {
64 T::encode(*self, encoder, out, constraint)
65 }
66}
67
68unsafe impl<'a, W, E, T> Encode<W, E> for &'a Box<T>
69where
70 W: Wire,
71 E: ?Sized,
72 &'a T: Encode<W, E>,
73{
74 fn encode(
75 self,
76 encoder: &mut E,
77 out: &mut MaybeUninit<W>,
78 constraint: W::Constraint,
79 ) -> Result<(), EncodeError> {
80 <&'a T>::encode(self, encoder, out, constraint)
81 }
82}
83
84unsafe impl<W, E, T> EncodeOption<W, E> for Box<T>
85where
86 W: Wire,
87 E: ?Sized,
88 T: EncodeOption<W, E>,
89{
90 fn encode_option(
91 this: Option<Self>,
92 encoder: &mut E,
93 out: &mut MaybeUninit<W>,
94 constraint: W::Constraint,
95 ) -> Result<(), EncodeError> {
96 T::encode_option(this.map(|value| *value), encoder, out, constraint)
97 }
98}
99
100unsafe impl<'a, W, E, T> EncodeOption<W, E> for &'a Box<T>
101where
102 W: Wire,
103 E: ?Sized,
104 &'a T: EncodeOption<W, E>,
105{
106 fn encode_option(
107 this: Option<Self>,
108 encoder: &mut E,
109 out: &mut MaybeUninit<W>,
110 constraint: W::Constraint,
111 ) -> Result<(), EncodeError> {
112 <&'a T>::encode_option(this.map(|value| &**value), encoder, out, constraint)
113 }
114}
115
116fn encode_to_array<A, W, E, T, const N: usize>(
117 value: A,
118 encoder: &mut E,
119 out: &mut MaybeUninit<[W; N]>,
120 constraint: W::Constraint,
121) -> Result<(), EncodeError>
122where
123 A: AsRef<[T]> + IntoIterator,
124 A::Item: Encode<W, E>,
125 W: Wire,
126 E: ?Sized,
127 T: Encode<W, E>,
128{
129 if T::COPY_OPTIMIZATION.is_enabled() {
130 unsafe {
132 copy_nonoverlapping(value.as_ref().as_ptr().cast(), out.as_mut_ptr(), 1);
133 }
134 } else {
135 for (i, item) in value.into_iter().enumerate() {
136 let out_i = unsafe { &mut *out.as_mut_ptr().cast::<MaybeUninit<W>>().add(i) };
146 item.encode(encoder, out_i, constraint)?;
147 }
148 }
149 Ok(())
150}
151
152unsafe impl<W, E, T, const N: usize> Encode<[W; N], E> for [T; N]
153where
154 W: Wire,
155 E: ?Sized,
156 T: Encode<W, E>,
157{
158 const COPY_OPTIMIZATION: CopyOptimization<Self, [W; N]> = T::COPY_OPTIMIZATION.infer_array();
159
160 fn encode(
161 self,
162 encoder: &mut E,
163 out: &mut MaybeUninit<[W; N]>,
164 constraint: W::Constraint,
165 ) -> Result<(), EncodeError> {
166 encode_to_array(self, encoder, out, constraint)
167 }
168}
169
170unsafe impl<'a, W, E, T, const N: usize> Encode<[W; N], E> for &'a [T; N]
171where
172 W: Wire,
173 E: ?Sized,
174 T: Encode<W, E>,
175 &'a T: Encode<W, E>,
176{
177 fn encode(
178 self,
179 encoder: &mut E,
180 out: &mut MaybeUninit<[W; N]>,
181 constraint: W::Constraint,
182 ) -> Result<(), EncodeError> {
183 encode_to_array(self, encoder, out, constraint)
184 }
185}
186
187unsafe impl<W, E, T> Encode<W, E> for Option<T>
188where
189 W: Wire,
190 E: ?Sized,
191 T: EncodeOption<W, E>,
192{
193 fn encode(
194 self,
195 encoder: &mut E,
196 out: &mut MaybeUninit<W>,
197 constraint: W::Constraint,
198 ) -> Result<(), EncodeError> {
199 T::encode_option(self, encoder, out, constraint)
200 }
201}
202
203unsafe impl<'a, W, E, T> Encode<W, E> for &'a Option<T>
204where
205 W: Wire,
206 E: ?Sized,
207 Option<&'a T>: Encode<W, E>,
208{
209 fn encode(
210 self,
211 encoder: &mut E,
212 out: &mut MaybeUninit<W>,
213 constraint: W::Constraint,
214 ) -> Result<(), EncodeError> {
215 self.as_ref().encode(encoder, out, constraint)
216 }
217}