//! Add, remove, or modify a collation use std::cmp::Ordering; use std::os::raw::{c_char, c_int, c_void}; use std::panic::{catch_unwind, UnwindSafe}; use std::ptr; use std::slice;
impl InnerConnection { fn create_collation<C>(&mutself, collation_name: &str, x_compare: C) -> Result<()> where
C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'static,
{ unsafeextern"C"fn call_boxed_closure<C>(
arg1: *mut c_void,
arg2: c_int,
arg3: *const c_void,
arg4: c_int,
arg5: *const c_void,
) -> c_int where
C: Fn(&str, &str) -> Ordering,
{ let r = catch_unwind(|| { let boxed_f: *mut C = arg1.cast::<C>();
assert!(!boxed_f.is_null(), "Internal error - null function pointer"); let s1 = { let c_slice = slice::from_raw_parts(arg3.cast::<u8>(), arg2 as usize);
String::from_utf8_lossy(c_slice)
}; let s2 = { let c_slice = slice::from_raw_parts(arg5.cast::<u8>(), arg4 as usize);
String::from_utf8_lossy(c_slice)
};
(*boxed_f)(s1.as_ref(), s2.as_ref())
}); let t = match r {
Err(_) => { return -1; // FIXME How ?
}
Ok(r) => r,
};
match t {
Ordering::Less => -1,
Ordering::Equal => 0,
Ordering::Greater => 1,
}
}
let boxed_f: *mut C = Box::into_raw(Box::new(x_compare)); let c_name = str_to_cstring(collation_name)?; let flags = ffi::SQLITE_UTF8; let r = unsafe {
ffi::sqlite3_create_collation_v2( self.db(),
c_name.as_ptr(),
flags,
boxed_f.cast::<c_void>(),
Some(call_boxed_closure::<C>),
Some(free_boxed_value::<C>),
)
}; let res = self.decode_result(r); // The xDestroy callback is not called if the sqlite3_create_collation_v2() // function fails. if res.is_err() {
drop(unsafe { Box::from_raw(boxed_f) });
}
res
}
if e_text_rep != ffi::SQLITE_UTF8 { // TODO: validate return;
}
let callback: fn(&Connection, &str) -> Result<()> = mem::transmute(arg1); let res = catch_unwind(|| { let conn = Connection::from_handle(arg2).unwrap(); let collation_name = { let c_slice = CStr::from_ptr(arg3).to_bytes();
str::from_utf8(c_slice).expect("illegal collation sequence name")
};
callback(&conn, collation_name)
}); if res.is_err() { return; // FIXME How ?
}
}
let r = unsafe {
ffi::sqlite3_collation_needed( self.db(),
x_coll_needed as *mut c_void,
Some(collation_needed_callback),
)
}; self.decode_result(r)
}
#[inline] fn remove_collation(&mutself, collation_name: &str) -> Result<()> { let c_name = str_to_cstring(collation_name)?; let r = unsafe {
ffi::sqlite3_create_collation_v2( self.db(),
c_name.as_ptr(),
ffi::SQLITE_UTF8,
ptr::null_mut(),
None,
None,
)
}; self.decode_result(r)
}
}
#[cfg(test)] mod test { usecrate::{Connection, Result}; use fallible_streaming_iterator::FallibleStreamingIterator; use std::cmp::Ordering; use unicase::UniCase;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.