From db0ed2ef02f28a8b393eb3640959587bfe1a7e52 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 30 Apr 2021 23:09:05 +0000 Subject: [PATCH] Resolve issues with Str introduced when it became ownable 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 | 2 +- c-bindings-gen/src/types.rs | 11 +++++------ lightning-c-bindings/src/c_types/mod.rs | 18 ++++++++++++++++-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index 7f5a3ed..81f26bf 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -966,7 +966,7 @@ fn writeln_impl(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(); diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 395441b..d945431 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -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()"), diff --git a/lightning-c-bindings/src/c_types/mod.rs b/lightning-c-bindings/src/c_types/mod.rs index b28bc80..3d45802 100644 --- a/lightning-c-bindings/src/c_types/mod.rs +++ b/lightning-c-bindings/src/c_types/mod.rs @@ -382,11 +382,25 @@ impl Into 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 for String { fn into(self) -> Str { -- 2.39.5