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 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() { 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(slot: Slot<'_, Self>, mut decoder: &mut D) -> Result<(), DecodeError> {
93 munge!(let Self { mut ptr } = slot);
94
95 if WirePointer::is_encoded_present(ptr.as_mut())? {
96 let mut value = decoder.take_slot::<T>()?;
97 T::decode(value.as_mut(), decoder)?;
98 WirePointer::set_decoded(ptr, value.as_mut_ptr());
99 }
100
101 Ok(())
102 }
103}
104
105impl<T: EncodableOption> Encodable for Option<T> {
106 type Encoded = T::EncodedOption;
107}
108
109unsafe impl<E: ?Sized, T: EncodeOption<E>> Encode<E> for Option<T> {
110 fn encode(
111 self,
112 encoder: &mut E,
113 out: &mut MaybeUninit<Self::Encoded>,
114 ) -> Result<(), EncodeError> {
115 T::encode_option(self, encoder, out)
116 }
117}
118
119unsafe impl<E: ?Sized, T: EncodeOptionRef<E>> EncodeRef<E> for Option<T> {
120 fn encode_ref(
121 &self,
122 encoder: &mut E,
123 out: &mut MaybeUninit<Self::Encoded>,
124 ) -> Result<(), EncodeError> {
125 T::encode_option_ref(self.as_ref(), encoder, out)
126 }
127}
128
129impl<T: FromWire<W>, W> FromWireOption<WireBox<'_, W>> for T {
130 fn from_wire_option(wire: WireBox<'_, W>) -> Option<Self> {
131 wire.into_option().map(T::from_wire)
132 }
133}
134
135impl<T: FromWireRef<W>, W> FromWireOptionRef<WireBox<'_, W>> for T {
136 fn from_wire_option_ref(wire: &WireBox<'_, W>) -> Option<Self> {
137 wire.as_ref().map(T::from_wire_ref)
138 }
139}