[librsvg: 2/5] Use data_url::mime::Mime instead of a String in BinaryData.mime_type




commit 6ace08acacd00db2d6e9a5b03224dcb32dcf792d
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Mar 17 12:55:15 2021 -0600

    Use data_url::mime::Mime instead of a String in BinaryData.mime_type
    
    Types are good [citation needed].

 src/css.rs      |  9 +++++++--
 src/document.rs | 14 ++++++++++----
 src/io.rs       | 29 +++++++++++++++++++++++------
 3 files changed, 40 insertions(+), 12 deletions(-)
---
diff --git a/src/css.rs b/src/css.rs
index a577d419..2c98d648 100644
--- a/src/css.rs
+++ b/src/css.rs
@@ -78,6 +78,7 @@ use cssparser::{
     CowRcStr, DeclarationListParser, DeclarationParser, Parser, ParserInput, QualifiedRuleParser,
     RuleListParser, SourceLocation, ToCss, _cssparser_internal_to_lowercase,
 };
+use data_url::mime::Mime;
 use markup5ever::{namespace_url, ns, LocalName, Namespace, Prefix, QualName};
 use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint};
 use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode, QuirksMode};
@@ -696,10 +697,10 @@ impl Stylesheet {
             .and_then(|data| {
                 let BinaryData {
                     data: bytes,
-                    content_type,
+                    mime_type,
                 } = data;
 
-                if content_type.as_ref().map(String::as_ref) == Some("text/css") {
+                if is_text_css(&mime_type) {
                     Ok(bytes)
                 } else {
                     rsvg_log!("\"{}\" is not of type text/css; ignoring", aurl);
@@ -751,6 +752,10 @@ impl Stylesheet {
     }
 }
 
+fn is_text_css(mime_type: &Mime) -> bool {
+    mime_type.type_ == "text" && mime_type.subtype == "css"
+}
+
 /// Runs the CSS cascade on the specified tree from all the stylesheets
 pub fn cascade(
     root: &mut Node,
diff --git a/src/document.rs b/src/document.rs
index dc106fd9..47e71ad6 100644
--- a/src/document.rs
+++ b/src/document.rs
@@ -1,5 +1,6 @@
 //! Main SVG document structure.
 
+use data_url::mime::Mime;
 use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
 use markup5ever::QualName;
 use once_cell::sync::Lazy;
@@ -9,6 +10,7 @@ use std::collections::HashMap;
 use std::fmt;
 use std::include_str;
 use std::rc::Rc;
+use std::str::FromStr;
 
 use crate::css::{self, Origin, Stylesheet};
 use crate::error::{AcquireError, AllowedUrlError, LoadingError, NodeIdError};
@@ -248,7 +250,7 @@ fn load_image(
 ) -> Result<SharedImageSurface, LoadingError> {
     let BinaryData {
         data: bytes,
-        mut content_type,
+        mime_type,
     } = io::acquire_data(&aurl, None)?;
 
     if bytes.is_empty() {
@@ -260,9 +262,13 @@ fn load_image(
     // Adobe Illustrator generate data: URLs without MIME-type for image
     // data.  We'll catch this and fall back to sniffing by unsetting the
     // content_type.
-    if content_type.as_deref() == Some("text/plain;charset=US-ASCII") {
-        content_type = None;
-    }
+    let unspecified_mime_type = Mime::from_str("text/plain;charset=US-ASCII").unwrap();
+
+    let content_type = if mime_type == unspecified_mime_type {
+        None
+    } else {
+        Some(format!("{}/{}", mime_type.type_, mime_type.subtype))
+    };
 
     let loader = if let Some(ref content_type) = content_type {
         PixbufLoader::new_with_mime_type(content_type)?
diff --git a/src/io.rs b/src/io.rs
index dbdf3dfd..bb787bbe 100644
--- a/src/io.rs
+++ b/src/io.rs
@@ -1,8 +1,10 @@
 //! Utilities to acquire streams and data from from URLs.
 
+use data_url::{mime::Mime, DataUrl};
 use gio::{Cancellable, File as GFile, FileExt, InputStream, MemoryInputStream};
 use glib::{self, Bytes as GBytes, Cast};
 use std::fmt;
+use std::str::FromStr;
 
 use crate::url_resolver::AllowedUrl;
 
@@ -28,13 +30,21 @@ impl fmt::Display for IoError {
 
 pub struct BinaryData {
     pub data: Vec<u8>,
-    pub content_type: Option<String>,
+    pub mime_type: Mime,
 }
 
 fn decode_data_uri(uri: &str) -> Result<BinaryData, IoError> {
-    let data_url = data_url::DataUrl::process(uri).map_err(|_| IoError::BadDataUrl)?;
+    let data_url = DataUrl::process(uri).map_err(|_| IoError::BadDataUrl)?;
 
-    let mime_type = data_url.mime_type().to_string();
+    let mime = data_url.mime_type();
+
+    // data_url::mime::Mime doesn't impl Clone, so do it by hand
+
+    let mime_type = Mime {
+        type_: mime.type_.clone(),
+        subtype: mime.subtype.clone(),
+        parameters: mime.parameters.clone(),
+    };
 
     let (bytes, fragment_id) = data_url.decode_to_vec().map_err(|_| IoError::BadDataUrl)?;
 
@@ -49,7 +59,7 @@ fn decode_data_uri(uri: &str) -> Result<BinaryData, IoError> {
 
     Ok(BinaryData {
         data: bytes,
-        content_type: Some(mime_type),
+        mime_type,
     })
 }
 
@@ -95,11 +105,18 @@ pub fn acquire_data(
         let (contents, _etag) = file.load_contents(cancellable)?;
 
         let (content_type, _uncertain) = gio::content_type_guess(Some(uri), &contents);
-        let mime_type = gio::content_type_get_mime_type(&content_type).map(String::from);
+
+        let mime_type = if let Some(mime_type_str) = gio::content_type_get_mime_type(&content_type)
+        {
+            Mime::from_str(&mime_type_str)
+                .expect("gio::content_type_get_mime_type returned an invalid MIME-type!?")
+        } else {
+            Mime::from_str("application/octet-stream").unwrap()
+        };
 
         Ok(BinaryData {
             data: contents,
-            content_type: mime_type.map(From::from),
+            mime_type,
         })
     }
 }


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