1#![forbid(unsafe_code)]
9
10extern crate proc_macro;
11
12use irox_tools::iterators::Itertools;
13use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
14
15pub trait DeriveMethods: Extend<TokenStream> + Extend<TokenTree> {
18 fn add_ident(&mut self, name: &str) {
20 self.extend(Self::create_ident(name))
21 }
22 fn create_punct(ch: char) -> TokenStream {
24 TokenStream::from_iter([TokenTree::Punct(Punct::new(ch, Spacing::Alone))])
25 }
26 fn create_punct2(ch: char, ch2: char) -> TokenStream {
28 TokenStream::from_iter([
29 TokenTree::Punct(Punct::new(ch, Spacing::Joint)),
30 TokenTree::Punct(Punct::new(ch2, Spacing::Alone)),
31 ])
32 }
33 fn create_literal(val: &str) -> TokenStream {
35 TokenStream::from_iter([TokenTree::Literal(Literal::string(val))])
36 }
37 fn create_ident(name: &str) -> TokenStream {
39 TokenStream::from_iter([TokenTree::Ident(Ident::new(name, Span::call_site()))])
40 }
41 fn create_ref_ident(name: &str) -> TokenStream {
43 TokenStream::from_iter([Self::create_punct('&'), Self::create_ident(name)])
44 }
45 fn create_ref_ident_lifetime(name: &str, lifetime: &str) -> TokenStream {
47 TokenStream::from_iter([
48 TokenStream::from_iter([
49 TokenTree::Punct(Punct::new('&', Spacing::Alone)),
50 TokenTree::Punct(Punct::new('\'', Spacing::Joint)),
51 TokenTree::Ident(Ident::new(lifetime, Span::call_site())),
52 ]),
53 Self::create_ident(name),
54 ])
55 }
56 fn create_ref_ident_static(name: &str) -> TokenStream {
58 Self::create_ref_ident_lifetime(name, "static")
59 }
60 fn create_mut_ref_ident(name: &str) -> TokenStream {
62 TokenStream::from_iter([
63 Self::create_punct('&'),
64 Self::create_ident("mut"),
65 Self::create_ident(name),
66 ])
67 }
68 fn create_mut_ref_ident_lifetime(name: &str, lifetime: &str) -> TokenStream {
70 TokenStream::from_iter([
71 TokenStream::from_iter([
72 TokenTree::Punct(Punct::new('&', Spacing::Alone)),
73 TokenTree::Punct(Punct::new('\'', Spacing::Joint)),
74 TokenTree::Ident(Ident::new(lifetime, Span::call_site())),
75 ]),
76 Self::create_ident("mut"),
77 Self::create_ident(name),
78 ])
79 }
80 fn create_wrapped_braces(inner: TokenStream) -> TokenStream {
82 TokenStream::from_iter([TokenTree::Group(Group::new(Delimiter::Brace, inner))])
83 }
84 fn add_punc(&mut self, ch: char) {
86 self.extend(Self::create_punct(ch))
87 }
88 fn add_punc2(&mut self, ch: char, ch2: char) {
90 self.extend([
91 TokenTree::Punct(Punct::new(ch, Spacing::Joint)),
92 TokenTree::Punct(Punct::new(ch2, Spacing::Alone)),
93 ])
94 }
95 fn add_comma(&mut self) {
97 self.add_punc(',')
98 }
99 fn wrap_generics(&mut self, inner: TokenStream) {
101 self.add_punc('<');
102 self.extend([inner]);
103 self.add_punc('>');
104 }
105
106 fn add_fn(&mut self, name: &str) {
108 self.add_ident("fn");
109 self.add_ident(name);
110 }
111 fn add_generics(&mut self, id: &str, generics: TokenStream) {
113 self.add_punc('<');
114 self.add_ident(id);
115 self.add_punc(':');
116 self.extend(generics);
117 self.add_punc('>');
118 }
119 fn create_path(elems: &[&str]) -> TokenStream {
121 elems
122 .iter()
123 .map(|e| TokenTree::Ident(Ident::new(e, Span::call_site())))
124 .joining_multi(&[
125 TokenTree::Punct(Punct::new(':', Spacing::Joint)),
126 TokenTree::Punct(Punct::new(':', Spacing::Alone)),
127 ])
128 .collect()
129 }
130 fn add_path(&mut self, elems: &[&str]) {
132 self.extend(Self::create_path(elems))
133 }
134 fn add_parens(&mut self, inside_parens: TokenStream) {
136 self.extend([TokenTree::Group(Group::new(
137 Delimiter::Parenthesis,
138 inside_parens,
139 ))]);
140 }
141 fn add_single_arrow(&mut self) {
143 self.add_punc2('-', '>')
144 }
145 fn add_double_arrow(&mut self) {
147 self.add_punc2('=', '>')
148 }
149 fn append_match_item(&mut self, matching: TokenStream, result: TokenStream) {
151 self.extend([
152 matching,
153 TokenStream::from_iter([
154 TokenTree::Punct(Punct::new('=', Spacing::Joint)),
155 TokenTree::Punct(Punct::new('>', Spacing::Alone)),
156 ]),
157 TokenStream::create_wrapped_braces(result),
158 TokenStream::create_punct(','),
159 ])
160 }
161 fn return_result(&mut self, ok: TokenStream, err: TokenStream) {
163 self.add_single_arrow();
164 self.add_ident("Result");
165 self.add_punc('<');
166 self.extend(ok);
167 self.add_punc(',');
168 self.extend(err);
169 self.add_punc('>');
170 }
171
172 fn create_empty_type() -> TokenStream {
174 TokenStream::from_iter([TokenTree::Group(Group::new(
175 Delimiter::Parenthesis,
176 TokenStream::new(),
177 ))])
178 }
179
180 fn wrap_braces(&mut self, inner: TokenStream) {
182 self.extend([TokenTree::Group(Group::new(Delimiter::Brace, inner))])
183 }
184 fn wrap_brackets(&mut self, inner: TokenStream) {
186 self.extend([TokenTree::Group(Group::new(Delimiter::Bracket, inner))])
187 }
188
189 fn add_literal(&mut self, literal: Literal) {
191 self.extend([TokenTree::Literal(literal)])
192 }
193
194 fn add_ident_type(&mut self, ident: Ident) {
196 self.extend([TokenTree::Ident(ident)])
197 }
198 fn add_must_use(&mut self) {
200 self.extend([
201 TokenTree::Punct(Punct::new('#', Spacing::Alone)),
202 TokenTree::Group(Group::new(
203 Delimiter::Bracket,
204 TokenStream::create_ident("must_use"),
205 )),
206 ])
207 }
208 fn add_getter(&mut self, name: &str, output_type: TokenStream) {
209 self.add_ident("pub");
210 self.add_ident("fn");
211 self.add_ident(name);
212 self.add_parens(TokenStream::create_ref_ident("self"));
213 self.add_single_arrow();
214 self.extend([output_type])
215 }
216}
217
218impl DeriveMethods for TokenStream {}