fidl_next_codec/wire/
boxed.rs1use core::fmt;
6use core::mem::{forget, MaybeUninit};
7use core::ptr::NonNull;
8
9use munge::munge;
10
11use crate::{
12 Decode, DecodeError, Decoder, DecoderExt as _, Encodable, EncodableOption, Encode, EncodeError,
13 EncodeOption, EncodeOptionRef, EncodeRef, FromWire, FromWireOption, FromWireOptionRef,
14 FromWireRef, Slot, 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() {
82 None
83 } else {
84 unsafe { Some(ptr.read()) }
85 }
86 }
87}
88
89impl<T: fmt::Debug> fmt::Debug for WireBox<'_, T> {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 self.as_ref().fmt(f)
92 }
93}
94
95unsafe impl<D: Decoder + ?Sized, T: Decode<D>> Decode<D> for WireBox<'static, T> {
96 fn decode(slot: Slot<'_, Self>, mut decoder: &mut D) -> 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)?;
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 ) -> Result<(), EncodeError> {
119 T::encode_option(self, encoder, out)
120 }
121}
122
123unsafe impl<E: ?Sized, T: EncodeOptionRef<E>> EncodeRef<E> for Option<T> {
124 fn encode_ref(
125 &self,
126 encoder: &mut E,
127 out: &mut MaybeUninit<Self::Encoded>,
128 ) -> Result<(), EncodeError> {
129 T::encode_option_ref(self.as_ref(), encoder, out)
130 }
131}
132
133impl<T: FromWire<W>, W> FromWireOption<WireBox<'_, W>> for T {
134 fn from_wire_option(wire: WireBox<'_, W>) -> Option<Self> {
135 wire.into_option().map(T::from_wire)
136 }
137}
138
139impl<T: FromWireRef<W>, W> FromWireOptionRef<WireBox<'_, W>> for T {
140 fn from_wire_option_ref(wire: &WireBox<'_, W>) -> Option<Self> {
141 wire.as_ref().map(T::from_wire_ref)
142 }
143}