diff --git a/Cargo.lock b/Cargo.lock index c33ee8e7..1314a830 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,7 @@ dependencies = [ "graphite-document-core", "graphite-proc-macros", "log", + "thiserror", ] [[package]] @@ -155,6 +156,26 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-xid" version = "0.2.1" diff --git a/client/web/wasm/src/wrappers.rs b/client/web/wasm/src/wrappers.rs index 474d3213..e018bb78 100644 --- a/client/web/wasm/src/wrappers.rs +++ b/client/web/wasm/src/wrappers.rs @@ -24,41 +24,54 @@ impl Color { } } +macro_rules! match_string_to_enum { + (match ($e:expr) {$($var:ident),* $(,)?}) => { + match $e { + $( + stringify!($var) => Some($var), + )* + _ => None + } + }; +} + pub fn translate_tool(name: &str) -> Option { - match name { - "Select" => Some(ToolType::Select), - "Crop" => Some(ToolType::Crop), - "Navigate" => Some(ToolType::Navigate), - "Sample" => Some(ToolType::Sample), - "Text" => Some(ToolType::Text), - "Fill" => Some(ToolType::Fill), - "Gradient" => Some(ToolType::Gradient), - "Brush" => Some(ToolType::Brush), - "Heal" => Some(ToolType::Heal), - "Clone" => Some(ToolType::Clone), - "Patch" => Some(ToolType::Patch), - "BlurSharpen" => Some(ToolType::BlurSharpen), - "Relight" => Some(ToolType::Relight), - "Path" => Some(ToolType::Path), - "Pen" => Some(ToolType::Pen), - "Freehand" => Some(ToolType::Freehand), - "Spline" => Some(ToolType::Spline), - "Line" => Some(ToolType::Line), - "Rectangle" => Some(ToolType::Rectangle), - "Ellipse" => Some(ToolType::Ellipse), - "Shape" => Some(ToolType::Shape), - _ => None, - } + use ToolType::*; + + match_string_to_enum!(match (name) { + Select, + Crop, + Navigate, + Sample, + Text, + Fill, + Gradient, + Brush, + Heal, + Clone, + Patch, + BlurSharpen, + Relight, + Path, + Pen, + Freehand, + Spline, + Line, + Rectangle, + Ellipse, + Shape + }) } pub fn translate_append_mode(name: &str) -> Option { - match name { - "New" => Some(SelectAppendMode::New), - "Add" => Some(SelectAppendMode::Add), - "Subtract" => Some(SelectAppendMode::Subtract), - "Intersect" => Some(SelectAppendMode::Intersect), - _ => None, - } + use SelectAppendMode::*; + + match_string_to_enum!(match (name) { + New, + Add, + Subtract, + Intersect + }) } pub fn translate_key(name: &str) -> events::Key { diff --git a/core/editor/Cargo.toml b/core/editor/Cargo.toml index babe6572..d3d9a06b 100644 --- a/core/editor/Cargo.toml +++ b/core/editor/Cargo.toml @@ -11,6 +11,7 @@ license = "Apache-2.0" [dependencies] log = "0.4" bitflags = "1.2.1" +thiserror = "1.0.24" [dependencies.document-core] path = "../document" diff --git a/core/editor/src/dispatcher/events.rs b/core/editor/src/dispatcher/events.rs index 70c51d30..764cf79c 100644 --- a/core/editor/src/dispatcher/events.rs +++ b/core/editor/src/dispatcher/events.rs @@ -31,10 +31,14 @@ pub enum Response { impl fmt::Display for Response { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match self { - Response::UpdateCanvas { document: _ } => write!(formatter, "UpdateCanvas"), - Response::SetActiveTool { tool_name: _ } => write!(formatter, "SetActiveTool"), - } + use Response::*; + + let name = match_variant_name!(match (self) { + UpdateCanvas, + SetActiveTool + }); + + formatter.write_str(name) } } diff --git a/core/editor/src/error.rs b/core/editor/src/error.rs index 84982e3f..5b355fb9 100644 --- a/core/editor/src/error.rs +++ b/core/editor/src/error.rs @@ -1,32 +1,22 @@ use crate::events::Event; use crate::Color; -use std::error::Error; -use std::fmt::{self, Display}; +use thiserror::Error; /// The error type used by the Graphite editor. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Error)] pub enum EditorError { + #[error("Failed to execute operation: {0}")] InvalidOperation(String), + #[error("Failed to dispatch event: {0}")] InvalidEvent(String), + #[error("{0}")] Misc(String), + #[error("Tried to construct an invalid color {0:?}")] Color(String), + #[error("The requested tool does not exist")] UnknownTool, } -impl Display for EditorError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - EditorError::InvalidOperation(e) => write!(f, "Failed to execute operation: {}", e), - EditorError::InvalidEvent(e) => write!(f, "Failed to dispatch event: {}", e), - EditorError::Misc(e) => write!(f, "{}", e), - EditorError::Color(c) => write!(f, "Tried to construct an invalid color {:?}", c), - EditorError::UnknownTool => write!(f, "The requested tool does not exist"), - } - } -} - -impl Error for EditorError {} - macro_rules! derive_from { ($type:ty, $kind:ident) => { impl From<$type> for EditorError { diff --git a/core/editor/src/macros.rs b/core/editor/src/macros.rs index 54e62a88..d87a58cb 100644 --- a/core/editor/src/macros.rs +++ b/core/editor/src/macros.rs @@ -47,3 +47,40 @@ macro_rules! gen_tools_hash_map { hash_map }}; } + +/// Creates a string representation of an enum value that exactly matches the given name of each enum variant +/// +/// # Example +/// +/// ```ignore +/// enum E { +/// A(u8), +/// B +/// } +/// +/// // this line is important +/// use E::*; +/// +/// let a = E::A(7); +/// let s = match_variant_name!(match (a) { A, B }); +/// ``` +/// +/// expands to +/// +/// ```ignore +/// // ... +/// +/// let s = match a { +/// A { .. } => "A", +/// B { .. } => "B" +/// }; +/// ``` +macro_rules! match_variant_name { + (match ($e:expr) { $($v:ident),* $(,)? }) => { + match $e { + $( + $v { .. } => stringify!(v) + ),* + } + }; +} diff --git a/core/editor/src/tools/mod.rs b/core/editor/src/tools/mod.rs index 360262cb..8cba2777 100644 --- a/core/editor/src/tools/mod.rs +++ b/core/editor/src/tools/mod.rs @@ -124,29 +124,33 @@ pub enum ToolType { impl fmt::Display for ToolType { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match self { - ToolType::Select => write!(formatter, "Select"), - ToolType::Crop => write!(formatter, "Crop"), - ToolType::Navigate => write!(formatter, "Navigate"), - ToolType::Sample => write!(formatter, "Sample"), - ToolType::Text => write!(formatter, "Text"), - ToolType::Fill => write!(formatter, "Fill"), - ToolType::Gradient => write!(formatter, "Gradient"), - ToolType::Brush => write!(formatter, "Brush"), - ToolType::Heal => write!(formatter, "Heal"), - ToolType::Clone => write!(formatter, "Clone"), - ToolType::Patch => write!(formatter, "Patch"), - ToolType::BlurSharpen => write!(formatter, "BlurSharpen"), - ToolType::Relight => write!(formatter, "Relight"), - ToolType::Path => write!(formatter, "Path"), - ToolType::Pen => write!(formatter, "Pen"), - ToolType::Freehand => write!(formatter, "Freehand"), - ToolType::Spline => write!(formatter, "Spline"), - ToolType::Line => write!(formatter, "Line"), - ToolType::Rectangle => write!(formatter, "Rectangle"), - ToolType::Ellipse => write!(formatter, "Ellipse"), - ToolType::Shape => write!(formatter, "Shape"), - } + use ToolType::*; + + let name = match_variant_name!(match (self) { + Select, + Crop, + Navigate, + Sample, + Text, + Fill, + Gradient, + Brush, + Heal, + Clone, + Patch, + BlurSharpen, + Relight, + Path, + Pen, + Freehand, + Spline, + Line, + Rectangle, + Ellipse, + Shape + }); + + formatter.write_str(name) } }