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#[macro_export]
63macro_rules! fixed_alias {
64 ($vis:vis $name:ident, $size:literal, $doc:literal) => {
65 #[doc = $doc]
66 const _: () = { let _ = [(); $size][0]; };
67 $vis type $name = $crate::Fixed<[u8; $size]>;
68 };
69 ($vis:vis $name:ident, $size:literal) => {
70 #[doc = concat!("Fixed-size secure secret (", stringify!($size), " bytes)")]
71 const _: () = { let _ = [(); $size][0]; };
72 $vis type $name = $crate::Fixed<[u8; $size]>;
73 };
74 ($name:ident, $size:literal, $doc:literal) => {
75 #[doc = $doc]
76 const _: () = { let _ = [(); $size][0]; };
77 type $name = $crate::Fixed<[u8; $size]>;
78 };
79 ($name:ident, $size:literal) => {
80 #[doc = concat!("Fixed-size secure secret (", stringify!($size), " bytes)")]
81 const _: () = { let _ = [(); $size][0]; };
82 type $name = $crate::Fixed<[u8; $size]>;
83 };
84}