1use core::mem::{MaybeUninit, needs_drop};
6use core::{fmt, slice};
7
8use munge::munge;
9
10use super::raw::RawWireVector;
11use crate::{
12 Constrained, Decode, DecodeError, Decoder, DecoderExt as _, Encode, EncodeError, EncodeOption,
13 Encoder, EncoderExt as _, FromWire, FromWireOption, FromWireOptionRef, FromWireRef,
14 IntoNatural, Slot, ValidationError, Wire, WirePointer, WireVector,
15};
16
17#[repr(transparent)]
19pub struct WireOptionalVector<'de, T> {
20 raw: RawWireVector<'de, T>,
21}
22
23unsafe impl<T: Wire> Wire for WireOptionalVector<'static, T> {
24 type Owned<'de> = WireOptionalVector<'de, T::Owned<'de>>;
25
26 #[inline]
27 fn zero_padding(out: &mut MaybeUninit<Self>) {
28 munge!(let Self { raw } = out);
29 RawWireVector::<T>::zero_padding(raw);
30 }
31}
32
33impl<T> Drop for WireOptionalVector<'_, T> {
34 fn drop(&mut self) {
35 if needs_drop::<T>() && self.is_some() {
36 unsafe {
37 self.raw.as_slice_ptr().drop_in_place();
38 }
39 }
40 }
41}
42
43impl<'de, T> WireOptionalVector<'de, T> {
44 pub fn encode_present(out: &mut MaybeUninit<Self>, len: u64) {
46 munge!(let Self { raw } = out);
47 RawWireVector::encode_present(raw, len);
48 }
49
50 pub fn encode_absent(out: &mut MaybeUninit<Self>) {
52 munge!(let Self { raw } = out);
53 RawWireVector::encode_absent(raw);
54 }
55
56 pub fn is_some(&self) -> bool {
58 !self.raw.as_ptr().is_null()
59 }
60
61 pub fn is_none(&self) -> bool {
63 !self.is_some()
64 }
65
66 pub fn as_ref(&self) -> Option<&WireVector<'_, T>> {
68 if self.is_some() { Some(unsafe { &*(self as *const Self).cast() }) } else { None }
69 }
70
71 pub fn to_option(self) -> Option<WireVector<'de, T>> {
73 if self.is_some() {
74 Some(unsafe { core::mem::transmute::<Self, WireVector<'de, T>>(self) })
75 } else {
76 None
77 }
78 }
79
80 pub unsafe fn decode_raw<D>(
87 mut slot: Slot<'_, Self>,
88 mut decoder: &mut D,
89 max_len: u64,
90 ) -> Result<(), DecodeError>
91 where
92 D: Decoder + ?Sized,
93 T: Decode<D>,
94 {
95 munge!(let Self { raw: RawWireVector { len, mut ptr } } = slot.as_mut());
96
97 if WirePointer::is_encoded_present(ptr.as_mut())? {
98 if **len > max_len {
99 return Err(DecodeError::Validation(ValidationError::VectorTooLong {
100 count: **len,
101 limit: max_len,
102 }));
103 }
104
105 let mut slice = decoder.take_slice_slot::<T>(**len as usize)?;
106 WirePointer::set_decoded(ptr, slice.as_mut_ptr().cast());
107 } else if *len != 0 {
108 return Err(DecodeError::InvalidOptionalSize(**len));
109 }
110
111 Ok(())
112 }
113
114 pub(crate) fn validate_max_len(
116 slot: Slot<'_, Self>,
117 limit: u64,
118 ) -> Result<(), crate::ValidationError> {
119 munge!(let Self { raw: RawWireVector { len, ptr } } = slot);
120 let count = **len;
121 let is_present = ptr.as_bytes() != [0; 8];
122 if is_present && count > limit {
123 Err(ValidationError::VectorTooLong { count, limit })
124 } else {
125 Ok(())
126 }
127 }
128}
129
130type VectorConstraint<T> = (u64, <T as Constrained>::Constraint);
131
132impl<T: Constrained> Constrained for WireOptionalVector<'_, T> {
133 type Constraint = VectorConstraint<T>;
134
135 fn validate(slot: Slot<'_, Self>, constraint: Self::Constraint) -> Result<(), ValidationError> {
136 let (limit, _member_constraint) = constraint;
137
138 Self::validate_max_len(slot, limit)
139 }
140}
141
142impl<T: fmt::Debug> fmt::Debug for WireOptionalVector<'_, T> {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 self.as_ref().fmt(f)
145 }
146}
147
148unsafe impl<D: Decoder + ?Sized, T: Decode<D>> Decode<D> for WireOptionalVector<'static, T> {
149 fn decode(
150 mut slot: Slot<'_, Self>,
151 mut decoder: &mut D,
152 constraint: <Self as Constrained>::Constraint,
153 ) -> Result<(), DecodeError> {
154 munge!(let Self { raw: RawWireVector { len, mut ptr } } = slot.as_mut());
155
156 let (length_constraint, member_constraint) = constraint;
157
158 if WirePointer::is_encoded_present(ptr.as_mut())? {
159 if **len > length_constraint {
160 return Err(DecodeError::Validation(ValidationError::VectorTooLong {
161 count: **len,
162 limit: length_constraint,
163 }));
164 }
165
166 let mut slice = decoder.take_slice_slot::<T>(**len as usize)?;
167 for i in 0..**len as usize {
168 T::decode(slice.index(i), decoder, member_constraint)?;
169 }
170 WirePointer::set_decoded(ptr, slice.as_mut_ptr().cast());
171 } else if *len != 0 {
172 return Err(DecodeError::InvalidOptionalSize(**len));
173 }
174
175 Ok(())
176 }
177}
178
179#[inline]
180fn encode_to_optional_vector<V, W, E, T>(
181 value: Option<V>,
182 encoder: &mut E,
183 out: &mut MaybeUninit<WireOptionalVector<'static, W>>,
184 constraint: VectorConstraint<W>,
185) -> Result<(), EncodeError>
186where
187 V: AsRef<[T]> + IntoIterator,
188 V::IntoIter: ExactSizeIterator,
189 V::Item: Encode<W, E>,
190 W: Constrained + Wire,
191 E: Encoder + ?Sized,
192 T: Encode<W, E>,
193{
194 let (length_constraint, member_constraint) = constraint;
195
196 if let Some(value) = value {
197 let len = value.as_ref().len();
198
199 if len as u64 > length_constraint {
200 return Err(EncodeError::Validation(ValidationError::VectorTooLong {
201 count: len as u64,
202 limit: length_constraint,
203 }));
204 }
205
206 if T::COPY_OPTIMIZATION.is_enabled() {
207 let slice = value.as_ref();
208 let bytes = unsafe { slice::from_raw_parts(slice.as_ptr().cast(), size_of_val(slice)) };
212 encoder.write(bytes);
213 } else {
214 encoder.encode_next_iter(value.into_iter(), member_constraint)?;
215 }
216 WireOptionalVector::encode_present(out, len as u64);
217 } else {
218 WireOptionalVector::encode_absent(out);
219 }
220 Ok(())
221}
222
223unsafe impl<W, E, T> EncodeOption<WireOptionalVector<'static, W>, E> for Vec<T>
224where
225 W: Constrained + Wire,
226 E: Encoder + ?Sized,
227 T: Encode<W, E>,
228{
229 fn encode_option(
230 this: Option<Self>,
231 encoder: &mut E,
232 out: &mut MaybeUninit<WireOptionalVector<'static, W>>,
233 constraint: <WireOptionalVector<'static, W> as Constrained>::Constraint,
234 ) -> Result<(), EncodeError> {
235 encode_to_optional_vector(this, encoder, out, constraint)
236 }
237}
238
239unsafe impl<'a, W, E, T> EncodeOption<WireOptionalVector<'static, W>, E> for &'a Vec<T>
240where
241 W: Constrained + Wire,
242 E: Encoder + ?Sized,
243 T: Encode<W, E>,
244 &'a T: Encode<W, E>,
245{
246 fn encode_option(
247 this: Option<Self>,
248 encoder: &mut E,
249 out: &mut MaybeUninit<WireOptionalVector<'static, W>>,
250 constraint: VectorConstraint<W>,
251 ) -> Result<(), EncodeError> {
252 encode_to_optional_vector(this, encoder, out, constraint)
253 }
254}
255
256unsafe impl<W, E, T, const N: usize> EncodeOption<WireOptionalVector<'static, W>, E> for [T; N]
257where
258 W: Constrained + Wire,
259 E: Encoder + ?Sized,
260 T: Encode<W, E>,
261{
262 fn encode_option(
263 this: Option<Self>,
264 encoder: &mut E,
265 out: &mut MaybeUninit<WireOptionalVector<'static, W>>,
266 constraint: VectorConstraint<W>,
267 ) -> Result<(), EncodeError> {
268 encode_to_optional_vector(this, encoder, out, constraint)
269 }
270}
271
272unsafe impl<'a, W, E, T, const N: usize> EncodeOption<WireOptionalVector<'static, W>, E>
273 for &'a [T; N]
274where
275 W: Constrained + Wire,
276 E: Encoder + ?Sized,
277 T: Encode<W, E>,
278 &'a T: Encode<W, E>,
279{
280 fn encode_option(
281 this: Option<Self>,
282 encoder: &mut E,
283 out: &mut MaybeUninit<WireOptionalVector<'static, W>>,
284 constraint: VectorConstraint<W>,
285 ) -> Result<(), EncodeError> {
286 encode_to_optional_vector(this, encoder, out, constraint)
287 }
288}
289
290unsafe impl<'a, W, E, T> EncodeOption<WireOptionalVector<'static, W>, E> for &'a [T]
291where
292 W: Constrained + Wire,
293 E: Encoder + ?Sized,
294 T: Encode<W, E>,
295 &'a T: Encode<W, E>,
296{
297 fn encode_option(
298 this: Option<Self>,
299 encoder: &mut E,
300 out: &mut MaybeUninit<WireOptionalVector<'static, W>>,
301 constraint: VectorConstraint<W>,
302 ) -> Result<(), EncodeError> {
303 encode_to_optional_vector(this, encoder, out, constraint)
304 }
305}
306
307impl<T: FromWire<W>, W> FromWireOption<WireOptionalVector<'_, W>> for Vec<T> {
308 fn from_wire_option(wire: WireOptionalVector<'_, W>) -> Option<Self> {
309 wire.to_option().map(Vec::from_wire)
310 }
311}
312
313impl<T: IntoNatural> IntoNatural for WireOptionalVector<'_, T> {
314 type Natural = Option<Vec<T::Natural>>;
315}
316
317impl<T: FromWireRef<W>, W> FromWireOptionRef<WireOptionalVector<'_, W>> for Vec<T> {
318 fn from_wire_option_ref(wire: &WireOptionalVector<'_, W>) -> Option<Self> {
319 wire.as_ref().map(Vec::from_wire_ref)
320 }
321}