fidl_next_codec/wire/vec/
required.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use core::mem::{needs_drop, MaybeUninit};
6use core::ops::Deref;
7use core::ptr::{copy_nonoverlapping, NonNull};
8use core::{fmt, slice};
9
10use munge::munge;
11
12use super::raw::RawWireVector;
13use crate::{
14    Decode, DecodeError, Decoder, DecoderExt as _, Encodable, Encode, EncodeError, EncodeRef,
15    Encoder, EncoderExt as _, Slot, TakeFrom, WirePointer, ZeroPadding,
16};
17
18/// A FIDL vector
19#[repr(transparent)]
20pub struct WireVector<T> {
21    raw: RawWireVector<T>,
22}
23
24unsafe impl<T> ZeroPadding for WireVector<T> {
25    #[inline]
26    fn zero_padding(out: &mut MaybeUninit<Self>) {
27        munge!(let Self { raw } = out);
28        RawWireVector::<T>::zero_padding(raw);
29    }
30}
31
32impl<T> Drop for WireVector<T> {
33    fn drop(&mut self) {
34        if needs_drop::<T>() {
35            unsafe {
36                self.raw.as_slice_ptr().drop_in_place();
37            }
38        }
39    }
40}
41
42impl<T> WireVector<T> {
43    /// Encodes that a vector is present in a slot.
44    pub fn encode_present(out: &mut MaybeUninit<Self>, len: u64) {
45        munge!(let Self { raw } = out);
46        RawWireVector::encode_present(raw, len);
47    }
48
49    /// Returns the length of the vector in elements.
50    pub fn len(&self) -> usize {
51        self.raw.len() as usize
52    }
53
54    /// Returns whether the vector is empty.
55    pub fn is_empty(&self) -> bool {
56        self.len() == 0
57    }
58
59    /// Returns a pointer to the elements of the vector.
60    fn as_slice_ptr(&self) -> NonNull<[T]> {
61        unsafe { NonNull::new_unchecked(self.raw.as_slice_ptr()) }
62    }
63
64    /// Returns a slice of the elements of the vector.
65    pub fn as_slice(&self) -> &[T] {
66        unsafe { self.as_slice_ptr().as_ref() }
67    }
68
69    /// Decodes a wire vector which contains raw data.
70    ///
71    /// # Safety
72    ///
73    /// The elements of the wire vecot rmust not need to be individually decoded, and must always be
74    /// valid.
75    pub unsafe fn decode_raw<D>(
76        mut slot: Slot<'_, Self>,
77        mut decoder: &mut D,
78    ) -> Result<(), DecodeError>
79    where
80        D: Decoder + ?Sized,
81        T: Decode<D>,
82    {
83        munge!(let Self { raw: RawWireVector { len, mut ptr } } = slot.as_mut());
84
85        if !WirePointer::is_encoded_present(ptr.as_mut())? {
86            return Err(DecodeError::RequiredValueAbsent);
87        }
88
89        let mut slice = decoder.take_slice_slot::<T>(**len as usize)?;
90        WirePointer::set_decoded(ptr, slice.as_mut_ptr().cast());
91
92        Ok(())
93    }
94}
95
96impl<T> Deref for WireVector<T> {
97    type Target = [T];
98
99    fn deref(&self) -> &Self::Target {
100        self.as_slice()
101    }
102}
103
104impl<T: fmt::Debug> fmt::Debug for WireVector<T> {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        self.as_slice().fmt(f)
107    }
108}
109
110unsafe impl<D: Decoder + ?Sized, T: Decode<D>> Decode<D> for WireVector<T> {
111    fn decode(mut slot: Slot<'_, Self>, mut decoder: &mut D) -> Result<(), DecodeError> {
112        munge!(let Self { raw: RawWireVector { len, mut ptr } } = slot.as_mut());
113
114        if !WirePointer::is_encoded_present(ptr.as_mut())? {
115            return Err(DecodeError::RequiredValueAbsent);
116        }
117
118        let mut slice = decoder.take_slice_slot::<T>(**len as usize)?;
119        for i in 0..**len as usize {
120            T::decode(slice.index(i), decoder)?;
121        }
122        WirePointer::set_decoded(ptr, slice.as_mut_ptr().cast());
123
124        Ok(())
125    }
126}
127
128#[inline]
129fn encode_to_vector<V, E, T>(
130    value: V,
131    encoder: &mut E,
132    out: &mut MaybeUninit<WireVector<T::Encoded>>,
133) -> Result<(), EncodeError>
134where
135    V: AsRef<[T]> + IntoIterator,
136    V::IntoIter: ExactSizeIterator,
137    V::Item: Encode<E, Encoded = T::Encoded>,
138    E: Encoder + ?Sized,
139    T: Encode<E>,
140{
141    let len = value.as_ref().len();
142    if T::COPY_OPTIMIZATION.is_enabled() {
143        let slice = value.as_ref();
144        // SAFETY: `T` has copy optimization enabled, which guarantees that it has no uninit bytes
145        // and can be copied directly to the output instead of calling `encode`. This means that we
146        // may cast `&[T]` to `&[u8]` and write those bytes.
147        let bytes = unsafe { slice::from_raw_parts(slice.as_ptr().cast(), size_of_val(slice)) };
148        encoder.write(bytes);
149    } else {
150        encoder.encode_next_iter(value.into_iter())?;
151    }
152    WireVector::encode_present(out, len as u64);
153    Ok(())
154}
155
156impl<T: Encodable> Encodable for Vec<T> {
157    type Encoded = WireVector<T::Encoded>;
158}
159
160unsafe impl<E: Encoder + ?Sized, T: Encode<E>> Encode<E> for Vec<T> {
161    fn encode(
162        self,
163        encoder: &mut E,
164        out: &mut MaybeUninit<Self::Encoded>,
165    ) -> Result<(), EncodeError> {
166        encode_to_vector(self, encoder, out)
167    }
168}
169
170unsafe impl<E: Encoder + ?Sized, T: EncodeRef<E>> EncodeRef<E> for Vec<T> {
171    fn encode_ref(
172        &self,
173        encoder: &mut E,
174        out: &mut MaybeUninit<Self::Encoded>,
175    ) -> Result<(), EncodeError> {
176        encode_to_vector(self, encoder, out)
177    }
178}
179
180impl<T: Encodable> Encodable for &[T] {
181    type Encoded = WireVector<T::Encoded>;
182}
183
184unsafe impl<E: Encoder + ?Sized, T: EncodeRef<E>> Encode<E> for &[T] {
185    fn encode(
186        self,
187        encoder: &mut E,
188        out: &mut MaybeUninit<Self::Encoded>,
189    ) -> Result<(), EncodeError> {
190        encode_to_vector(self, encoder, out)
191    }
192}
193
194impl<T: TakeFrom<WT>, WT> TakeFrom<WireVector<WT>> for Vec<T> {
195    fn take_from(from: &WireVector<WT>) -> Self {
196        let mut result = Vec::<T>::with_capacity(from.len());
197        if T::COPY_OPTIMIZATION.is_enabled() {
198            unsafe {
199                copy_nonoverlapping(from.as_ptr().cast(), result.as_mut_ptr(), from.len());
200            }
201            unsafe {
202                result.set_len(from.len());
203            }
204        } else {
205            for item in from.as_slice() {
206                result.push(T::take_from(item));
207            }
208        }
209        result
210    }
211}