1#![allow(clippy::module_name_repetitions)]
7
8#[cfg(feature = "proc_macro2")]
9pub use proc_macro2::Delimiter;
10
11#[cfg(not(feature = "proc_macro2"))]
12pub use proc_macro::Delimiter;
13
14use crate::{
15 private, Error, Group, Parse, Parser, Result, ToTokens, TokenIter, TokenStream, TokenTree,
16};
17
18use crate::fundamental::count_tokens_recursive;
20
21macro_rules! make_group {
22 ($($name:ident: $delimiter:ident);* $(;)?) => {
23 $(
24 #[doc = stringify!(A opaque group of tokens within a $delimiter)]
25 #[derive(Debug, Clone)]
26 pub struct $name(pub Group);
27
28 impl From<$name> for Group {
29 #[inline]
30 fn from(group: $name) -> Self {
31 group.0
32 }
33 }
34
35 impl Parser for $name {
36 fn parser(tokens: &mut TokenIter) -> Result<Self> {
37 match tokens.next() {
38 Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::$delimiter => {
39 let nested_count = count_tokens_recursive(group.stream());
41 tokens.add(nested_count);
42 Ok(Self(group))
43 }
44 at => Error::unexpected_token(at, tokens),
45 }
46 }
47 }
48
49 impl ToTokens for $name {
50 fn to_tokens(&self, tokens: &mut TokenStream) {
51 self.0.to_tokens(tokens);
52 }
53 }
54
55 impl private::Sealed for $name {}
56
57 impl GroupDelimiter for $name {
58 fn delimiter(&self) -> Delimiter {
59 Delimiter::$delimiter
60 }
61 }
62
63 impl From<$name> for TokenTree {
64 fn from(group: $name) -> Self {
65 group.0.into()
66 }
67 }
68 )*
69 };
70}
71
72make_group! {
73 ParenthesisGroup: Parenthesis;
74 BraceGroup: Brace;
75 BracketGroup: Bracket;
76 NoneGroup: None;
77}
78
79#[test]
80fn test_bracegroup_into_tt() {
81 let mut token_iter = "{a b c}".to_token_iter();
82 let group = BraceGroup::parse(&mut token_iter).unwrap();
83 let _: TokenTree = group.into();
84}
85
86pub trait GroupDelimiter: private::Sealed {
88 fn delimiter(&self) -> Delimiter;
90}
91
92#[derive(Clone)]
95pub struct GroupContaining<C> {
96 pub delimiter: Delimiter,
98 pub content: C,
100}
101
102impl<C> GroupContaining<C> {
103 pub const fn new(delimiter: Delimiter, content: C) -> Self {
117 Self { delimiter, content }
118 }
119}
120
121impl<C: Parse> Parser for GroupContaining<C> {
122 fn parser(tokens: &mut TokenIter) -> Result<Self> {
123 let group = Group::parser(tokens)?;
124 let delimiter = group.delimiter();
125
126 let content = tokens.parse_group::<C>(group.stream())?;
127
128 Ok(Self { delimiter, content })
129 }
130}
131
132impl<C: ToTokens> ToTokens for GroupContaining<C> {
133 fn to_tokens(&self, tokens: &mut TokenStream) {
134 Group::new(self.delimiter, self.content.to_token_stream()).to_tokens(tokens);
135 }
136}
137
138#[mutants::skip]
139impl<C: std::fmt::Debug> std::fmt::Debug for GroupContaining<C> {
140 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
141 f.debug_struct(&format!("GroupContaining<{}>", std::any::type_name::<C>()))
142 .field("delimiter", &self.delimiter)
143 .field("content", &self.content)
144 .finish()
145 }
146}
147
148impl<C> private::Sealed for GroupContaining<C> {}
149
150impl<C> GroupDelimiter for GroupContaining<C> {
151 fn delimiter(&self) -> Delimiter {
152 self.delimiter
153 }
154}
155
156impl<C: ToTokens> From<GroupContaining<C>> for TokenTree {
157 fn from(group: GroupContaining<C>) -> Self {
158 Group::new(group.delimiter(), group.content.to_token_stream()).into()
159 }
160}
161
162#[test]
163fn test_groupcontaining_into_tt() {
164 let mut token_iter = "{a b c}".to_token_iter();
165 let group = GroupContaining::<TokenStream>::parse(&mut token_iter).unwrap();
166 let _: TokenTree = group.into();
167}
168
169macro_rules! make_group_containing {
170 ($($name:ident: $delimiter:ident);* $(;)?) => {
171 $(
172 #[doc = stringify!(Parseable content within a $delimiter)]
173 #[derive(Clone)]
174 pub struct $name<C>{
175 pub content: C
177 }
178
179 impl<C> $name<C> {
180 #[doc = stringify!(create a new $name instance)]
181 pub const fn new(content: C) -> Self {
182 Self{content}
183 }
184 }
185
186 impl<C: Parse> Parser for $name<C> {
187 fn parser(tokens: &mut TokenIter) -> Result<Self> {
188 match tokens.next() {
189 Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::$delimiter => {
190 let content = tokens.parse_group::<C>(group.stream())?;
191 Ok(Self{content})
192 }
193 at => Error::unexpected_token(at, tokens),
194 }
195 }
196 }
197
198 impl<C: ToTokens> ToTokens for $name<C> {
199 fn to_tokens(&self, tokens: &mut TokenStream) {
200 Group::new(Delimiter::$delimiter, self.content.to_token_stream()).to_tokens(tokens);
201 }
202 }
203
204 impl<C: std::fmt::Debug> std::fmt::Debug
205 for $name<C>
206 {
207 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
208 f.debug_tuple(&format!(
209 stringify!($name<{}>),
210 std::any::type_name::<C>()
211 ))
212 .field(&self.content)
213 .finish()
214 }
215 }
216
217 impl<C> private::Sealed for $name<C> {}
218
219 impl<C> GroupDelimiter for $name<C> {
220 fn delimiter(&self) -> Delimiter {
221 Delimiter::$delimiter
222 }
223 }
224
225 impl<C: ToTokens> From<$name<C>> for TokenTree {
226 fn from(group: $name<C>) -> Self {
227 Group::new(Delimiter::$delimiter, group.content.to_token_stream()).into()
228 }
229 }
230 )*
231 };
232}
233
234make_group_containing! {
235 ParenthesisGroupContaining: Parenthesis;
236 BraceGroupContaining: Brace;
237 BracketGroupContaining: Bracket;
238 NoneGroupContaining: None;
239}
240
241#[test]
242fn test_bracegroupcontaining_into_tt() {
243 let mut token_iter = "{a b c}".to_token_iter();
244 let group = BraceGroupContaining::<TokenStream>::parse(&mut token_iter).unwrap();
245 let _: TokenTree = group.into();
246}