Skip to main content

reifydb_macro_impl/
generate.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
5
6pub fn ident(name: &str) -> TokenTree {
7	TokenTree::Ident(Ident::new(name, Span::call_site()))
8}
9
10pub fn underscore() -> TokenTree {
11	"_".parse::<TokenStream>().unwrap().into_iter().next().unwrap()
12}
13
14#[allow(dead_code)]
15pub fn ident_raw(name: &str) -> TokenTree {
16	if let Some(stripped) = name.strip_prefix("r#") {
17		TokenTree::Ident(Ident::new_raw(stripped, Span::call_site()))
18	} else {
19		TokenTree::Ident(Ident::new(name, Span::call_site()))
20	}
21}
22
23pub fn punct(ch: char) -> TokenTree {
24	TokenTree::Punct(Punct::new(ch, Spacing::Alone))
25}
26
27pub fn punct_joint(ch: char) -> TokenTree {
28	TokenTree::Punct(Punct::new(ch, Spacing::Joint))
29}
30
31pub fn literal_str(s: &str) -> TokenTree {
32	TokenTree::Literal(Literal::string(s))
33}
34
35pub fn literal_usize(n: usize) -> TokenTree {
36	TokenTree::Literal(Literal::usize_unsuffixed(n))
37}
38
39pub fn group(delimiter: Delimiter, tokens: impl IntoIterator<Item = TokenTree>) -> TokenTree {
40	TokenTree::Group(Group::new(delimiter, tokens.into_iter().collect()))
41}
42
43pub fn parens(tokens: impl IntoIterator<Item = TokenTree>) -> TokenTree {
44	group(Delimiter::Parenthesis, tokens)
45}
46
47pub fn braces(tokens: impl IntoIterator<Item = TokenTree>) -> TokenTree {
48	group(Delimiter::Brace, tokens)
49}
50
51pub fn brackets(tokens: impl IntoIterator<Item = TokenTree>) -> TokenTree {
52	group(Delimiter::Bracket, tokens)
53}
54
55pub fn path_sep() -> impl Iterator<Item = TokenTree> {
56	[punct_joint(':'), punct(':')].into_iter()
57}
58
59pub fn path(segments: &[&str]) -> Vec<TokenTree> {
60	let mut tokens = Vec::new();
61	let mut prev_was_empty = false;
62
63	for (i, seg) in segments.iter().enumerate() {
64		let need_sep = if i == 0 {
65			seg.is_empty()
66		} else {
67			!prev_was_empty
68		};
69
70		if need_sep {
71			tokens.extend(path_sep());
72		}
73
74		if !seg.is_empty() {
75			tokens.push(ident(seg));
76		}
77
78		prev_was_empty = seg.is_empty();
79	}
80	tokens
81}
82
83pub fn arrow() -> impl Iterator<Item = TokenTree> {
84	[punct_joint('-'), punct('>')].into_iter()
85}
86
87pub fn fat_arrow() -> impl Iterator<Item = TokenTree> {
88	[punct_joint('='), punct('>')].into_iter()
89}
90
91#[allow(dead_code)]
92pub fn generics(inner: impl IntoIterator<Item = TokenTree>) -> Vec<TokenTree> {
93	let mut tokens = vec![punct('<')];
94	tokens.extend(inner);
95	tokens.push(punct('>'));
96	tokens
97}
98
99#[allow(dead_code)]
100pub fn extend(tokens: &mut Vec<TokenTree>, iter: impl IntoIterator<Item = TokenTree>) {
101	tokens.extend(iter);
102}
103
104pub fn compile_error(message: &str) -> TokenStream {
105	let tokens = vec![ident("compile_error"), punct('!'), parens([literal_str(message)])];
106	tokens.into_iter().collect()
107}