[librsvg] Xml2Parser: Use an Rc instead of box-a-pointer shenanigans



commit 9a5b9a476c8701073c74b2ad1ee1eeeabed5dcfb
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Dec 7 10:15:34 2018 -0600

    Xml2Parser: Use an Rc instead of box-a-pointer shenanigans
    
    The gio functions we call already return a proper glib::Error, not a
    glib_sys::GError, so use Proper Rust Types(tm) instead of messing
    around with pointers.

 rsvg_internals/src/xml2_load.rs | 44 +++++++++++++++++++++--------------------
 1 file changed, 23 insertions(+), 21 deletions(-)
---
diff --git a/rsvg_internals/src/xml2_load.rs b/rsvg_internals/src/xml2_load.rs
index ef900676..fa5993da 100644
--- a/rsvg_internals/src/xml2_load.rs
+++ b/rsvg_internals/src/xml2_load.rs
@@ -5,8 +5,10 @@ use gio;
 use gio::prelude::*;
 use gio_sys;
 use glib_sys;
+use std::cell::RefCell;
 use std::mem;
 use std::ptr;
+use std::rc::Rc;
 use std::slice;
 use std::str;
 
@@ -218,7 +220,7 @@ fn set_xml_parse_options(parser: xmlParserCtxtPtr, unlimited_size: bool) {
 struct StreamCtx {
     stream: gio::InputStream,
     cancellable: Option<gio::Cancellable>,
-    gio_error: *mut *mut glib_sys::GError,
+    gio_error: Rc<RefCell<Option<glib::Error>>>,
 }
 
 // read() callback from xmlCreateIOParserCtxt()
@@ -229,8 +231,10 @@ unsafe extern "C" fn stream_ctx_read(
 ) -> libc::c_int {
     let ctx = &mut *(context as *mut StreamCtx);
 
+    let mut err_ref = ctx.gio_error.borrow_mut();
+
     // has the error been set already?
-    if !(*ctx.gio_error).is_null() {
+    if err_ref.is_some() {
         return -1;
     }
 
@@ -240,8 +244,8 @@ unsafe extern "C" fn stream_ctx_read(
         Ok(size) => size as libc::c_int,
 
         Err(e) => {
-            let e: *const glib_sys::GError = e.to_glib_full();
-            *ctx.gio_error = e as *mut _;
+            // Just store the first I/O error we get; ignore subsequent ones.
+            *err_ref = Some(e);
             -1
         }
     }
@@ -255,10 +259,11 @@ unsafe extern "C" fn stream_ctx_close(context: *mut libc::c_void) -> libc::c_int
         Ok(()) => 0,
 
         Err(e) => {
+            let mut err_ref = ctx.gio_error.borrow_mut();
+
             // don't overwrite a previous error
-            if (*ctx.gio_error).is_null() {
-                let e: *const glib_sys::GError = e.to_glib_full();
-                *ctx.gio_error = e as *mut _;
+            if err_ref.is_none() {
+                *err_ref = Some(e);
             }
 
             -1
@@ -272,7 +277,7 @@ unsafe extern "C" fn stream_ctx_close(context: *mut libc::c_void) -> libc::c_int
 
 struct Xml2Parser {
     parser: xmlParserCtxtPtr,
-    gio_error: Box<*mut glib_sys::GError>,
+    gio_error: Rc<RefCell<Option<glib::Error>>>,
 }
 
 impl Xml2Parser {
@@ -286,17 +291,15 @@ impl Xml2Parser {
         // xmlCreateIOParserCtxt() is successful, needs to hold a
         // location to place a GError from within the I/O callbacks
         // stream_ctx_read() and stream_ctx_close().  We put this
-        // location in a Box so that it can outlive the call to
+        // location in an Rc so that it can outlive the call to
         // xmlCreateIOParserCtxt() in case that fails, since on
         // failure that function frees the StreamCtx.
-        let mut gio_error: Box<*mut glib_sys::GError> = Box::new(ptr::null_mut());
-
-        let p_gio_error: *mut *mut glib_sys::GError = &mut *gio_error;
+        let gio_error = Rc::new(RefCell::new(None));
 
         let ctx = Box::new(StreamCtx {
             stream,
             cancellable,
-            gio_error: p_gio_error,
+            gio_error: gio_error.clone(),
         });
 
         let mut sax_handler = get_xml2_sax_handler();
@@ -326,17 +329,16 @@ impl Xml2Parser {
         unsafe {
             let xml_parse_success = xmlParseDocument(self.parser) == 0;
 
-            let io_success = self.gio_error.is_null();
+            let mut err_ref = self.gio_error.borrow_mut();
+
+            let io_error = err_ref.take();
 
-            if !io_success {
-                Err(ParseFromStreamError::IoError(from_glib_full(
-                    *self.gio_error,
-                )))
+            if let Some(io_error) = io_error {
+                Err(ParseFromStreamError::IoError(io_error))
             } else if !xml_parse_success {
                 let xerr = xmlCtxtGetLastError(self.parser as *mut _);
-                Err(ParseFromStreamError::XmlParseError(xml2_error_to_string(
-                    xerr,
-                )))
+                let msg = xml2_error_to_string(xerr);
+                Err(ParseFromStreamError::XmlParseError(msg))
             } else {
                 Ok(())
             }


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