Resolve issues with Str introduced when it became ownable
authorMatt Corallo <git@bluematt.me>
Fri, 30 Apr 2021 23:09:05 +0000 (23:09 +0000)
committerMatt Corallo <git@bluematt.me>
Fri, 30 Apr 2021 23:41:31 +0000 (23:41 +0000)
When converting from a Str to an &str, we previously took ownership
of the Str, copied the pointer to its characters to an &str and
returned the &str. This made the returned bytes always unreadable.

Further, there is now no reason to use Vec_u8Z for owned Strs, so
we swap for Str as well.

c-bindings-gen/src/main.rs
c-bindings-gen/src/types.rs
lightning-c-bindings/src/c_types/mod.rs

index 7f5a3ed4b33c0fa66b213646f8c720189593f330..81f26bfa9ee3fce3da20931b431a90cfb91fee4b 100644 (file)
@@ -966,7 +966,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
                                                        writeln!(w, "#[no_mangle]").unwrap();
                                                        writeln!(w, "/// Read a {} object from a string", ident).unwrap();
                                                        writeln!(w, "pub extern \"C\" fn {}_from_str(s: crate::c_types::Str) -> {} {{", ident, container).unwrap();
-                                                       writeln!(w, "\tmatch {}::from_str(s.into()) {{", resolved_path).unwrap();
+                                                       writeln!(w, "\tmatch {}::from_str(s.into_str()) {{", resolved_path).unwrap();
                                                        writeln!(w, "\t\tOk(r) => {{").unwrap();
                                                        let new_var = types.write_to_c_conversion_new_var(w, &format_ident!("r"), &*i.self_ty, Some(&gen_types), false);
                                                        write!(w, "\t\t\tcrate::c_types::CResultTempl::ok(\n\t\t\t\t").unwrap();
index 395441b185f15476be764de81d7401b968795d85..d945431199eab2ba51a9fffac3498f0bd3d5582c 100644 (file)
@@ -842,8 +842,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "[u8; 3]" if !is_ref => Some("crate::c_types::ThreeBytes"), // Used for RGB values
 
                        "str" if is_ref => Some("crate::c_types::Str"),
-                       "String" if !is_ref => Some("crate::c_types::derived::CVec_u8Z"),
-                       "String" if is_ref => Some("crate::c_types::Str"),
+                       "String" => Some("crate::c_types::Str"),
 
                        "std::time::Duration" => Some("u64"),
                        "std::time::SystemTime" => Some("u64"),
@@ -915,7 +914,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "[usize]" if is_ref => Some(""),
 
                        "str" if is_ref => Some(""),
-                       "String" if !is_ref => Some("String::from_utf8("),
+                       "String" => Some(""),
                        // Note that we'll panic for String if is_ref, as we only have non-owned memory, we
                        // cannot create a &String.
 
@@ -980,8 +979,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "[u8]" if is_ref => Some(".to_slice()"),
                        "[usize]" if is_ref => Some(".to_slice()"),
 
-                       "str" if is_ref => Some(".into()"),
-                       "String" if !is_ref => Some(".into_rust()).unwrap()"),
+                       "str" if is_ref => Some(".into_str()"),
+                       "String" => Some(".into_string()"),
 
                        "std::time::Duration" => Some(")"),
                        "std::time::SystemTime" => Some("))"),
@@ -1129,8 +1128,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "[usize]" if is_ref => Some(""),
 
                        "str" if is_ref => Some(".into()"),
-                       "String" if !is_ref => Some(".into_bytes().into()"),
                        "String" if is_ref => Some(".as_str().into()"),
+                       "String" => Some(".into()"),
 
                        "std::time::Duration" => Some(".as_secs()"),
                        "std::time::SystemTime" => Some(".duration_since(::std::time::SystemTime::UNIX_EPOCH).expect(\"Times must be post-1970\").as_secs()"),
index b28bc80fd264f8ea232723adabc07614a1525b6c..3d45802e8063850cc2f71983e47daeefce11a304 100644 (file)
@@ -382,11 +382,25 @@ impl Into<Str> for &'static str {
                Str { chars: self.as_ptr(), len: self.len(), chars_is_owned: false }
        }
 }
-impl Into<&'static str> for Str {
-       fn into(self) -> &'static str {
+impl Str {
+       pub(crate) fn into_str(&self) -> &'static str {
                if self.len == 0 { return ""; }
                std::str::from_utf8(unsafe { std::slice::from_raw_parts(self.chars, self.len) }).unwrap()
        }
+       pub(crate) fn into_string(self) -> String {
+               let bytes = if self.len == 0 {
+                       Vec::new()
+               } else if self.chars_is_owned {
+                       unsafe {
+                               Box::from_raw(std::slice::from_raw_parts_mut(unsafe { self.chars as *mut u8 }, self.len))
+                       }.into()
+               } else {
+                       let mut ret = Vec::with_capacity(self.len);
+                       ret.extend_from_slice(unsafe { std::slice::from_raw_parts(self.chars, self.len) });
+                       ret
+               };
+               String::from_utf8(bytes).unwrap()
+       }
 }
 impl Into<Str> for String {
        fn into(self) -> Str {