diff options
author | Federico Mena Quintero <federico@gnome.org> | 2022-10-24 16:18:54 -0500 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2022-11-04 09:33:33 -0600 |
commit | a14e4cf78bd38c5ef692539088a4d558619fde00 (patch) | |
tree | 87e2161f5d1f7622602fcf2d92ea3a2966bc5220 | |
parent | cddfb67bde046e54cf4c8aa36e521817c5c04ec5 (diff) | |
download | librsvg-a14e4cf78bd38c5ef692539088a4d558619fde00.tar.gz |
SystemLanguage: turn into an enum; store Valid and Invalid variants
Previously, parsing an invalid BCP47 language tag would be reported as
an Err(), and the corresponding element inside a <switch> would be set
"in error". Then, the <switch> implementation would detect that the
child element is in error and ignore it.
We are switching to storing the error condition in the SystemLanguage itself.
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/763>
-rw-r--r-- | src/cond.rs | 81 | ||||
-rw-r--r-- | src/element.rs | 10 |
2 files changed, 55 insertions, 36 deletions
diff --git a/src/cond.rs b/src/cond.rs index 99fc99c8..04c01042 100644 --- a/src/cond.rs +++ b/src/cond.rs @@ -9,6 +9,7 @@ use language_tags::LanguageTag; use crate::accept_language::{LanguageTags, UserLanguage}; use crate::error::*; +use crate::session::Session; // No extensions at the moment. static IMPLEMENTED_EXTENSIONS: &[&str] = &[]; @@ -77,8 +78,18 @@ impl RequiredFeatures { } } +/// The systemLanguage attribute inside `<cond>` element's children. +/// +/// Parsing the value of a `systemLanguage` attribute may fail if the document supplies +/// invalid BCP47 language tags. In that case, we store an `Invalid` variant. +/// +/// That variant is used later, during [`SystemLanguage::eval`], to see whether the +/// `<cond>` should match or not. #[derive(Debug, PartialEq)] -pub struct SystemLanguage(LanguageTags); +pub enum SystemLanguage { + Valid(LanguageTags), + Invalid, +} impl SystemLanguage { /// Parse a `systemLanguage` attribute and match it against a given `Locale` @@ -96,7 +107,7 @@ impl SystemLanguage { /// /// [`systemLanguage`]: https://www.w3.org/TR/SVG/struct.html#ConditionalProcessingSystemLanguageAttribute /// [BCP47]: http://www.ietf.org/rfc/bcp/bcp47.txt - pub fn from_attribute(s: &str) -> Result<SystemLanguage, ValueErrorKind> { + pub fn from_attribute(s: &str, session: &Session) -> SystemLanguage { let attribute_tags = s .split(',') .map(str::trim) @@ -105,14 +116,28 @@ impl SystemLanguage { ValueErrorKind::parse_error(&format!("invalid language tag: \"{}\"", e)) }) }) - .collect::<Result<Vec<LanguageTag>, _>>()?; - - Ok(SystemLanguage(LanguageTags::from(attribute_tags))) + .collect::<Result<Vec<LanguageTag>, _>>(); + + match attribute_tags { + Ok(tags) => SystemLanguage::Valid(LanguageTags::from(tags)), + + Err(e) => { + rsvg_log!( + session, + "ignoring systemLanguage attribute with invalid value: {}", + e + ); + SystemLanguage::Invalid + } + } } /// Evaluate a systemLanguage value for conditional processing. pub fn eval(&self, user_language: &UserLanguage) -> bool { - user_language.any_matches(&self.0) + match *self { + SystemLanguage::Valid(ref tags) => user_language.any_matches(tags), + SystemLanguage::Invalid => false, + } } } @@ -160,66 +185,58 @@ mod tests { #[test] fn system_language() { + let session = Session::new_for_test_suite(); + let locale = Locale::new("de,en-US").unwrap(); let user_language = UserLanguage::LanguageTags(LanguageTags::from_locale(&locale).unwrap()); - assert!(SystemLanguage::from_attribute("").is_err()); + assert!(matches!( + SystemLanguage::from_attribute("", &session), + SystemLanguage::Invalid + )); - assert!(SystemLanguage::from_attribute("12345").is_err()); + assert!(matches!( + SystemLanguage::from_attribute("12345", &session), + SystemLanguage::Invalid + )); assert_eq!( - SystemLanguage::from_attribute("fr") - .unwrap() - .eval(&user_language), + SystemLanguage::from_attribute("fr", &session).eval(&user_language), false ); assert_eq!( - SystemLanguage::from_attribute("en") - .unwrap() - .eval(&user_language), + SystemLanguage::from_attribute("en", &session).eval(&user_language), false ); assert_eq!( - SystemLanguage::from_attribute("de") - .unwrap() - .eval(&user_language), + SystemLanguage::from_attribute("de", &session).eval(&user_language), true ); assert_eq!( - SystemLanguage::from_attribute("en-US") - .unwrap() - .eval(&user_language), + SystemLanguage::from_attribute("en-US", &session).eval(&user_language), true ); assert_eq!( - SystemLanguage::from_attribute("en-GB") - .unwrap() - .eval(&user_language), + SystemLanguage::from_attribute("en-GB", &session).eval(&user_language), false ); assert_eq!( - SystemLanguage::from_attribute("DE") - .unwrap() - .eval(&user_language), + SystemLanguage::from_attribute("DE", &session).eval(&user_language), true ); assert_eq!( - SystemLanguage::from_attribute("de-LU") - .unwrap() - .eval(&user_language), + SystemLanguage::from_attribute("de-LU", &session).eval(&user_language), true ); assert_eq!( - SystemLanguage::from_attribute("fr, de") - .unwrap() - .eval(&user_language), + SystemLanguage::from_attribute("fr, de", &session).eval(&user_language), true ); } diff --git a/src/element.rs b/src/element.rs index 958665fd..f868dc59 100644 --- a/src/element.rs +++ b/src/element.rs @@ -130,7 +130,7 @@ impl<T: SetAttributes + Draw> ElementInner<T> { }; let mut set_attributes = || -> Result<(), ElementError> { - e.set_conditional_processing_attributes()?; + e.set_conditional_processing_attributes(session)?; e.set_presentation_attributes(session); Ok(()) }; @@ -192,7 +192,10 @@ impl<T: SetAttributes + Draw> ElementInner<T> { .unwrap_or(true) } - fn set_conditional_processing_attributes(&mut self) -> Result<(), ElementError> { + fn set_conditional_processing_attributes( + &mut self, + session: &Session, + ) -> Result<(), ElementError> { for (attr, value) in self.attributes.iter() { match attr.expanded() { expanded_name!("", "requiredExtensions") => { @@ -204,8 +207,7 @@ impl<T: SetAttributes + Draw> ElementInner<T> { } expanded_name!("", "systemLanguage") => { - self.system_language = - Some(SystemLanguage::from_attribute(value).attribute(attr)?); + self.system_language = Some(SystemLanguage::from_attribute(value, session)); } _ => {} |