secure_gate/macros/dynamic_alias.rs
1/// Creates a type alias for [`Dynamic<T>`](crate::Dynamic).
2///
3/// Generates a named, optionally-documented type alias. The generated type inherits
4/// all `Dynamic<T>` methods including `expose_secret()`, `with_secret()`, `to_hex()`, etc.
5///
6/// *Requires feature `alloc`.*
7///
8/// # Syntax
9///
10/// ```text
11/// dynamic_alias!(pub Name, T); // public, auto-generated doc
12/// dynamic_alias!(pub(crate) Name, T); // crate-visible
13/// dynamic_alias!(Name, T); // private
14/// dynamic_alias!(pub Name, T, "doc string"); // with custom doc
15/// ```
16///
17/// # Examples
18///
19/// All three visibility forms:
20///
21/// ```rust
22/// use secure_gate::{dynamic_alias, RevealSecret};
23///
24/// dynamic_alias!(pub Password, String); // public
25/// dynamic_alias!(pub(crate) SessionToken, Vec<u8>); // crate-visible
26/// dynamic_alias!(private_key_bytes, Vec<u8>); // private
27///
28/// let pw: Password = "hunter2".into();
29/// pw.with_secret(|s| assert!(!s.is_empty()));
30/// ```
31///
32/// With a custom doc string:
33///
34/// ```rust
35/// use secure_gate::{dynamic_alias, RevealSecret};
36///
37/// dynamic_alias!(pub Token, Vec<u8>, "OAuth 2.0 bearer token.");
38/// let token: Token = vec![1u8, 2, 3].into();
39/// assert_eq!(token.expose_secret(), &[1, 2, 3]);
40/// ```
41///
42/// # Implementation Notes
43///
44/// `dynamic_alias!` has **no zero-size or type-level guard** — any `T` is accepted.
45/// Macro-generated aliases lack runtime size checks beyond what `Dynamic<T>` itself provides.
46/// Note that unlike `fixed_alias!`, this macro (and the generic dynamic variant) allows zero-sized or empty inner types with no compile-time rejection.
47/// Validate expected inner types and sizes in unit tests:
48///
49/// ```rust
50/// use secure_gate::dynamic_alias;
51///
52/// dynamic_alias!(pub ApiToken, Vec<u8>);
53/// // In your tests: assert!(token.len() > 0);
54/// ```
55///
56/// # Security
57///
58/// Generated aliases inherit all [`Dynamic`](crate::Dynamic) security guarantees: zeroize
59/// on drop (including spare capacity), redacted `Debug`, explicit access only.
60///
61/// # See also
62///
63/// - [`dynamic_generic_alias!`](crate::dynamic_generic_alias) — when the inner type varies
64/// - [`fixed_alias!`](crate::fixed_alias) — stack-allocated alternative
65#[cfg(feature = "alloc")]
66#[macro_export]
67macro_rules! dynamic_alias {
68 ($vis:vis $name:ident, $inner:ty, $doc:literal) => {
69 #[doc = $doc]
70 $vis type $name = $crate::Dynamic<$inner>;
71 };
72 ($vis:vis $name:ident, $inner:ty) => {
73 #[doc = concat!("Secure heap-allocated ", stringify!($inner))]
74 $vis type $name = $crate::Dynamic<$inner>;
75 };
76 ($name:ident, $inner:ty, $doc:literal) => {
77 #[doc = $doc]
78 type $name = $crate::Dynamic<$inner>;
79 };
80 ($name:ident, $inner:ty) => {
81 #[doc = concat!("Secure heap-allocated ", stringify!($inner))]
82 type $name = $crate::Dynamic<$inner>;
83 };
84}