vitaminc_protected/as_protected_ref.rs
1use crate::Controlled;
2use std::borrow::Cow;
3
4/// Trait for types that can be converted to a `ProtectedRef`.
5/// Conceptually similar to the `AsRef` trait in `std` but for `Protected` types.
6/// This prevents the inner value from being accessed directly.
7/// The trait is sealed so it cannot be implemented outside of this crate.
8///
9/// # Implementing `AsProtectedRef`
10///
11/// Implementing `AsProtectedRef` for a type allows it to be used in functions that take a `ProtectedRef`.
12/// Note, that such implementations must be defined on inner types that already implement `AsProtectedRef`
13/// because `ProtectedRef` cannot be constructed from the inner type directly.
14///
15/// ```
16/// use vitaminc_protected::{AsProtectedRef, Protected, ProtectedRef};
17///
18/// pub struct SensitiveData(Protected<Vec<u8>>);
19///
20/// impl AsProtectedRef<'_, Vec<u8>> for SensitiveData {
21/// fn as_protected_ref(&self) -> ProtectedRef<Vec<u8>> {
22/// self.0.as_protected_ref()
23/// }
24/// }
25///
26/// let data = SensitiveData(Protected::new(Vec::new()));
27/// let pref: ProtectedRef<Vec<u8>> = data.as_protected_ref();
28/// ```
29///
30pub trait AsProtectedRef<'a, A: ?Sized> {
31 fn as_protected_ref(&'a self) -> ProtectedRef<'a, A>;
32}
33
34impl<'a, T> AsProtectedRef<'a, <T as Controlled>::Inner> for T
35where
36 //<T as ControlledPrivate>::Inner: AsRef<A>,
37 T: Controlled,
38{
39 fn as_protected_ref(&'a self) -> ProtectedRef<'a, <T as Controlled>::Inner> {
40 ProtectedRef(self.risky_ref())
41 }
42}
43
44impl<'a, const N: usize> AsProtectedRef<'a, [u8; N]> for [u8; N] {
45 fn as_protected_ref(&'a self) -> ProtectedRef<'a, [u8; N]> {
46 ProtectedRef(self)
47 }
48}
49
50// TODO: This is only really needed for compatability (so that types not using this API don't have to be moved).
51// It might make sense to put this behind a feature flag.
52/// String references cannot be zeroized, so we can't implement `Zeroize` for `Protected<&str>`.
53/// Instead, we implement `AsProtectedRef` to allow the use of string references in functions that take them.
54impl<'a> AsProtectedRef<'a, [u8]> for str {
55 fn as_protected_ref(&'a self) -> ProtectedRef<'a, [u8]> {
56 ProtectedRef(self.as_bytes())
57 }
58}
59
60impl<'a> AsProtectedRef<'a, [u8]> for Cow<'a, str> {
61 fn as_protected_ref(&'a self) -> ProtectedRef<'a, [u8]> {
62 ProtectedRef(self.as_bytes())
63 }
64}
65
66/// A wrapper around a reference to prevent inner access.
67/// Conceptually similar to `&T` but prevents direct access to the inner value outside of this crate.
68pub struct ProtectedRef<'a, T>(&'a T)
69where
70 T: ?Sized;
71
72impl<'a, T: ?Sized> ProtectedRef<'a, T> {
73 pub(crate) fn inner_ref(&self) -> &T {
74 self.0
75 }
76}