secure_gate/scoped.rs
1//! Scoped access shared by plain and sealed secrets. Requires the `sealed` feature.
2//!
3//! [`RevealScoped`] is the part of [`RevealSecret`] that a sealed type can also offer:
4//! access through a closure, with no reference that outlives it. It is implemented for
5//! every [`RevealSecret`] type by a blanket impl, and directly for
6//! [`SealedFixed`](crate::SealedFixed) and [`SealedDynamic`](crate::SealedDynamic), so
7//! generic code that only reads through a closure can take either.
8//!
9//! ```rust
10//! use secure_gate::scoped::RevealScoped;
11//! use secure_gate::{Fixed, Prekey, SealedFixed};
12//!
13//! fn first_byte<S: RevealScoped<Inner = [u8; 32]>>(s: &S) -> u8 {
14//! s.with_secret(|b| b[0])
15//! }
16//!
17//! let prekey = Prekey::new();
18//! assert_eq!(first_byte(&Fixed::new([1u8; 32])), 1);
19//! assert_eq!(first_byte(&SealedFixed::seal(Fixed::new([2u8; 32]), &prekey)), 2);
20//! ```
21//!
22//! # Why this trait is not at the crate root
23//!
24//! Its method is named `with_secret`, like [`RevealSecret`]'s. If both were re-exported
25//! from the root, `use secure_gate::*;` would put both in scope and every
26//! `fixed.with_secret(..)` would fail with `E0034` (multiple applicable items). Import it
27//! by path, as above. Sealed types also have `with_secret` as an inherent method, so
28//! calling it on them needs no import at all.
29//!
30//! The same collision happens in any scope that imports both traits by name. There, call
31//! the one you mean with a qualified path: `RevealScoped::with_secret(&s, |b| ..)`.
32
33use crate::RevealSecret;
34
35/// Read access through a closure only. See the [module docs](self).
36pub trait RevealScoped {
37 /// The secret's type as the closure sees it.
38 type Inner: ?Sized;
39
40 /// Calls `f` with a reference to the secret that cannot outlive the call.
41 fn with_secret<F, R>(&self, f: F) -> R
42 where
43 F: FnOnce(&Self::Inner) -> R;
44}
45
46impl<T: RevealSecret + ?Sized> RevealScoped for T {
47 type Inner = <T as RevealSecret>::Inner;
48
49 #[inline(always)]
50 fn with_secret<F, R>(&self, f: F) -> R
51 where
52 F: FnOnce(&Self::Inner) -> R,
53 {
54 RevealSecret::with_secret(self, f)
55 }
56}