secure_gate/macros/fixed_generic_alias.rs
1/// Creates a const-generic type alias `Name<const N: usize>` for [`Fixed<[u8; N]>`](crate::Fixed).
2///
3/// Useful when you need a single reusable name for fixed-size secrets across multiple sizes.
4///
5/// # Syntax
6///
7/// ```text
8/// fixed_generic_alias!(pub Name, "doc string"); // public with custom doc
9/// fixed_generic_alias!(pub(crate) Name); // crate-visible, auto-generated doc
10/// ```
11///
12/// # Examples
13///
14/// ```rust
15/// use secure_gate::{fixed_generic_alias, RevealSecret};
16///
17/// fixed_generic_alias!(pub SecretBuffer, "Generic fixed-size secret buffer.");
18///
19/// let key: SecretBuffer<32> = [0u8; 32].into();
20/// key.with_secret(|b| assert_eq!(b.len(), 32));
21///
22/// let nonce: SecretBuffer<12> = [0u8; 12].into();
23/// nonce.with_secret(|b| assert_eq!(b.len(), 12));
24/// ```
25///
26/// # Implementation Notes
27///
28/// Unlike [`fixed_alias!`](crate::fixed_alias), which rejects `N = 0` at the call site
29/// via a compile-time index-out-of-bounds trick, `fixed_generic_alias!` cannot apply
30/// that guard because `N` is a const generic parameter not known at macro-invocation
31/// time. As a result, `SecretBuffer::<0>` compiles successfully and produces a
32/// zero-byte `Fixed<[u8; 0]>`. Such a type is valid Rust but has no cryptographic
33/// utility and should never appear in production code. Validate that `N > 0` in your
34/// tests (e.g. `assert!(core::mem::size_of::<SecretBuffer<32>>() == 32);`).
35///
36/// See also [`fixed_alias!`](crate::fixed_alias) (preferred when size is known at the
37/// call site) and [`dynamic_generic_alias!`](crate::dynamic_generic_alias) (heap alternative).
38#[macro_export]
39macro_rules! fixed_generic_alias {
40 ($vis:vis $name:ident, $doc:literal) => {
41 #[doc = $doc]
42 $vis type $name<const N: usize> = $crate::Fixed<[u8; N]>;
43 };
44 ($vis:vis $name:ident) => {
45 #[doc = "Fixed-size secure byte buffer"]
46 $vis type $name<const N: usize> = $crate::Fixed<[u8; N]>;
47 };
48}