From bbb6ca7033da150a040f9a447df4688c248f01b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Sun, 9 Jun 2024 20:08:24 +0200 Subject: [PATCH 1/3] Replace strum with hand-implemented `Display` --- Cargo.lock | 4 --- crates/compiler/Cargo.toml | 2 -- .../listeners/error_listener/diagnostic.rs | 12 ++++++++- crates/core/Cargo.toml | 2 -- crates/core/src/operator.rs | 26 ++++++++++++++++++- 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1bee6631..42052e51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4874,8 +4874,6 @@ dependencies = [ "rand", "regex", "serde", - "strum", - "strum_macros", "thiserror", "yarnspinner_core", ] @@ -4889,8 +4887,6 @@ dependencies = [ "paste", "prost", "serde", - "strum", - "strum_macros", "thiserror", "yarnspinner_macros", ] diff --git a/crates/compiler/Cargo.toml b/crates/compiler/Cargo.toml index d63a2a00..fd801c70 100644 --- a/crates/compiler/Cargo.toml +++ b/crates/compiler/Cargo.toml @@ -20,8 +20,6 @@ better_any = "=0.2.0" regex = "1" yarnspinner_core = { path = "../core", version = "0.2" } thiserror = "1" -strum = "0.26" -strum_macros = "0.26" annotate-snippets = "0.10" serde = { version = "1", features = ["derive"], optional = true } bevy = { version = "0.13", default-features = false, optional = true } diff --git a/crates/compiler/src/listeners/error_listener/diagnostic.rs b/crates/compiler/src/listeners/error_listener/diagnostic.rs index 61082a5b..37de07f0 100644 --- a/crates/compiler/src/listeners/error_listener/diagnostic.rs +++ b/crates/compiler/src/listeners/error_listener/diagnostic.rs @@ -4,6 +4,7 @@ use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, So use antlr_rust::rule_context::CustomRuleContext; use antlr_rust::token::Token; use antlr_rust::token_factory::TokenFactory; +use core::fmt; use std::fmt::{Display, Formatter}; use std::ops::Range; use yarnspinner_core::prelude::*; @@ -184,7 +185,7 @@ impl DiagnosticVec for Vec { /// ## Implementation notes /// /// The `Info` variant was not implemented because it was unused. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash, strum_macros::Display)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)] #[cfg_attr(feature = "bevy", derive(Reflect))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "bevy", reflect(Debug, PartialEq, Default, Hash))] @@ -206,3 +207,12 @@ pub enum DiagnosticSeverity { /// but do not cause the compilation process to fail. Warning, } + +impl fmt::Display for DiagnosticSeverity { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + DiagnosticSeverity::Error => f.write_str("Error"), + DiagnosticSeverity::Warning => f.write_str("Warning"), + } + } +} diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 357f59d4..c91a87d2 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -18,8 +18,6 @@ bevy = ["dep:bevy"] bytes = "1" paste = "1" yarnspinner_macros = { path = "../macros", version = "0.1" } -strum = "0.26" -strum_macros = "0.26" thiserror = "1" prost = "0.12" serde = { version = "1", features = ["derive"], optional = true } diff --git a/crates/core/src/operator.rs b/crates/core/src/operator.rs index 71b6eced..84606552 100644 --- a/crates/core/src/operator.rs +++ b/crates/core/src/operator.rs @@ -1,9 +1,10 @@ #[cfg(any(feature = "bevy", feature = "serde"))] use crate::prelude::*; +use core::fmt; use std::borrow::Cow; /// The available operators that can be used with Yarn values. -#[derive(Debug, Clone, Copy, PartialEq, Eq, strum_macros::Display)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "bevy", derive(Reflect))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "bevy", reflect(Debug, PartialEq))] @@ -83,6 +84,29 @@ pub enum Operator { Modulo, } +impl fmt::Display for Operator { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Operator::EqualTo => f.write_str("EqualTo"), + Operator::GreaterThan => f.write_str("GreaterThan"), + Operator::GreaterThanOrEqualTo => f.write_str("GreaterThanOrEqualTo"), + Operator::LessThan => f.write_str("LessThan"), + Operator::LessThanOrEqualTo => f.write_str("LessThanOrEqualTo"), + Operator::NotEqualTo => f.write_str("NotEqualTo"), + Operator::Or => f.write_str("Or"), + Operator::And => f.write_str("And"), + Operator::Xor => f.write_str("Xor"), + Operator::Not => f.write_str("Not"), + Operator::UnarySubtract => f.write_str("UnarySubtract"), + Operator::Add => f.write_str("Add"), + Operator::Subtract => f.write_str("Subtract"), + Operator::Multiply => f.write_str("Multiply"), + Operator::Divide => f.write_str("Divide"), + Operator::Modulo => f.write_str("Modulo"), + } + } +} + /// Implementing this is probably bad practice, but this greatly reduces boilerplate when used with `yarn_fn_registry!` impl From for Cow<'static, str> { fn from(value: Operator) -> Self { From 805bafcd44ba2ecfd4cf7f72954676b29a1bcd4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Sun, 9 Jun 2024 20:34:24 +0200 Subject: [PATCH 2/3] Replace thiserror with hand-implemented `Error` --- Cargo.lock | 3 - crates/compiler/Cargo.toml | 1 - crates/compiler/src/output.rs | 6 +- crates/core/Cargo.toml | 1 - crates/core/src/generated/ext.rs | 6 +- crates/core/src/types/type.rs | 17 ++++- crates/core/src/yarn_value.rs | 51 ++++++++++--- crates/runtime/Cargo.toml | 1 - crates/runtime/src/dialogue.rs | 66 ++++++++++++----- .../runtime/src/markup/markup_parse_error.rs | 71 ++++++++++++++----- crates/runtime/src/variable_storage.rs | 26 ++++--- 11 files changed, 185 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 42052e51..eca143b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4874,7 +4874,6 @@ dependencies = [ "rand", "regex", "serde", - "thiserror", "yarnspinner_core", ] @@ -4887,7 +4886,6 @@ dependencies = [ "paste", "prost", "serde", - "thiserror", "yarnspinner_macros", ] @@ -4921,7 +4919,6 @@ dependencies = [ "once_cell", "regex", "serde", - "thiserror", "unicode-normalization", "unicode-segmentation", "yarnspinner_core", diff --git a/crates/compiler/Cargo.toml b/crates/compiler/Cargo.toml index fd801c70..66f87ca0 100644 --- a/crates/compiler/Cargo.toml +++ b/crates/compiler/Cargo.toml @@ -19,7 +19,6 @@ antlr-rust = "=0.3.0-beta" better_any = "=0.2.0" regex = "1" yarnspinner_core = { path = "../core", version = "0.2" } -thiserror = "1" annotate-snippets = "0.10" serde = { version = "1", features = ["derive"], optional = true } bevy = { version = "0.13", default-features = false, optional = true } diff --git a/crates/compiler/src/output.rs b/crates/compiler/src/output.rs index 8f84fa8f..e7be3eed 100644 --- a/crates/compiler/src/output.rs +++ b/crates/compiler/src/output.rs @@ -4,8 +4,8 @@ use crate::listeners::*; pub use crate::output::{debug_info::*, declaration::*, string_info::*}; use crate::prelude::*; use std::collections::HashMap; +use std::error::Error; use std::fmt::{Debug, Display}; -use thiserror::Error; use yarnspinner_core::prelude::*; mod debug_info; @@ -123,7 +123,7 @@ impl Compilation { /// A collection of [`Diagnostic`] objects that describe problems that occurred during compilation. /// At least one of these diagnostics will have a severity of [`DiagnosticSeverity::Error`]. -#[derive(Error, Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "bevy", derive(Reflect))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "bevy", reflect(Debug, PartialEq, Hash))] @@ -133,6 +133,8 @@ impl Compilation { )] pub struct CompilerError(pub Vec); +impl Error for CompilerError {} + impl Debug for CompilerError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // This looks evil, but we support really nice error messages through Display, diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index c91a87d2..adcefff4 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -18,7 +18,6 @@ bevy = ["dep:bevy"] bytes = "1" paste = "1" yarnspinner_macros = { path = "../macros", version = "0.1" } -thiserror = "1" prost = "0.12" serde = { version = "1", features = ["derive"], optional = true } bevy = { version = "0.13", default-features = false, optional = true } diff --git a/crates/core/src/generated/ext.rs b/crates/core/src/generated/ext.rs index 0406791a..f2848b2a 100644 --- a/crates/core/src/generated/ext.rs +++ b/crates/core/src/generated/ext.rs @@ -1,8 +1,8 @@ //! Contains extensions to generated types that in the original implementation are sprinkled around the repo via partial classes use crate::prelude::*; +use std::error::Error; use std::fmt::{Debug, Display}; -use thiserror::Error; impl From for Operand { fn from(s: String) -> Self { @@ -94,7 +94,7 @@ impl From for YarnValue { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "bevy", derive(Reflect))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "bevy", reflect(Debug, PartialEq))] @@ -104,6 +104,8 @@ impl From for YarnValue { )] pub struct InvalidOpCodeError(pub i32); +impl Error for InvalidOpCodeError {} + impl Display for InvalidOpCodeError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?} is not a valid OpCode", self.0) diff --git a/crates/core/src/types/type.rs b/crates/core/src/types/type.rs index f036441a..bb71869f 100644 --- a/crates/core/src/types/type.rs +++ b/crates/core/src/types/type.rs @@ -6,8 +6,8 @@ use crate::types::string::string_type_properties; use crate::types::*; use paste::paste; use std::any::TypeId; +use std::error::Error; use std::fmt::{Debug, Display}; -use thiserror::Error; /// All types in the virtual machine, both built-in, i.e. usable in Yarn scripts, and internal. /// @@ -262,10 +262,21 @@ impl From<&YarnValue> for Type { } } -#[derive(Error, Debug)] +#[derive(Debug)] /// Represents a failure to dynamically convert a [`TypeId`] to a [`Type`]. #[allow(missing_docs)] pub enum InvalidDowncastError { - #[error("Cannot convert TypeId {:?} to a Yarn Spinner `Type`", .0)] InvalidTypeId(TypeId), } + +impl Error for InvalidDowncastError {} + +impl Display for InvalidDowncastError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + InvalidDowncastError::InvalidTypeId(id) => { + write!(f, "Cannot convert TypeId {id:?} to a Yarn Spinner `Type`") + } + } + } +} diff --git a/crates/core/src/yarn_value.rs b/crates/core/src/yarn_value.rs index 71069404..80195732 100644 --- a/crates/core/src/yarn_value.rs +++ b/crates/core/src/yarn_value.rs @@ -1,8 +1,8 @@ //! Implements a subset of dotnet's [`Convert`](https://learn.microsoft.com/en-us/dotnet/api/system.convert?view=net-8.0) type. #[cfg(any(feature = "bevy", feature = "serde"))] use crate::prelude::*; +use std::error::Error; use std::fmt::{Display, Formatter}; -use thiserror::Error; /// Represents a Yarn value. The chosen variant corresponds to the last assignment of the value, /// with the type being inferred from the type checker. @@ -205,15 +205,50 @@ impl IntoYarnValueFromNonYarnValue for bool { } /// Represents a failure to convert one variant of [`YarnValue`] to a base type. -#[derive(Error, Debug)] +#[derive(Debug)] #[allow(missing_docs)] pub enum YarnValueCastError { - #[error(transparent)] - ParseFloatError(#[from] std::num::ParseFloatError), - #[error(transparent)] - ParseIntError(#[from] std::num::ParseIntError), - #[error(transparent)] - ParseBoolError(#[from] std::str::ParseBoolError), + ParseFloatError(std::num::ParseFloatError), + ParseIntError(std::num::ParseIntError), + ParseBoolError(std::str::ParseBoolError), +} + +impl Error for YarnValueCastError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + YarnValueCastError::ParseFloatError(e) => Some(e), + YarnValueCastError::ParseIntError(e) => Some(e), + YarnValueCastError::ParseBoolError(e) => Some(e), + } + } +} + +impl Display for YarnValueCastError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + YarnValueCastError::ParseFloatError(e) => Display::fmt(e, f), + YarnValueCastError::ParseIntError(e) => Display::fmt(e, f), + YarnValueCastError::ParseBoolError(e) => Display::fmt(e, f), + } + } +} + +impl From for YarnValueCastError { + fn from(value: std::num::ParseFloatError) -> Self { + Self::ParseFloatError(value) + } +} + +impl From for YarnValueCastError { + fn from(value: std::num::ParseIntError) -> Self { + Self::ParseIntError(value) + } +} + +impl From for YarnValueCastError { + fn from(value: std::str::ParseBoolError) -> Self { + Self::ParseBoolError(value) + } } impl Display for YarnValue { diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index 0582dc40..a9675bb6 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -29,6 +29,5 @@ icu_locid = { version = "1", features = ["std"] } fixed_decimal = { version = "0.5", features = ["ryu", "std"] } once_cell = "1" regex = "1" -thiserror = "1" serde = { version = "1", features = ["derive"], optional = true } bevy = { version = "0.13", default-features = false, optional = true } diff --git a/crates/runtime/src/dialogue.rs b/crates/runtime/src/dialogue.rs index 276a170b..1687c34b 100644 --- a/crates/runtime/src/dialogue.rs +++ b/crates/runtime/src/dialogue.rs @@ -4,8 +4,8 @@ use crate::markup::{DialogueTextProcessor, LineParser, MarkupParseError}; use crate::prelude::*; use log::error; use std::collections::HashMap; -use std::fmt::Debug; -use thiserror::Error; +use std::error::Error; +use std::fmt::{self, Debug, Display}; use yarnspinner_core::prelude::*; /// Co-ordinates the execution of Yarn programs. @@ -21,40 +21,72 @@ pub struct Dialogue { pub type Result = std::result::Result; #[allow(missing_docs)] -#[derive(Debug, Error)] +#[derive(Debug)] pub enum DialogueError { - #[error(transparent)] - MarkupParseError(#[from] MarkupParseError), - #[error("Line ID \"{id}\" not found in line provider with language code {language_code:?}")] + MarkupParseError(MarkupParseError), LineProviderError { id: LineId, language_code: Option, }, - #[error("{selected_option_id:?} is not a valid option ID (expected a number between 0 and {max_id}.")] InvalidOptionIdError { selected_option_id: OptionId, max_id: usize, }, - #[error("An option was selected, but the dialogue wasn't waiting for a selection. \ - This method should only be called after the Dialogue is waiting for the user to select an option.")] UnexpectedOptionSelectionError, - #[error("Dialogue was asked to continue running, but it is waiting for the user to select an option first.")] ContinueOnOptionSelectionError, - #[error("Cannot continue running dialogue. No node has been selected.")] NoNodeSelectedOnContinue, - #[error("No program has been loaded. Cannot continue running dialogue.")] NoProgramLoaded, - #[error("No node named \"{node_name}\" has been loaded.")] - InvalidNode { node_name: String }, - #[error(transparent)] - VariableStorageError(#[from] VariableStorageError), - #[error("Function \"{function_name}\" not found in library: {library}")] + InvalidNode { + node_name: String, + }, + VariableStorageError(VariableStorageError), FunctionNotFound { function_name: String, library: Library, }, } +impl Error for DialogueError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + use DialogueError::*; + match self { + MarkupParseError(e) => e.source(), + VariableStorageError(e) => e.source(), + _ => None, + } + } +} + +impl Display for DialogueError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use DialogueError::*; + match self { + MarkupParseError(e) => Display::fmt(e, f), + LineProviderError { id, language_code } => write!(f, "Line ID \"{id}\" not found in line provider with language code {language_code:?}"), + InvalidOptionIdError { selected_option_id, max_id } => write!(f, "{selected_option_id:?} is not a valid option ID (expected a number between 0 and {max_id}."), + UnexpectedOptionSelectionError => f.write_str("An option was selected, but the dialogue wasn't waiting for a selection. This method should only be called after the Dialogue is waiting for the user to select an option."), + ContinueOnOptionSelectionError => f.write_str("Dialogue was asked to continue running, but it is waiting for the user to select an option first."), + NoNodeSelectedOnContinue => f.write_str("Cannot continue running dialogue. No node has been selected."), + NoProgramLoaded => f.write_str("No program has been loaded. Cannot continue running dialogue."), + InvalidNode { node_name } => write!(f, "No node named \"{node_name}\" has been loaded."), + VariableStorageError(e) => Display::fmt(e, f), + FunctionNotFound { function_name, library } => write!(f, "Function \"{function_name}\" not found in library: {library}"), + } + } +} + +impl From for DialogueError { + fn from(source: MarkupParseError) -> Self { + DialogueError::MarkupParseError(source) + } +} + +impl From for DialogueError { + fn from(source: VariableStorageError) -> Self { + DialogueError::VariableStorageError(source) + } +} + impl Dialogue { /// Creates a new [`Dialogue`] instance with the given [`VariableStorage`] and [`TextProvider`]. /// - The [`TextProvider`] is used to retrieve the text of lines and options. diff --git a/crates/runtime/src/markup/markup_parse_error.rs b/crates/runtime/src/markup/markup_parse_error.rs index f125ccbe..f5a794d9 100644 --- a/crates/runtime/src/markup/markup_parse_error.rs +++ b/crates/runtime/src/markup/markup_parse_error.rs @@ -1,10 +1,11 @@ use crate::markup::TRIM_WHITESPACE_PROPERTY; #[cfg(any(feature = "bevy", feature = "serde"))] use crate::prelude::*; -use thiserror::Error; +use std::error::Error; +use std::fmt; #[allow(missing_docs)] -#[derive(Error, Debug, PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "bevy", derive(Reflect))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "bevy", reflect(Debug, PartialEq, Hash))] @@ -13,35 +14,71 @@ use thiserror::Error; reflect(Serialize, Deserialize) )] pub enum MarkupParseError { - #[error("Error parsing line {input}: attribute {name:?} at position {position} has a {type_} property \"{TRIM_WHITESPACE_PROPERTY}\" - this property is required to be a boolean value.")] TrimWhitespaceAttributeIsNotBoolean { input: String, name: Option, position: usize, type_: String, }, - #[error("Line ended when expecting whitespace instead: \"{input}\"")] - UnexpectedWhitespaceEnd { input: String }, - #[error("Unexpected end of line inside markup in line \"{input}\"")] - UnexpectedEndOfLine { input: String }, - #[error("Expected a {character} inside markup in line \"{input}\"")] - UnexpectedCharacter { input: String, character: char }, - #[error("Unexpected close marker {name} at position {position} in line {input}")] + UnexpectedWhitespaceEnd { + input: String, + }, + UnexpectedEndOfLine { + input: String, + }, + UnexpectedCharacter { + input: String, + character: char, + }, UnmatchedCloseMarker { input: String, name: String, position: usize, }, - #[error("Expected an identifier inside markup in line \"{input}\"")] - NoIdentifierFound { input: String }, - #[error("Expected a string inside markup in line \"{input}\"")] - NoStringFound { input: String }, - #[error("Invalid escaped character in line \"{input}\"")] - InvalidEscapeSequence { input: String }, - #[error("Unterminated marker {name} in line {input} at position {position}")] + NoIdentifierFound { + input: String, + }, + NoStringFound { + input: String, + }, + InvalidEscapeSequence { + input: String, + }, UnterminatedMarker { input: String, name: String, position: usize, }, } + +impl Error for MarkupParseError {} + +impl fmt::Display for MarkupParseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use MarkupParseError::*; + match self { + TrimWhitespaceAttributeIsNotBoolean { + input, + name, + position, + type_, + } => write!(f, "Error parsing line {input}: attribute {name:?} at position {position} has a {type_} property \"{TRIM_WHITESPACE_PROPERTY}\" - this property is required to be a boolean value."), + UnexpectedWhitespaceEnd { input } => write!(f, "Line ended when expecting whitespace instead: \"{input}\""), + UnexpectedEndOfLine { input } => write!(f, "Unexpected end of line inside markup in line \"{input}\""), + UnexpectedCharacter { input, character } => write!(f, "Expected a {character} inside markup in line \"{input}\""), + UnmatchedCloseMarker { + input, + name, + position, + } => write!(f, "Unexpected close marker {name} at position {position} in line {input}"), + NoIdentifierFound { input } => write!(f, "Expected an identifier inside markup in line \"{input}\""), + NoStringFound { input } => write!(f, "Expected a string inside markup in line \"{input}\""), + InvalidEscapeSequence { input } => write!(f, "Invalid escaped character in line \"{input}\""), + UnterminatedMarker { + input, + name, + position, + } => write!(f, "Unterminated marker {name} in line {input} at position {position}"), + } + } +} diff --git a/crates/runtime/src/variable_storage.rs b/crates/runtime/src/variable_storage.rs index f833e6f7..b023aae8 100644 --- a/crates/runtime/src/variable_storage.rs +++ b/crates/runtime/src/variable_storage.rs @@ -1,9 +1,9 @@ //! Adapted from , which we split off into multiple files use std::any::Any; use std::collections::HashMap; -use std::fmt::Debug; +use std::error::Error; +use std::fmt::{self, Debug, Display}; use std::sync::{Arc, RwLock}; -use thiserror::Error; use yarnspinner_core::prelude::*; #[allow(missing_docs)] @@ -55,16 +55,24 @@ impl Extend<(String, YarnValue)> for Box { } #[allow(missing_docs)] -#[derive(Debug, Error)] +#[derive(Debug)] pub enum VariableStorageError { - #[error("{name} is not a valid variable name: Variable names must start with a '$'. (Did you mean to use '${name}'?)")] InvalidVariableName { name: String }, - #[error("Variable name {name} is not defined")] VariableNotFound { name: String }, - #[error("Internal variable storage error: {error}")] - InternalError { - error: Box, - }, + InternalError { error: Box }, +} + +impl Error for VariableStorageError {} + +impl Display for VariableStorageError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use VariableStorageError::*; + match self { + InvalidVariableName { name } => write!(f, "{name} is not a valid variable name: Variable names must start with a \'$\'. (Did you mean to use \'${name}\'?)"), + VariableNotFound { name } => write!(f, "Variable name {name} is not defined"), + InternalError { error } => write!(f, "Internal variable storage error: {error}"), + } + } } impl Clone for Box { From b7163434ee918e185069ff22f928ffab4a7faf67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Sun, 9 Jun 2024 21:26:05 +0200 Subject: [PATCH 3/3] Remove dependency on paste --- Cargo.lock | 2 -- crates/core/Cargo.toml | 2 -- crates/core/src/types/type.rs | 61 +++++++++++++++++++++-------------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eca143b4..5609a0f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4882,8 +4882,6 @@ name = "yarnspinner_core" version = "0.2.0" dependencies = [ "bevy", - "bytes", - "paste", "prost", "serde", "yarnspinner_macros", diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index adcefff4..a9cc3ce6 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -15,8 +15,6 @@ serde = ["dep:serde", "bevy?/serialize"] bevy = ["dep:bevy"] [dependencies] -bytes = "1" -paste = "1" yarnspinner_macros = { path = "../macros", version = "0.1" } prost = "0.12" serde = { version = "1", features = ["derive"], optional = true } diff --git a/crates/core/src/types/type.rs b/crates/core/src/types/type.rs index bb71869f..1aa8d9ad 100644 --- a/crates/core/src/types/type.rs +++ b/crates/core/src/types/type.rs @@ -4,7 +4,6 @@ use crate::types::boolean::boolean_type_properties; use crate::types::number::number_type_properties; use crate::types::string::string_type_properties; use crate::types::*; -use paste::paste; use std::any::TypeId; use std::error::Error; use std::fmt::{Debug, Display}; @@ -169,33 +168,30 @@ impl TypeProperties { // on [`Type`] results in more compile-time safety. macro_rules! impl_type { - ($($yarn_type:pat => [$($base_type:path,)*] ,)*) => { + ($($yarn_type:expr => [$($ext:ident for $base_type:path,)*] ,)*) => { $( $( - - paste! { - /// Convenience trait for getting a [`Type`] out of a base type. - #[allow(non_camel_case_types)] - pub trait [<$base_type Ext>] { - /// Get the corresponding [`Type`] - fn r#type() -> Type; - } - impl [<$base_type Ext>] for $base_type { - fn r#type() -> Type { - $yarn_type - } + /// Convenience trait for getting a [`Type`] out of a base type. + #[allow(non_camel_case_types)] + pub trait $ext { + /// Get the corresponding [`Type`] + fn r#type() -> Type; + } + impl $ext for $base_type { + fn r#type() -> Type { + $yarn_type } + } - impl From<&$base_type> for Type { - fn from(_value: &$base_type) -> Self { - $yarn_type - } + impl From<&$base_type> for Type { + fn from(_value: &$base_type) -> Self { + $yarn_type } + } - impl From<$base_type> for Type { - fn from(_value: $base_type) -> Self { - $yarn_type - } + impl From<$base_type> for Type { + fn from(_value: $base_type) -> Self { + $yarn_type } } )* @@ -204,9 +200,24 @@ macro_rules! impl_type { } impl_type! { - Type::Number => [f32, f64, i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize,], - Type::String => [String,], - Type::Boolean => [bool,], + Type::Number => [ + f32Ext for f32, + f64Ext for f64, + i8Ext for i8, + i16Ext for i16, + i32Ext for i32, + i64Ext for i64, + i128Ext for i128, + u8Ext for u8, + u16Ext for u16, + u32Ext for u32, + u64Ext for u64, + u128Ext for u128, + usizeExt for usize, + isizeExt for isize, + ], + Type::String => [StringExt for String,], + Type::Boolean => [boolExt for bool,], } impl From<&str> for Type {