fidl_next_codec/wire/
boxed.rs1use core::fmt;
6use core::mem::{MaybeUninit, forget};
7use core::ptr::NonNull;
8
9use munge::munge;
10
11use crate::{
12 Constrained, Decode, DecodeError, Decoder, DecoderExt as _, Encodable, EncodableOption, Encode,
13 EncodeError, EncodeOption, EncodeOptionRef, EncodeRef, FromWire, FromWireOption,
14 FromWireOptionRef, FromWireRef, IntoNatural, Slot, ValidationError, Wire, WirePointer,
15};
16
17#[repr(C)]
19pub struct WireBox<'de, T> {
20 ptr: WirePointer<'de, T>,
21}
22
23unsafe impl<T: Send> Send for WireBox<'_, T> {}
26
27unsafe impl<T: Sync> Sync for WireBox<'_, T> {}
29
30impl<T> Drop for WireBox<'_, T> {
31 fn drop(&mut self) {
32 if self.is_some() {
33 unsafe {
34 self.ptr.as_ptr().drop_in_place();
35 }
36 }
37 }
38}
39
40unsafe impl<T: Wire> Wire for WireBox<'static, T> {
41 type Decoded<'de> = WireBox<'de, T::Decoded<'de>>;
42
43 #[inline]
44 fn zero_padding(_: &mut MaybeUninit<Self>) {
45 }
47}
48
49impl<T> WireBox<'_, T> {
50 pub fn encode_present(out: &mut MaybeUninit<Self>) {
52 munge!(let Self { ptr } = out);
53 WirePointer::encode_present(ptr);
54 }
55
56 pub fn encode_absent(out: &mut MaybeUninit<Self>) {
58 munge!(let Self { ptr } = out);
59 WirePointer::encode_absent(ptr);
60 }
61
62 pub fn is_some(&self) -> bool {
64 !self.ptr.as_ptr().is_null()
65 }
66
67 pub fn is_none(&self) -> bool {
69 !self.is_some()
70 }
71
72 pub fn as_ref(&self) -> Option<&T> {
74 NonNull::new(self.ptr.as_ptr()).map(|ptr| unsafe { ptr.as_ref() })
75 }
76
77 pub fn into_option(self) -> Option<T> {
79 let ptr = self.ptr.as_ptr();
80 forget(self);
81 if ptr.is_null() { None } else { unsafe { Some(ptr.read()) } }
82 }
83}
84
85impl<T: fmt::Debug> fmt::Debug for WireBox<'_, T> {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 self.as_ref().fmt(f)
88 }
89}
90
91unsafe impl<D: Decoder + ?Sized, T: Decode<D>> Decode<D> for WireBox<'static, T> {
92 fn decode(
93 slot: Slot<'_, Self>,
94 mut decoder: &mut D,
95 constraint: <Self as Constrained>::Constraint,
96 ) -> Result<(), DecodeError> {
97 munge!(let Self { mut ptr } = slot);
98
99 if WirePointer::is_encoded_present(ptr.as_mut())? {
100 let mut value = decoder.take_slot::<T>()?;
101 T::decode(value.as_mut(), decoder, constraint)?;
102 WirePointer::set_decoded(ptr, value.as_mut_ptr());
103 }
104
105 Ok(())
106 }
107}
108
109impl<T: EncodableOption> Encodable for Option<T> {
110 type Encoded = T::EncodedOption;
111}
112
113unsafe impl<E: ?Sized, T: EncodeOption<E>> Encode<E> for Option<T> {
114 fn encode(
115 self,
116 encoder: &mut E,
117 out: &mut MaybeUninit<Self::Encoded>,
118 constraint: <Self::Encoded as Constrained>::Constraint,
119 ) -> Result<(), EncodeError> {
120 T::encode_option(self, encoder, out, constraint)
121 }
122}
123
124unsafe impl<E: ?Sized, T: EncodeOptionRef<E>> EncodeRef<E> for Option<T> {
125 fn encode_ref(
126 &self,
127 encoder: &mut E,
128 out: &mut MaybeUninit<Self::Encoded>,
129 constraint: <Self::Encoded as Constrained>::Constraint,
130 ) -> Result<(), EncodeError> {
131 T::encode_option_ref(self.as_ref(), encoder, out, constraint)
132 }
133}
134
135impl<T: FromWire<W>, W> FromWireOption<WireBox<'_, W>> for T {
136 fn from_wire_option(wire: WireBox<'_, W>) -> Option<Self> {
137 wire.into_option().map(T::from_wire)
138 }
139}
140
141impl<T: IntoNatural> IntoNatural for WireBox<'_, T> {
142 type Natural = Option<T::Natural>;
143}
144
145impl<T: FromWireRef<W>, W> FromWireOptionRef<WireBox<'_, W>> for T {
146 fn from_wire_option_ref(wire: &WireBox<'_, W>) -> Option<Self> {
147 wire.as_ref().map(T::from_wire_ref)
148 }
149}
150
151impl<T: Constrained> Constrained for WireBox<'_, T> {
152 type Constraint = T::Constraint;
153
154 fn validate(slot: Slot<'_, Self>, constraint: Self::Constraint) -> Result<(), ValidationError> {
155 munge!(let Self { ptr } = slot);
156
157 let ptr = unsafe { ptr.deref_unchecked() };
158 let ptr = ptr.as_ptr();
159 let member_slot = unsafe { Slot::new_unchecked(ptr) };
160 T::validate(member_slot, constraint)
161 }
162}