1use crate::lex::{Cursor, LexError, Scan};
2use crate::span::DelimSpan;
3use crate::{Delim, Span, TokenStream, TokenTree};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Group {
7 pub(crate) delim: Delim,
8 pub(crate) span: DelimSpan,
9 pub(crate) tokens: TokenStream,
10}
11
12impl Group {
13 #[inline]
14 pub fn new(delim: Delim, stream: TokenStream) -> Self {
15 Self {
16 delim,
17 span: DelimSpan::new(Span::call_site(), Span::call_site()),
18 tokens: stream,
19 }
20 }
21
22 #[inline]
23 pub fn delim(&self) -> Delim {
24 self.delim
25 }
26
27 #[inline]
28 pub fn span(&self) -> DelimSpan {
29 self.span
30 }
31
32 #[inline]
33 pub fn stream(&self) -> &TokenStream {
34 &self.tokens
35 }
36
37 #[inline]
38 pub fn set_span(&mut self, span: DelimSpan) {
39 self.span = span;
40 }
41
42 #[inline]
43 pub fn to_token_tree(&self) -> TokenTree {
44 TokenTree::Group(self.clone())
45 }
46
47 #[inline]
48 pub fn into_token_tree(self) -> TokenTree {
49 TokenTree::Group(self)
50 }
51}
52
53impl std::fmt::Display for Group {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 match self.delim {
56 Delim::None => write!(f, "{}", self.tokens),
57 d => write!(f, "{}{}{}", d.open(), self.tokens, d.close()),
58 }
59 }
60}
61
62impl Scan for Group {
63 fn scan(cursor: Cursor<'_>) -> Result<(Cursor<'_>, Self), LexError> {
64 let ch = cursor.first().ok_or(cursor.error())?;
65 let delim = Delim::from_open(ch).ok_or(cursor.error())?;
66 let c = cursor.advance_by(ch.len_utf8());
67 let (c, inner) = TokenStream::scan(c)?;
68 let close_ch = c
69 .first()
70 .ok_or_else(|| cursor.error().message(format!("unclosed delimiter '{}'", delim.open())))?;
71
72 let close_delim = Delim::from_close(close_ch).ok_or_else(|| {
73 c.error()
74 .message(format!("expected '{}', found '{}'", delim.close(), close_ch))
75 })?;
76
77 if delim != close_delim {
78 return Err(c.error().message(format!(
79 "mismatched delimiter: expected '{}', found '{}'",
80 delim.close(),
81 close_ch,
82 )));
83 }
84
85 let c = c.advance_by(close_ch.len_utf8());
86 let mut group = Self::new(delim, inner);
87 group.set_span(DelimSpan::new(cursor.span(), c.span()));
88
89 Ok((c, group))
90 }
91}
92
93impl crate::ToTokens for Group {
94 fn to_tokens(&self, tokens: &mut crate::TokenStream) {
95 tokens.extend_one(crate::TokenTree::Group(self.clone()));
96 }
97}
98
99impl crate::Spanner for Group {
100 fn span(&self) -> Span {
101 self.span.span()
102 }
103}
104
105#[cfg(feature = "serde")]
106impl serde::Serialize for Group {
107 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
108 where
109 S: serde::Serializer,
110 {
111 use serde::ser::SerializeStruct;
112
113 let mut o = s.serialize_struct("Group", 2)?;
114 o.serialize_field("delim", &self.delim)?;
115 o.serialize_field("tokens", &self.tokens)?;
116 o.end()
117 }
118}