fidl_next_codec/wire/vec/
optional.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;
6use core::{fmt, slice};
7
8use munge::munge;
9
10use super::raw::RawWireVector;
11use crate::{
12    Decode, DecodeError, Decoder, DecoderExt as _, Encodable, EncodableOption, Encode, EncodeError,
13    EncodeOption, Encoder, EncoderExt as _, Slot, TakeFrom, WirePointer, WireVector, ZeroPadding,
14};
15
16/// An optional FIDL vector
17#[repr(transparent)]
18pub struct WireOptionalVector<T> {
19    raw: RawWireVector<T>,
20}
21
22unsafe impl<T> ZeroPadding for WireOptionalVector<T> {
23    #[inline]
24    unsafe fn zero_padding(ptr: *mut Self) {
25        unsafe {
26            RawWireVector::<T>::zero_padding(ptr.cast());
27        }
28    }
29}
30
31impl<T> Drop for WireOptionalVector<T> {
32    fn drop(&mut self) {
33        if needs_drop::<T>() && self.is_some() {
34            unsafe {
35                self.raw.as_slice_ptr().drop_in_place();
36            }
37        }
38    }
39}
40
41impl<T> WireOptionalVector<T> {
42    /// Encodes that a vector is present in a slot.
43    pub fn encode_present(slot: Slot<'_, Self>, len: u64) {
44        munge!(let Self { raw } = slot);
45        RawWireVector::encode_present(raw, len);
46    }
47
48    /// Encodes that a vector is absent in a slot.
49    pub fn encode_absent(slot: Slot<'_, Self>) {
50        munge!(let Self { raw } = slot);
51        RawWireVector::encode_absent(raw);
52    }
53
54    /// Returns whether the vector is present.
55    pub fn is_some(&self) -> bool {
56        !self.raw.as_ptr().is_null()
57    }
58
59    /// Returns whether the vector is absent.
60    pub fn is_none(&self) -> bool {
61        !self.is_some()
62    }
63
64    /// Gets a reference to the vector, if any.
65    pub fn as_ref(&self) -> Option<&WireVector<T>> {
66        if self.is_some() {
67            Some(unsafe { &*(self as *const Self).cast() })
68        } else {
69            None
70        }
71    }
72
73    /// Decodes a wire vector which contains raw data.
74    ///
75    /// # Safety
76    ///
77    /// The elements of the wire vecot rmust not need to be individually decoded, and must always be
78    /// valid.
79    pub unsafe fn decode_raw<D>(
80        mut slot: Slot<'_, Self>,
81        mut decoder: &mut D,
82    ) -> Result<(), DecodeError>
83    where
84        D: Decoder + ?Sized,
85        T: Decode<D>,
86    {
87        munge!(let Self { raw: RawWireVector { len, mut ptr } } = slot.as_mut());
88
89        if WirePointer::is_encoded_present(ptr.as_mut())? {
90            let mut slice = decoder.take_slice_slot::<T>(**len as usize)?;
91            WirePointer::set_decoded(ptr, slice.as_mut_ptr().cast());
92        } else if *len != 0 {
93            return Err(DecodeError::InvalidOptionalSize(**len));
94        }
95
96        Ok(())
97    }
98}
99
100impl<T: fmt::Debug> fmt::Debug for WireOptionalVector<T> {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        self.as_ref().fmt(f)
103    }
104}
105
106unsafe impl<D: Decoder + ?Sized, T: Decode<D>> Decode<D> for WireOptionalVector<T> {
107    fn decode(mut slot: Slot<'_, Self>, mut decoder: &mut D) -> Result<(), DecodeError> {
108        munge!(let Self { raw: RawWireVector { len, mut ptr } } = slot.as_mut());
109
110        if WirePointer::is_encoded_present(ptr.as_mut())? {
111            let slice = decoder.decode_next_slice::<T>(**len as usize)?;
112            WirePointer::set_decoded(ptr, slice.into_raw().cast());
113        } else if *len != 0 {
114            return Err(DecodeError::InvalidOptionalSize(**len));
115        }
116
117        Ok(())
118    }
119}
120
121impl<T: Encodable> EncodableOption for Vec<T> {
122    type EncodedOption = WireOptionalVector<T::Encoded>;
123}
124
125impl<E: Encoder + ?Sized, T: Encode<E>> EncodeOption<E> for Vec<T> {
126    fn encode_option(
127        this: Option<&mut Self>,
128        encoder: &mut E,
129        slot: Slot<'_, Self::EncodedOption>,
130    ) -> Result<(), EncodeError> {
131        if let Some(vec) = this {
132            if T::COPY_OPTIMIZATION.is_enabled() {
133                let bytes = unsafe {
134                    slice::from_raw_parts(vec.as_ptr().cast(), vec.len() * size_of::<T>())
135                };
136                encoder.write(bytes);
137            } else {
138                encoder.encode_next_slice(vec.as_mut_slice())?;
139            }
140            WireOptionalVector::encode_present(slot, vec.len() as u64);
141        } else {
142            WireOptionalVector::encode_absent(slot);
143        }
144
145        Ok(())
146    }
147}
148
149impl<T: TakeFrom<WT>, WT> TakeFrom<WireOptionalVector<WT>> for Option<Vec<T>> {
150    fn take_from(from: &WireOptionalVector<WT>) -> Self {
151        from.as_ref().map(Vec::take_from)
152    }
153}