Move CString-creation methods to TypedValue.

This commit is contained in:
Richard Newman 2018-04-25 13:45:31 -07:00
parent 5440efa4bf
commit a6ec3f2272
3 changed files with 70 additions and 27 deletions

View file

@ -8,6 +8,11 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
use ::std::ffi::{
CString,
};
use ::std::os::raw::c_char;
use ::std::rc::{ use ::std::rc::{
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<Uuid> { pub fn into_uuid(self) -> Option<Uuid> {
match self { match self {
TypedValue::Uuid(v) => Some(v), TypedValue::Uuid(v) => Some(v),

View file

@ -52,7 +52,6 @@ pub mod utils;
pub use utils::strings::{ pub use utils::strings::{
c_char_to_string, c_char_to_string,
c_char_from_rc,
kw_from_string, kw_from_string,
string_to_c_char, string_to_c_char,
}; };
@ -276,7 +275,7 @@ pub unsafe extern "C" fn typed_value_as_entid(typed_value: *mut TypedValue) ->
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn typed_value_as_kw(typed_value: *mut TypedValue) -> *const c_char { pub unsafe extern "C" fn typed_value_as_kw(typed_value: *mut TypedValue) -> *const c_char {
let typed_value = Box::from_raw(typed_value); 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 //as_boolean
@ -305,20 +304,20 @@ pub unsafe extern "C" fn typed_value_as_timestamp(typed_value: *mut TypedValue)
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn typed_value_as_string(typed_value: *mut TypedValue) -> *const c_char { pub unsafe extern "C" fn typed_value_as_string(typed_value: *mut TypedValue) -> *const c_char {
let typed_value = Box::from_raw(typed_value); 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 //as_uuid
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn typed_value_as_uuid(typed_value: *mut TypedValue) -> *const c_char { pub unsafe extern "C" fn typed_value_as_uuid(typed_value: *mut TypedValue) -> *const c_char {
let typed_value = Box::from_raw(typed_value); 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] #[no_mangle]
pub unsafe extern "C" fn row_at_index(rows: *mut Vec<Vec<TypedValue>>, index: c_int) -> *mut Vec<TypedValue> { pub unsafe extern "C" fn row_at_index(rows: *mut Vec<Vec<TypedValue>>, index: c_int) -> *mut Vec<TypedValue> {
let result = &*rows; 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] #[no_mangle]
@ -342,62 +341,62 @@ pub unsafe extern "C" fn values_iter(values: *mut Vec<TypedValue>) -> *mut Type
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn values_iter_next(iter: *mut TypedValueIterator) -> *const TypedValue { pub unsafe extern "C" fn values_iter_next(iter: *mut TypedValueIterator) -> *const TypedValue {
let iter = &mut *iter; 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 //as_long
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn values_iter_next_as_long(iter: *mut TypedValueIterator) -> *const i64 { pub unsafe extern "C" fn values_iter_next_as_long(iter: *mut TypedValueIterator) -> *const i64 {
let iter = &mut *iter; 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 // as ref
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn values_iter_next_as_entid(iter: *mut TypedValueIterator) -> *const Entid { pub unsafe extern "C" fn values_iter_next_as_entid(iter: *mut TypedValueIterator) -> *const Entid {
let iter = &mut *iter; 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 // as kw
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn values_iter_next_as_kw(iter: *mut TypedValueIterator) -> *const c_char { pub unsafe extern "C" fn values_iter_next_as_kw(iter: *mut TypedValueIterator) -> *const c_char {
let iter = &mut *iter; 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 //as_boolean
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn values_iter_next_as_boolean(iter: *mut TypedValueIterator) -> *const bool { pub unsafe extern "C" fn values_iter_next_as_boolean(iter: *mut TypedValueIterator) -> *const bool {
let iter = &mut *iter; 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 //as_double
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn values_iter_next_as_double(iter: *mut TypedValueIterator) -> *const f64 { pub unsafe extern "C" fn values_iter_next_as_double(iter: *mut TypedValueIterator) -> *const f64 {
let iter = &mut *iter; 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 //as_timestamp
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn values_iter_next_as_timestamp(iter: *mut TypedValueIterator) -> *const i64 { pub unsafe extern "C" fn values_iter_next_as_timestamp(iter: *mut TypedValueIterator) -> *const i64 {
let iter = &mut *iter; 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 //as_string
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn values_iter_next_as_string(iter: *mut TypedValueIterator) -> *const c_char { pub unsafe extern "C" fn values_iter_next_as_string(iter: *mut TypedValueIterator) -> *const c_char {
let iter = &mut *iter; 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 //as_uuid
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn values_iter_next_as_uuid(iter: *mut TypedValueIterator) -> *const c_char { pub unsafe extern "C" fn values_iter_next_as_uuid(iter: *mut TypedValueIterator) -> *const c_char {
let iter = &mut *iter; 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] #[no_mangle]
@ -426,7 +425,7 @@ pub unsafe extern "C" fn value_at_index_as_entid(values: *mut Vec<TypedValue>, i
pub unsafe extern "C" fn value_at_index_as_kw(values: *mut Vec<TypedValue>, index: c_int) -> *const c_char { pub unsafe extern "C" fn value_at_index_as_kw(values: *mut Vec<TypedValue>, index: c_int) -> *const c_char {
let result = &*values; let result = &*values;
let value = result.get(index as usize).expect("No value at index"); 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 //as_boolean
@ -458,7 +457,7 @@ pub unsafe extern "C" fn value_at_index_as_timestamp(values: *mut Vec<TypedValue
pub unsafe extern "C" fn value_at_index_as_string(values: *mut Vec<TypedValue>, index: c_int) -> *mut c_char { pub unsafe extern "C" fn value_at_index_as_string(values: *mut Vec<TypedValue>, index: c_int) -> *mut c_char {
let result = &*values; let result = &*values;
let value = result.get(index as usize).expect("No value at index"); 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 //as_uuid
@ -466,7 +465,7 @@ pub unsafe extern "C" fn value_at_index_as_string(values: *mut Vec<TypedValue>,
pub unsafe extern "C" fn value_at_index_as_uuid(values: *mut Vec<TypedValue>, index: c_int) -> *mut c_char { pub unsafe extern "C" fn value_at_index_as_uuid(values: *mut Vec<TypedValue>, index: c_int) -> *mut c_char {
let result = &*values; let result = &*values;
let value = result.get(index as usize).expect("No value at index"); 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 // TODO: q_prepare

View file

@ -9,13 +9,11 @@
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
pub mod strings { pub mod strings {
use std;
use std::ffi::{ use std::ffi::{
CString, CString,
CStr CStr
}; };
use std::os::raw::c_char; use std::os::raw::c_char;
use std::rc::Rc;
use mentat::{ use mentat::{
NamespacedKeyword, NamespacedKeyword,
@ -31,19 +29,12 @@ pub mod strings {
CString::new(r_string.into()).unwrap().into_raw() 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 { pub fn kw_from_string(mut keyword_string: String) -> NamespacedKeyword {
let attr_name = keyword_string.split_off(1); let attr_name = keyword_string.split_off(1);
let parts: Vec<&str> = attr_name.split("/").collect(); let parts: Vec<&str> = attr_name.split("/").collect();
NamespacedKeyword::new(parts[0], parts[1]) NamespacedKeyword::new(parts[0], parts[1])
} }
pub fn c_char_from_rc(rc_string: Rc<String>) -> *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 { pub mod log {