fidl_next_codec/
from_wire.rs1use core::mem::{forget, MaybeUninit};
6use core::ptr::copy_nonoverlapping;
7
8use crate::{
9 CopyOptimization, WireF32, WireF64, WireI16, WireI32, WireI64, WireU16, WireU32, WireU64,
10};
11
12pub trait FromWire<W>: Sized {
14 const COPY_OPTIMIZATION: CopyOptimization<W, Self> = CopyOptimization::disable();
18
19 fn from_wire(wire: W) -> Self;
21}
22
23pub trait FromWireRef<W>: FromWire<W> {
25 fn from_wire_ref(wire: &W) -> Self;
27}
28
29pub trait FromWireOption<W>: Sized {
31 fn from_wire_option(wire: W) -> Option<Self>;
33}
34
35pub trait FromWireOptionRef<W>: FromWireOption<W> {
37 fn from_wire_option_ref(wire: &W) -> Option<Self>;
39}
40
41macro_rules! impl_primitive {
42 ($ty:ty) => {
43 impl_primitive!($ty, $ty);
44 };
45 ($ty:ty, $enc:ty) => {
46 impl FromWire<$enc> for $ty {
47 const COPY_OPTIMIZATION: CopyOptimization<$enc, $ty> =
48 CopyOptimization::<$enc, $ty>::PRIMITIVE;
49
50 #[inline]
51 fn from_wire(wire: $enc) -> Self {
52 wire.into()
53 }
54 }
55
56 impl FromWireRef<$enc> for $ty {
57 #[inline]
58 fn from_wire_ref(wire: &$enc) -> Self {
59 (*wire).into()
60 }
61 }
62 };
63}
64
65macro_rules! impl_primitives {
66 ($($ty:ty $(, $enc:ty)?);* $(;)?) => {
67 $(
68 impl_primitive!($ty $(, $enc)?);
69 )*
70 }
71}
72
73impl_primitives! {
74 ();
75
76 bool;
77
78 i8;
79 i16, WireI16; i32, WireI32; i64, WireI64;
80 WireI16; WireI32; WireI64;
81
82 u8;
83 u16, WireU16; u32, WireU32; u64, WireU64;
84 WireU16; WireU32; WireU64;
85
86 f32, WireF32; f64, WireF64;
87 WireF32; WireF64;
88}
89
90impl<T: FromWire<W>, W, const N: usize> FromWire<[W; N]> for [T; N] {
91 fn from_wire(wire: [W; N]) -> Self {
92 let mut result = MaybeUninit::<[T; N]>::uninit();
93 if T::COPY_OPTIMIZATION.is_enabled() {
94 unsafe {
96 copy_nonoverlapping(wire.as_ptr().cast(), result.as_mut_ptr(), 1);
97 }
98 forget(wire);
99 } else {
100 for (i, item) in wire.into_iter().enumerate() {
101 unsafe {
102 result.as_mut_ptr().cast::<T>().add(i).write(T::from_wire(item));
103 }
104 }
105 }
106 unsafe { result.assume_init() }
107 }
108}
109
110impl<T: FromWireRef<W>, W, const N: usize> FromWireRef<[W; N]> for [T; N] {
111 fn from_wire_ref(wire: &[W; N]) -> Self {
112 let mut result = MaybeUninit::<[T; N]>::uninit();
113 if T::COPY_OPTIMIZATION.is_enabled() {
114 unsafe {
116 copy_nonoverlapping(wire.as_ptr().cast(), result.as_mut_ptr(), 1);
117 }
118 } else {
119 for (i, item) in wire.iter().enumerate() {
120 unsafe {
121 result.as_mut_ptr().cast::<T>().add(i).write(T::from_wire_ref(item));
122 }
123 }
124 }
125 unsafe { result.assume_init() }
126 }
127}
128
129impl<T: FromWire<W>, W> FromWire<W> for Box<T> {
130 fn from_wire(wire: W) -> Self {
131 Box::new(T::from_wire(wire))
132 }
133}
134
135impl<T: FromWireRef<W>, W> FromWireRef<W> for Box<T> {
136 fn from_wire_ref(wire: &W) -> Self {
137 Box::new(T::from_wire_ref(wire))
138 }
139}
140
141impl<T: FromWireOption<W>, W> FromWire<W> for Option<T> {
142 fn from_wire(wire: W) -> Self {
143 T::from_wire_option(wire)
144 }
145}
146
147impl<T: FromWireOptionRef<W>, W> FromWireRef<W> for Option<T> {
148 fn from_wire_ref(wire: &W) -> Self {
149 T::from_wire_option_ref(wire)
150 }
151}