[librsvg] node.rs: New function rsvg_node_is_same() to compare node pointers



commit aec1ceac95759cdea7330d51c4e877e6edc93347
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Feb 16 21:08:16 2017 -0600

    node.rs: New function rsvg_node_is_same() to compare node pointers
    
    On the C side, two RsvgNode* can be different and yet refer to the same
    Node in the Rust code.  This function can be used to test for that.
    
    That is,
    
      if (node_a == node_b)
    
    is no longer valid in the C code.  Instead, use this:
    
      if (rsvg_node_is_same (node_a, node_b))

 rsvg-private.h   |    4 +++
 rust/src/lib.rs  |    1 +
 rust/src/node.rs |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 70 insertions(+), 2 deletions(-)
---
diff --git a/rsvg-private.h b/rsvg-private.h
index 1d24f2f..955fa2f 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -358,6 +358,10 @@ G_GNUC_INTERNAL
 RsvgNodeType rsvg_node_get_type (RsvgNode *node);
 
 /* Implemented in rust/src/node.rs */
+G_GNUC_INTERNAL
+gboolean rsvg_node_is_same (RsvgNode *node1, RsvgNode *node2);
+
+/* Implemented in rust/src/node.rs */
 /* Call this as newref = rsvg_node_ref (node);  You don't own the node anymore, just the newref! */
 G_GNUC_INTERNAL
 RsvgNode *rsvg_node_ref (RsvgNode *node) G_GNUC_WARN_UNUSED_RESULT;
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index a3cea12..8826619 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -59,6 +59,7 @@ pub use node::{
     rsvg_node_get_parent,
     rsvg_node_ref,
     rsvg_node_unref,
+    rsvg_node_is_same,
     rsvg_node_get_state,
     rsvg_node_add_child,
     rsvg_node_set_atts,
diff --git a/rust/src/node.rs b/rust/src/node.rs
index 5ede878..0eb18c0 100644
--- a/rust/src/node.rs
+++ b/rust/src/node.rs
@@ -173,9 +173,9 @@ pub extern fn rsvg_node_get_parent (raw_node: *const RsvgNode) -> *const RsvgNod
 }
 
 #[no_mangle]
-pub unsafe extern fn rsvg_node_ref (raw_node: *mut RsvgNode) -> *mut RsvgNode {
+pub extern fn rsvg_node_ref (raw_node: *mut RsvgNode) -> *mut RsvgNode {
     assert! (!raw_node.is_null ());
-    let node: &RsvgNode = & *raw_node;
+    let node: &RsvgNode = unsafe { & *raw_node };
 
     box_node (node.clone ())
 }
@@ -189,6 +189,30 @@ pub extern fn rsvg_node_unref (raw_node: *mut RsvgNode) -> *mut RsvgNode {
     ptr::null_mut () // so the caller can do "node = rsvg_node_unref (node);" and lose access to the node
 }
 
+// See https://github.com/rust-lang/rust/issues/36497 - this is what
+// added Rc::ptr_eq(), but we don't want to depend on unstable Rust
+// just yet.
+
+fn rc_node_ptr_eq<T: ?Sized> (this: &Rc<T>, other: &Rc<T>) -> bool {
+    let this_ptr: *const T = &**this;
+    let other_ptr: *const T = &**other;
+    this_ptr == other_ptr
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_is_same (raw_node1: *const RsvgNode, raw_node2: *const RsvgNode) -> bool {
+    if raw_node1.is_null () && raw_node2.is_null () {
+        true
+    } else if !raw_node1.is_null () && !raw_node2.is_null () {
+        let node1: &RsvgNode = unsafe { & *raw_node1 };
+        let node2: &RsvgNode = unsafe { & *raw_node2 };
+
+        rc_node_ptr_eq (node1, node2)
+    } else {
+        false
+    }
+}
+
 #[no_mangle]
 pub extern fn rsvg_node_get_state (raw_node: *const RsvgNode) -> *mut RsvgState {
     assert! (!raw_node.is_null ());
@@ -285,4 +309,43 @@ mod tests {
         ref1 = unsafe { rsvg_node_unref (ref1) };
         assert! (weak.upgrade ().is_none ());
     }
+
+    #[test]
+    fn reffed_node_is_same_as_original_node () {
+        let node = Rc::new (Node::new (NodeType::Path,
+                                       None,
+                                       ptr::null_mut (),
+                                       Box::new (TestNodeImpl {})));
+
+        let mut ref1 = box_node (node);
+
+        let mut ref2 = unsafe { rsvg_node_ref (ref1) };
+
+        unsafe { assert! (rsvg_node_is_same (ref1, ref2)); }
+
+        ref1 = rsvg_node_unref (ref1);
+        ref2 = rsvg_node_unref (ref2);
+    }
+
+    #[test]
+    fn different_nodes_have_different_pointers () {
+        let node1 = Rc::new (Node::new (NodeType::Path,
+                                       None,
+                                       ptr::null_mut (),
+                                       Box::new (TestNodeImpl {})));
+
+        let mut ref1 = box_node (node1);
+
+        let node2 = Rc::new (Node::new (NodeType::Path,
+                                       None,
+                                       ptr::null_mut (),
+                                       Box::new (TestNodeImpl {})));
+
+        let mut ref2 = box_node (node2);
+
+        unsafe { assert! (!rsvg_node_is_same (ref1, ref2)); }
+
+        ref1 = rsvg_node_unref (ref1);
+        ref2 = rsvg_node_unref (ref2);
+    }
 }


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