From a6ec3f227230dff557959437b78e5606bcfc421c Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Wed, 25 Apr 2018 13:45:31 -0700 Subject: [PATCH] Move CString-creation methods to TypedValue. --- core/src/types.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++++ ffi/src/lib.rs | 33 ++++++++++++++--------------- ffi/src/utils.rs | 11 +--------- 3 files changed, 70 insertions(+), 27 deletions(-) diff --git a/core/src/types.rs b/core/src/types.rs index da49d7f6..57df0a99 100644 --- a/core/src/types.rs +++ b/core/src/types.rs @@ -8,6 +8,11 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. +use ::std::ffi::{ + CString, +}; +use ::std::os::raw::c_char; + use ::std::rc::{ Rc, }; @@ -525,6 +530,54 @@ impl TypedValue { } } + pub fn into_c_string(self) -> Option<*mut c_char> { + match self { + TypedValue::String(v) => { + // Get an independent copy of the string. + let s: String = v.cloned(); + + // Make a CString out of the new bytes. + let c: CString = CString::new(s).expect("String conversion failed!"); + + // Return a C-owned pointer. + Some(c.into_raw()) + }, + _ => None, + } + } + + pub fn into_kw_c_string(self) -> Option<*mut c_char> { + match self { + TypedValue::Keyword(v) => { + // Get an independent copy of the string. + let s: String = v.to_string(); + + // Make a CString out of the new bytes. + let c: CString = CString::new(s).expect("String conversion failed!"); + + // Return a C-owned pointer. + Some(c.into_raw()) + }, + _ => None, + } + } + + pub fn into_uuid_c_string(self) -> Option<*mut c_char> { + match self { + TypedValue::Uuid(v) => { + // Get an independent copy of the string. + let s: String = v.hyphenated().to_string(); + + // Make a CString out of the new bytes. + let c: CString = CString::new(s).expect("String conversion failed!"); + + // Return a C-owned pointer. + Some(c.into_raw()) + }, + _ => None, + } + } + pub fn into_uuid(self) -> Option { match self { TypedValue::Uuid(v) => Some(v), diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index ff52d649..50ab0096 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -52,7 +52,6 @@ pub mod utils; pub use utils::strings::{ c_char_to_string, - c_char_from_rc, kw_from_string, string_to_c_char, }; @@ -276,7 +275,7 @@ pub unsafe extern "C" fn typed_value_as_entid(typed_value: *mut TypedValue) -> #[no_mangle] pub unsafe extern "C" fn typed_value_as_kw(typed_value: *mut TypedValue) -> *const c_char { let typed_value = Box::from_raw(typed_value); - string_to_c_char(typed_value.into_kw().expect("Typed value cannot be coerced into a Namespaced Keyword").to_string()) + typed_value.into_kw_c_string().expect("Typed value cannot be coerced into a Namespaced Keyword") } //as_boolean @@ -305,20 +304,20 @@ pub unsafe extern "C" fn typed_value_as_timestamp(typed_value: *mut TypedValue) #[no_mangle] pub unsafe extern "C" fn typed_value_as_string(typed_value: *mut TypedValue) -> *const c_char { let typed_value = Box::from_raw(typed_value); - c_char_from_rc(typed_value.into_string().expect("Typed value cannot be coerced into a String")) + typed_value.into_c_string().expect("Typed value cannot be coerced into a String") } //as_uuid #[no_mangle] pub unsafe extern "C" fn typed_value_as_uuid(typed_value: *mut TypedValue) -> *const c_char { let typed_value = Box::from_raw(typed_value); - string_to_c_char(typed_value.into_uuid_string().expect("Typed value cannot be coerced into a Uuid")) + typed_value.into_uuid_c_string().expect("Typed value cannot be coerced into a String") } #[no_mangle] pub unsafe extern "C" fn row_at_index(rows: *mut Vec>, index: c_int) -> *mut Vec { let result = &*rows; - result.get(index as usize).map_or(std::ptr::null_mut(), |v| Box::into_raw(Box::new(v.clone()))) + result.get(index as usize).map_or_else(std::ptr::null_mut, |v| Box::into_raw(Box::new(v.clone()))) } #[no_mangle] @@ -342,62 +341,62 @@ pub unsafe extern "C" fn values_iter(values: *mut Vec) -> *mut Type #[no_mangle] pub unsafe extern "C" fn values_iter_next(iter: *mut TypedValueIterator) -> *const TypedValue { let iter = &mut *iter; - iter.next().map_or(std::ptr::null_mut(), |v| &v as *const TypedValue) + iter.next().map_or_else(std::ptr::null, |v| &v as *const TypedValue) } //as_long #[no_mangle] pub unsafe extern "C" fn values_iter_next_as_long(iter: *mut TypedValueIterator) -> *const i64 { let iter = &mut *iter; - iter.next().map_or(std::ptr::null_mut(), |v| &v.into_long().expect("Typed value cannot be coerced into a Long") as *const i64) + iter.next().map_or_else(std::ptr::null, |v| &v.into_long().expect("Typed value cannot be coerced into a Long") as *const i64) } // as ref #[no_mangle] pub unsafe extern "C" fn values_iter_next_as_entid(iter: *mut TypedValueIterator) -> *const Entid { let iter = &mut *iter; - iter.next().map_or(std::ptr::null_mut(), |v| &v.into_entid().expect("Typed value cannot be coerced into am Entid") as *const Entid) + iter.next().map_or_else(std::ptr::null, |v| &v.into_entid().expect("Typed value cannot be coerced into am Entid") as *const Entid) } // as kw #[no_mangle] pub unsafe extern "C" fn values_iter_next_as_kw(iter: *mut TypedValueIterator) -> *const c_char { let iter = &mut *iter; - iter.next().map_or(std::ptr::null_mut(), |v| string_to_c_char(v.into_kw().expect("Typed value cannot be coerced into a Namespaced Keyword").to_string())) + iter.next().map_or_else(std::ptr::null, |v| v.into_kw_c_string().expect("Typed value cannot be coerced into a Namespaced Keyword")) } //as_boolean #[no_mangle] pub unsafe extern "C" fn values_iter_next_as_boolean(iter: *mut TypedValueIterator) -> *const bool { let iter = &mut *iter; - iter.next().map_or(std::ptr::null_mut(), |v| &v.into_boolean().expect("Typed value cannot be coerced into a Boolean") as *const bool) + iter.next().map_or_else(std::ptr::null, |v| &v.into_boolean().expect("Typed value cannot be coerced into a Boolean") as *const bool) } //as_double #[no_mangle] pub unsafe extern "C" fn values_iter_next_as_double(iter: *mut TypedValueIterator) -> *const f64 { let iter = &mut *iter; - iter.next().map_or(std::ptr::null_mut(), |v| &v.into_double().expect("Typed value cannot be coerced into a Double") as *const f64) + iter.next().map_or_else(std::ptr::null, |v| &v.into_double().expect("Typed value cannot be coerced into a Double") as *const f64) } //as_timestamp #[no_mangle] pub unsafe extern "C" fn values_iter_next_as_timestamp(iter: *mut TypedValueIterator) -> *const i64 { let iter = &mut *iter; - iter.next().map_or(std::ptr::null_mut(), |v| v.into_timestamp().expect("Typed value cannot be coerced into a Timestamp") as *const i64) + iter.next().map_or_else(std::ptr::null, |v| v.into_timestamp().expect("Typed value cannot be coerced into a Timestamp") as *const i64) } //as_string #[no_mangle] pub unsafe extern "C" fn values_iter_next_as_string(iter: *mut TypedValueIterator) -> *const c_char { let iter = &mut *iter; - iter.next().map_or(std::ptr::null_mut(), |v| c_char_from_rc(v.into_string().expect("Typed value cannot be coerced into a String"))) + iter.next().map_or_else(std::ptr::null, |v| v.into_c_string().expect("Typed value cannot be coerced into a String")) } //as_uuid #[no_mangle] pub unsafe extern "C" fn values_iter_next_as_uuid(iter: *mut TypedValueIterator) -> *const c_char { let iter = &mut *iter; - iter.next().map_or(std::ptr::null_mut(), |v| string_to_c_char(v.into_uuid_string().expect("Typed value cannot be coerced into a Uuid"))) + iter.next().map_or_else(std::ptr::null, |v| v.into_uuid_c_string().expect("Typed value cannot be coerced into a Uuid")) } #[no_mangle] @@ -426,7 +425,7 @@ pub unsafe extern "C" fn value_at_index_as_entid(values: *mut Vec, i pub unsafe extern "C" fn value_at_index_as_kw(values: *mut Vec, index: c_int) -> *const c_char { let result = &*values; let value = result.get(index as usize).expect("No value at index"); - string_to_c_char(value.clone().into_kw().expect("Typed value cannot be coerced into a Namespaced Keyword").to_string()) + value.clone().into_kw_c_string().expect("Typed value cannot be coerced into a Namespaced Keyword") } //as_boolean @@ -458,7 +457,7 @@ pub unsafe extern "C" fn value_at_index_as_timestamp(values: *mut Vec, index: c_int) -> *mut c_char { let result = &*values; let value = result.get(index as usize).expect("No value at index"); - c_char_from_rc(value.clone().into_string().expect("Typed value cannot be coerced into a String")) + value.clone().into_c_string().expect("Typed value cannot be coerced into a String") } //as_uuid @@ -466,7 +465,7 @@ pub unsafe extern "C" fn value_at_index_as_string(values: *mut Vec, pub unsafe extern "C" fn value_at_index_as_uuid(values: *mut Vec, index: c_int) -> *mut c_char { let result = &*values; let value = result.get(index as usize).expect("No value at index"); - string_to_c_char(value.clone().into_uuid_string().expect("Typed value cannot be coerced into a Uuid")) + value.clone().into_uuid_c_string().expect("Typed value cannot be coerced into a Uuid") } // TODO: q_prepare diff --git a/ffi/src/utils.rs b/ffi/src/utils.rs index 97a6111d..42e812ce 100644 --- a/ffi/src/utils.rs +++ b/ffi/src/utils.rs @@ -9,13 +9,11 @@ // specific language governing permissions and limitations under the License. pub mod strings { - use std; use std::ffi::{ CString, CStr }; use std::os::raw::c_char; - use std::rc::Rc; use mentat::{ NamespacedKeyword, @@ -31,19 +29,12 @@ pub mod strings { CString::new(r_string.into()).unwrap().into_raw() } + // TODO: validate. The input might not be a keyword! pub fn kw_from_string(mut keyword_string: String) -> NamespacedKeyword { let attr_name = keyword_string.split_off(1); let parts: Vec<&str> = attr_name.split("/").collect(); NamespacedKeyword::new(parts[0], parts[1]) } - - pub fn c_char_from_rc(rc_string: Rc) -> *mut c_char { - if let Some(str_ptr) = unsafe { Rc::into_raw(rc_string).as_ref() } { - string_to_c_char(str_ptr.clone()) - } else { - std::ptr::null_mut() - } - } } pub mod log {