Skip to content

Commit

Permalink
Use Option<NonNull<DatabaseError>> instead of `*const DatabaseError…
Browse files Browse the repository at this point in the history
…`. Both types have the same ABI, but the first one is safer to deal with.
  • Loading branch information
koutheir committed Jul 18, 2024
1 parent bef2f23 commit c88e338
Showing 1 changed file with 22 additions and 24 deletions.
46 changes: 22 additions & 24 deletions src/idioms/ffi/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,45 +55,43 @@ pub mod errors {
pub mod c_api {
use super::errors::DatabaseError;
use core::ptr;
#[no_mangle]
pub extern "C" fn db_error_description(e: *const DatabaseError) -> *mut libc::c_char {
let error: &DatabaseError = unsafe {
// SAFETY: pointer lifetime is greater than the current stack frame
&*e
};
pub extern "C" fn db_error_description(
e: Option<ptr::NonNull<DatabaseError>>
) -> Option<ptr::NonNull<libc::c_char>> {
// SAFETY: we assume that the lifetime of `e` is greater than
// the current stack frame.
let error = unsafe { e?.as_ref() };
let error_str: String = match error {
DatabaseError::IsReadOnly => {
format!("cannot write to read-only database");
format!("cannot write to read-only database")
}
DatabaseError::IOError(e) => {
format!("I/O Error: {e}");
format!("I/O Error: {e}")
}
DatabaseError::FileCorrupted(s) => {
format!("File corrupted, run repair: {}", &s);
format!("File corrupted, run repair: {}", &s)
}
};
let c_error = unsafe {
// SAFETY: copying error_str to an allocated buffer with a NUL
// character at the end
let mut malloc: *mut u8 = libc::malloc(error_str.len() + 1) as *mut _;
if malloc.is_null() {
return std::ptr::null_mut();
}
let src = error_str.as_bytes().as_ptr();
std::ptr::copy_nonoverlapping(src, malloc, error_str.len());
let error_bytes = error_str.as_bytes();
std::ptr::write(malloc.add(error_str.len()), 0);
malloc as *mut libc::c_char
let c_error = unsafe {
// SAFETY: copying error_bytes to an allocated buffer with a '\0'
// byte at the end.
let buffer = ptr::NonNull::<u8>::new(libc::malloc(error_bytes.len() + 1).cast())?;
buffer
.as_ptr()
.copy_from_nonoverlapping(error_bytes.as_ptr(), error_bytes.len());
buffer.as_ptr().add(error_bytes.len()).write(0_u8);
buffer
};
c_error
Some(c_error.cast())
}
}
```
Expand Down

0 comments on commit c88e338

Please sign in to comment.