valence_command/parsers/
strings.rs

1use bevy_derive::Deref;
2use valence_server::protocol::packets::play::command_tree_s2c::StringArg;
3
4use super::Parser;
5use crate::parsers::{CommandArg, CommandArgParseError, ParseInput};
6
7impl CommandArg for String {
8    fn parse_arg(input: &mut ParseInput) -> Result<Self, CommandArgParseError> {
9        input.skip_whitespace();
10        Ok(input.pop_word().to_owned())
11    }
12
13    fn display() -> Parser {
14        Parser::String(StringArg::SingleWord)
15    }
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Default, Deref)]
19pub struct GreedyString(pub String);
20
21impl CommandArg for GreedyString {
22    fn parse_arg(input: &mut ParseInput) -> Result<Self, CommandArgParseError> {
23        input.skip_whitespace();
24        Ok(GreedyString(
25            match input.pop_all() {
26                Some(s) => s,
27                None => return Err(CommandArgParseError::InvalidArgLength),
28            }
29            .to_owned(),
30        ))
31    }
32
33    fn display() -> Parser {
34        Parser::String(StringArg::GreedyPhrase)
35    }
36}
37
38#[derive(Debug, Clone, PartialEq, Eq, Default, Deref)]
39pub struct QuotableString(pub String);
40
41impl CommandArg for QuotableString {
42    fn parse_arg(input: &mut ParseInput) -> Result<Self, CommandArgParseError> {
43        input.skip_whitespace();
44        match input.peek() {
45            Some('"') => {
46                input.pop();
47                let mut s = String::new();
48                let mut escaped = false;
49                while let Some(c) = input.pop() {
50                    if escaped {
51                        s.push(c);
52                        escaped = false;
53                    } else if c == '\\' {
54                        escaped = true;
55                    } else if c == '"' {
56                        return Ok(QuotableString(s));
57                    } else {
58                        s.push(c);
59                    }
60                }
61                Err(CommandArgParseError::InvalidArgLength)
62            }
63            Some(_) => Ok(QuotableString(String::parse_arg(input)?)),
64            None => Err(CommandArgParseError::InvalidArgLength),
65        }
66    }
67
68    fn display() -> Parser {
69        Parser::String(StringArg::QuotablePhrase)
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn test_quotable_string() {
79        let mut input = ParseInput::new("\"hello world\"");
80        assert_eq!(
81            "hello world",
82            QuotableString::parse_arg(&mut input).unwrap().0
83        );
84        assert!(input.is_done());
85
86        let mut input = ParseInput::new("\"hello w\"orld");
87        assert_eq!("hello w", QuotableString::parse_arg(&mut input).unwrap().0);
88        assert!(!input.is_done());
89
90        let mut input = ParseInput::new("hello world\"");
91        assert_eq!("hello", QuotableString::parse_arg(&mut input).unwrap().0);
92        assert!(!input.is_done());
93    }
94
95    #[test]
96    fn test_greedy_string() {
97        let mut input = ParseInput::new("hello world");
98        assert_eq!(
99            "hello world",
100            GreedyString::parse_arg(&mut input).unwrap().0
101        );
102        assert!(input.is_done());
103    }
104    #[test]
105    fn test_string() {
106        let mut input = ParseInput::new("hello world");
107        assert_eq!("hello", String::parse_arg(&mut input).unwrap());
108        assert_eq!("world", String::parse_arg(&mut input).unwrap());
109        assert!(input.is_done());
110    }
111}