[librsvg] rsvg_handle_new_from_file(): Port the implementation to Rust



commit 169bf43e3cd8dc64ba420415c53365c45e9dcf51
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Jan 16 13:51:45 2019 -0600

    rsvg_handle_new_from_file(): Port the implementation to Rust
    
    The C code had an additional check for the resulting GFile to actually
    be able to produce a URI.  I think this is how it intended to catch
    invalid URIs being passed to g_file_new_for_uri().
    
    The code now uses Rust constructs to decide whether to call
    g_file_new_for_uri() or g_file_new_for_path(), so I've removed that
    check.  In any case, an invalid GFile should only produce I/O errors,
    which will get caught during the loading stage.

 librsvg/rsvg-handle.c        | 37 ++++++-------------------------------
 rsvg_internals/src/handle.rs | 24 +++++++++++++++++++++++-
 rsvg_internals/src/lib.rs    |  1 +
 3 files changed, 30 insertions(+), 32 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 3e903573..88621087 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -181,6 +181,8 @@ extern void rsvg_handle_rust_set_size_callback (RsvgHandleRust *raw_handle,
                                                 RsvgSizeFunc size_func,
                                                 gpointer user_data,
                                                 GDestroyNotify destroy_notify);
+extern RsvgHandle *rsvg_handle_rust_new_from_file (const char *filename,
+                                                   GError **error);
 extern RsvgHandle *rsvg_handle_rust_new_from_gfile_sync (GFile *file,
                                                          RsvgHandleFlags flags,
                                                          GCancellable *cancellable,
@@ -488,7 +490,7 @@ rsvg_handle_new_from_data (const guint8 *data, gsize data_len, GError **error)
 
 /**
  * rsvg_handle_new_from_file:
- * @file_name: The file name to load. If built with gnome-vfs, can be a URI.
+ * @filename: The file name to load, or a URI.
  * @error: return location for errors
  *
  * Loads the SVG specified by @file_name.
@@ -497,39 +499,12 @@ rsvg_handle_new_from_data (const guint8 *data, gsize data_len, GError **error)
  * Since: 2.14
  */
 RsvgHandle *
-rsvg_handle_new_from_file (const gchar *file_name, GError **error)
+rsvg_handle_new_from_file (const gchar *filename, GError **error)
 {
-    gchar *base_uri;
-    RsvgHandle *handle;
-    GFile *file;
-    char *scheme;
-
-    g_return_val_if_fail (file_name != NULL, NULL);
+    g_return_val_if_fail (filename != NULL, NULL);
     g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-    scheme = g_uri_parse_scheme (file_name);
-    if (scheme) {
-        file = g_file_new_for_uri (file_name);
-        g_free (scheme);
-    } else {
-        file = g_file_new_for_path (file_name);
-    }
-
-    base_uri = g_file_get_uri (file);
-    if (!base_uri) {
-        g_set_error (error,
-                     G_IO_ERROR,
-                     G_IO_ERROR_FAILED,
-                     _("Cannot obtain URI from '%s'"), file_name);
-        g_object_unref (file);
-        return NULL;
-    }
-    g_free (base_uri);
-
-    handle = rsvg_handle_new_from_gfile_sync (file, 0, NULL, error);
-    g_object_unref (file);
-
-    return handle;
+    return rsvg_handle_rust_new_from_file (filename, error);
 }
 
 /**
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index cfe8994e..c7516f21 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -1,7 +1,8 @@
 use std;
 use std::cell::{Cell, RefCell};
-use std::ffi::CString;
+use std::ffi::{CStr, CString};
 use std::mem;
+use std::path::PathBuf;
 use std::ptr;
 use std::rc::Rc;
 use std::slice;
@@ -1011,6 +1012,27 @@ pub unsafe extern "C" fn rsvg_handle_rust_get_position_sub(
     }
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_new_from_file(
+    filename: *const libc::c_char,
+    error: *mut *mut glib_sys::GError,
+) -> *mut RsvgHandle {
+    // This API lets the caller pass a URI, or a file name in the operating system's
+    // encoding.  So, first we'll see if it's UTF-8, and in that case, try the URL version.
+    // Otherwise, we'll try building a path name.
+
+    let cstr = CStr::from_ptr(filename);
+
+    let file = cstr
+        .to_str()
+        .map_err(|_| ())
+        .and_then(|utf8| Url::parse(utf8).map_err(|_| ()))
+        .and_then(|url| Ok(gio::File::new_for_uri(url.as_str())))
+        .unwrap_or_else(|_| gio::File::new_for_path(PathBuf::from_glib_none(filename)));
+
+    rsvg_handle_rust_new_from_gfile_sync(file.to_glib_none().0, 0, ptr::null_mut(), error)
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_handle_rust_new_from_gfile_sync(
     file: *mut gio_sys::GFile,
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 5ad608b6..72e7d572 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -55,6 +55,7 @@ pub use handle::{
     rsvg_handle_rust_has_sub,
     rsvg_handle_rust_new,
     rsvg_handle_rust_new_from_data,
+    rsvg_handle_rust_new_from_file,
     rsvg_handle_rust_new_from_gfile_sync,
     rsvg_handle_rust_new_from_stream_sync,
     rsvg_handle_rust_read_stream_sync,


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