Skip to content

Commit 5080189

Browse files
committed
feat(commands): vanilla arg types and props, fix some graph issues
1 parent f7971f1 commit 5080189

File tree

14 files changed

+446
-164
lines changed

14 files changed

+446
-164
lines changed

src/lib/commands/src/arg/parser/int.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@ use std::sync::{Arc, Mutex};
22

33
use crate::{ctx::CommandContext, input::CommandInput, ParserResult};
44

5-
use super::{utils::error, ArgumentParser};
5+
use super::{
6+
utils::error,
7+
vanilla::{
8+
int::IntParserFlags, MinecraftArgument, MinecraftArgumentProperties, MinecraftArgumentType,
9+
},
10+
ArgumentParser,
11+
};
612

713
pub struct IntParser;
814

@@ -22,4 +28,11 @@ impl ArgumentParser for IntParser {
2228
{
2329
IntParser
2430
}
31+
32+
fn vanilla(&self) -> MinecraftArgument {
33+
MinecraftArgument {
34+
argument_type: MinecraftArgumentType::Int,
35+
props: MinecraftArgumentProperties::Int(IntParserFlags::default()),
36+
}
37+
}
2538
}

src/lib/commands/src/arg/parser/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ use crate::{ctx::CommandContext, input::CommandInput, ParserResult};
55
pub mod int;
66
pub mod string;
77
pub mod utils;
8+
pub mod vanilla;
89

910
pub trait ArgumentParser: Send + Sync {
1011
fn parse(&self, context: Arc<CommandContext>, input: Arc<Mutex<CommandInput>>) -> ParserResult;
1112
fn new() -> Self
1213
where
1314
Self: Sized;
15+
fn vanilla(&self) -> vanilla::MinecraftArgument;
1416
}

src/lib/commands/src/arg/parser/string.rs

Lines changed: 70 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@ use std::sync::{Arc, Mutex};
22

33
use crate::{ctx::CommandContext, input::CommandInput, ParserResult};
44

5-
use super::{utils::parser_error, ArgumentParser};
5+
use super::{
6+
utils::parser_error,
7+
vanilla::{
8+
string::StringParsingBehavior, MinecraftArgument, MinecraftArgumentProperties,
9+
MinecraftArgumentType,
10+
},
11+
ArgumentParser,
12+
};
613

714
pub struct SingleStringParser;
815

@@ -22,6 +29,13 @@ impl ArgumentParser for SingleStringParser {
2229
{
2330
SingleStringParser
2431
}
32+
33+
fn vanilla(&self) -> MinecraftArgument {
34+
MinecraftArgument {
35+
argument_type: MinecraftArgumentType::String,
36+
props: MinecraftArgumentProperties::String(StringParsingBehavior::default()),
37+
}
38+
}
2539
}
2640

2741
pub struct GreedyStringParser;
@@ -57,56 +71,68 @@ impl ArgumentParser for GreedyStringParser {
5771
{
5872
GreedyStringParser
5973
}
74+
75+
fn vanilla(&self) -> MinecraftArgument {
76+
MinecraftArgument {
77+
argument_type: MinecraftArgumentType::String,
78+
props: MinecraftArgumentProperties::String(StringParsingBehavior::Greedy),
79+
}
80+
}
6081
}
6182
pub struct QuotedStringParser;
6283

6384
impl ArgumentParser for QuotedStringParser {
6485
fn parse(&self, _ctx: Arc<CommandContext>, input: Arc<Mutex<CommandInput>>) -> ParserResult {
6586
let mut input = input.lock().unwrap();
66-
6787
input.skip_whitespace(u32::MAX, false);
6888

69-
if input.peek() != Some('"') {
70-
return Err(parser_error("expected opening quote"));
71-
}
72-
73-
input.read(1);
74-
75-
let mut result = String::new();
76-
let mut escaped = false;
77-
78-
while input.has_remaining_input() {
79-
let current = input.peek();
80-
81-
match current {
82-
None => return Err(parser_error("unterminated quoted string")),
83-
Some(c) => {
84-
input.read(1);
85-
86-
if escaped {
87-
match c {
88-
'"' | '\\' => result.push(c),
89-
'n' => result.push('\n'),
90-
'r' => result.push('\r'),
91-
't' => result.push('\t'),
92-
_ => {
93-
result.push('\\');
94-
result.push(c);
89+
// If it starts with a quote, use quoted string parsing
90+
if input.peek() == Some('"') {
91+
input.read(1); // consume the opening quote
92+
93+
let mut result = String::new();
94+
let mut escaped = false;
95+
96+
while input.has_remaining_input() {
97+
let current = input.peek();
98+
99+
match current {
100+
None => return Err(parser_error("unterminated quoted string")),
101+
Some(c) => {
102+
input.read(1);
103+
104+
if escaped {
105+
match c {
106+
'"' | '\\' => result.push(c),
107+
'n' => result.push('\n'),
108+
'r' => result.push('\r'),
109+
't' => result.push('\t'),
110+
_ => {
111+
result.push('\\');
112+
result.push(c);
113+
}
114+
}
115+
escaped = false;
116+
} else {
117+
match c {
118+
'"' => return Ok(Box::new(result)),
119+
'\\' => escaped = true,
120+
_ => result.push(c),
95121
}
96-
}
97-
escaped = false;
98-
} else {
99-
match c {
100-
'"' => return Ok(Box::new(result)),
101-
'\\' => escaped = true,
102-
_ => result.push(c),
103122
}
104123
}
105124
}
106125
}
107-
}
108126

109-
Err(parser_error("unterminated quoted string"))
127+
Err(parser_error("unterminated quoted string"))
128+
} else {
129+
// If no quotes, parse as single word
130+
if input.peek_string().is_empty() {
131+
return Err(parser_error("input cannot be empty"));
132+
}
133+
134+
Ok(Box::new(input.read_string()))
135+
}
110136
}
111137

112138
fn new() -> Self
@@ -115,4 +141,11 @@ impl ArgumentParser for QuotedStringParser {
115141
{
116142
QuotedStringParser
117143
}
144+
145+
fn vanilla(&self) -> MinecraftArgument {
146+
MinecraftArgument {
147+
argument_type: MinecraftArgumentType::String,
148+
props: MinecraftArgumentProperties::String(StringParsingBehavior::Quotable),
149+
}
150+
}
118151
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use std::io::Write;
2+
3+
use ferrumc_net_codec::encode::{NetEncode, NetEncodeOpts, NetEncodeResult};
4+
use tokio::io::AsyncWrite;
5+
6+
#[derive(Clone, Debug, PartialEq, Default)]
7+
pub struct FloatParserFlags {
8+
pub min: Option<f32>,
9+
pub max: Option<f32>,
10+
}
11+
12+
impl NetEncode for FloatParserFlags {
13+
fn encode<W: Write>(&self, writer: &mut W, opts: &NetEncodeOpts) -> NetEncodeResult<()> {
14+
let mut flags = 0u8;
15+
if self.min.is_some() {
16+
flags |= 0x01;
17+
}
18+
if self.max.is_some() {
19+
flags |= 0x02;
20+
}
21+
flags.encode(writer, opts)?;
22+
self.min.encode(writer, opts)?;
23+
self.max.encode(writer, opts)
24+
}
25+
26+
async fn encode_async<W: AsyncWrite + Unpin>(
27+
&self,
28+
writer: &mut W,
29+
opts: &NetEncodeOpts,
30+
) -> NetEncodeResult<()> {
31+
let mut flags = 0u8;
32+
if self.min.is_some() {
33+
flags |= 0x01;
34+
}
35+
if self.max.is_some() {
36+
flags |= 0x02;
37+
}
38+
flags.encode_async(writer, opts).await?;
39+
self.min.encode_async(writer, opts).await?;
40+
self.max.encode_async(writer, opts).await
41+
}
42+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use std::io::Write;
2+
3+
use ferrumc_net_codec::encode::{NetEncode, NetEncodeOpts, NetEncodeResult};
4+
use tokio::io::AsyncWrite;
5+
6+
#[derive(Clone, Debug, PartialEq, Default)]
7+
pub struct IntParserFlags {
8+
pub min: Option<i32>,
9+
pub max: Option<i32>,
10+
}
11+
12+
impl NetEncode for IntParserFlags {
13+
fn encode<W: Write>(&self, writer: &mut W, opts: &NetEncodeOpts) -> NetEncodeResult<()> {
14+
let mut flags = 0u8;
15+
if self.min.is_some() {
16+
flags |= 0x01;
17+
}
18+
if self.max.is_some() {
19+
flags |= 0x02;
20+
}
21+
flags.encode(writer, opts)?;
22+
self.min.encode(writer, opts)?;
23+
self.max.encode(writer, opts)
24+
}
25+
26+
async fn encode_async<W: AsyncWrite + Unpin>(
27+
&self,
28+
writer: &mut W,
29+
opts: &NetEncodeOpts,
30+
) -> NetEncodeResult<()> {
31+
let mut flags = 0u8;
32+
if self.min.is_some() {
33+
flags |= 0x01;
34+
}
35+
if self.max.is_some() {
36+
flags |= 0x02;
37+
}
38+
flags.encode_async(writer, opts).await?;
39+
self.min.encode_async(writer, opts).await?;
40+
self.max.encode_async(writer, opts).await
41+
}
42+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use std::io::Write;
2+
3+
use ferrumc_net_codec::encode::{NetEncode, NetEncodeOpts, NetEncodeResult};
4+
use tokio::io::AsyncWrite;
5+
6+
#[derive(Clone, Debug, PartialEq, Default)]
7+
pub struct LongParserFlags {
8+
pub min: Option<i64>,
9+
pub max: Option<i64>,
10+
}
11+
12+
impl NetEncode for LongParserFlags {
13+
fn encode<W: Write>(&self, writer: &mut W, opts: &NetEncodeOpts) -> NetEncodeResult<()> {
14+
let mut flags = 0u8;
15+
if self.min.is_some() {
16+
flags |= 0x01;
17+
}
18+
if self.max.is_some() {
19+
flags |= 0x02;
20+
}
21+
flags.encode(writer, opts)?;
22+
self.min.encode(writer, opts)?;
23+
self.max.encode(writer, opts)
24+
}
25+
26+
async fn encode_async<W: AsyncWrite + Unpin>(
27+
&self,
28+
writer: &mut W,
29+
opts: &NetEncodeOpts,
30+
) -> NetEncodeResult<()> {
31+
let mut flags = 0u8;
32+
if self.min.is_some() {
33+
flags |= 0x01;
34+
}
35+
if self.max.is_some() {
36+
flags |= 0x02;
37+
}
38+
flags.encode_async(writer, opts).await?;
39+
self.min.encode_async(writer, opts).await?;
40+
self.max.encode_async(writer, opts).await
41+
}
42+
}

0 commit comments

Comments
 (0)