[librsvg: 93/95] PropertyBag: Don't do redundant UTF-8 validation when generating Rust strings



commit af5396832078460c04ba438aa7ea29dce8eb3438
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Feb 21 19:59:02 2018 -0600

    PropertyBag: Don't do redundant UTF-8 validation when generating Rust strings
    
    The CStr we store come from C strings from libxml2, so they have
    already been validated as UTF-8.

 rust/src/property_bag.rs | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)
---
diff --git a/rust/src/property_bag.rs b/rust/src/property_bag.rs
index ac558758..680b0c88 100644
--- a/rust/src/property_bag.rs
+++ b/rust/src/property_bag.rs
@@ -8,7 +8,7 @@ use std::collections::hash_map;
 use std::ffi::{CStr, CString};
 use std::ops::Deref;
 use std::ptr;
-use std::str::FromStr;
+use std::str::{self, FromStr};
 
 use attributes::Attribute;
 
@@ -20,6 +20,19 @@ pub struct PropertyBagIter<'a>(PropertyBagCStrIter<'a>);
 
 pub struct PropertyBagCStrIter<'a>(hash_map::Iter<'a, &'a CStr, (Attribute, &'a CStr)>);
 
+trait Utf8CStrToStr {
+    fn to_str_utf8(&self) -> &str;
+}
+
+impl Utf8CStrToStr for CStr {
+    fn to_str_utf8(&self) -> &str {
+        // We can *only* do this when the CStr comes from a C string that was validated
+        // as UTF-8 on the C side of things.  In our case, the C strings from libxml2 and
+        // are valid UTF-8.
+        unsafe { str::from_utf8_unchecked(self.to_bytes()) }
+    }
+}
+
 impl<'a> PropertyBag<'a> {
     pub unsafe fn new_from_key_value_pairs(pairs: *const *const libc::c_char) -> PropertyBag<'a> {
         let mut map = HashMap::new();
@@ -37,7 +50,7 @@ impl<'a> PropertyBag<'a> {
 
                     // We silently drop unknown attributes.  New attributes should be added in
                     // build.rs.
-                    if let Ok(attr) = Attribute::from_str(key_str.to_str().unwrap()) {
+                    if let Ok(attr) = Attribute::from_str(key_str.to_str_utf8()) {
                         map.insert(key_str, (attr, val_str));
                     }
                 } else {
@@ -92,7 +105,7 @@ impl<'a> Iterator for PropertyBagIter<'a> {
     type Item = (&'a str, Attribute, &'a str);
 
     fn next(&mut self) -> Option<Self::Item> {
-        self.0.next().map(|(k, a, v)| (k.to_str().unwrap(), a, v.to_str().unwrap()))
+        self.0.next().map(|(k, a, v)| (k.to_str_utf8(), a, v.to_str_utf8()))
     }
 }
 
@@ -242,8 +255,8 @@ mod tests {
                                                     &mut key as *mut _,
                                                     &mut att as *mut _,
                                                     &mut val as *mut _)) {
-            let k = unsafe { CStr::from_ptr(key).to_str().unwrap() };
-            let v = unsafe { CStr::from_ptr(val).to_str().unwrap() };
+            let k = unsafe { CStr::from_ptr(key).to_str_utf8() };
+            let v = unsafe { CStr::from_ptr(val).to_str_utf8() };
 
             if k == "rx" {
                 assert!(att == Attribute::Rx);


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