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}