[librsvg: 25/51] Introduce a ParseError type



commit b72421e1e488fde07043e4a7fb53e704b11b1c7a
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Dec 17 14:54:58 2019 -0600

    Introduce a ParseError type
    
    This is a type alias:
    
      type ParseError<'i> = cssparser::ParseError<'i, ValueErrorKind>;
    
    to represent short-lived errors.
    
    We also impl AttributeResultExt for results with that error type, to
    turn them into a long-lived NodeError.

 rsvg_internals/src/css.rs   |  5 ++-
 rsvg_internals/src/error.rs | 85 ++++++++++++++++++++++++++++++++++-----------
 2 files changed, 66 insertions(+), 24 deletions(-)
---
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
index 0fe1503a..f2f2619e 100644
--- a/rsvg_internals/src/css.rs
+++ b/rsvg_internals/src/css.rs
@@ -265,7 +265,7 @@ impl<'i> AtRuleParser<'i> for RuleParser {
         &mut self,
         name: CowRcStr<'i>,
         input: &mut Parser<'i, 't>,
-    ) -> Result<AtRuleType<Self::PreludeNoBlock, Self::PreludeBlock>, ParseError<'i, Self::Error>>
+    ) -> Result<AtRuleType<Self::PreludeNoBlock, Self::PreludeBlock>, cssparser::ParseError<'i, Self::Error>>
     {
         match_ignore_ascii_case! { &name,
             "import" => {
@@ -588,8 +588,7 @@ impl<'a> PartialOrd for Match<'a> {
 
 impl<'a> PartialEq for Match<'a> {
     fn eq(&self, other: &Self) -> bool {
-        self.origin == other.origin
-            && self.specificity == other.specificity
+        self.origin == other.origin && self.specificity == other.specificity
     }
 }
 
diff --git a/rsvg_internals/src/error.rs b/rsvg_internals/src/error.rs
index 5e558e5e..2ca560e7 100644
--- a/rsvg_internals/src/error.rs
+++ b/rsvg_internals/src/error.rs
@@ -4,13 +4,24 @@ use std::error::{self, Error};
 use std::fmt;
 
 use cairo;
-use cssparser::{BasicParseError, BasicParseErrorKind};
+use cssparser::{self, BasicParseError, BasicParseErrorKind, ParseErrorKind, ToCss};
 use glib;
 use markup5ever::QualName;
 
 use crate::allowed_url::Fragment;
 use crate::node::RsvgNode;
 
+/// A short-lived error.
+///
+/// The lifetime of the error is the same as the `cssparser::ParserInput` that
+/// was used to create a `cssparser::Parser`.  That is, it is the lifetime of
+/// the string data that is being parsed.
+///
+/// The code flow will sometimes require preserving this error as a long-lived struct;
+/// see the `impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>>` for that
+/// purpose.
+pub type ParseError<'i> = cssparser::ParseError<'i, ValueErrorKind>;
+
 /// A simple error which refers to an attribute's value
 #[derive(Debug, Clone, PartialEq)]
 pub enum ValueErrorKind {
@@ -39,17 +50,9 @@ impl fmt::Display for ValueErrorKind {
         match *self {
             ValueErrorKind::UnknownProperty => write!(f, "unknown property name"),
 
-            ValueErrorKind::Parse(ref s) => write!(
-                f,
-                "parse error: {}",
-                s
-            ),
-
-            ValueErrorKind::Value(ref s) => write!(
-                f,
-                "invalid value: {}",
-                s
-            ),
+            ValueErrorKind::Parse(ref s) => write!(f, "parse error: {}", s),
+
+            ValueErrorKind::Value(ref s) => write!(f, "invalid value: {}", s),
         }
     }
 }
@@ -79,7 +82,7 @@ impl fmt::Display for NodeError {
 
 impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
     fn from(e: BasicParseError<'_>) -> ValueErrorKind {
-        let BasicParseError { kind, location: _ } =  e;
+        let BasicParseError { kind, location: _ } = e;
 
         let msg = match kind {
             BasicParseErrorKind::UnexpectedToken(_) => "unexpected token",
@@ -129,17 +132,19 @@ pub enum AcquireError {
 impl fmt::Display for AcquireError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            AcquireError::LinkNotFound(ref frag) =>
-                write!(f, "link not found: {}", frag),
+            AcquireError::LinkNotFound(ref frag) => write!(f, "link not found: {}", frag),
 
-            AcquireError::InvalidLinkType(ref frag) =>
-                write!(f, "link {} is to object of invalid type", frag),
+            AcquireError::InvalidLinkType(ref frag) => {
+                write!(f, "link {} is to object of invalid type", frag)
+            }
 
-            AcquireError::CircularReference(ref node) =>
-                write!(f, "circular reference in node {}", node),
+            AcquireError::CircularReference(ref node) => {
+                write!(f, "circular reference in node {}", node)
+            }
 
-            AcquireError::MaxReferencesExceeded =>
-                write!(f, "maximum number of references exceeded"),
+            AcquireError::MaxReferencesExceeded => {
+                write!(f, "maximum number of references exceeded")
+            }
         }
     }
 }
@@ -176,6 +181,44 @@ impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O> for Result<O, E> {
     }
 }
 
+/// Turns a short-lived `ParseError` into a long-lived `NodeError`
+impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>> {
+    fn attribute(self, attr: QualName) -> Result<O, NodeError> {
+        self.map_err(|e| {
+            // FIXME: eventually, here we'll want to preserve the location information
+
+            let ParseError {
+                kind,
+                location: _location,
+            } = e;
+
+            match kind {
+                ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(tok)) => {
+                    let mut s = String::from("unexpected token '");
+                    tok.to_css(&mut s).unwrap(); // FIXME: what do we do with a fmt::Error?
+                    s.push_str("'");
+
+                    NodeError {
+                        attr,
+                        err: ValueErrorKind::Parse(s),
+                    }
+                },
+
+                ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => NodeError {
+                    attr,
+                    err: ValueErrorKind::parse_error("unexpected end of input"),
+                },
+
+                ParseErrorKind::Basic(_) => unreachable!(
+                    "attribute parsers should not return errors for CSS rules"
+                ),
+
+                ParseErrorKind::Custom(err) => NodeError { attr, err },
+            }
+        })
+    }
+}
+
 /// Errors returned when creating an `Href` out of a string
 #[derive(Debug, Clone, PartialEq)]
 pub enum HrefError {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]