use super::Value;
use crate::common::{
color::{Color, ParseColorError},
lexer,
percentage::Percentage,
};
use fraction::Fraction;
use regex::Regex;
use std::{convert::Infallible, error::Error, fmt::Display, str::ParseBoolError};
#[derive(Debug)]
pub enum TryIntoValueError<
StringError: Error,
RegexError: Error,
NumberError: Error,
PercentageError: Error,
BooleanError: Error,
ColorError: Error,
IdentifierError: Error,
> {
StringError(StringError),
RegexError(RegexError),
NumberError(NumberError),
PercentageError(PercentageError),
BooleanError(BooleanError),
ColorError(ColorError),
IdentifierError(IdentifierError),
}
impl<
StringError: Error,
RegexError: Error,
NumberError: Error,
PercentageError: Error,
BooleanError: Error,
ColorError: Error,
IdentifierError: Error,
> Display
for TryIntoValueError<
StringError,
RegexError,
NumberError,
PercentageError,
BooleanError,
ColorError,
IdentifierError,
>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
#[allow(deprecated)]
self.description().fmt(f)
}
}
impl<
StringError: Error,
RegexError: Error,
NumberError: Error,
PercentageError: Error,
BooleanError: Error,
ColorError: Error,
IdentifierError: Error,
> Error
for TryIntoValueError<
StringError,
RegexError,
NumberError,
PercentageError,
BooleanError,
ColorError,
IdentifierError,
>
{
#[allow(deprecated)]
fn description(&self) -> &str {
match self {
Self::StringError(e) => e.description(),
Self::RegexError(e) => e.description(),
Self::NumberError(e) => e.description(),
Self::PercentageError(e) => e.description(),
Self::BooleanError(e) => e.description(),
Self::ColorError(e) => e.description(),
Self::IdentifierError(e) => e.description(),
}
}
}
pub trait TryIntoValue {
type StringError: Error + Send + Sync + 'static;
type RegexError: Error + Send + Sync + 'static;
type NumberError: Error + Send + Sync + 'static;
type PercentageError: Error + Send + Sync + 'static;
type BooleanError: Error + Send + Sync + 'static;
type ColorError: Error + Send + Sync + 'static;
type IdentifierError: Error + Send + Sync + 'static;
fn string(self) -> Result<String, Self::StringError>;
fn regex(self) -> Result<Regex, Self::RegexError>;
fn number(self) -> Result<Fraction, Self::NumberError>;
fn percentage(self) -> Result<Percentage, Self::PercentageError>;
fn boolean(self) -> Result<bool, Self::BooleanError>;
fn color(self) -> Result<Color, Self::ColorError>;
fn identifier(self) -> Result<String, Self::IdentifierError>;
}
impl<T: TryIntoValue> TryFrom<lexer::Value<T>> for Value {
type Error = TryIntoValueError<
T::StringError,
T::RegexError,
T::NumberError,
T::PercentageError,
T::BooleanError,
T::ColorError,
T::IdentifierError,
>;
fn try_from(value: lexer::Value<T>) -> Result<Self, Self::Error> {
Ok(match value {
lexer::Value::String(s) => {
Self::String(s.string().map_err(TryIntoValueError::StringError)?)
}
lexer::Value::Regex(r) => {
Self::Regex(r.regex().map_err(TryIntoValueError::RegexError)?)
}
lexer::Value::Number(n) => {
Self::Number(n.number().map_err(TryIntoValueError::NumberError)?)
}
lexer::Value::Percentage(n) => {
Self::Percentage(n.percentage().map_err(TryIntoValueError::PercentageError)?)
}
lexer::Value::Boolean(b) => {
Self::Boolean(b.boolean().map_err(TryIntoValueError::BooleanError)?)
}
lexer::Value::Color(c) => {
Self::Color(c.color().map_err(TryIntoValueError::ColorError)?)
}
})
}
}
impl TryIntoValue for &str {
type StringError = Infallible;
type RegexError = regex::Error;
type NumberError = fraction::error::ParseError;
type PercentageError = fraction::error::ParseError;
type BooleanError = ParseBoolError;
type ColorError = ParseColorError;
type IdentifierError = Infallible;
fn string(self) -> Result<String, Self::StringError> {
Ok(self.to_string())
}
fn regex(self) -> Result<Regex, Self::RegexError> {
self.parse()
}
fn number(self) -> Result<Fraction, Self::NumberError> {
self.parse()
}
fn percentage(self) -> Result<Percentage, Self::PercentageError> {
self.parse().map(Percentage)
}
fn boolean(self) -> Result<bool, Self::BooleanError> {
self.parse()
}
fn color(self) -> Result<Color, Self::ColorError> {
self.parse()
}
fn identifier(self) -> Result<String, Self::IdentifierError> {
Ok(self.to_string())
}
}