valence_command/
parsers.rs
1pub mod angle;
3pub mod block_pos;
4pub mod bool;
5pub mod color;
6pub mod column_pos;
7pub mod entity_anchor;
8pub mod entity_selector;
9pub mod gamemode;
10pub mod inventory_slot;
11pub mod numbers;
12pub mod rotation;
13pub mod score_holder;
14pub mod strings;
15pub mod swizzle;
16pub mod time;
17pub mod vec2;
18pub mod vec3;
19
20use std::ops::Add;
21
22pub use block_pos::BlockPos;
23pub use column_pos::ColumnPos;
24pub use entity_anchor::EntityAnchor;
25pub use entity_selector::EntitySelector;
26pub use inventory_slot::InventorySlot;
27pub use rotation::Rotation;
28pub use score_holder::ScoreHolder;
29pub use strings::{GreedyString, QuotableString};
30pub use swizzle::Swizzle;
31use thiserror::Error;
32pub use time::Time;
33use tracing::error;
34pub(crate) use valence_server::protocol::packets::play::command_tree_s2c::Parser;
35pub use vec2::Vec2;
36pub use vec3::Vec3;
37
38pub trait CommandArg: Sized {
39 fn arg_from_str(string: &str) -> Result<Self, CommandArgParseError> {
40 Self::parse_arg(&mut ParseInput::new(string))
41 }
42
43 fn parse_arg(input: &mut ParseInput) -> Result<Self, CommandArgParseError>;
44 fn display() -> Parser;
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
49pub struct ParseInput<'a>(&'a str);
50
51impl<'a> ParseInput<'a> {
52 fn advance(&mut self) {
53 self.advance_n_chars(1);
54 }
55
56 fn advance_n_chars(&mut self, n: usize) {
57 if self.is_done() {
58 return;
59 }
60 match self.0.char_indices().nth(n) {
61 Some((len, _)) => {
62 self.0 = &self.0[len..];
63 }
64 None => {
65 self.0 = &self.0[self.0.len()..];
66 }
67 }
68 }
69
70 fn advance_n_bytes(&mut self, n: usize) {
71 if self.is_done() {
72 return;
73 }
74 self.0 = &self.0[n..];
75 }
76 pub fn new(input: &'a str) -> Self {
77 ParseInput(input)
78 }
79
80 pub fn peek(&self) -> Option<char> {
82 self.0.chars().next()
83 }
84
85 pub fn peek_n(&self, n: usize) -> &'a str {
87 self.0
88 .char_indices()
89 .nth(n)
90 .map_or(self.0, |(idx, _)| &self.0[..idx])
91 }
92
93 pub fn peek_word(&self) -> &'a str {
95 self.0
96 .char_indices()
97 .find(|(_, c)| c.is_whitespace())
98 .map_or(self.0, |(idx, _)| &self.0[..idx])
99 }
100
101 pub fn is_done(&self) -> bool {
103 self.0.is_empty()
104 }
105
106 pub fn pop(&mut self) -> Option<char> {
108 let c = self.peek()?;
109 self.advance();
110 Some(c)
111 }
112
113 pub fn pop_n(&mut self, n: usize) -> &str {
115 let s = self.peek_n(n);
116 self.advance_n_bytes(s.len());
117 s
118 }
119
120 pub fn pop_word(&mut self) -> &str {
122 let s = self.peek_word();
123 self.advance_n_bytes(s.len());
124 s
125 }
126
127 pub fn pop_all(&mut self) -> Option<&str> {
129 let s = self.0;
130 self.advance_n_bytes(self.0.len());
131 Some(s)
132 }
133
134 pub fn pop_to_next(&mut self, c: char) -> Option<&str> {
136 let pos = self.0.find(c)?;
137 let s = &self.0[..pos];
138 self.advance_n_bytes(pos);
139 Some(s)
140 }
141
142 pub fn match_next(&mut self, string: &str) -> bool {
144 if self
145 .0
146 .to_lowercase()
147 .starts_with(string.to_lowercase().as_str())
148 {
149 self.advance_n_bytes(string.len());
150 true
151 } else {
152 false
153 }
154 }
155
156 pub fn skip_whitespace(&mut self) {
158 while let Some(c) = self.peek() {
159 if c.is_whitespace() {
160 self.advance();
161 } else {
162 break;
163 }
164 }
165 }
166
167 pub fn into_inner(self) -> &'a str {
169 self.0
170 }
171
172 #[allow(clippy::len_without_is_empty)]
173 pub fn len(&self) -> usize {
174 self.0.len()
175 }
176}
177
178#[derive(Debug, Error)]
179pub enum CommandArgParseError {
180 #[error("invalid argument, expected {expected} got {got}")] InvalidArgument { expected: String, got: String },
183 #[error("invalid argument length")]
184 InvalidArgLength,
185}
186
187#[derive(Debug, Clone, Copy, PartialEq, Eq)]
188pub enum AbsoluteOrRelative<T> {
189 Absolute(T),
190 Relative(T), }
192
193impl<T> AbsoluteOrRelative<T>
194where
195 T: Add<Output = T> + Copy,
196{
197 pub fn get(&self, original: T) -> T {
198 match self {
199 Self::Absolute(num) => *num,
200 Self::Relative(num) => *num + original,
201 }
202 }
203}
204
205impl<T> CommandArg for AbsoluteOrRelative<T>
206where
207 T: CommandArg + Default,
208{
209 fn parse_arg(input: &mut ParseInput) -> Result<Self, CommandArgParseError> {
210 input.skip_whitespace();
211 if input.peek() == Some('~') {
212 input.advance();
213 if input.peek() == Some(' ') || input.peek().is_none() {
214 Ok(AbsoluteOrRelative::Relative(T::default()))
215 } else {
216 Ok(AbsoluteOrRelative::Relative(T::parse_arg(input)?))
217 }
218 } else if input.peek() == Some(' ') || input.peek().is_none() {
219 Err(CommandArgParseError::InvalidArgLength)
220 } else {
221 Ok(AbsoluteOrRelative::Absolute(T::parse_arg(input)?))
222 }
223 }
224
225 fn display() -> Parser {
226 T::display()
227 }
228}
229
230impl<T: Default> Default for AbsoluteOrRelative<T> {
231 fn default() -> Self {
232 AbsoluteOrRelative::Absolute(T::default())
233 }
234}
235
236#[cfg(test)]
237mod test {
238 use super::*;
239 #[test]
240 fn test_parse_input() {
241 let mut input = ParseInput::new("The QuIck brown FOX jumps over the lazy dog");
242 assert_eq!(input.peek(), Some('T'));
243 assert_eq!(input.peek_n(0), "");
244 assert_eq!(input.peek_n(1), "T");
245 assert_eq!(input.peek_n(2), "Th");
246 assert_eq!(input.peek_n(3), "The");
247
248 assert_eq!(input.peek_word(), "The");
249 input.pop_word();
250 input.skip_whitespace();
251 assert_eq!(input.peek_word(), "QuIck");
252
253 assert!(input.match_next("quick"));
254 input.pop();
255 assert_eq!(input.peek_word(), "brown");
256
257 assert!(input.match_next("brown fox"));
258 assert_eq!(input.pop_all(), Some(" jumps over the lazy dog"));
259 }
260 #[test]
261 fn test_absolute_or_relative() {
262 let mut input = ParseInput::new("~");
263 assert_eq!(
264 AbsoluteOrRelative::<i32>::parse_arg(&mut input).unwrap(),
265 AbsoluteOrRelative::Relative(0)
266 );
267 assert!(input.is_done());
268
269 let mut input = ParseInput::new("~1");
270 assert_eq!(
271 AbsoluteOrRelative::<i32>::parse_arg(&mut input).unwrap(),
272 AbsoluteOrRelative::Relative(1)
273 );
274 assert!(input.is_done());
275
276 let mut input = ParseInput::new("~1.5");
277 assert_eq!(
278 AbsoluteOrRelative::<f32>::parse_arg(&mut input).unwrap(),
279 AbsoluteOrRelative::Relative(1.5)
280 );
281 assert!(input.is_done());
282
283 let mut input = ParseInput::new("1");
284 assert_eq!(
285 AbsoluteOrRelative::<i32>::parse_arg(&mut input).unwrap(),
286 AbsoluteOrRelative::Absolute(1)
287 );
288 assert!(input.is_done());
289
290 let mut input = ParseInput::new("1.5 ");
291 assert_eq!(
292 AbsoluteOrRelative::<f32>::parse_arg(&mut input).unwrap(),
293 AbsoluteOrRelative::Absolute(1.5)
294 );
295 assert!(!input.is_done());
296
297 let mut input = ParseInput::new("1.5 2");
298 assert_eq!(
299 AbsoluteOrRelative::<f32>::parse_arg(&mut input).unwrap(),
300 AbsoluteOrRelative::Absolute(1.5)
301 );
302 assert!(!input.is_done());
303 assert_eq!(
304 AbsoluteOrRelative::<f32>::parse_arg(&mut input).unwrap(),
305 AbsoluteOrRelative::Absolute(2.0)
306 );
307 assert!(input.is_done());
308 }
309}