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}