[librsvg: 10/18] rsvg_get_input_stream_for_loading(): Port to Rust



commit a688447c0b2d91c9f085973aac87f401ee2cf2b8
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Nov 23 12:07:49 2018 -0600

    rsvg_get_input_stream_for_loading(): Port to Rust

 Cargo.lock                |  2 ++
 librsvg/rsvg-load.c       | 39 +++--------------------------
 rsvg_internals/Cargo.toml |  2 ++
 rsvg_internals/src/io.rs  | 63 ++++++++++++++++++++++++++++++++++++++++++++++-
 rsvg_internals/src/lib.rs |  4 ++-
 5 files changed, 72 insertions(+), 38 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 37be5da3..d8410398 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -942,6 +942,8 @@ dependencies = [
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "float-cmp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdk-pixbuf 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gio-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c
index 27b9fe30..45a33d35 100644
--- a/librsvg/rsvg-load.c
+++ b/librsvg/rsvg-load.c
@@ -641,44 +641,11 @@ close_impl (RsvgLoad *load, GError ** error)
 #define GZ_MAGIC_0 ((guchar) 0x1f)
 #define GZ_MAGIC_1 ((guchar) 0x8b)
 
-static GInputStream *
+/* Implemented in rsvg_internals/src/io.rs */
+extern GInputStream *
 rsvg_get_input_stream_for_loading (GInputStream *stream,
                                    GCancellable *cancellable,
-                                   GError      **error)
-{
-    gssize num_read;
-    const guchar *buf;
-
-    /* detect zipped streams */
-    stream = g_buffered_input_stream_new (stream);
-    num_read = g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (stream), 2, cancellable, error);
-    if (num_read < 2) {
-        g_object_unref (stream);
-        if (num_read < 0) {
-            g_assert (error == NULL || *error != NULL);
-        } else {
-            g_set_error (error, rsvg_error_quark (), RSVG_ERROR_FAILED,
-                         _("Input file is too short"));
-        }
-
-        return NULL;
-    }
-
-    buf = g_buffered_input_stream_peek_buffer (G_BUFFERED_INPUT_STREAM (stream), NULL);
-    if ((buf[0] == GZ_MAGIC_0) && (buf[1] == GZ_MAGIC_1)) {
-        GConverter *converter;
-        GInputStream *conv_stream;
-
-        converter = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
-        conv_stream = g_converter_input_stream_new (stream, converter);
-        g_object_unref (converter);
-        g_object_unref (stream);
-
-        stream = conv_stream;
-    }
-
-    return stream;
-}
+                                   GError      **error);
 
 gboolean
 rsvg_load_read_stream_sync (RsvgLoad     *load,
diff --git a/rsvg_internals/Cargo.toml b/rsvg_internals/Cargo.toml
index b6e8d44f..02257492 100644
--- a/rsvg_internals/Cargo.toml
+++ b/rsvg_internals/Cargo.toml
@@ -28,6 +28,8 @@ downcast-rs = "^1.0.0"
 encoding = "0.2.33"
 float-cmp = "0.4.0"
 gdk-pixbuf = "0.5.0"
+gio = "0.5.1"
+gio-sys = "0.7.0"
 glib = "0.6.0"
 glib-sys = "0.7.0"
 itertools = "0.7.4"
diff --git a/rsvg_internals/src/io.rs b/rsvg_internals/src/io.rs
index 3997fc98..a3e6b700 100644
--- a/rsvg_internals/src/io.rs
+++ b/rsvg_internals/src/io.rs
@@ -1,11 +1,22 @@
 use data_url;
+use gio_sys;
 use glib_sys;
 use libc;
 
+use gio::{
+    BufferedInputStream,
+    BufferedInputStreamExt,
+    Cancellable,
+    ConverterInputStream,
+    InputStream,
+    ZlibCompressorFormat,
+    ZlibDecompressor,
+};
 use glib::translate::*;
+use glib::Cast;
 use std::ptr;
 
-use error::{set_gerror, LoadingError};
+use error::{set_gerror, LoadingError, RsvgError};
 use handle::BinaryData;
 use util::utf8_cstr;
 
@@ -75,3 +86,53 @@ pub fn rsvg_decode_data_uri(
         }
     }
 }
+
+// Header of a gzip data stream
+const GZ_MAGIC_0: u8 = 0x1f;
+const GZ_MAGIC_1: u8 = 0x8b;
+
+fn get_input_stream_for_loading(
+    stream: InputStream,
+    cancellable: Option<Cancellable>,
+) -> Result<InputStream, glib::Error> {
+    // detect gzipped streams (svgz)
+
+    let buffered = BufferedInputStream::new(&stream);
+    let num_read = buffered.fill(2, cancellable.as_ref())?;
+    if num_read < 2 {
+        // FIXME: this string was localized in the original; localize it
+        return Err(glib::Error::new(RsvgError, "Input file is too short"));
+    }
+
+    let buf = buffered.peek_buffer();
+    assert!(buf.len() >= 2);
+    if buf[0] == GZ_MAGIC_0 && buf[1] == GZ_MAGIC_1 {
+        let decomp = ZlibDecompressor::new(ZlibCompressorFormat::Gzip);
+        let converter = ConverterInputStream::new(&buffered, &decomp);
+        Ok(converter.upcast::<InputStream>())
+    } else {
+        Ok(buffered.upcast::<InputStream>())
+    }
+}
+
+#[no_mangle]
+pub unsafe fn rsvg_get_input_stream_for_loading(
+    stream: *mut gio_sys::GInputStream,
+    cancellable: *mut gio_sys::GCancellable,
+    error: *mut *mut glib_sys::GError,
+) -> *mut gio_sys::GInputStream {
+    let stream = from_glib_borrow(stream);
+    let cancellable = from_glib_borrow(cancellable);
+
+    match get_input_stream_for_loading(stream, cancellable) {
+        Ok(stream) => stream.to_glib_full(),
+
+        Err(e) => {
+            if !error.is_null() {
+                *error = e.to_glib_full() as *mut _;
+            }
+
+            ptr::null_mut()
+        }
+    }
+}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 34bde426..bde0ed33 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -10,6 +10,8 @@ extern crate downcast_rs;
 extern crate encoding;
 extern crate float_cmp;
 extern crate gdk_pixbuf;
+extern crate gio;
+extern crate gio_sys;
 extern crate glib;
 extern crate glib_sys;
 extern crate itertools;
@@ -45,7 +47,7 @@ pub use drawing_ctx::{
 
 pub use handle::rsvg_handle_load_css;
 
-pub use io::rsvg_decode_data_uri;
+pub use io::{rsvg_decode_data_uri, rsvg_get_input_stream_for_loading};
 
 pub use node::rsvg_node_unref;
 


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