use crate::errors::FfiError;
use crate::memory::FfiBuffer;
pub type FfiBufferResult = Result<FfiBuffer, FfiError>;
pub struct BridgeValue {
inner: FfiBuffer,
}
impl BridgeValue {
pub fn new<T: serde::Serialize>(value: &T) -> Result<Self, FfiError> {
Ok(BridgeValue {
inner: FfiBuffer::from_json(value)?,
})
}
pub fn decode<T: serde::de::DeserializeOwned>(&self) -> Result<T, FfiError> {
unsafe { self.inner.to_json() }
}
pub fn into_buffer(self) -> FfiBuffer {
self.inner
}
}
#[inline]
pub unsafe fn check_not_null<T>(ptr: *const T) -> Result<*const T, FfiError> {
if ptr.is_null() {
Err(FfiError::NullPointer)
} else {
Ok(ptr)
}
}
#[inline]
pub unsafe fn check_not_null_mut<T>(ptr: *mut T) -> Result<*mut T, FfiError> {
if ptr.is_null() {
Err(FfiError::NullPointer)
} else {
Ok(ptr)
}
}
pub unsafe fn cstr_to_string(ptr: *const std::os::raw::c_char) -> Result<String, FfiError> {
if ptr.is_null() {
return Err(FfiError::NullPointer);
}
std::ffi::CStr::from_ptr(ptr)
.to_str()
.map(|s| s.to_string())
.map_err(|e| FfiError::InvalidUtf8(e.to_string()))
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]
struct Point {
x: i32,
y: i32,
}
#[test]
fn bridge_value_round_trip() {
let p = Point { x: 10, y: -5 };
let bv = BridgeValue::new(&p).unwrap();
let decoded: Point = bv.decode().unwrap();
assert_eq!(decoded, p);
crate::memory::ffi_buffer_free(bv.into_buffer());
}
#[test]
fn check_not_null_with_null_ptr() {
let ptr: *const u8 = std::ptr::null();
let result = unsafe { check_not_null(ptr) };
assert!(matches!(result, Err(FfiError::NullPointer)));
}
#[test]
fn check_not_null_with_valid_ptr() {
let value: u8 = 42;
let ptr: *const u8 = &value;
let result = unsafe { check_not_null(ptr) };
assert!(result.is_ok());
}
}