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 _, FromWire, FromWireOption,
13 FromWireOptionRef, FromWireRef, IntoNatural, Slot, ValidationError, Wire, WirePointer,
14};
15
16#[repr(C)]
18pub struct WireBox<'de, T> {
19 ptr: WirePointer<'de, T>,
20}
21
22unsafe impl<T: Send> Send for WireBox<'_, T> {}
25
26unsafe impl<T: Sync> Sync for WireBox<'_, T> {}
28
29impl<T> Drop for WireBox<'_, T> {
30 fn drop(&mut self) {
31 if self.is_some() {
32 unsafe {
33 self.ptr.as_ptr().drop_in_place();
34 }
35 }
36 }
37}
38
39unsafe impl<T: Wire> Wire for WireBox<'static, T> {
40 type Owned<'de> = WireBox<'de, T::Owned<'de>>;
41
42 #[inline]
43 fn zero_padding(_: &mut MaybeUninit<Self>) {
44 }
46}
47
48impl<T> WireBox<'_, T> {
49 pub fn encode_present(out: &mut MaybeUninit<Self>) {
51 munge!(let Self { ptr } = out);
52 WirePointer::encode_present(ptr);
53 }
54
55 pub fn encode_absent(out: &mut MaybeUninit<Self>) {
57 munge!(let Self { ptr } = out);
58 WirePointer::encode_absent(ptr);
59 }
60
61 pub fn is_some(&self) -> bool {
63 !self.ptr.as_ptr().is_null()
64 }
65
66 pub fn is_none(&self) -> bool {
68 !self.is_some()
69 }
70
71 pub fn as_ref(&self) -> Option<&T> {
73 NonNull::new(self.ptr.as_ptr()).map(|ptr| unsafe { ptr.as_ref() })
74 }
75
76 pub fn into_option(self) -> Option<T> {
78 let ptr = self.ptr.as_ptr();
79 forget(self);
80 if ptr.is_null() { None } else { unsafe { Some(ptr.read()) } }
81 }
82}
83
84impl<T: fmt::Debug> fmt::Debug for WireBox<'_, T> {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 self.as_ref().fmt(f)
87 }
88}
89
90unsafe impl<D: Decoder + ?Sized, T: Decode<D>> Decode<D> for WireBox<'static, T> {
91 fn decode(
92 slot: Slot<'_, Self>,
93 mut decoder: &mut D,
94 constraint: <Self as Constrained>::Constraint,
95 ) -> Result<(), DecodeError> {
96 munge!(let Self { mut ptr } = slot);
97
98 if WirePointer::is_encoded_present(ptr.as_mut())? {
99 let mut value = decoder.take_slot::<T>()?;
100 T::decode(value.as_mut(), decoder, constraint)?;
101 WirePointer::set_decoded(ptr, value.as_mut_ptr());
102 }
103
104 Ok(())
105 }
106}
107
108impl<T: FromWire<W>, W> FromWireOption<WireBox<'_, W>> for T {
109 fn from_wire_option(wire: WireBox<'_, W>) -> Option<Self> {
110 wire.into_option().map(T::from_wire)
111 }
112}
113
114impl<T: IntoNatural> IntoNatural for WireBox<'_, T> {
115 type Natural = Option<T::Natural>;
116}
117
118impl<T: FromWireRef<W>, W> FromWireOptionRef<WireBox<'_, W>> for T {
119 fn from_wire_option_ref(wire: &WireBox<'_, W>) -> Option<Self> {
120 wire.as_ref().map(T::from_wire_ref)
121 }
122}
123
124impl<T: Constrained> Constrained for WireBox<'_, T> {
125 type Constraint = T::Constraint;
126
127 fn validate(slot: Slot<'_, Self>, constraint: Self::Constraint) -> Result<(), ValidationError> {
128 munge!(let Self { ptr } = slot);
129
130 let ptr = unsafe { ptr.deref_unchecked() };
131 let ptr = ptr.as_ptr();
132 let member_slot = unsafe { Slot::new_unchecked(ptr) };
133 T::validate(member_slot, constraint)
134 }
135}