diff --git a/color/src/lib.rs b/color/src/lib.rs
index 8933f32..06f7aae 100644
--- a/color/src/lib.rs
+++ b/color/src/lib.rs
@@ -40,7 +40,7 @@ pub use colorspace::{
pub use dynamic::{DynamicColor, Interpolator};
pub use gradient::{gradient, GradientIter};
pub use missing::Missing;
-pub use parse::{parse_color, Error};
+pub use parse::{parse_color, ParseError};
pub use tag::ColorSpaceTag;
const fn u8_to_f32(x: u32) -> f32 {
diff --git a/color/src/parse.rs b/color/src/parse.rs
index 9afd9f7..b5bf341 100644
--- a/color/src/parse.rs
+++ b/color/src/parse.rs
@@ -3,19 +3,95 @@
//! Parse CSS4 color
+use core::error::Error;
use core::f64;
+use core::fmt;
use core::str::FromStr;
use crate::{AlphaColor, ColorSpaceTag, DynamicColor, Missing, Srgb};
-// TODO: proper error type, maybe include string offset
+// TODO: maybe include string offset
/// Error type for parse errors.
///
-/// Currently just a static string, but likely will be changed to
-/// an enum.
-///
/// Discussion question: should it also contain a string offset?
-pub type Error = &'static str;
+#[derive(Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub enum ParseError {
+ /// Unclosed comment
+ UnclosedComment,
+ /// Unknown angle dimesnion
+ UnknownAngleDimension,
+ /// Unknown angle
+ UnknownAngle,
+ /// Unknown color component
+ UnknownColorComponent,
+ /// Unknown color identifier
+ UnknownColorIdentifier,
+ /// Unknown color space
+ UnknownColorSpace,
+ /// Unknown color syntax
+ UnknownColorSyntax,
+ /// Expected arguments
+ ExpectedArguments,
+ /// Expected closing parenthesis
+ ExpectedClosingParenthesis,
+ /// Expected color space identifier
+ ExpectedColorSpaceIdentifier,
+ /// Expected comma
+ ExpectedComma,
+ /// Invalid hex digit
+ InvalidHexDigit,
+ /// Wrong number of hex digits
+ WrongNumberOfHexDigits,
+}
+
+impl Error for ParseError {}
+
+impl fmt::Display for ParseError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ Self::UnclosedComment => {
+ write!(f, "unclosed comment")
+ }
+ Self::UnknownAngleDimension => {
+ write!(f, "unknown angle dimension")
+ }
+ Self::UnknownAngle => {
+ write!(f, "unknown angle")
+ }
+ Self::UnknownColorComponent => {
+ write!(f, "unknown color component")
+ }
+ Self::UnknownColorIdentifier => {
+ write!(f, "unknown color identifier")
+ }
+ Self::UnknownColorSpace => {
+ write!(f, "unknown color space")
+ }
+ Self::UnknownColorSyntax => {
+ write!(f, "unknown color syntax")
+ }
+ Self::ExpectedArguments => {
+ write!(f, "expected arguments")
+ }
+ Self::ExpectedClosingParenthesis => {
+ write!(f, "expected closing parenthesis")
+ }
+ Self::ExpectedColorSpaceIdentifier => {
+ write!(f, "expected color space identifier")
+ }
+ Self::ExpectedComma => {
+ write!(f, "expected comma")
+ }
+ Self::InvalidHexDigit => {
+ write!(f, "invalid hex digit")
+ }
+ Self::WrongNumberOfHexDigits => {
+ write!(f, "wrong number of hex digits")
+ }
+ }
+ }
+}
#[derive(Default)]
struct Parser<'a> {
@@ -57,12 +133,12 @@ impl<'a> Parser<'a> {
}
// This will be called at the start of most tokens.
- fn consume_comments(&mut self) -> Result<(), Error> {
+ fn consume_comments(&mut self) -> Result<(), ParseError> {
while self.s[self.ix..].starts_with("/*") {
if let Some(i) = self.s[self.ix + 2..].find("*/") {
self.ix += i + 4;
} else {
- return Err("unclosed comment");
+ return Err(ParseError::UnclosedComment);
}
}
Ok(())
@@ -220,18 +296,18 @@ impl<'a> Parser<'a> {
}
/// Parse a color component.
- fn scaled_component(&mut self, scale: f64, pct_scale: f64) -> Result