192 lines
5.9 KiB
Rust
192 lines
5.9 KiB
Rust
use super::data::PacketEncoder;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Commands {
|
|
nodes: Vec<CommandNode>,
|
|
}
|
|
|
|
impl Commands {
|
|
pub fn new() -> Self {
|
|
let root = CommandNode {
|
|
executable: false,
|
|
redirect: None,
|
|
children: Vec::new(),
|
|
suggestion: None,
|
|
type_data: CommandNodeType::Root
|
|
};
|
|
let simple_cmd_arg = CommandNode {
|
|
executable: true,
|
|
redirect: None,
|
|
children: Vec::new(),
|
|
suggestion: None,
|
|
type_data: CommandNodeType::Argument { name: "[args]".to_owned(), parser: Parser::String { kind: StringKind::Greedy } }
|
|
};
|
|
Self {
|
|
nodes: vec![root, simple_cmd_arg],
|
|
}
|
|
}
|
|
|
|
pub fn create_node(
|
|
&mut self,
|
|
parent: i32,
|
|
type_data: CommandNodeType,
|
|
executable: bool,
|
|
redirect: Option<i32>,
|
|
suggestion: Option<String>
|
|
) -> Option<i32> {
|
|
if parent < 0 || parent >= self.nodes.len() as i32 {
|
|
return None
|
|
}
|
|
if let Some(redirect) = redirect {
|
|
if redirect < 0 || redirect >= self.nodes.len() as i32 {
|
|
return None
|
|
}
|
|
}
|
|
if let CommandNodeType::Root = type_data {
|
|
return None
|
|
}
|
|
let id = self.nodes.len() as i32;
|
|
self.nodes.push(CommandNode {
|
|
executable,
|
|
redirect,
|
|
children: Vec::new(),
|
|
suggestion,
|
|
type_data,
|
|
});
|
|
self.nodes[parent as usize].children.push(id);
|
|
Some(id)
|
|
}
|
|
|
|
pub fn create_simple_cmd(&mut self, name: &str) -> Option<i32> {
|
|
let id = self.create_node(0, CommandNodeType::Literal { name: name.to_owned() }, true, None, None)?;
|
|
self.add_child(id, 1);
|
|
Some(id)
|
|
}
|
|
|
|
pub fn add_child(&mut self, node: i32, child: i32) {
|
|
self.nodes[node as usize].children.push(child);
|
|
}
|
|
|
|
pub fn encode(&self, encoder: &mut impl PacketEncoder) {
|
|
encoder.write_varint(self.nodes.len() as i32);
|
|
for node in &self.nodes {
|
|
node.encode(encoder);
|
|
}
|
|
// root node
|
|
encoder.write_varint(0);
|
|
}
|
|
}
|
|
|
|
pub enum NodeError {
|
|
InvalidParent(i32),
|
|
InvalidRedirect(i32),
|
|
BadTypeData,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct CommandNode {
|
|
executable: bool,
|
|
redirect: Option<i32>,
|
|
children: Vec<i32>,
|
|
suggestion: Option<String>,
|
|
type_data: CommandNodeType,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum CommandNodeType {
|
|
Root,
|
|
Literal { name: String },
|
|
Argument { name: String, parser: Parser }
|
|
}
|
|
|
|
impl CommandNode {
|
|
pub fn encode(&self, encoder: &mut impl PacketEncoder) {
|
|
let mut flags = match self.type_data {
|
|
CommandNodeType::Root => 0,
|
|
CommandNodeType::Literal{..} => 1,
|
|
CommandNodeType::Argument{..} => 2,
|
|
};
|
|
if self.executable { flags |= 4; }
|
|
if self.redirect.is_some() { flags |= 8; }
|
|
if self.suggestion.is_some() { flags |= 16; }
|
|
encoder.write_byte(flags);
|
|
encoder.write_varint(self.children.len() as i32);
|
|
for child in &self.children {
|
|
encoder.write_varint(*child);
|
|
}
|
|
if let Some(redirect) = &self.redirect {
|
|
encoder.write_varint(*redirect);
|
|
}
|
|
match &self.type_data {
|
|
CommandNodeType::Root => (),
|
|
CommandNodeType::Literal { name } => {
|
|
encoder.write_string(32767, &name);
|
|
}
|
|
CommandNodeType::Argument { name, parser } => {
|
|
encoder.write_string(32767, &name);
|
|
parser.encode(encoder);
|
|
}
|
|
}
|
|
if let Some(suggestion) = &self.suggestion {
|
|
encoder.write_string(32767, &suggestion);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub enum Parser {
|
|
Bool,
|
|
Float { min: Option<f32>, max: Option<f32>, },
|
|
Double { min: Option<f64>, max: Option<f64>, },
|
|
Int { min: Option<i32>, max: Option<i32>, },
|
|
Long { min: Option<i64>, max: Option<i64>, },
|
|
String { kind: StringKind },
|
|
}
|
|
|
|
impl Parser {
|
|
pub fn encode(&self, encoder: &mut impl PacketEncoder) {
|
|
match self {
|
|
Self::Bool => encoder.write_varint(0),
|
|
Self::Float{ min, max } => {
|
|
encoder.write_varint(1);
|
|
encoder.write_byte( if min.is_some() { 1 } else { 0 } + if max.is_some() { 2 } else { 0 } );
|
|
if let Some(min) = min { encoder.write_float(*min) };
|
|
if let Some(max) = max { encoder.write_float(*max) };
|
|
},
|
|
Self::Double{ min, max } => {
|
|
encoder.write_varint(2);
|
|
encoder.write_byte( if min.is_some() { 1 } else { 0 } + if max.is_some() { 2 } else { 0 } );
|
|
if let Some(min) = min { encoder.write_double(*min) };
|
|
if let Some(max) = max { encoder.write_double(*max) };
|
|
},
|
|
Self::Int{ min, max } => {
|
|
encoder.write_varint(3);
|
|
encoder.write_byte( if min.is_some() { 1 } else { 0 } + if max.is_some() { 2 } else { 0 } );
|
|
if let Some(min) = min { encoder.write_int(*min) };
|
|
if let Some(max) = max { encoder.write_int(*max) };
|
|
},
|
|
Self::Long{ min, max } => {
|
|
encoder.write_varint(4);
|
|
encoder.write_byte( if min.is_some() { 1 } else { 0 } + if max.is_some() { 2 } else { 0 } );
|
|
if let Some(min) = min { encoder.write_long(*min) };
|
|
if let Some(max) = max { encoder.write_long(*max) };
|
|
},
|
|
Self::String{ kind } => {
|
|
encoder.write_varint(5);
|
|
encoder.write_varint(match kind {
|
|
StringKind::Single => 0,
|
|
StringKind::Quoted => 1,
|
|
StringKind::Greedy => 2,
|
|
})
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub enum StringKind {
|
|
Single,
|
|
Quoted,
|
|
Greedy,
|
|
}
|