aboutsummaryrefslogtreecommitdiff
path: root/azalea-brigadier/src/errors
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-brigadier/src/errors')
-rw-r--r--azalea-brigadier/src/errors/builtin_errors.rs153
-rw-r--r--azalea-brigadier/src/errors/command_syntax_error.rs93
-rw-r--r--azalea-brigadier/src/errors/mod.rs5
3 files changed, 251 insertions, 0 deletions
diff --git a/azalea-brigadier/src/errors/builtin_errors.rs b/azalea-brigadier/src/errors/builtin_errors.rs
new file mode 100644
index 00000000..36803397
--- /dev/null
+++ b/azalea-brigadier/src/errors/builtin_errors.rs
@@ -0,0 +1,153 @@
+use std::fmt;
+
+use super::command_syntax_error::CommandSyntaxError;
+use crate::string_reader::StringReader;
+
+#[derive(Clone, PartialEq)]
+pub enum BuiltInError {
+ DoubleTooSmall { found: f64, min: f64 },
+ DoubleTooBig { found: f64, max: f64 },
+
+ FloatTooSmall { found: f32, min: f32 },
+ FloatTooBig { found: f32, max: f32 },
+
+ IntegerTooSmall { found: i32, min: i32 },
+ IntegerTooBig { found: i32, max: i32 },
+
+ LongTooSmall { found: i64, min: i64 },
+ LongTooBig { found: i64, max: i64 },
+
+ LiteralIncorrect { expected: String },
+
+ ReaderExpectedStartOfQuote,
+ ReaderExpectedEndOfQuote,
+ ReaderInvalidEscape { character: char },
+ ReaderInvalidBool { value: String },
+ ReaderInvalidInt { value: String },
+ ReaderExpectedInt,
+ ReaderInvalidLong { value: String },
+ ReaderExpectedLong,
+ ReaderInvalidDouble { value: String },
+ ReaderExpectedDouble,
+ ReaderInvalidFloat { value: String },
+ ReaderExpectedFloat,
+ ReaderExpectedBool,
+ ReaderExpectedSymbol { symbol: char },
+
+ DispatcherUnknownCommand,
+ DispatcherUnknownArgument,
+ DispatcherExpectedArgumentSeparator,
+ DispatcherParseException { message: String },
+}
+
+impl fmt::Debug for BuiltInError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ BuiltInError::DoubleTooSmall { found, min } => {
+ write!(f, "Double must not be less than {min}, found {found}")
+ }
+ BuiltInError::DoubleTooBig { found, max } => {
+ write!(f, "Double must not be more than {max}, found {found}")
+ }
+
+ BuiltInError::FloatTooSmall { found, min } => {
+ write!(f, "Float must not be less than {min}, found {found}")
+ }
+ BuiltInError::FloatTooBig { found, max } => {
+ write!(f, "Float must not be more than {max}, found {found}")
+ }
+
+ BuiltInError::IntegerTooSmall { found, min } => {
+ write!(f, "Integer must not be less than {min}, found {found}")
+ }
+ BuiltInError::IntegerTooBig { found, max } => {
+ write!(f, "Integer must not be more than {max}, found {found}")
+ }
+
+ BuiltInError::LongTooSmall { found, min } => {
+ write!(f, "Long must not be less than {min}, found {found}")
+ }
+ BuiltInError::LongTooBig { found, max } => {
+ write!(f, "Long must not be more than {max}, found {found}")
+ }
+
+ BuiltInError::LiteralIncorrect { expected } => {
+ write!(f, "Expected literal {expected}")
+ }
+
+ BuiltInError::ReaderExpectedStartOfQuote => {
+ write!(f, "Expected quote to start a string")
+ }
+ BuiltInError::ReaderExpectedEndOfQuote => {
+ write!(f, "Unclosed quoted string")
+ }
+ BuiltInError::ReaderInvalidEscape { character } => {
+ write!(f, "Invalid escape sequence '{character}' in quoted string")
+ }
+ BuiltInError::ReaderInvalidBool { value } => {
+ write!(
+ f,
+ "Invalid bool, expected true or false but found '{value}'"
+ )
+ }
+ BuiltInError::ReaderInvalidInt { value } => {
+ write!(f, "Invalid Integer '{value}'")
+ }
+ BuiltInError::ReaderExpectedInt => {
+ write!(f, "Expected Integer")
+ }
+ BuiltInError::ReaderInvalidLong { value } => {
+ write!(f, "Invalid long '{value}'")
+ }
+ BuiltInError::ReaderExpectedLong => {
+ write!(f, "Expected long")
+ }
+ BuiltInError::ReaderInvalidDouble { value } => {
+ write!(f, "Invalid double '{value}'")
+ }
+ BuiltInError::ReaderExpectedDouble => {
+ write!(f, "Expected double")
+ }
+ BuiltInError::ReaderInvalidFloat { value } => {
+ write!(f, "Invalid Float '{value}'")
+ }
+ BuiltInError::ReaderExpectedFloat => {
+ write!(f, "Expected Float")
+ }
+ BuiltInError::ReaderExpectedBool => {
+ write!(f, "Expected bool")
+ }
+ BuiltInError::ReaderExpectedSymbol { symbol } => {
+ write!(f, "Expected '{symbol}'")
+ }
+
+ BuiltInError::DispatcherUnknownCommand => {
+ write!(f, "Unknown command")
+ }
+ BuiltInError::DispatcherUnknownArgument => {
+ write!(f, "Incorrect argument for command")
+ }
+ BuiltInError::DispatcherExpectedArgumentSeparator => {
+ write!(
+ f,
+ "Expected whitespace to end one argument, but found trailing data"
+ )
+ }
+ BuiltInError::DispatcherParseException { message } => {
+ write!(f, "Could not parse command: {message}")
+ }
+ }
+ }
+}
+
+impl BuiltInError {
+ pub fn create(self) -> CommandSyntaxError {
+ let message = format!("{self:?}");
+ CommandSyntaxError::create(self, message)
+ }
+
+ pub fn create_with_context(self, reader: &StringReader) -> CommandSyntaxError {
+ let message = format!("{self:?}");
+ CommandSyntaxError::new(self, message, reader.string(), reader.cursor())
+ }
+}
diff --git a/azalea-brigadier/src/errors/command_syntax_error.rs b/azalea-brigadier/src/errors/command_syntax_error.rs
new file mode 100644
index 00000000..a476fec4
--- /dev/null
+++ b/azalea-brigadier/src/errors/command_syntax_error.rs
@@ -0,0 +1,93 @@
+use std::{
+ cmp,
+ fmt::{self, Debug, Write},
+};
+
+use super::builtin_errors::BuiltInError;
+
+#[derive(Clone, PartialEq)]
+pub struct CommandSyntaxError {
+ kind: BuiltInError,
+ message: String,
+ input: Option<String>,
+ cursor: Option<usize>,
+}
+
+const CONTEXT_AMOUNT: usize = 10;
+
+impl CommandSyntaxError {
+ pub fn new(kind: BuiltInError, message: String, input: &str, cursor: usize) -> Self {
+ Self {
+ kind,
+ message,
+ input: Some(input.to_string()),
+ cursor: Some(cursor),
+ }
+ }
+
+ pub fn create(kind: BuiltInError, message: String) -> Self {
+ Self {
+ kind,
+ message,
+ input: None,
+ cursor: None,
+ }
+ }
+
+ pub fn message(&self) -> String {
+ let mut message = self.message.clone();
+ let context = self.context();
+ if let Some(context) = context {
+ write!(
+ message,
+ " at position {}: {context}",
+ self.cursor.unwrap_or(usize::MAX)
+ )
+ .unwrap();
+ }
+ message
+ }
+
+ pub fn raw_message(&self) -> &String {
+ &self.message
+ }
+
+ pub fn context(&self) -> Option<String> {
+ if let Some(input) = &self.input
+ && let Some(cursor) = self.cursor
+ {
+ let mut builder = String::new();
+ let cursor = cmp::min(input.len(), cursor);
+
+ if cursor > CONTEXT_AMOUNT {
+ builder.push_str("...");
+ }
+
+ builder.push_str(
+ &input[(cmp::max(0, cursor as isize - CONTEXT_AMOUNT as isize) as usize)..cursor],
+ );
+ builder.push_str("<--[HERE]");
+
+ return Some(builder);
+ }
+ None
+ }
+
+ pub fn kind(&self) -> &BuiltInError {
+ &self.kind
+ }
+
+ pub fn input(&self) -> &Option<String> {
+ &self.input
+ }
+
+ pub fn cursor(&self) -> Option<usize> {
+ self.cursor
+ }
+}
+
+impl Debug for CommandSyntaxError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}", self.message())
+ }
+}
diff --git a/azalea-brigadier/src/errors/mod.rs b/azalea-brigadier/src/errors/mod.rs
new file mode 100644
index 00000000..facebe5e
--- /dev/null
+++ b/azalea-brigadier/src/errors/mod.rs
@@ -0,0 +1,5 @@
+mod builtin_errors;
+mod command_syntax_error;
+
+pub use builtin_errors::BuiltInError;
+pub use command_syntax_error::CommandSyntaxError;