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