fidl_next_codec/
take.rs
1use core::mem::MaybeUninit;
6use core::ptr::copy_nonoverlapping;
7
8use crate::{
9 CopyOptimization, WireF32, WireF64, WireI16, WireI32, WireI64, WireU16, WireU32, WireU64,
10};
11
12pub trait TakeFrom<T: ?Sized> {
14 const COPY_OPTIMIZATION: CopyOptimization<Self> = CopyOptimization::disable();
21
22 fn take_from(from: &T) -> Self;
24}
25
26macro_rules! impl_primitive {
27 ($from:ty, $to:ty) => {
28 impl TakeFrom<$from> for $to {
29 const COPY_OPTIMIZATION: CopyOptimization<Self> = unsafe {
32 CopyOptimization::enable_if(
33 size_of::<Self>() <= 1 || cfg!(target_endian = "little"),
34 )
35 };
36
37 #[inline]
38 fn take_from(from: &$from) -> $to {
39 (*from).into()
40 }
41 }
42 };
43}
44
45macro_rules! impl_primitives {
46 ($($from:ty, $to:ty);* $(;)?) => {
47 $(
48 impl_primitive!($from, $to);
49 )*
50 }
51}
52
53impl_primitives! {
54 bool, bool;
55
56 i8, i8;
57 WireI16, i16; WireI16, WireI16;
58 WireI32, i32; WireI32, WireI32;
59 WireI64, i64; WireI64, WireI64;
60
61 u8, u8;
62 WireU16, u16; WireU16, WireU16;
63 WireU32, u32; WireU32, WireU32;
64 WireU64, u64; WireU64, WireU64;
65
66 WireF32, f32; WireF32, WireF32;
67 WireF64, f64; WireF64, WireF64;
68}
69
70impl<T: TakeFrom<WT>, WT, const N: usize> TakeFrom<[WT; N]> for [T; N] {
71 const COPY_OPTIMIZATION: CopyOptimization<Self> =
72 unsafe { CopyOptimization::enable_if(T::COPY_OPTIMIZATION.is_enabled()) };
73
74 fn take_from(from: &[WT; N]) -> Self {
75 let mut result = MaybeUninit::<[T; N]>::uninit();
76 if T::COPY_OPTIMIZATION.is_enabled() {
77 unsafe {
79 copy_nonoverlapping(from.as_ptr().cast(), result.as_mut_ptr(), 1);
80 }
81 } else {
82 for (i, item) in from.iter().enumerate() {
83 let taken = T::take_from(item);
84 unsafe {
85 result.as_mut_ptr().cast::<T>().add(i).write(taken);
86 }
87 }
88 }
89 unsafe { result.assume_init() }
90 }
91}
92
93impl<T: TakeFrom<WT>, WT> TakeFrom<WT> for Box<T> {
94 fn take_from(from: &WT) -> Self {
95 Box::new(T::take_from(from))
96 }
97}