wlan_common/
sequestered.rs

1// Copyright 2022 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
5//! Data isolation.
6
7// TODO(https://fxbug.dev/42067751): This type should not derive `PartialEq`. Though it only allows trivial
8//                         observation (i.e., "is this black box the same as that black box?"),
9//                         that is observation nonetheless and client code could foreseeably branch
10//                         based on this query. It is implemented to ease the implementation of
11//                         tests, where assertions of equality are ubiquitous.
12/// Isolates data such that it is inaccessible without explicitly releasing it.
13///
14/// Sequestered data cannot be directly read nor written while contained (though it can be
15/// trivially replaced). This is useful for data that must be "ferried" through a system but should
16/// not generally be examined nor inspected, in particular when inspection of the data would
17/// otherwise seem innocuous but implicitly violates a design contract or introduces an unwanted
18/// data dependency.
19///
20/// **This type cannot completely prevent reads and writes.** Rather, it makes reads and writes
21/// very explicit and more obvious in order to avoid mistakes in data APIs.
22///
23/// Sequestering data is trivial and is done via the core `From` and `Into` traits. Releasing data
24/// is intentionally more explicit and requires the use of fully-qualified syntax that names the
25/// `Sequestered` type.
26///
27/// As sequestered data is considered a "black box", `Sequestered` only implements the `Clone` and
28/// `Debug` traits (so long as the type `T` provides implementations). Note that `Copy` is not
29/// implemented, because releasing data would not be strictly affine and data could be implicitly
30/// copied out of fields via `release`. This is not only implicit, but can be counterintuitive in
31/// some contexts, because `release` moves a copy of the `Sequestered`.
32///
33/// `Sequestered` also implements `PartialEq` largely for testing. See https://fxbug.dev/42067751.
34#[derive(Clone, Debug, PartialEq)]
35#[repr(transparent)]
36pub struct Sequestered<T>(T);
37
38impl<T> Sequestered<T> {
39    /// Releases the sequestered data.
40    ///
41    /// Releasing should be performed sparingly, carefully, and typically at API boundaries where
42    /// there is no longer a need to prevent reads of the data. Releases, which are explicit,
43    /// should be given extra scrutiny, somewhat like `unsafe` code.
44    ///
45    /// This function does not use a receiver and so requires fully-qualified syntax in order to
46    /// make releases more explicit and obvious.
47    ///
48    /// # Examples
49    ///
50    /// ```rust,ignore
51    /// // Sequester data.
52    /// let text: Sequestered<&'static str> = "lorem ipsum".into();
53    /// // Release data. The fully-qualified syntax is required.
54    /// let text = Sequestered::release(text);
55    /// ```
56    #[inline(always)]
57    pub fn release(sequestered: Self) -> T {
58        sequestered.0
59    }
60}
61
62impl<T> From<T> for Sequestered<T> {
63    #[inline(always)]
64    fn from(inner: T) -> Self {
65        Sequestered(inner)
66    }
67}