Skip to main content

fidl_next_codec/convert/
from.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use core::mem::{MaybeUninit, forget};
6use core::ptr::copy_nonoverlapping;
7
8use crate::CopyOptimization;
9
10/// A type which is convertible from an owned value.
11pub trait FromWire<W>: Sized {
12    /// Whether the conversion from `W` to `Self` is equivalent to copying the raw bytes of `W`.
13    ///
14    /// Copy optimization is disabled by default.
15    const COPY_OPTIMIZATION: CopyOptimization<W, Self> = CopyOptimization::disable();
16
17    /// Converts the given owned value to this type.
18    fn from_wire(wire: W) -> Self;
19}
20
21/// A type which is convertible from a reference.
22pub trait FromWireRef<W>: FromWire<W> {
23    /// Converts the given reference to this type.
24    fn from_wire_ref(wire: &W) -> Self;
25}
26
27/// An optional type which is convertible from an owned value.
28pub trait FromWireOption<W>: Sized {
29    /// Converts the given owned value to an option of this type.
30    fn from_wire_option(wire: W) -> Option<Self>;
31}
32
33/// An optional type which is convertible from a reference.
34pub trait FromWireOptionRef<W>: FromWireOption<W> {
35    /// Converts the given reference to an option of this type.
36    fn from_wire_option_ref(wire: &W) -> Option<Self>;
37}
38
39impl<T: FromWire<W>, W, const N: usize> FromWire<[W; N]> for [T; N] {
40    fn from_wire(wire: [W; N]) -> Self {
41        let mut result = MaybeUninit::<[T; N]>::uninit();
42        if T::COPY_OPTIMIZATION.is_enabled() {
43            // SAFETY: `T` has copy optimization enabled and so is safe to copy bytewise.
44            unsafe {
45                copy_nonoverlapping(wire.as_ptr().cast(), result.as_mut_ptr(), 1);
46            }
47            forget(wire);
48        } else {
49            for (i, item) in wire.into_iter().enumerate() {
50                unsafe {
51                    result.as_mut_ptr().cast::<T>().add(i).write(T::from_wire(item));
52                }
53            }
54        }
55        unsafe { result.assume_init() }
56    }
57}
58
59impl<T: FromWireRef<W>, W, const N: usize> FromWireRef<[W; N]> for [T; N] {
60    fn from_wire_ref(wire: &[W; N]) -> Self {
61        let mut result = MaybeUninit::<[T; N]>::uninit();
62        if T::COPY_OPTIMIZATION.is_enabled() {
63            // SAFETY: `T` has copy optimization enabled and so is safe to copy bytewise.
64            unsafe {
65                copy_nonoverlapping(wire.as_ptr().cast(), result.as_mut_ptr(), 1);
66            }
67        } else {
68            for (i, item) in wire.iter().enumerate() {
69                unsafe {
70                    result.as_mut_ptr().cast::<T>().add(i).write(T::from_wire_ref(item));
71                }
72            }
73        }
74        unsafe { result.assume_init() }
75    }
76}
77
78impl<T: FromWire<W>, W> FromWire<W> for Box<T> {
79    fn from_wire(wire: W) -> Self {
80        Box::new(T::from_wire(wire))
81    }
82}
83
84impl<T: FromWireRef<W>, W> FromWireRef<W> for Box<T> {
85    fn from_wire_ref(wire: &W) -> Self {
86        Box::new(T::from_wire_ref(wire))
87    }
88}
89
90impl<T: FromWireOption<W>, W> FromWire<W> for Option<T> {
91    fn from_wire(wire: W) -> Self {
92        T::from_wire_option(wire)
93    }
94}
95
96impl<T: FromWireOptionRef<W>, W> FromWireRef<W> for Option<T> {
97    fn from_wire_ref(wire: &W) -> Self {
98        T::from_wire_option_ref(wire)
99    }
100}