1use crate::errors::FfiError;
7use crate::memory::FfiBuffer;
8
9pub type FfiBufferResult = Result<FfiBuffer, FfiError>;
13
14pub struct BridgeValue {
21 inner: FfiBuffer,
22}
23
24impl BridgeValue {
25 pub fn new<T: serde::Serialize>(value: &T) -> Result<Self, FfiError> {
27 Ok(BridgeValue {
28 inner: FfiBuffer::from_json(value)?,
29 })
30 }
31
32 pub fn decode<T: serde::de::DeserializeOwned>(&self) -> Result<T, FfiError> {
34 unsafe { self.inner.to_json() }
35 }
36
37 pub fn into_buffer(self) -> FfiBuffer {
39 self.inner
40 }
41}
42
43#[inline]
51pub unsafe fn check_not_null<T>(ptr: *const T) -> Result<*const T, FfiError> {
52 if ptr.is_null() {
53 Err(FfiError::NullPointer)
54 } else {
55 Ok(ptr)
56 }
57}
58
59#[inline]
65pub unsafe fn check_not_null_mut<T>(ptr: *mut T) -> Result<*mut T, FfiError> {
66 if ptr.is_null() {
67 Err(FfiError::NullPointer)
68 } else {
69 Ok(ptr)
70 }
71}
72
73pub unsafe fn cstr_to_string(ptr: *const std::os::raw::c_char) -> Result<String, FfiError> {
79 if ptr.is_null() {
80 return Err(FfiError::NullPointer);
81 }
82 std::ffi::CStr::from_ptr(ptr)
83 .to_str()
84 .map(|s| s.to_string())
85 .map_err(|e| FfiError::InvalidUtf8(e.to_string()))
86}
87
88#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]
95 struct Point {
96 x: i32,
97 y: i32,
98 }
99
100 #[test]
101 fn bridge_value_round_trip() {
102 let p = Point { x: 10, y: -5 };
103 let bv = BridgeValue::new(&p).unwrap();
104 let decoded: Point = bv.decode().unwrap();
105 assert_eq!(decoded, p);
106 crate::memory::ffi_buffer_free(bv.into_buffer());
108 }
109
110 #[test]
111 fn check_not_null_with_null_ptr() {
112 let ptr: *const u8 = std::ptr::null();
113 let result = unsafe { check_not_null(ptr) };
114 assert!(matches!(result, Err(FfiError::NullPointer)));
115 }
116
117 #[test]
118 fn check_not_null_with_valid_ptr() {
119 let value: u8 = 42;
120 let ptr: *const u8 = &value;
121 let result = unsafe { check_not_null(ptr) };
122 assert!(result.is_ok());
123 }
124}