pub struct Fixed<T>(/* private fields */);Expand description
Stack-allocated secure secret wrapper.
This is a zero-cost wrapper for fixed-size secrets like byte arrays or primitives. The inner field is private, forcing all access through explicit methods.
Security invariants:
- No
DereforAsRef— prevents silent access or borrowing. - No implicit
Copy— even for[u8; N], duplication must be explicit via.clone(). Debugis always redacted.
§Examples
Basic usage:
use secure_gate::Fixed;
let secret = Fixed::new(42u32);
assert_eq!(*secret.expose_secret(), 42);For byte arrays (most common):
use secure_gate::{Fixed, fixed_alias};
fixed_alias!(Aes256Key, 32);
let key_bytes = [0x42u8; 32];
let key: Aes256Key = Fixed::from(key_bytes);
assert_eq!(key.len(), 32);
assert_eq!(key.expose_secret()[0], 0x42);With zeroize feature (automatic wipe on drop):
use secure_gate::Fixed;
let mut secret = Fixed::new([1u8, 2, 3]);
drop(secret); // memory wiped automaticallyImplementations§
Source§impl<T> Fixed<T>
impl<T> Fixed<T>
Sourcepub const fn new(value: T) -> Self
pub const fn new(value: T) -> Self
Wrap a value in a Fixed secret.
This is zero-cost and const-friendly.
§Example
use secure_gate::Fixed;
const SECRET: Fixed<u32> = Fixed::new(42);Sourcepub const fn expose_secret(&self) -> &T
pub const fn expose_secret(&self) -> &T
Expose the inner value for read-only access.
This is the only way to read the secret — loud and auditable.
§Example
use secure_gate::Fixed;
let secret = Fixed::new("hunter2");
assert_eq!(secret.expose_secret(), &"hunter2");Sourcepub fn expose_secret_mut(&mut self) -> &mut T
pub fn expose_secret_mut(&mut self) -> &mut T
Expose the inner value for mutable access.
This is the only way to mutate the secret — loud and auditable.
§Example
use secure_gate::Fixed;
let mut secret = Fixed::new([1u8, 2, 3]);
secret.expose_secret_mut()[0] = 42;
assert_eq!(secret.expose_secret()[0], 42);Sourcepub fn into_inner(self) -> T
pub fn into_inner(self) -> T
Consume the wrapper and return the inner value.
Useful for passing secrets to functions that consume ownership.
Note: If zeroize is enabled, prefer dropping the Fixed to ensure wiping.
§Example
use secure_gate::Fixed;
let secret = Fixed::new(42u32);
let inner = secret.into_inner();
assert_eq!(inner, 42);Sourcepub fn no_clone(self) -> FixedNoClone<T>
pub fn no_clone(self) -> FixedNoClone<T>
Convert to a non-cloneable variant.
This prevents accidental cloning of the secret.
§Example
use secure_gate::Fixed;
let secret = Fixed::new([1u8; 32]);
let no_clone = secret.no_clone();
// no_clone cannot be clonedSource§impl<const N: usize> Fixed<[u8; N]>
impl<const N: usize> Fixed<[u8; N]>
Sourcepub const fn len(&self) -> usize
pub const fn len(&self) -> usize
Returns the fixed length in bytes.
This is safe public metadata — does not expose the secret.
Sourcepub const fn is_empty(&self) -> bool
pub const fn is_empty(&self) -> bool
Returns true if the fixed secret is empty (zero-length).
This is safe public metadata — does not expose the secret.
Sourcepub fn from_slice(bytes: &[u8]) -> Self
pub fn from_slice(bytes: &[u8]) -> Self
Create from a byte slice of exactly N bytes.
Panics if the slice length does not match N.
§Example
use secure_gate::Fixed;
let bytes: &[u8] = &[1, 2, 3];
let secret = Fixed::<[u8; 3]>::from_slice(bytes);
assert_eq!(secret.expose_secret(), &[1, 2, 3]);Trait Implementations§
impl<T: Zeroize> ZeroizeOnDrop for Fixed<T>
zeroize only.