1use std::borrow::Cow;
2
3#[derive(Debug, Clone)]
5pub struct TokenStream {
6 inner: String,
7}
8
9impl TokenStream {
10 pub fn new() -> Self {
12 Self {
13 inner: String::new(),
14 }
15 }
16
17 pub fn append(&mut self, ident: Ident) {
21 self.push_space();
22 self.inner.push_str(ident.as_str())
23 }
24
25 pub fn combine(&mut self, other: &TokenStream) {
29 self.push_space();
30 self.inner.push_str(&other.inner)
31 }
32
33 pub fn as_str(&self) -> &str {
35 &self.inner
36 }
37
38 pub fn into_string(self) -> String {
40 self.inner
41 }
42
43 pub fn parse<T: std::str::FromStr>(self) -> Result<T, T::Err> {
47 self.into_string().parse()
48 }
49
50 pub(crate) fn push_space(&mut self) {
51 match self.last_char() {
52 None | Some(' ') => {}
53 _ => self.inner.push(' '),
54 }
55 }
56
57 pub(crate) fn push(&mut self, c: char) {
58 self.inner.push(c)
59 }
60
61 pub(crate) fn push_str(&mut self, str: &str) {
62 self.inner.push_str(str)
63 }
64
65 fn last_char(&self) -> Option<char> {
66 self.inner.chars().last()
67 }
68}
69
70impl std::iter::FromIterator<TokenStream> for TokenStream {
71 fn from_iter<I: IntoIterator<Item = TokenStream>>(iter: I) -> Self {
72 iter.into_iter()
73 .fold(None, |accum: Option<TokenStream>, n| {
74 let mut ts = accum.unwrap_or_else(TokenStream::new);
75 ts.combine(&n);
76 Some(ts)
77 })
78 .unwrap_or(TokenStream::new())
79 }
80}
81
82#[derive(Clone, Debug)]
84pub struct Ident {
85 inner: Cow<'static, str>,
86}
87
88impl Ident {
89 pub fn new<T: Into<Cow<'static, str>>>(str: T) -> Self {
91 Self { inner: str.into() }
92 }
93
94 pub fn as_str(&self) -> &str {
96 &*self.inner
97 }
98}
99
100impl std::fmt::Display for Ident {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 write!(f, "{}", self.as_str())
103 }
104}
105impl PartialEq<&str> for Ident {
106 fn eq(&self, other: &&str) -> bool {
107 self.as_str() == *other
108 }
109}
110
111#[derive(Copy, Clone)]
113pub enum Delimiter {
114 Bracket,
116 Brace,
118 Parenthesis,
120}
121
122impl Delimiter {
123 pub fn open(self) -> char {
125 match self {
126 Delimiter::Bracket => '[',
127 Delimiter::Brace => '{',
128 Delimiter::Parenthesis => '(',
129 }
130 }
131
132 pub fn close(self) -> char {
134 match self {
135 Delimiter::Bracket => ']',
136 Delimiter::Brace => '}',
137 Delimiter::Parenthesis => ')',
138 }
139 }
140}
141
142pub struct Literal {
144 inner: String,
145}
146
147macro_rules! unsuffixed {
148 ($ty:ty => $name:ident) => {
149 pub fn $name(n: $ty) -> Self {
150 Self {
151 inner: n.to_string(),
152 }
153 }
154 };
155}
156
157impl Literal {
158 unsuffixed!(u32 => u32_unsuffixed);
159 unsuffixed!(u16 => u16_unsuffixed);
160 unsuffixed!(u8 => u8_unsuffixed);
161
162 pub fn byte_string(s: &[u8]) -> Self {
163 Self {
164 inner: format!(
165 "b\"{}\"",
166 std::str::from_utf8(s).expect("Could not turn bytes into byte literal")
167 ),
168 }
169 }
170
171 pub fn as_str(&self) -> &str {
172 &self.inner
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179 #[test]
180 fn accept_owned_and_borrowed() {
181 assert_eq!(
182 Ident::new("hello").as_str(),
183 Ident::new(String::from("hello")).as_str()
184 );
185 }
186}
187
188impl std::fmt::Display for TokenStream {
189 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190 write!(f, "{}", self.as_str())
191 }
192}