Avoid using MaybeUninit for pointers

This commit is contained in:
Thom Chiovoloni 2020-04-06 19:53:55 -07:00
parent 53c99f940e
commit 8f7fc7d976
3 changed files with 42 additions and 72 deletions

View File

@ -1,5 +1,4 @@
use std::ffi::CString; use std::ffi::CString;
use std::mem::MaybeUninit;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
#[cfg(feature = "load_extension")] #[cfg(feature = "load_extension")]
use std::path::Path; use std::path::Path;
@ -81,9 +80,8 @@ impl InnerConnection {
}; };
unsafe { unsafe {
let mut db = MaybeUninit::uninit(); let mut db: *mut ffi::sqlite3 = ptr::null_mut();
let r = ffi::sqlite3_open_v2(c_path.as_ptr(), db.as_mut_ptr(), flags.bits(), z_vfs); let r = ffi::sqlite3_open_v2(c_path.as_ptr(), &mut db, flags.bits(), z_vfs);
let db: *mut ffi::sqlite3 = db.assume_init();
if r != ffi::SQLITE_OK { if r != ffi::SQLITE_OK {
let e = if db.is_null() { let e = if db.is_null() {
error_from_sqlite_code(r, Some(c_path.to_string_lossy().to_string())) error_from_sqlite_code(r, Some(c_path.to_string_lossy().to_string()))
@ -196,28 +194,22 @@ impl InnerConnection {
pub fn load_extension(&self, dylib_path: &Path, entry_point: Option<&str>) -> Result<()> { pub fn load_extension(&self, dylib_path: &Path, entry_point: Option<&str>) -> Result<()> {
let dylib_str = super::path_to_cstring(dylib_path)?; let dylib_str = super::path_to_cstring(dylib_path)?;
unsafe { unsafe {
let mut errmsg = MaybeUninit::uninit(); let mut errmsg: *mut c_char = ptr::null_mut();
let r = if let Some(entry_point) = entry_point { let r = if let Some(entry_point) = entry_point {
let c_entry = str_to_cstring(entry_point)?; let c_entry = str_to_cstring(entry_point)?;
ffi::sqlite3_load_extension( ffi::sqlite3_load_extension(
self.db, self.db,
dylib_str.as_ptr(), dylib_str.as_ptr(),
c_entry.as_ptr(), c_entry.as_ptr(),
errmsg.as_mut_ptr(), &mut errmsg,
) )
} else { } else {
ffi::sqlite3_load_extension( ffi::sqlite3_load_extension(self.db, dylib_str.as_ptr(), ptr::null(), &mut errmsg)
self.db,
dylib_str.as_ptr(),
ptr::null(),
errmsg.as_mut_ptr(),
)
}; };
if r == ffi::SQLITE_OK { if r == ffi::SQLITE_OK {
Ok(()) Ok(())
} else { } else {
let errmsg: *mut c_char = errmsg.assume_init(); let message = super::errmsg_to_string(errmsg);
let message = super::errmsg_to_string(&*errmsg);
ffi::sqlite3_free(errmsg as *mut ::std::os::raw::c_void); ffi::sqlite3_free(errmsg as *mut ::std::os::raw::c_void);
Err(error_from_sqlite_code(r, Some(message))) Err(error_from_sqlite_code(r, Some(message)))
} }

View File

@ -1028,25 +1028,23 @@ mod test {
// statement first. // statement first.
let raw_stmt = { let raw_stmt = {
use super::str_to_cstring; use super::str_to_cstring;
use std::mem::MaybeUninit;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr; use std::ptr;
let raw_db = db.db.borrow_mut().db; let raw_db = db.db.borrow_mut().db;
let sql = "SELECT 1"; let sql = "SELECT 1";
let mut raw_stmt = MaybeUninit::uninit(); let mut raw_stmt: *mut ffi::sqlite3_stmt = ptr::null_mut();
let cstring = str_to_cstring(sql).unwrap(); let cstring = str_to_cstring(sql).unwrap();
let rc = unsafe { let rc = unsafe {
ffi::sqlite3_prepare_v2( ffi::sqlite3_prepare_v2(
raw_db, raw_db,
cstring.as_ptr(), cstring.as_ptr(),
(sql.len() + 1) as c_int, (sql.len() + 1) as c_int,
raw_stmt.as_mut_ptr(), &mut raw_stmt,
ptr::null_mut(), ptr::null_mut(),
) )
}; };
assert_eq!(rc, ffi::SQLITE_OK); assert_eq!(rc, ffi::SQLITE_OK);
let raw_stmt: *mut ffi::sqlite3_stmt = unsafe { raw_stmt.assume_init() };
raw_stmt raw_stmt
}; };

View File

@ -4,7 +4,6 @@
use std::ffi::CStr; use std::ffi::CStr;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::os::raw::{c_char, c_int, c_uchar, c_void}; use std::os::raw::{c_char, c_int, c_uchar, c_void};
use std::panic::{catch_unwind, RefUnwindSafe}; use std::panic::{catch_unwind, RefUnwindSafe};
use std::ptr; use std::ptr;
@ -43,9 +42,8 @@ impl Session<'_> {
let db = db.db.borrow_mut().db; let db = db.db.borrow_mut().db;
let mut s = MaybeUninit::uninit(); let mut s: *mut ffi::sqlite3_session = ptr::null_mut();
check!(unsafe { ffi::sqlite3session_create(db, name.as_ptr(), s.as_mut_ptr()) }); check!(unsafe { ffi::sqlite3session_create(db, name.as_ptr(), &mut s) });
let s: *mut ffi::sqlite3_session = unsafe { s.assume_init() };
Ok(Session { Ok(Session {
phantom: PhantomData, phantom: PhantomData,
@ -113,9 +111,8 @@ impl Session<'_> {
/// Generate a Changeset /// Generate a Changeset
pub fn changeset(&mut self) -> Result<Changeset> { pub fn changeset(&mut self) -> Result<Changeset> {
let mut n = 0; let mut n = 0;
let mut cs = MaybeUninit::uninit(); let mut cs: *mut c_void = ptr::null_mut();
check!(unsafe { ffi::sqlite3session_changeset(self.s, &mut n, cs.as_mut_ptr()) }); check!(unsafe { ffi::sqlite3session_changeset(self.s, &mut n, &mut cs) });
let cs: *mut c_void = unsafe { cs.assume_init() };
Ok(Changeset { cs, n }) Ok(Changeset { cs, n })
} }
@ -135,9 +132,8 @@ impl Session<'_> {
/// Generate a Patchset /// Generate a Patchset
pub fn patchset(&mut self) -> Result<Changeset> { pub fn patchset(&mut self) -> Result<Changeset> {
let mut n = 0; let mut n = 0;
let mut ps = MaybeUninit::uninit(); let mut ps: *mut c_void = ptr::null_mut();
check!(unsafe { ffi::sqlite3session_patchset(self.s, &mut n, ps.as_mut_ptr()) }); check!(unsafe { ffi::sqlite3session_patchset(self.s, &mut n, &mut ps) });
let ps: *mut c_void = unsafe { ps.assume_init() };
// TODO Validate: same struct // TODO Validate: same struct
Ok(Changeset { cs: ps, n }) Ok(Changeset { cs: ps, n })
} }
@ -160,10 +156,11 @@ impl Session<'_> {
let from = from.to_cstring()?; let from = from.to_cstring()?;
let table = str_to_cstring(table)?.as_ptr(); let table = str_to_cstring(table)?.as_ptr();
unsafe { unsafe {
let mut errmsg = MaybeUninit::uninit(); let mut errmsg = ptr::null_mut();
let r = ffi::sqlite3session_diff(self.s, from.as_ptr(), table, errmsg.as_mut_ptr()); let r =
ffi::sqlite3session_diff(self.s, from.as_ptr(), table, &mut errmsg as *mut *mut _);
if r != ffi::SQLITE_OK { if r != ffi::SQLITE_OK {
let errmsg: *mut c_char = errmsg.assume_init(); let errmsg: *mut c_char = errmsg;
let message = errmsg_to_string(&*errmsg); let message = errmsg_to_string(&*errmsg);
ffi::sqlite3_free(errmsg as *mut ::std::os::raw::c_void); ffi::sqlite3_free(errmsg as *mut ::std::os::raw::c_void);
return Err(error_from_sqlite_code(r, Some(message))); return Err(error_from_sqlite_code(r, Some(message)));
@ -258,17 +255,17 @@ impl Changeset {
/// Invert a changeset /// Invert a changeset
pub fn invert(&self) -> Result<Changeset> { pub fn invert(&self) -> Result<Changeset> {
let mut n = 0; let mut n = 0;
let mut cs = MaybeUninit::uninit(); let mut cs = ptr::null_mut();
check!(unsafe { ffi::sqlite3changeset_invert(self.n, self.cs, &mut n, cs.as_mut_ptr()) }); check!(unsafe {
let cs: *mut c_void = unsafe { cs.assume_init() }; ffi::sqlite3changeset_invert(self.n, self.cs, &mut n, &mut cs as *mut *mut _)
});
Ok(Changeset { cs, n }) Ok(Changeset { cs, n })
} }
/// Create an iterator to traverse a changeset /// Create an iterator to traverse a changeset
pub fn iter(&self) -> Result<ChangesetIter<'_>> { pub fn iter(&self) -> Result<ChangesetIter<'_>> {
let mut it = MaybeUninit::uninit(); let mut it = ptr::null_mut();
check!(unsafe { ffi::sqlite3changeset_start(it.as_mut_ptr(), self.n, self.cs) }); check!(unsafe { ffi::sqlite3changeset_start(&mut it as *mut *mut _, self.n, self.cs) });
let it: *mut ffi::sqlite3_changeset_iter = unsafe { it.assume_init() };
Ok(ChangesetIter { Ok(ChangesetIter {
phantom: PhantomData, phantom: PhantomData,
it, it,
@ -279,11 +276,10 @@ impl Changeset {
/// Concatenate two changeset objects /// Concatenate two changeset objects
pub fn concat(a: &Changeset, b: &Changeset) -> Result<Changeset> { pub fn concat(a: &Changeset, b: &Changeset) -> Result<Changeset> {
let mut n = 0; let mut n = 0;
let mut cs = MaybeUninit::uninit(); let mut cs = ptr::null_mut();
check!(unsafe { check!(unsafe {
ffi::sqlite3changeset_concat(a.n, a.cs, b.n, b.cs, &mut n, cs.as_mut_ptr()) ffi::sqlite3changeset_concat(a.n, a.cs, b.n, b.cs, &mut n, &mut cs as *mut *mut _)
}); });
let cs: *mut c_void = unsafe { cs.assume_init() };
Ok(Changeset { cs, n }) Ok(Changeset { cs, n })
} }
} }
@ -307,15 +303,14 @@ pub struct ChangesetIter<'changeset> {
impl ChangesetIter<'_> { impl ChangesetIter<'_> {
/// Create an iterator on `input` /// Create an iterator on `input`
pub fn start_strm<'input>(input: &&'input mut dyn Read) -> Result<ChangesetIter<'input>> { pub fn start_strm<'input>(input: &&'input mut dyn Read) -> Result<ChangesetIter<'input>> {
let mut it = MaybeUninit::uninit(); let mut it = ptr::null_mut();
check!(unsafe { check!(unsafe {
ffi::sqlite3changeset_start_strm( ffi::sqlite3changeset_start_strm(
it.as_mut_ptr(), &mut it as *mut *mut _,
Some(x_input), Some(x_input),
input as *const &mut dyn Read as *mut c_void, input as *const &mut dyn Read as *mut c_void,
) )
}); });
let it: *mut ffi::sqlite3_changeset_iter = unsafe { it.assume_init() };
Ok(ChangesetIter { Ok(ChangesetIter {
phantom: PhantomData, phantom: PhantomData,
it, it,
@ -396,13 +391,12 @@ impl ChangesetItem {
/// `SQLITE_CHANGESET_CONFLICT` conflict handler callback. /// `SQLITE_CHANGESET_CONFLICT` conflict handler callback.
pub fn conflict(&self, col: usize) -> Result<ValueRef<'_>> { pub fn conflict(&self, col: usize) -> Result<ValueRef<'_>> {
unsafe { unsafe {
let mut p_value = MaybeUninit::uninit(); let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
check!(ffi::sqlite3changeset_conflict( check!(ffi::sqlite3changeset_conflict(
self.it, self.it,
col as i32, col as i32,
p_value.as_mut_ptr() &mut p_value,
)); ));
let p_value: *mut ffi::sqlite3_value = p_value.assume_init();
Ok(ValueRef::from_value(p_value)) Ok(ValueRef::from_value(p_value))
} }
} }
@ -425,13 +419,8 @@ impl ChangesetItem {
/// `SQLITE_INSERT`. /// `SQLITE_INSERT`.
pub fn new_value(&self, col: usize) -> Result<ValueRef<'_>> { pub fn new_value(&self, col: usize) -> Result<ValueRef<'_>> {
unsafe { unsafe {
let mut p_value = MaybeUninit::uninit(); let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
check!(ffi::sqlite3changeset_new( check!(ffi::sqlite3changeset_new(self.it, col as i32, &mut p_value,));
self.it,
col as i32,
p_value.as_mut_ptr()
));
let p_value: *mut ffi::sqlite3_value = p_value.assume_init();
Ok(ValueRef::from_value(p_value)) Ok(ValueRef::from_value(p_value))
} }
} }
@ -442,13 +431,8 @@ impl ChangesetItem {
/// `SQLITE_UPDATE`. /// `SQLITE_UPDATE`.
pub fn old_value(&self, col: usize) -> Result<ValueRef<'_>> { pub fn old_value(&self, col: usize) -> Result<ValueRef<'_>> {
unsafe { unsafe {
let mut p_value = MaybeUninit::uninit(); let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
check!(ffi::sqlite3changeset_old( check!(ffi::sqlite3changeset_old(self.it, col as i32, &mut p_value,));
self.it,
col as i32,
p_value.as_mut_ptr()
));
let p_value: *mut ffi::sqlite3_value = p_value.assume_init();
Ok(ValueRef::from_value(p_value)) Ok(ValueRef::from_value(p_value))
} }
} }
@ -459,15 +443,14 @@ impl ChangesetItem {
let mut code = 0; let mut code = 0;
let mut indirect = 0; let mut indirect = 0;
let tab = unsafe { let tab = unsafe {
let mut pz_tab = MaybeUninit::uninit(); let mut pz_tab: *const c_char = ptr::null();
check!(ffi::sqlite3changeset_op( check!(ffi::sqlite3changeset_op(
self.it, self.it,
pz_tab.as_mut_ptr(), &mut pz_tab,
&mut number_of_columns, &mut number_of_columns,
&mut code, &mut code,
&mut indirect &mut indirect
)); ));
let pz_tab: *const c_char = pz_tab.assume_init();
CStr::from_ptr(pz_tab) CStr::from_ptr(pz_tab)
}; };
let table_name = tab.to_str()?; let table_name = tab.to_str()?;
@ -483,13 +466,12 @@ impl ChangesetItem {
pub fn pk(&self) -> Result<&[u8]> { pub fn pk(&self) -> Result<&[u8]> {
let mut number_of_columns = 0; let mut number_of_columns = 0;
unsafe { unsafe {
let mut pks = MaybeUninit::uninit(); let mut pks: *mut c_uchar = ptr::null_mut();
check!(ffi::sqlite3changeset_pk( check!(ffi::sqlite3changeset_pk(
self.it, self.it,
pks.as_mut_ptr(), &mut pks,
&mut number_of_columns &mut number_of_columns
)); ));
let pks: *mut c_uchar = pks.assume_init();
Ok(from_raw_parts(pks, number_of_columns as usize)) Ok(from_raw_parts(pks, number_of_columns as usize))
} }
} }
@ -503,9 +485,8 @@ pub struct Changegroup {
impl Changegroup { impl Changegroup {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let mut cg = MaybeUninit::uninit(); let mut cg = ptr::null_mut();
check!(unsafe { ffi::sqlite3changegroup_new(cg.as_mut_ptr()) }); check!(unsafe { ffi::sqlite3changegroup_new(&mut cg) });
let cg: *mut ffi::sqlite3_changegroup = unsafe { cg.assume_init() };
Ok(Changegroup { cg }) Ok(Changegroup { cg })
} }
@ -531,9 +512,8 @@ impl Changegroup {
/// Obtain a composite Changeset /// Obtain a composite Changeset
pub fn output(&mut self) -> Result<Changeset> { pub fn output(&mut self) -> Result<Changeset> {
let mut n = 0; let mut n = 0;
let mut output = MaybeUninit::uninit(); let mut output: *mut c_void = ptr::null_mut();
check!(unsafe { ffi::sqlite3changegroup_output(self.cg, &mut n, output.as_mut_ptr()) }); check!(unsafe { ffi::sqlite3changegroup_output(self.cg, &mut n, &mut output) });
let output: *mut c_void = unsafe { output.assume_init() };
Ok(Changeset { cs: output, n }) Ok(Changeset { cs: output, n })
} }