souvenir_macros/lib.rs
1#![forbid(unsafe_code)]
2
3//! # souvenir_macros
4//!
5//! This crate contains procedural macros for
6//! [`souvenir`](https://docs.rs/souvenir/latest/souvenir/).
7//! This crate is not intended to be used directly.
8
9extern crate proc_macro;
10
11mod id;
12mod identifiable;
13mod prefix;
14mod tagged;
15
16use proc_macro::TokenStream;
17
18/// Create an `Id` based on some literal input.
19/// All inputs are verified at compile time to ensure that the `Id` is valid.
20///
21/// If the full string representation of an `Id` is provided, it is parsed.
22/// If only a prefix is provided, a random `Id` with the provided prefix will
23/// be generated at runtime.
24///
25/// ```
26/// # use souvenir::{id, Id, Tagged};
27/// let id: Id = id!("user_02v58c5a3fy30k560qrtg4");
28/// assert_eq!(id, "user_02v58c5a3fy30k560qrtg4".parse().unwrap());
29///
30/// let id2: Id = id!("user");
31/// assert_eq!(id2.prefix().to_string(), "user");
32///
33/// #[derive(Tagged)]
34/// #[souvenir(tag = "user")]
35/// struct User;
36///
37/// let id3: Id = id!(User);
38/// assert_eq!(id3.prefix().to_string(), "user");
39/// ```
40#[proc_macro]
41pub fn id(input: TokenStream) -> TokenStream {
42 id::id(input)
43}
44
45/// Create a `Prefix` based on some literal input.
46/// All inputs are verified at compile time to ensure that the `Prefix` is
47/// valid.
48///
49/// ```
50/// # use souvenir::{prefix, Id, Prefix};
51/// let prefix: Prefix = prefix!("hi");
52/// assert_eq!(prefix.to_string(), "hi");
53///
54/// let id: Id = Id::random(prefix);
55/// assert_eq!(id.prefix(), prefix);
56/// ```
57#[proc_macro]
58pub fn prefix(input: TokenStream) -> TokenStream {
59 prefix::prefix(input)
60}
61
62/// Automatically implement `Identifiable`.
63///
64/// ```
65/// # use souvenir::{id, Id, Identifiable};
66/// #[derive(Identifiable)]
67/// struct User {
68/// #[souvenir(id)]
69/// id: Id,
70/// }
71///
72/// let user = User { id: id!("user") };
73/// assert_eq!(user.id, user.id());
74/// ```
75#[proc_macro_derive(Identifiable, attributes(souvenir))]
76pub fn identifiable(input: TokenStream) -> TokenStream {
77 identifiable::identifiable(input)
78}
79
80/// Automatically implement `Tagged`.
81///
82/// ```
83/// # use souvenir::{id, prefix, Id, Tagged};
84///
85/// #[derive(Tagged)]
86/// #[souvenir(tag = "user")]
87/// struct User;
88///
89/// assert_eq!(User::PREFIX, prefix!("user"));
90/// ```
91#[proc_macro_derive(Tagged, attributes(souvenir))]
92pub fn tagged(input: TokenStream) -> TokenStream {
93 tagged::tagged(input)
94}