udled_tokenizers/
string.rs

1use alloc::format;
2use udled::{
3    any, tokenizers::Exclude, AsChar, AsSlice, Buffer, Error, Item, Reader, Tokenizer, TokenizerExt,
4};
5
6#[derive(Debug, Clone, Copy, Default)]
7pub struct Str;
8
9impl<'input, B> Tokenizer<'input, B> for Str
10where
11    B: Buffer<'input>,
12    B::Item: AsChar,
13    B::Source: AsSlice<'input>,
14{
15    type Token = Item<<B::Source as AsSlice<'input>>::Slice>;
16    fn to_token<'a>(&self, reader: &mut Reader<'_, 'input, B>) -> Result<Self::Token, Error> {
17        reader.parse(
18            (
19                '"',
20                ('\\', any!('\\', '\'', '"', 'r', 'n', '0'))
21                    .or(Exclude::new('\\'.or('"')))
22                    .until('"')
23                    .optional(),
24                '"'.map_err(|_, _| format!("Expected unicode string")),
25            )
26                .slice(),
27        )
28    }
29
30    fn peek<'a>(&self, reader: &mut Reader<'_, 'input, B>) -> bool {
31        reader.is('"')
32    }
33}
34
35#[cfg(test)]
36mod test {
37
38    use udled::{Input, Span};
39
40    use super::*;
41
42    #[test]
43    fn empty_string() {
44        let mut input = Input::new(r#""""#);
45        let str = input.parse(Str).unwrap();
46        assert_eq!(str.value, r#""""#);
47        assert_eq!(str.span, Span::new(0, 2));
48    }
49
50    #[test]
51    fn string() {
52        let mut input = Input::new(r#""Hello, World!""#);
53        let str = input.parse(Str).unwrap();
54        assert_eq!(str.value, r#""Hello, World!""#);
55        assert_eq!(str.span, Span::new(0, 15));
56    }
57
58    #[test]
59    fn string_escape() {
60        let mut input = Input::new(r#""Hello, \n World!""#);
61        let str = input.parse(Str).unwrap();
62        assert_eq!(str.value, r#""Hello, \n World!""#);
63        assert_eq!(str.span, Span::new(0, 18));
64    }
65}