Skip to main content

fidl_next_codec/
copy_optimization.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::marker::PhantomData;
6
7/// An optimization hint about whether the conversion from `T` to `U` is equivalent to copying the
8/// raw bytes of `T`.
9pub struct CopyOptimization<T: ?Sized, U: ?Sized>(bool, PhantomData<(*mut T, *mut U)>);
10
11impl<T: ?Sized, U: ?Sized> CopyOptimization<T, U> {
12    /// Returns a `CopyOptimization` hint with the optimization enabled.
13    ///
14    /// # Safety
15    ///
16    /// `T` and `U` must be the same size and must not have any uninit bytes (e.g. padding).
17    pub const unsafe fn enable() -> Self {
18        Self(true, PhantomData)
19    }
20
21    /// Returns a `CopyOptimization` hint with the optimization enabled if `value` is `true`.
22    ///
23    /// # Safety
24    ///
25    /// `T` and `U` must be the same size and must not have any uninit bytes (e.g. padding) if
26    /// `value` is `true`.
27    pub const unsafe fn enable_if(value: bool) -> Self {
28        Self(value, PhantomData)
29    }
30
31    /// Returns a `CopyOptimization` hint with the optimization disabled.
32    pub const fn disable() -> Self {
33        Self(false, PhantomData)
34    }
35
36    /// Returns whether the optimization is enabled.
37    pub const fn is_enabled(&self) -> bool {
38        self.0
39    }
40
41    /// Infers whether the conversion from `[T; N]` to `[U; N]` is copy-optimizable based on the
42    /// conversion from `T` to `U`.
43    pub const fn infer_array<const N: usize>(&self) -> CopyOptimization<[T; N], [U; N]>
44    where
45        T: Sized,
46        U: Sized,
47    {
48        // SAFETY: If `T` and `U` are copy-optimizable, then `[T; N]` and `[U; N]` are also
49        // copy-optimizable.
50        unsafe { CopyOptimization::enable_if(self.is_enabled()) }
51    }
52
53    /// Infers whether the conversion from `[T]` to `[U]` is copy-optimizable based on the
54    /// conversion from `T` to `U`.
55    pub const fn infer_slice(&self) -> CopyOptimization<[T], [U]>
56    where
57        T: Sized,
58        U: Sized,
59    {
60        // SAFETY: If `T` and `U` are copy-optimizable, then `[T]` and `[U]` are also
61        // copy-optimizable.
62        unsafe { CopyOptimization::enable_if(self.is_enabled()) }
63    }
64}
65
66impl<T: ?Sized> CopyOptimization<T, T> {
67    /// Returns an enabled `CopyOptimization`, as copy optimization is always enabled from a type to
68    /// itself.
69    pub const fn identity() -> Self {
70        // SAFETY: A type is always copy-optimizable to itself.
71        unsafe { Self::enable() }
72    }
73}