1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 06:16:04 +00:00

implement missing brigadier features and cleanup some more

This commit is contained in:
mat 2025-05-30 20:07:28 -03:30
parent da73b4316d
commit a5e7ff771d
26 changed files with 436 additions and 289 deletions

View file

@ -1,13 +1,13 @@
use std::{any::Any, sync::Arc};
use crate::{
exceptions::CommandSyntaxException,
errors::CommandSyntaxError,
string_reader::StringReader,
suggestion::{Suggestions, SuggestionsBuilder},
};
pub trait ArgumentType {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxException>;
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxError>;
fn list_suggestions(&self, _builder: SuggestionsBuilder) -> Suggestions {
Suggestions::default()

View file

@ -3,7 +3,7 @@ use std::{any::Any, sync::Arc};
use super::ArgumentType;
use crate::{
context::CommandContext,
exceptions::CommandSyntaxException,
errors::CommandSyntaxError,
string_reader::StringReader,
suggestion::{Suggestions, SuggestionsBuilder},
};
@ -12,7 +12,7 @@ use crate::{
struct Boolean;
impl ArgumentType for Boolean {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxException> {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxError> {
Ok(Arc::new(reader.read_boolean()?))
}

View file

@ -3,7 +3,7 @@ use std::{any::Any, sync::Arc};
use super::ArgumentType;
use crate::{
context::CommandContext,
exceptions::{BuiltInExceptions, CommandSyntaxException},
errors::{BuiltInError, CommandSyntaxError},
string_reader::StringReader,
};
@ -14,14 +14,14 @@ struct Double {
}
impl ArgumentType for Double {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxException> {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxError> {
let start = reader.cursor;
let result = reader.read_double()?;
if let Some(minimum) = self.minimum
&& result < minimum
{
reader.cursor = start;
return Err(BuiltInExceptions::DoubleTooSmall {
return Err(BuiltInError::DoubleTooSmall {
found: result,
min: minimum,
}
@ -31,7 +31,7 @@ impl ArgumentType for Double {
&& result > maximum
{
reader.cursor = start;
return Err(BuiltInExceptions::DoubleTooBig {
return Err(BuiltInError::DoubleTooBig {
found: result,
max: maximum,
}

View file

@ -3,7 +3,7 @@ use std::{any::Any, sync::Arc};
use super::ArgumentType;
use crate::{
context::CommandContext,
exceptions::{BuiltInExceptions, CommandSyntaxException},
errors::{BuiltInError, CommandSyntaxError},
string_reader::StringReader,
};
@ -14,14 +14,14 @@ struct Float {
}
impl ArgumentType for Float {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxException> {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxError> {
let start = reader.cursor;
let result = reader.read_float()?;
if let Some(minimum) = self.minimum
&& result < minimum
{
reader.cursor = start;
return Err(BuiltInExceptions::FloatTooSmall {
return Err(BuiltInError::FloatTooSmall {
found: result,
min: minimum,
}
@ -31,7 +31,7 @@ impl ArgumentType for Float {
&& result > maximum
{
reader.cursor = start;
return Err(BuiltInExceptions::FloatTooBig {
return Err(BuiltInError::FloatTooBig {
found: result,
max: maximum,
}

View file

@ -3,7 +3,7 @@ use std::{any::Any, sync::Arc};
use super::ArgumentType;
use crate::{
context::CommandContext,
exceptions::{BuiltInExceptions, CommandSyntaxException},
errors::{BuiltInError, CommandSyntaxError},
string_reader::StringReader,
};
@ -14,14 +14,14 @@ struct Integer {
}
impl ArgumentType for Integer {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxException> {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxError> {
let start = reader.cursor;
let result = reader.read_int()?;
if let Some(minimum) = self.minimum
&& result < minimum
{
reader.cursor = start;
return Err(BuiltInExceptions::IntegerTooSmall {
return Err(BuiltInError::IntegerTooSmall {
found: result,
min: minimum,
}
@ -31,7 +31,7 @@ impl ArgumentType for Integer {
&& result > maximum
{
reader.cursor = start;
return Err(BuiltInExceptions::IntegerTooBig {
return Err(BuiltInError::IntegerTooBig {
found: result,
max: maximum,
}

View file

@ -3,7 +3,7 @@ use std::{any::Any, sync::Arc};
use super::ArgumentType;
use crate::{
context::CommandContext,
exceptions::{BuiltInExceptions, CommandSyntaxException},
errors::{BuiltInError, CommandSyntaxError},
string_reader::StringReader,
};
@ -14,14 +14,14 @@ struct Long {
}
impl ArgumentType for Long {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxException> {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxError> {
let start = reader.cursor;
let result = reader.read_long()?;
if let Some(minimum) = self.minimum
&& result < minimum
{
reader.cursor = start;
return Err(BuiltInExceptions::LongTooSmall {
return Err(BuiltInError::LongTooSmall {
found: result,
min: minimum,
}
@ -31,7 +31,7 @@ impl ArgumentType for Long {
&& result > maximum
{
reader.cursor = start;
return Err(BuiltInExceptions::LongTooBig {
return Err(BuiltInError::LongTooBig {
found: result,
max: maximum,
}

View file

@ -1,9 +1,7 @@
use std::{any::Any, sync::Arc};
use super::ArgumentType;
use crate::{
context::CommandContext, exceptions::CommandSyntaxException, string_reader::StringReader,
};
use crate::{context::CommandContext, errors::CommandSyntaxError, string_reader::StringReader};
pub enum StringArgument {
/// Match up until the next space.
@ -16,7 +14,7 @@ pub enum StringArgument {
}
impl ArgumentType for StringArgument {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxException> {
fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxError> {
let result = match self {
StringArgument::SingleWord => reader.read_unquoted_string().to_string(),
StringArgument::QuotablePhrase => reader.read_string()?,

View file

@ -5,6 +5,7 @@ use parking_lot::RwLock;
use super::{literal_argument_builder::Literal, required_argument_builder::Argument};
use crate::{
context::CommandContext,
errors::CommandSyntaxError,
modifier::RedirectModifier,
tree::{Command, CommandNode},
};
@ -89,6 +90,16 @@ impl<S> ArgumentBuilder<S> {
pub fn executes<F>(mut self, f: F) -> Self
where
F: Fn(&CommandContext<S>) -> i32 + Send + Sync + 'static,
{
self.command = Some(Arc::new(move |ctx: &CommandContext<S>| Ok(f(ctx))));
self
}
/// Same as [`Self::executes`] but returns a `Result<i32,
/// CommandSyntaxError>`.
pub fn executes_result<F>(mut self, f: F) -> Self
where
F: Fn(&CommandContext<S>) -> Result<i32, CommandSyntaxError> + Send + Sync + 'static,
{
self.command = Some(Arc::new(f));
self

View file

@ -8,7 +8,7 @@ use super::argument_builder::{ArgumentBuilder, ArgumentBuilderType};
use crate::{
arguments::ArgumentType,
context::CommandContext,
exceptions::CommandSyntaxException,
errors::CommandSyntaxError,
string_reader::StringReader,
suggestion::{SuggestionProvider, Suggestions, SuggestionsBuilder},
};
@ -33,7 +33,7 @@ impl<S> Argument<S> {
}
}
pub fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxException> {
pub fn parse(&self, reader: &mut StringReader) -> Result<Arc<dyn Any>, CommandSyntaxError> {
self.parser.parse(reader)
}

View file

@ -1,7 +1,7 @@
use std::{
cmp::Ordering,
collections::{HashMap, HashSet},
mem, ptr,
ptr,
rc::Rc,
sync::Arc,
};
@ -10,9 +10,10 @@ use parking_lot::RwLock;
use crate::{
builder::argument_builder::ArgumentBuilder,
context::{CommandContext, CommandContextBuilder},
exceptions::{BuiltInExceptions, CommandSyntaxException},
context::{CommandContextBuilder, ContextChain},
errors::{BuiltInError, CommandSyntaxError},
parse_results::ParseResults,
result_consumer::{DefaultResultConsumer, ResultConsumer},
string_reader::StringReader,
suggestion::{Suggestions, SuggestionsBuilder},
tree::CommandNode,
@ -30,12 +31,14 @@ where
Self: Sync + Send,
{
pub root: Arc<RwLock<CommandNode<S>>>,
consumer: Box<dyn ResultConsumer<S> + Send + Sync>,
}
impl<S> CommandDispatcher<S> {
pub fn new() -> Self {
Self {
root: Arc::new(RwLock::new(CommandNode::default())),
consumer: Box::new(DefaultResultConsumer),
}
}
@ -64,10 +67,10 @@ impl<S> CommandDispatcher<S> {
node: &Arc<RwLock<CommandNode<S>>>,
original_reader: &StringReader,
context_so_far: CommandContextBuilder<'a, S>,
) -> Result<ParseResults<'a, S>, CommandSyntaxException> {
) -> Result<ParseResults<'a, S>, CommandSyntaxError> {
let source = context_so_far.source.clone();
#[allow(clippy::mutable_key_type)] // this is fine because we don't mutate the key
let mut errors = HashMap::<Rc<CommandNode<S>>, CommandSyntaxException>::new();
let mut errors = HashMap::<Rc<CommandNode<S>>, CommandSyntaxError>::new();
let mut potentials: Vec<ParseResults<S>> = vec![];
let cursor = original_reader.cursor();
@ -83,7 +86,7 @@ impl<S> CommandDispatcher<S> {
if let Err(ex) = parse_with_context_result {
errors.insert(
Rc::new((*child.read()).clone()),
BuiltInExceptions::DispatcherParseException {
BuiltInError::DispatcherParseException {
message: ex.message(),
}
.create_with_context(&reader),
@ -94,8 +97,7 @@ impl<S> CommandDispatcher<S> {
if reader.can_read() && reader.peek() != ' ' {
errors.insert(
Rc::new((*child.read()).clone()),
BuiltInExceptions::DispatcherExpectedArgumentSeparator
.create_with_context(&reader),
BuiltInError::DispatcherExpectedArgumentSeparator.create_with_context(&reader),
);
reader.cursor = cursor;
continue;
@ -179,11 +181,11 @@ impl<S> CommandDispatcher<S> {
&self,
input: impl Into<StringReader>,
source: S,
) -> Result<i32, CommandSyntaxException> {
) -> Result<i32, CommandSyntaxError> {
let input = input.into();
let parse = self.parse(input, source);
Self::execute_parsed(parse)
self.execute_parsed(parse)
}
pub fn add_paths(
@ -235,91 +237,26 @@ impl<S> CommandDispatcher<S> {
}
/// Executes a given pre-parsed command.
pub fn execute_parsed(parse: ParseResults<S>) -> Result<i32, CommandSyntaxException> {
pub fn execute_parsed(&self, parse: ParseResults<S>) -> Result<i32, CommandSyntaxError> {
if parse.reader.can_read() {
if parse.exceptions.len() == 1 {
return Err(parse.exceptions.values().next().unwrap().clone());
}
if parse.context.range.is_empty() {
return Err(
BuiltInExceptions::DispatcherUnknownCommand.create_with_context(&parse.reader)
);
}
return Err(
BuiltInExceptions::DispatcherUnknownArgument.create_with_context(&parse.reader)
);
return Err(if parse.exceptions.len() == 1 {
parse.exceptions.values().next().unwrap().clone()
} else if parse.context.range.is_empty() {
BuiltInError::DispatcherUnknownCommand.create_with_context(&parse.reader)
} else {
BuiltInError::DispatcherUnknownArgument.create_with_context(&parse.reader)
});
}
let mut result = 0i32;
let mut successful_forks = 0;
let mut forked = false;
let mut found_command = false;
let command = parse.reader.string();
let original = parse.context.build(command);
let mut contexts = vec![original];
let mut next: Vec<CommandContext<S>> = vec![];
let original = Rc::new(parse.context.build(command));
let flat_context = ContextChain::try_flatten(original.clone());
let Some(flat_context) = flat_context else {
self.consumer.on_command_complete(original, false, 0);
return Err(BuiltInError::DispatcherUnknownCommand.create_with_context(&parse.reader));
};
while !contexts.is_empty() {
for context in &contexts {
let child = &context.child;
if let Some(child) = child {
forked |= child.forks;
if child.has_nodes() {
found_command = true;
let modifier = &context.modifier;
if let Some(modifier) = modifier {
let results = modifier(context);
match results {
Ok(results) => {
if !results.is_empty() {
next.extend(
results.iter().map(|s| child.copy_for(s.clone())),
);
}
}
_ => {
// TODO
// self.consumer.on_command_complete(context, false, 0);
if !forked {
return Err(results.err().unwrap());
}
}
}
} else {
next.push(child.copy_for(context.source.clone()));
}
}
} else if let Some(context_command) = &context.command {
found_command = true;
let value = context_command(context);
result += value;
// consumer.on_command_complete(context, true, value);
successful_forks += 1;
// TODO: allow context_command to error and handle
// those errors
}
}
// move next into contexts and clear next
mem::swap(&mut contexts, &mut next);
next.clear();
}
if !found_command {
// consumer.on_command_complete(original, false, 0);
return Err(
BuiltInExceptions::DispatcherUnknownCommand.create_with_context(&parse.reader)
);
}
// TODO: this is not how vanilla does it but it works
Ok(if successful_forks >= 2 {
successful_forks
} else {
result
})
// Ok(if forked { successful_forks } else { result })
flat_context.execute_all(original.source().clone(), self.consumer.as_ref())
}
pub fn get_all_usage(

View file

@ -10,16 +10,16 @@ use crate::{
/// A built `CommandContextBuilder`.
pub struct CommandContext<S> {
pub source: Arc<S>,
pub input: String,
pub arguments: HashMap<String, ParsedArgument>,
pub command: Command<S>,
pub root_node: Arc<RwLock<CommandNode<S>>>,
pub nodes: Vec<ParsedCommandNode<S>>,
pub range: StringRange,
pub child: Option<Rc<CommandContext<S>>>,
pub modifier: Option<Arc<RedirectModifier<S>>>,
pub forks: bool,
pub(super) source: Arc<S>,
pub(super) input: String,
pub(super) arguments: HashMap<String, ParsedArgument>,
pub(super) command: Command<S>,
pub(super) root_node: Arc<RwLock<CommandNode<S>>>,
pub(super) nodes: Vec<ParsedCommandNode<S>>,
pub(super) range: StringRange,
pub(super) child: Option<Rc<CommandContext<S>>>,
pub(super) modifier: Option<Arc<RedirectModifier<S>>>,
pub(super) forks: bool,
}
impl<S> Clone for CommandContext<S> {
@ -59,8 +59,10 @@ impl<S> Debug for CommandContext<S> {
impl<S> CommandContext<S> {
pub fn copy_for(&self, source: Arc<S>) -> Self {
if Arc::ptr_eq(&source, &self.source) {
// fast path
return self.clone();
}
CommandContext {
source,
input: self.input.clone(),
@ -75,12 +77,56 @@ impl<S> CommandContext<S> {
}
}
pub fn child(&self) -> Option<&CommandContext<S>> {
self.child.as_ref().map(|c| c.as_ref())
}
pub fn last_child(&self) -> &CommandContext<S> {
let mut result = self;
while let Some(child) = result.child() {
result = child;
}
result
}
pub fn command(&self) -> &Command<S> {
&self.command
}
pub fn source(&self) -> &Arc<S> {
&self.source
}
pub fn argument(&self, name: &str) -> Option<&dyn Any> {
let argument = self.arguments.get(name);
argument.map(|a| a.result.as_ref())
}
pub fn redirect_modifier(&self) -> Option<&RedirectModifier<S>> {
self.modifier.as_ref().map(|m| m.as_ref())
}
pub fn range(&self) -> &StringRange {
&self.range
}
pub fn input(&self) -> &str {
&self.input
}
pub fn root_node(&self) -> &Arc<RwLock<CommandNode<S>>> {
&self.root_node
}
pub fn nodes(&self) -> &[ParsedCommandNode<S>] {
&self.nodes
}
pub fn has_nodes(&self) -> bool {
!self.nodes.is_empty()
}
pub fn argument(&self, name: &str) -> Option<Arc<dyn Any>> {
let argument = self.arguments.get(name);
argument.map(|a| a.result.clone())
pub fn is_forked(&self) -> bool {
self.forks
}
}

View file

@ -0,0 +1,169 @@
use std::{rc::Rc, sync::Arc};
use super::CommandContext;
use crate::{errors::CommandSyntaxError, result_consumer::ResultConsumer};
pub struct ContextChain<S> {
modifiers: Vec<Rc<CommandContext<S>>>,
executable: Rc<CommandContext<S>>,
next_stage_cache: Option<Rc<ContextChain<S>>>,
}
impl<S> ContextChain<S> {
pub fn new(modifiers: Vec<Rc<CommandContext<S>>>, executable: Rc<CommandContext<S>>) -> Self {
if executable.command.is_none() {
panic!("Last command in chain must be executable");
}
Self {
modifiers,
executable,
next_stage_cache: None,
}
}
pub fn try_flatten(root_context: Rc<CommandContext<S>>) -> Option<Self> {
let mut modifiers = Vec::new();
let mut current = root_context;
loop {
let child = current.child.clone();
let Some(child) = child else {
// Last entry must be executable command
if current.command.is_none() {
return None;
}
return Some(ContextChain::new(modifiers, current));
};
modifiers.push(current);
current = child;
}
}
pub fn run_modifier(
modifier: Rc<CommandContext<S>>,
source: Arc<S>,
result_consumer: &dyn ResultConsumer<S>,
forked_mode: bool,
) -> Result<Vec<Arc<S>>, CommandSyntaxError> {
let source_modifier = modifier.redirect_modifier();
let Some(source_modifier) = source_modifier else {
return Ok(vec![source]);
};
let context_to_use = Rc::new(modifier.copy_for(source));
let err = match (source_modifier)(&context_to_use) {
Ok(res) => return Ok(res),
Err(e) => e,
};
result_consumer.on_command_complete(context_to_use, false, 0);
if forked_mode {
return Ok(vec![]);
}
Err(err)
}
pub fn run_executable(
&self,
executable: Rc<CommandContext<S>>,
source: Arc<S>,
result_consumer: &dyn ResultConsumer<S>,
forked_mode: bool,
) -> Result<i32, CommandSyntaxError> {
let context_to_use = Rc::new(executable.copy_for(source));
let Some(command) = &executable.command else {
unimplemented!();
};
let err = match (command)(&context_to_use) {
Ok(result) => {
result_consumer.on_command_complete(context_to_use, true, result);
return if forked_mode { Ok(1) } else { Ok(result) };
}
Err(err) => err,
};
result_consumer.on_command_complete(context_to_use, false, 0);
if forked_mode { Ok(0) } else { Err(err) }
}
pub fn execute_all(
&self,
source: Arc<S>,
result_consumer: &(dyn ResultConsumer<S>),
) -> Result<i32, CommandSyntaxError> {
if self.modifiers.is_empty() {
return self.run_executable(self.executable.clone(), source, result_consumer, false);
}
let mut forked_mode = false;
let mut current_sources = vec![source];
for modifier in &self.modifiers {
forked_mode |= modifier.is_forked();
let mut next_sources = Vec::new();
for source_to_run in current_sources {
next_sources.extend(Self::run_modifier(
modifier.clone(),
source_to_run.clone(),
result_consumer,
forked_mode,
)?);
}
if next_sources.is_empty() {
return Ok(0);
}
current_sources = next_sources;
}
let mut result = 0;
for execution_source in current_sources {
result += self.run_executable(
self.executable.clone(),
execution_source,
result_consumer,
forked_mode,
)?;
}
Ok(result)
}
pub fn stage(&self) -> Stage {
if self.modifiers.is_empty() {
Stage::Execute
} else {
Stage::Modify
}
}
pub fn top_context(&self) -> Rc<CommandContext<S>> {
self.modifiers
.first()
.cloned()
.unwrap_or_else(|| self.executable.clone())
}
pub fn next_stage(&mut self) -> Option<Rc<ContextChain<S>>> {
let modifier_count = self.modifiers.len();
if modifier_count == 0 {
return None;
}
if self.next_stage_cache.is_none() {
self.next_stage_cache = Some(Rc::new(ContextChain::new(
self.modifiers[1..].to_vec(),
self.executable.clone(),
)));
}
self.next_stage_cache.clone()
}
}
pub enum Stage {
Modify,
Execute,
}

View file

@ -1,5 +1,6 @@
mod command_context;
mod command_context_builder;
mod context_chain;
mod parsed_argument;
mod parsed_command_node;
mod string_range;
@ -7,6 +8,7 @@ pub mod suggestion_context;
pub use command_context::CommandContext;
pub use command_context_builder::CommandContextBuilder;
pub use context_chain::ContextChain;
pub use parsed_argument::ParsedArgument;
pub use parsed_command_node::ParsedCommandNode;
pub use string_range::StringRange;

View file

@ -1,10 +1,10 @@
use std::fmt;
use super::command_syntax_exception::CommandSyntaxException;
use super::command_syntax_error::CommandSyntaxError;
use crate::string_reader::StringReader;
#[derive(Clone, PartialEq)]
pub enum BuiltInExceptions {
pub enum BuiltInError {
DoubleTooSmall { found: f64, min: f64 },
DoubleTooBig { found: f64, max: f64 },
@ -40,114 +40,114 @@ pub enum BuiltInExceptions {
DispatcherParseException { message: String },
}
impl fmt::Debug for BuiltInExceptions {
impl fmt::Debug for BuiltInError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BuiltInExceptions::DoubleTooSmall { found, min } => {
BuiltInError::DoubleTooSmall { found, min } => {
write!(f, "Double must not be less than {min}, found {found}")
}
BuiltInExceptions::DoubleTooBig { found, max } => {
BuiltInError::DoubleTooBig { found, max } => {
write!(f, "Double must not be more than {max}, found {found}")
}
BuiltInExceptions::FloatTooSmall { found, min } => {
BuiltInError::FloatTooSmall { found, min } => {
write!(f, "Float must not be less than {min}, found {found}")
}
BuiltInExceptions::FloatTooBig { found, max } => {
BuiltInError::FloatTooBig { found, max } => {
write!(f, "Float must not be more than {max}, found {found}")
}
BuiltInExceptions::IntegerTooSmall { found, min } => {
BuiltInError::IntegerTooSmall { found, min } => {
write!(f, "Integer must not be less than {min}, found {found}")
}
BuiltInExceptions::IntegerTooBig { found, max } => {
BuiltInError::IntegerTooBig { found, max } => {
write!(f, "Integer must not be more than {max}, found {found}")
}
BuiltInExceptions::LongTooSmall { found, min } => {
BuiltInError::LongTooSmall { found, min } => {
write!(f, "Long must not be less than {min}, found {found}")
}
BuiltInExceptions::LongTooBig { found, max } => {
BuiltInError::LongTooBig { found, max } => {
write!(f, "Long must not be more than {max}, found {found}")
}
BuiltInExceptions::LiteralIncorrect { expected } => {
BuiltInError::LiteralIncorrect { expected } => {
write!(f, "Expected literal {expected}")
}
BuiltInExceptions::ReaderExpectedStartOfQuote => {
BuiltInError::ReaderExpectedStartOfQuote => {
write!(f, "Expected quote to start a string")
}
BuiltInExceptions::ReaderExpectedEndOfQuote => {
BuiltInError::ReaderExpectedEndOfQuote => {
write!(f, "Unclosed quoted string")
}
BuiltInExceptions::ReaderInvalidEscape { character } => {
BuiltInError::ReaderInvalidEscape { character } => {
write!(f, "Invalid escape sequence '{character}' in quoted string")
}
BuiltInExceptions::ReaderInvalidBool { value } => {
BuiltInError::ReaderInvalidBool { value } => {
write!(
f,
"Invalid bool, expected true or false but found '{value}'"
)
}
BuiltInExceptions::ReaderInvalidInt { value } => {
BuiltInError::ReaderInvalidInt { value } => {
write!(f, "Invalid Integer '{value}'")
}
BuiltInExceptions::ReaderExpectedInt => {
BuiltInError::ReaderExpectedInt => {
write!(f, "Expected Integer")
}
BuiltInExceptions::ReaderInvalidLong { value } => {
BuiltInError::ReaderInvalidLong { value } => {
write!(f, "Invalid long '{value}'")
}
BuiltInExceptions::ReaderExpectedLong => {
BuiltInError::ReaderExpectedLong => {
write!(f, "Expected long")
}
BuiltInExceptions::ReaderInvalidDouble { value } => {
BuiltInError::ReaderInvalidDouble { value } => {
write!(f, "Invalid double '{value}'")
}
BuiltInExceptions::ReaderExpectedDouble => {
BuiltInError::ReaderExpectedDouble => {
write!(f, "Expected double")
}
BuiltInExceptions::ReaderInvalidFloat { value } => {
BuiltInError::ReaderInvalidFloat { value } => {
write!(f, "Invalid Float '{value}'")
}
BuiltInExceptions::ReaderExpectedFloat => {
BuiltInError::ReaderExpectedFloat => {
write!(f, "Expected Float")
}
BuiltInExceptions::ReaderExpectedBool => {
BuiltInError::ReaderExpectedBool => {
write!(f, "Expected bool")
}
BuiltInExceptions::ReaderExpectedSymbol { symbol } => {
BuiltInError::ReaderExpectedSymbol { symbol } => {
write!(f, "Expected '{symbol}'")
}
BuiltInExceptions::DispatcherUnknownCommand => {
BuiltInError::DispatcherUnknownCommand => {
write!(f, "Unknown command")
}
BuiltInExceptions::DispatcherUnknownArgument => {
BuiltInError::DispatcherUnknownArgument => {
write!(f, "Incorrect argument for command")
}
BuiltInExceptions::DispatcherExpectedArgumentSeparator => {
BuiltInError::DispatcherExpectedArgumentSeparator => {
write!(
f,
"Expected whitespace to end one argument, but found trailing data"
)
}
BuiltInExceptions::DispatcherParseException { message } => {
BuiltInError::DispatcherParseException { message } => {
write!(f, "Could not parse command: {message}")
}
}
}
}
impl BuiltInExceptions {
pub fn create(self) -> CommandSyntaxException {
impl BuiltInError {
pub fn create(self) -> CommandSyntaxError {
let message = format!("{self:?}");
CommandSyntaxException::create(self, message)
CommandSyntaxError::create(self, message)
}
pub fn create_with_context(self, reader: &StringReader) -> CommandSyntaxException {
pub fn create_with_context(self, reader: &StringReader) -> CommandSyntaxError {
let message = format!("{self:?}");
CommandSyntaxException::new(self, message, reader.string(), reader.cursor())
CommandSyntaxError::new(self, message, reader.string(), reader.cursor())
}
}

View file

@ -1,13 +1,13 @@
use std::{
cmp,
fmt::{self, Write},
fmt::{self, Debug, Write},
};
use super::builtin_exceptions::BuiltInExceptions;
use super::builtin_errors::BuiltInError;
#[derive(Clone, PartialEq)]
pub struct CommandSyntaxException {
pub type_: BuiltInExceptions,
pub struct CommandSyntaxError {
kind: BuiltInError,
message: String,
input: Option<String>,
cursor: Option<usize>,
@ -15,19 +15,19 @@ pub struct CommandSyntaxException {
const CONTEXT_AMOUNT: usize = 10;
impl CommandSyntaxException {
pub fn new(type_: BuiltInExceptions, message: String, input: &str, cursor: usize) -> Self {
impl CommandSyntaxError {
pub fn new(kind: BuiltInError, message: String, input: &str, cursor: usize) -> Self {
Self {
type_,
kind,
message,
input: Some(input.to_string()),
cursor: Some(cursor),
}
}
pub fn create(type_: BuiltInExceptions, message: String) -> Self {
pub fn create(kind: BuiltInError, message: String) -> Self {
Self {
type_,
kind,
message,
input: None,
cursor: None,
@ -40,9 +40,8 @@ impl CommandSyntaxException {
if let Some(context) = context {
write!(
message,
" at position {}: {}",
self.cursor.unwrap_or(usize::MAX),
context
" at position {}: {context}",
self.cursor.unwrap_or(usize::MAX)
)
.unwrap();
}
@ -74,8 +73,8 @@ impl CommandSyntaxException {
None
}
pub fn get_type(&self) -> &BuiltInExceptions {
&self.type_
pub fn kind(&self) -> &BuiltInError {
&self.kind
}
pub fn input(&self) -> &Option<String> {
@ -87,7 +86,7 @@ impl CommandSyntaxException {
}
}
impl fmt::Debug for CommandSyntaxException {
impl Debug for CommandSyntaxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.message())
}

View file

@ -0,0 +1,5 @@
mod builtin_errors;
mod command_syntax_error;
pub use builtin_errors::BuiltInError;
pub use command_syntax_error::CommandSyntaxError;

View file

@ -1,5 +0,0 @@
mod builtin_exceptions;
mod command_syntax_exception;
pub use builtin_exceptions::BuiltInExceptions;
pub use command_syntax_exception::CommandSyntaxException;

View file

@ -4,9 +4,10 @@ pub mod arguments;
pub mod builder;
pub mod command_dispatcher;
pub mod context;
pub mod exceptions;
pub mod errors;
pub mod modifier;
pub mod parse_results;
pub mod result_consumer;
pub mod string_reader;
pub mod suggestion;
pub mod tree;

View file

@ -1,6 +1,6 @@
use std::sync::Arc;
use crate::{context::CommandContext, exceptions::CommandSyntaxException};
use crate::{context::CommandContext, errors::CommandSyntaxError};
pub type RedirectModifier<S> =
dyn Fn(&CommandContext<S>) -> Result<Vec<Arc<S>>, CommandSyntaxException> + Send + Sync;
dyn Fn(&CommandContext<S>) -> Result<Vec<Arc<S>>, CommandSyntaxError> + Send + Sync;

View file

@ -1,14 +1,14 @@
use std::{collections::HashMap, fmt::Debug, rc::Rc};
use crate::{
context::CommandContextBuilder, exceptions::CommandSyntaxException,
string_reader::StringReader, tree::CommandNode,
context::CommandContextBuilder, errors::CommandSyntaxError, string_reader::StringReader,
tree::CommandNode,
};
pub struct ParseResults<'a, S> {
pub context: CommandContextBuilder<'a, S>,
pub reader: StringReader,
pub exceptions: HashMap<Rc<CommandNode<S>>, CommandSyntaxException>,
pub exceptions: HashMap<Rc<CommandNode<S>>, CommandSyntaxError>,
}
impl<S> Debug for ParseResults<'_, S> {

View file

@ -0,0 +1,12 @@
use std::rc::Rc;
use crate::context::CommandContext;
pub trait ResultConsumer<S> {
fn on_command_complete(&self, context: Rc<CommandContext<S>>, success: bool, result: i32);
}
pub struct DefaultResultConsumer;
impl<S> ResultConsumer<S> for DefaultResultConsumer {
fn on_command_complete(&self, _context: Rc<CommandContext<S>>, _success: bool, _result: i32) {}
}

View file

@ -1,6 +1,6 @@
use std::str::FromStr;
use crate::exceptions::{BuiltInExceptions, CommandSyntaxException};
use crate::errors::{BuiltInError, CommandSyntaxError};
#[derive(Clone)]
pub struct StringReader {
@ -91,19 +91,19 @@ impl StringReader {
}
}
pub fn read_int(&mut self) -> Result<i32, CommandSyntaxException> {
pub fn read_int(&mut self) -> Result<i32, CommandSyntaxError> {
let start = self.cursor;
while self.can_read() && StringReader::is_allowed_number(self.peek()) {
self.skip();
}
let number = &self.string[start..self.cursor];
if number.is_empty() {
return Err(BuiltInExceptions::ReaderExpectedInt.create_with_context(self));
return Err(BuiltInError::ReaderExpectedInt.create_with_context(self));
}
let result = i32::from_str(number);
if result.is_err() {
self.cursor = start;
return Err(BuiltInExceptions::ReaderInvalidInt {
return Err(BuiltInError::ReaderInvalidInt {
value: number.to_string(),
}
.create_with_context(self));
@ -112,19 +112,19 @@ impl StringReader {
Ok(result.unwrap())
}
pub fn read_long(&mut self) -> Result<i64, CommandSyntaxException> {
pub fn read_long(&mut self) -> Result<i64, CommandSyntaxError> {
let start = self.cursor;
while self.can_read() && StringReader::is_allowed_number(self.peek()) {
self.skip();
}
let number = &self.string[start..self.cursor];
if number.is_empty() {
return Err(BuiltInExceptions::ReaderExpectedLong.create_with_context(self));
return Err(BuiltInError::ReaderExpectedLong.create_with_context(self));
}
let result = i64::from_str(number);
if result.is_err() {
self.cursor = start;
return Err(BuiltInExceptions::ReaderInvalidLong {
return Err(BuiltInError::ReaderInvalidLong {
value: number.to_string(),
}
.create_with_context(self));
@ -133,19 +133,19 @@ impl StringReader {
Ok(result.unwrap())
}
pub fn read_double(&mut self) -> Result<f64, CommandSyntaxException> {
pub fn read_double(&mut self) -> Result<f64, CommandSyntaxError> {
let start = self.cursor;
while self.can_read() && StringReader::is_allowed_number(self.peek()) {
self.skip();
}
let number = &self.string[start..self.cursor];
if number.is_empty() {
return Err(BuiltInExceptions::ReaderExpectedDouble.create_with_context(self));
return Err(BuiltInError::ReaderExpectedDouble.create_with_context(self));
}
let result = f64::from_str(number);
if result.is_err() {
self.cursor = start;
return Err(BuiltInExceptions::ReaderInvalidDouble {
return Err(BuiltInError::ReaderInvalidDouble {
value: number.to_string(),
}
.create_with_context(self));
@ -154,19 +154,19 @@ impl StringReader {
Ok(result.unwrap())
}
pub fn read_float(&mut self) -> Result<f32, CommandSyntaxException> {
pub fn read_float(&mut self) -> Result<f32, CommandSyntaxError> {
let start = self.cursor;
while self.can_read() && StringReader::is_allowed_number(self.peek()) {
self.skip();
}
let number = &self.string[start..self.cursor];
if number.is_empty() {
return Err(BuiltInExceptions::ReaderExpectedFloat.create_with_context(self));
return Err(BuiltInError::ReaderExpectedFloat.create_with_context(self));
}
let result = f32::from_str(number);
if result.is_err() {
self.cursor = start;
return Err(BuiltInExceptions::ReaderInvalidFloat {
return Err(BuiltInError::ReaderInvalidFloat {
value: number.to_string(),
}
.create_with_context(self));
@ -193,22 +193,19 @@ impl StringReader {
&self.string[start..self.cursor]
}
pub fn read_quoted_string(&mut self) -> Result<String, CommandSyntaxException> {
pub fn read_quoted_string(&mut self) -> Result<String, CommandSyntaxError> {
if !self.can_read() {
return Ok(String::new());
}
let next = self.peek();
if !StringReader::is_quoted_string_start(next) {
return Err(BuiltInExceptions::ReaderExpectedStartOfQuote.create_with_context(self));
return Err(BuiltInError::ReaderExpectedStartOfQuote.create_with_context(self));
}
self.skip();
self.read_string_until(next)
}
pub fn read_string_until(
&mut self,
terminator: char,
) -> Result<String, CommandSyntaxException> {
pub fn read_string_until(&mut self, terminator: char) -> Result<String, CommandSyntaxError> {
let mut result = String::new();
let mut escaped = false;
while self.can_read() {
@ -219,7 +216,7 @@ impl StringReader {
escaped = false;
} else {
self.cursor -= 1;
return Err(BuiltInExceptions::ReaderInvalidEscape { character: c }
return Err(BuiltInError::ReaderInvalidEscape { character: c }
.create_with_context(self));
}
} else if c == SYNTAX_ESCAPE {
@ -231,10 +228,10 @@ impl StringReader {
}
}
Err(BuiltInExceptions::ReaderExpectedEndOfQuote.create_with_context(self))
Err(BuiltInError::ReaderExpectedEndOfQuote.create_with_context(self))
}
pub fn read_string(&mut self) -> Result<String, CommandSyntaxException> {
pub fn read_string(&mut self) -> Result<String, CommandSyntaxError> {
if !self.can_read() {
return Ok(String::new());
}
@ -246,11 +243,11 @@ impl StringReader {
Ok(self.read_unquoted_string().to_string())
}
pub fn read_boolean(&mut self) -> Result<bool, CommandSyntaxException> {
pub fn read_boolean(&mut self) -> Result<bool, CommandSyntaxError> {
let start = self.cursor;
let value = self.read_string()?;
if value.is_empty() {
return Err(BuiltInExceptions::ReaderExpectedBool.create_with_context(self));
return Err(BuiltInError::ReaderExpectedBool.create_with_context(self));
}
if value == "true" {
@ -259,15 +256,13 @@ impl StringReader {
Ok(false)
} else {
self.cursor = start;
Err(BuiltInExceptions::ReaderInvalidBool { value }.create_with_context(self))
Err(BuiltInError::ReaderInvalidBool { value }.create_with_context(self))
}
}
pub fn expect(&mut self, c: char) -> Result<(), CommandSyntaxException> {
pub fn expect(&mut self, c: char) -> Result<(), CommandSyntaxError> {
if !self.can_read() || self.peek() != c {
return Err(
BuiltInExceptions::ReaderExpectedSymbol { symbol: c }.create_with_context(self)
);
return Err(BuiltInError::ReaderExpectedSymbol { symbol: c }.create_with_context(self));
}
self.skip();
Ok(())

View file

@ -14,13 +14,14 @@ use crate::{
required_argument_builder::Argument,
},
context::{CommandContext, CommandContextBuilder, ParsedArgument, StringRange},
exceptions::{BuiltInExceptions, CommandSyntaxException},
errors::{BuiltInError, CommandSyntaxError},
modifier::RedirectModifier,
string_reader::StringReader,
suggestion::{Suggestions, SuggestionsBuilder},
};
pub type Command<S> = Option<Arc<dyn Fn(&CommandContext<S>) -> i32 + Send + Sync>>;
pub type Command<S> =
Option<Arc<dyn Fn(&CommandContext<S>) -> Result<i32, CommandSyntaxError> + Send + Sync>>;
/// An ArgumentBuilder that has been built.
#[non_exhaustive]
@ -149,7 +150,7 @@ impl<S> CommandNode<S> {
&self,
reader: &mut StringReader,
context_builder: &mut CommandContextBuilder<S>,
) -> Result<(), CommandSyntaxException> {
) -> Result<(), CommandSyntaxError> {
match self.value {
ArgumentBuilderType::Argument(ref argument) => {
let start = reader.cursor();
@ -176,7 +177,7 @@ impl<S> CommandNode<S> {
return Ok(());
}
Err(BuiltInExceptions::LiteralIncorrect {
Err(BuiltInError::LiteralIncorrect {
expected: literal.value.clone(),
}
.create_with_context(reader))

View file

@ -131,7 +131,7 @@ impl DispatchStorage {
///
/// Spawns an entity with the [`SpawnedEntity`] component.
fn command_spawn_entity(context: &CommandContext<WorldAccessor>) -> i32 {
context.source.lock().spawn(SpawnedEntity);
context.source().lock().spawn(SpawnedEntity);
0
}
@ -143,7 +143,7 @@ impl DispatchStorage {
let num = get_integer(context, "entities").unwrap();
for _ in 0..num {
context.source.lock().spawn(SpawnedEntity);
context.source().lock().spawn(SpawnedEntity);
}
0

View file

@ -5,7 +5,7 @@ use azalea_brigadier::{
builder::{literal_argument_builder::literal, required_argument_builder::argument},
command_dispatcher::CommandDispatcher,
context::CommandContext,
exceptions::{BuiltInExceptions, CommandSyntaxException},
errors::{BuiltInError, CommandSyntaxError},
string_reader::StringReader,
};
@ -50,10 +50,7 @@ fn execute_unknown_command() {
let execute_result = subject.execute("foo", &CommandSource {});
let err = execute_result.err().unwrap();
match err.type_ {
BuiltInExceptions::DispatcherUnknownCommand => {}
_ => panic!("Unexpected error"),
}
assert_eq!(err.kind(), &BuiltInError::DispatcherUnknownCommand);
assert_eq!(err.cursor().unwrap(), 0);
}
@ -65,10 +62,7 @@ fn execute_impermissible_command() {
let execute_result = subject.execute("foo", &CommandSource {});
let err = execute_result.err().unwrap();
match err.type_ {
BuiltInExceptions::DispatcherUnknownCommand => {}
_ => panic!("Unexpected error"),
}
assert_eq!(err.kind(), &BuiltInError::DispatcherUnknownCommand);
assert_eq!(err.cursor().unwrap(), 0);
}
@ -80,10 +74,7 @@ fn execute_empty_command() {
let execute_result = subject.execute("", &CommandSource {});
let err = execute_result.err().unwrap();
match err.type_ {
BuiltInExceptions::DispatcherUnknownCommand => {}
_ => panic!("Unexpected error"),
}
assert_eq!(err.kind(), &BuiltInError::DispatcherUnknownCommand);
assert_eq!(err.cursor().unwrap(), 0);
}
@ -95,10 +86,7 @@ fn execute_unknown_subcommand() {
let execute_result = subject.execute("foo bar", &CommandSource {});
let err = execute_result.err().unwrap();
match err.type_ {
BuiltInExceptions::DispatcherUnknownArgument => {}
_ => panic!("Unexpected error"),
}
assert_eq!(err.kind(), &BuiltInError::DispatcherUnknownArgument);
assert_eq!(err.cursor().unwrap(), 4);
}
@ -110,10 +98,7 @@ fn execute_incorrect_literal() {
let execute_result = subject.execute("foo baz", &CommandSource {});
let err = execute_result.err().unwrap();
match err.type_ {
BuiltInExceptions::DispatcherUnknownArgument => {}
_ => panic!("Unexpected error"),
}
assert_eq!(err.kind(), &BuiltInError::DispatcherUnknownArgument);
assert_eq!(err.cursor().unwrap(), 4);
}
@ -130,10 +115,7 @@ fn execute_ambiguous_incorrect_argument() {
let execute_result = subject.execute("foo unknown", &CommandSource {});
let err = execute_result.err().unwrap();
match err.type_ {
BuiltInExceptions::DispatcherUnknownArgument => {}
_ => panic!("Unexpected error"),
}
assert_eq!(err.kind(), &BuiltInError::DispatcherUnknownArgument);
assert_eq!(err.cursor().unwrap(), 4);
}
@ -245,7 +227,7 @@ fn execute_redirected_multiple_times() {
);
assert_eq!(*child2.unwrap().nodes[0].node.read(), *concrete_node.read());
assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 42);
assert_eq!(subject.execute_parsed(parse).unwrap(), 42);
}
#[test]
@ -255,7 +237,7 @@ fn execute_redirected() {
let source1 = Arc::new(CommandSource {});
let source2 = Arc::new(CommandSource {});
let modifier = move |_: &CommandContext<CommandSource>| -> Result<Vec<Arc<CommandSource>>, CommandSyntaxException> {
let modifier = move |_: &CommandContext<CommandSource>| -> Result<Vec<Arc<CommandSource>>, CommandSyntaxError> {
Ok(vec![source1.clone(), source2.clone()])
};
@ -281,7 +263,7 @@ fn execute_redirected() {
assert_eq!(*parent.nodes[0].node.read(), *concrete_node.read());
assert_eq!(*parent.source, CommandSource {});
assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 2);
assert_eq!(subject.execute_parsed(parse).unwrap(), 2);
}
#[test]
@ -297,10 +279,7 @@ fn execute_orphaned_subcommand() {
let result = subject.execute("foo 5", &CommandSource {});
assert!(result.is_err());
let result = result.unwrap_err();
assert_eq!(
*result.get_type(),
BuiltInExceptions::DispatcherUnknownCommand
);
assert_eq!(*result.kind(), BuiltInError::DispatcherUnknownCommand);
assert_eq!(result.cursor(), Some(5));
}
@ -327,10 +306,7 @@ fn parse_no_space_separator() {
let result = subject.execute("foo$", &CommandSource {});
assert!(result.is_err());
let result = result.unwrap_err();
assert_eq!(
*result.get_type(),
BuiltInExceptions::DispatcherUnknownCommand
);
assert_eq!(*result.kind(), BuiltInError::DispatcherUnknownCommand);
assert_eq!(result.cursor(), Some(0));
}
@ -348,7 +324,7 @@ fn execute_invalid_subcommand() {
assert!(result.is_err());
let result = result.unwrap_err();
// this fails for some reason, i blame mojang
// assert_eq!(*result.get_type(), BuiltInExceptions::ReaderExpectedInt);
// assert_eq!(*result.get_type(), BuiltInError::ReaderExpectedInt);
assert_eq!(result.cursor(), Some(4));
}

View file

@ -1,4 +1,4 @@
use azalea_brigadier::{exceptions::BuiltInExceptions, string_reader::StringReader};
use azalea_brigadier::{errors::BuiltInError, string_reader::StringReader};
#[test]
fn can_read() {
@ -222,7 +222,7 @@ fn read_quoted_string_no_open() {
let result = reader.read_quoted_string();
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedStartOfQuote);
assert_eq!(e.kind(), &BuiltInError::ReaderExpectedStartOfQuote);
assert_eq!(e.cursor(), Some(0));
}
}
@ -233,7 +233,7 @@ fn read_quoted_string_no_close() {
let result = reader.read_quoted_string();
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedEndOfQuote);
assert_eq!(e.kind(), &BuiltInError::ReaderExpectedEndOfQuote);
assert_eq!(e.cursor(), Some(12));
}
}
@ -245,8 +245,8 @@ fn read_quoted_string_invalid_escape() {
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(
e.get_type(),
&BuiltInExceptions::ReaderInvalidEscape { character: 'n' }
e.kind(),
&BuiltInError::ReaderInvalidEscape { character: 'n' }
);
assert_eq!(e.cursor(), Some(7));
}
@ -259,8 +259,8 @@ fn read_quoted_string_invalid_quote_escape() {
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(
e.get_type(),
&BuiltInExceptions::ReaderInvalidEscape { character: '"' }
e.kind(),
&BuiltInError::ReaderInvalidEscape { character: '"' }
);
assert_eq!(e.cursor(), Some(7));
}
@ -313,8 +313,8 @@ fn read_int_invalid() {
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(
e.get_type(),
&BuiltInExceptions::ReaderInvalidInt {
e.kind(),
&BuiltInError::ReaderInvalidInt {
value: "12.34".to_string()
}
);
@ -328,7 +328,7 @@ fn read_int_none() {
let result = reader.read_int();
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedInt);
assert_eq!(e.kind(), &BuiltInError::ReaderExpectedInt);
assert_eq!(e.cursor(), Some(0));
}
}
@ -372,8 +372,8 @@ fn read_long_invalid() {
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(
e.get_type(),
&BuiltInExceptions::ReaderInvalidLong {
e.kind(),
&BuiltInError::ReaderInvalidLong {
value: "12.34".to_string()
}
);
@ -387,7 +387,7 @@ fn read_long_none() {
let result = reader.read_long();
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedLong);
assert_eq!(e.kind(), &BuiltInError::ReaderExpectedLong);
assert_eq!(e.cursor(), Some(0));
}
}
@ -439,8 +439,8 @@ fn read_double_invalid() {
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(
e.get_type(),
&BuiltInExceptions::ReaderInvalidDouble {
e.kind(),
&BuiltInError::ReaderInvalidDouble {
value: "12.34.56".to_string()
}
);
@ -454,7 +454,7 @@ fn read_double_none() {
let result = reader.read_double();
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedDouble);
assert_eq!(e.kind(), &BuiltInError::ReaderExpectedDouble);
assert_eq!(e.cursor(), Some(0));
}
}
@ -506,8 +506,8 @@ fn read_float_invalid() {
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(
e.get_type(),
&BuiltInExceptions::ReaderInvalidFloat {
e.kind(),
&BuiltInError::ReaderInvalidFloat {
value: "12.34.56".to_string()
}
);
@ -521,7 +521,7 @@ fn read_float_none() {
let result = reader.read_float();
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedFloat);
assert_eq!(e.kind(), &BuiltInError::ReaderExpectedFloat);
assert_eq!(e.cursor(), Some(0));
}
}
@ -556,8 +556,8 @@ fn expect_incorrect() {
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(
e.get_type(),
&BuiltInExceptions::ReaderExpectedSymbol { symbol: 'a' }
e.kind(),
&BuiltInError::ReaderExpectedSymbol { symbol: 'a' }
);
assert_eq!(e.cursor(), Some(0));
}
@ -570,8 +570,8 @@ fn expect_none() {
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(
e.get_type(),
&BuiltInExceptions::ReaderExpectedSymbol { symbol: 'a' }
e.kind(),
&BuiltInError::ReaderExpectedSymbol { symbol: 'a' }
);
assert_eq!(e.cursor(), Some(0));
}
@ -591,8 +591,8 @@ fn read_boolean_incorrect() {
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(
e.get_type(),
&BuiltInExceptions::ReaderInvalidBool {
e.kind(),
&BuiltInError::ReaderInvalidBool {
value: "tuesday".to_string()
}
);
@ -606,7 +606,7 @@ fn read_boolean_none() {
let result = reader.read_boolean();
assert!(result.is_err());
if let Err(e) = result {
assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedBool);
assert_eq!(e.kind(), &BuiltInError::ReaderExpectedBool);
assert_eq!(e.cursor(), Some(0));
}
}