Skip to main content

secure_gate/macros/
fixed_alias.rs

1/// Creates a type alias for [`Fixed<[u8; N]>`](crate::Fixed).
2///
3/// Generates a named, optionally-documented type alias with a compile-time zero-size guard.
4/// The generated type inherits all `Fixed<[u8; N]>` methods including `expose_secret()`,
5/// `with_secret()`, `to_hex()`, etc.
6///
7/// # Syntax
8///
9/// ```text
10/// fixed_alias!(pub Name, N);                // public, auto-generated doc
11/// fixed_alias!(pub(crate) Name, N);         // crate-visible
12/// fixed_alias!(Name, N);                    // private
13/// fixed_alias!(pub Name, N, "doc string");  // with custom doc
14/// ```
15///
16/// # Examples
17///
18/// All three visibility forms:
19///
20/// ```rust
21/// use secure_gate::{fixed_alias, RevealSecret};
22///
23/// fixed_alias!(pub Aes256Key, 32);           // public
24/// fixed_alias!(pub(crate) HmacKey, 32);      // crate-visible
25/// fixed_alias!(private_nonce, 12);           // private (no modifier)
26///
27/// let key: Aes256Key = [42u8; 32].into();
28/// key.with_secret(|b| assert_eq!(b.len(), 32));
29/// ```
30///
31/// With a custom doc string:
32///
33/// ```rust
34/// use secure_gate::{fixed_alias, RevealSecret};
35///
36/// fixed_alias!(pub ApiKey, 32, "32-byte API authentication key.");
37/// let key: ApiKey = [0u8; 32].into();
38/// assert_eq!(key.expose_secret(), &[0u8; 32]);
39/// ```
40///
41/// Zero-size is a **compile error** (caught by the zero-size guard):
42///
43/// ```rust,compile_fail
44/// use secure_gate::fixed_alias;
45/// fixed_alias!(pub Bad, 0); // compile-time error: index out of bounds
46/// ```
47///
48/// # Implementation Notes
49///
50/// Each expansion emits `const _: () = { let _ = [(); N][0]; };` — a zero-cost
51/// compile-time guard that rejects `N = 0` with a const-evaluation panic.
52/// This is the **only** size check performed at compile time; there are no
53/// runtime checks for other size constraints. Validate expected sizes in unit tests:
54///
55/// ```rust
56/// use secure_gate::{fixed_alias, RevealSecret};
57///
58/// fixed_alias!(pub ChaChaKey, 32);
59/// // In your tests:
60/// assert_eq!(core::mem::size_of::<ChaChaKey>(), 32);
61/// ```
62///
63/// # Security
64///
65/// Generated aliases inherit all [`Fixed`](crate::Fixed) security guarantees: zeroize on
66/// drop, redacted `Debug`, explicit access only.
67///
68/// # See also
69///
70/// - [`fixed_generic_alias!`](crate::fixed_generic_alias) — when multiple sizes are needed
71/// - [`dynamic_alias!`](crate::dynamic_alias) — heap-allocated alternative
72#[macro_export]
73macro_rules! fixed_alias {
74    ($vis:vis $name:ident, $size:literal, $doc:literal) => {
75        #[doc = $doc]
76        const _: () = { let _ = [(); $size][0]; };
77        $vis type $name = $crate::Fixed<[u8; $size]>;
78    };
79    ($vis:vis $name:ident, $size:literal) => {
80        #[doc = concat!("Fixed-size secure secret (", stringify!($size), " bytes)")]
81        const _: () = { let _ = [(); $size][0]; };
82        $vis type $name = $crate::Fixed<[u8; $size]>;
83    };
84    ($name:ident, $size:literal, $doc:literal) => {
85        #[doc = $doc]
86        const _: () = { let _ = [(); $size][0]; };
87        type $name = $crate::Fixed<[u8; $size]>;
88    };
89    ($name:ident, $size:literal) => {
90        #[doc = concat!("Fixed-size secure secret (", stringify!($size), " bytes)")]
91        const _: () = { let _ = [(); $size][0]; };
92        type $name = $crate::Fixed<[u8; $size]>;
93    };
94}