diff --git a/crates/fj/src/models/context.rs b/crates/fj/src/models/context.rs index e64848102..c6cc14558 100644 --- a/crates/fj/src/models/context.rs +++ b/crates/fj/src/models/context.rs @@ -1,11 +1,3 @@ -use std::{ - collections::HashMap, - fmt::{self, Display, Formatter}, - str::FromStr, -}; - -use crate::models::Error; - /// Contextual information passed to a [`Model`][crate::models::Model] when it /// is being initialized. /// @@ -15,201 +7,6 @@ pub trait Context { fn get_argument(&self, name: &str) -> Option<&str>; } -impl Context for &'_ C { - fn get_argument(&self, name: &str) -> Option<&str> { - (**self).get_argument(name) - } -} - -impl Context for Box { - fn get_argument(&self, name: &str) -> Option<&str> { - (**self).get_argument(name) - } -} - -impl Context for std::rc::Rc { - fn get_argument(&self, name: &str) -> Option<&str> { - (**self).get_argument(name) - } -} - -impl Context for std::sync::Arc { - fn get_argument(&self, name: &str) -> Option<&str> { - (**self).get_argument(name) - } -} - -impl Context for HashMap { - fn get_argument(&self, name: &str) -> Option<&str> { - self.get(name).map(|s| s.as_str()) - } -} - -/// Extension methods for the [`Context`] type. -/// -/// By splitting these methods out into a separate trait, [`Context`] can stay -/// object-safe while allowing convenience methods that use generics. -pub trait ContextExt { - /// Get an argument, returning a [`MissingArgument`] error if it doesn't - /// exist. - fn get_required_argument( - &self, - name: &str, - ) -> Result<&str, MissingArgument>; - - /// Parse an argument from its string representation using [`FromStr`]. - fn parse_argument(&self, name: &str) -> Result - where - T: FromStr, - T::Err: std::error::Error + Send + Sync + 'static; - - /// Try to parse an argument, if it is present. - fn parse_optional_argument( - &self, - name: &str, - ) -> Result, ParseFailed> - where - T: FromStr, - T::Err: std::error::Error + Send + Sync + 'static; -} - -impl ContextExt for C { - fn get_required_argument( - &self, - name: &str, - ) -> Result<&str, MissingArgument> { - self.get_argument(name).ok_or_else(|| MissingArgument { - name: name.to_string(), - }) - } - - fn parse_argument(&self, name: &str) -> Result - where - T: FromStr, - T::Err: std::error::Error + Send + Sync + 'static, - { - let value = self.get_required_argument(name)?; - - value - .parse() - .map_err(|e| ParseFailed { - name: name.to_string(), - value: value.to_string(), - error: Box::new(e), - }) - .map_err(ContextError::from) - } - - fn parse_optional_argument( - &self, - name: &str, - ) -> Result, ParseFailed> - where - T: FromStr, - T::Err: std::error::Error + Send + Sync + 'static, - { - let value = match self.get_argument(name) { - Some(value) => value, - None => return Ok(None), - }; - - let parsed = value.parse().map_err(|e| ParseFailed { - name: name.to_string(), - value: value.to_string(), - error: Box::new(e), - })?; - - Ok(Some(parsed)) - } -} - -/// An error that may be returned from a [`Context`] method. -#[derive(Debug)] -pub enum ContextError { - /// An argument was missing. - MissingArgument(MissingArgument), - /// An argument was present, but we were unable to parse it into the final - /// type. - ParseFailed(ParseFailed), -} - -impl From for ContextError { - fn from(m: MissingArgument) -> Self { - ContextError::MissingArgument(m) - } -} - -impl From for ContextError { - fn from(p: ParseFailed) -> Self { - ContextError::ParseFailed(p) - } -} - -impl Display for ContextError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - ContextError::MissingArgument(_) => { - write!(f, "An argument was missing") - } - ContextError::ParseFailed(_) => { - write!(f, "Unable to parse an argument") - } - } - } -} - -impl std::error::Error for ContextError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - ContextError::MissingArgument(m) => Some(m), - ContextError::ParseFailed(p) => Some(p), - } - } -} - -/// The error returned when a required argument wasn't provided. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct MissingArgument { - /// The argument's name. - pub name: String, -} - -impl Display for MissingArgument { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let MissingArgument { name } = self; - - write!(f, "The \"{name}\" argument was missing") - } -} - -impl std::error::Error for MissingArgument {} - -/// The error returned when [`ContextExt::parse_argument()`] is unable to parse -/// the argument's value. -#[derive(Debug)] -pub struct ParseFailed { - /// The argument's name. - pub name: String, - /// The actual value. - pub value: String, - /// The error that occurred. - pub error: Error, -} - -impl Display for ParseFailed { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let ParseFailed { name, value, .. } = self; - - write!(f, "Unable to parse the \"{name}\" argument (\"{value:?}\")") - } -} - -impl std::error::Error for ParseFailed { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - Some(&*self.error) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/fj/src/models/host.rs b/crates/fj/src/models/host.rs index 19072c881..2f4c2f6c6 100644 --- a/crates/fj/src/models/host.rs +++ b/crates/fj/src/models/host.rs @@ -11,18 +11,6 @@ pub trait Host { fn register_boxed_model(&mut self, model: Box); } -impl Host for &'_ mut H { - fn register_boxed_model(&mut self, model: Box) { - (*self).register_boxed_model(model); - } -} - -impl Host for Box { - fn register_boxed_model(&mut self, model: Box) { - (**self).register_boxed_model(model); - } -} - /// Extension methods to augment the [`Host`] API. pub trait HostExt { /// Register a model with the Fornjot runtime. diff --git a/crates/fj/src/models/mod.rs b/crates/fj/src/models/mod.rs index 03c033a40..904bf53ed 100644 --- a/crates/fj/src/models/mod.rs +++ b/crates/fj/src/models/mod.rs @@ -6,9 +6,7 @@ mod metadata; mod model; pub use self::{ - context::{ - Context, ContextError, ContextExt, MissingArgument, ParseFailed, - }, + context::Context, host::{Host, HostExt}, metadata::{ArgumentMetadata, Metadata, ModelMetadata}, model::Model,