fidl_next_codec/wire/
boxed.rs1use core::fmt;
6use core::mem::MaybeUninit;
7use core::ptr::NonNull;
8
9use munge::munge;
10
11use crate::{
12 Decode, DecodeError, Decoder, DecoderExt as _, Encodable, EncodableOption, Encode, EncodeError,
13 EncodeOption, Slot, TakeFrom, WirePointer, ZeroPadding,
14};
15
16#[repr(C)]
18pub struct WireBox<T> {
19 ptr: WirePointer<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> ZeroPadding for WireBox<T> {
40 #[inline]
41 fn zero_padding(_: &mut MaybeUninit<Self>) {
42 }
44}
45
46impl<T> WireBox<T> {
47 pub fn encode_present(out: &mut MaybeUninit<Self>) {
49 munge!(let Self { ptr } = out);
50 WirePointer::encode_present(ptr);
51 }
52
53 pub fn encode_absent(out: &mut MaybeUninit<Self>) {
55 munge!(let Self { ptr } = out);
56 WirePointer::encode_absent(ptr);
57 }
58
59 pub fn is_some(&self) -> bool {
61 !self.ptr.as_ptr().is_null()
62 }
63
64 pub fn is_none(&self) -> bool {
66 !self.is_some()
67 }
68
69 pub fn as_ref(&self) -> Option<&T> {
71 NonNull::new(self.ptr.as_ptr()).map(|ptr| unsafe { ptr.as_ref() })
72 }
73}
74
75impl<T: fmt::Debug> fmt::Debug for WireBox<T> {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 self.as_ref().fmt(f)
78 }
79}
80
81unsafe impl<D: Decoder + ?Sized, T: Decode<D>> Decode<D> for WireBox<T> {
82 fn decode(slot: Slot<'_, Self>, mut decoder: &mut D) -> Result<(), DecodeError> {
83 munge!(let Self { mut ptr } = slot);
84
85 if WirePointer::is_encoded_present(ptr.as_mut())? {
86 let value = decoder.decode_next::<T>()?;
87 WirePointer::set_decoded(ptr, value.into_raw());
88 }
89
90 Ok(())
91 }
92}
93
94impl<T: EncodableOption> Encodable for Option<T> {
95 type Encoded = T::EncodedOption;
96}
97
98unsafe impl<E: ?Sized, T: EncodeOption<E>> Encode<E> for Option<T> {
99 fn encode(
100 &mut self,
101 encoder: &mut E,
102 out: &mut MaybeUninit<Self::Encoded>,
103 ) -> Result<(), EncodeError> {
104 T::encode_option(self.as_mut(), encoder, out)
105 }
106}
107
108impl<T: TakeFrom<WT>, WT> TakeFrom<WireBox<WT>> for Option<T> {
109 fn take_from(from: &WireBox<WT>) -> Self {
110 from.as_ref().map(|value| T::take_from(value))
111 }
112}