1use core::ffi::{c_char, c_void, CStr};
2
3pub use libsql_bindgen_macros::libsql_bindgen;
4
5static SQLITE_TEXT: u8 = 3;
6static SQLITE_BLOB: u8 = 4;
7static SQLITE_NULL: u8 = 5;
8
9pub trait FromLibSQL {
11 fn from_libsql_type(wasm_ptr: i32) -> Self;
12}
13
14pub trait IntoLibSQL {
16 fn into_libsql_type(self) -> i32;
17}
18
19impl FromLibSQL for &str {
20 fn from_libsql_type(wasm_ptr: i32) -> Self {
21 let raw_ptr = wasm_ptr as *const c_char;
22 unsafe {
23 if *raw_ptr != SQLITE_TEXT as c_char {
24 "???"
25 } else {
26 match CStr::from_ptr(raw_ptr.offset(1)).to_str() {
27 Ok(s) => s,
28 Err(_) => "!!!",
29 }
30 }
31 }
32 }
33}
34
35impl IntoLibSQL for &str {
36 fn into_libsql_type(self) -> i32 {
37 let mut mem: Vec<u8> = vec![0; self.len() + 2];
38 mem[0] = SQLITE_TEXT;
39 mem[1..=self.len()].copy_from_slice(self.as_bytes());
40 mem[self.len() + 1] = 0;
41 let ptr = mem.as_ptr() as i32;
42 std::mem::forget(mem);
43 ptr
44 }
45}
46
47impl FromLibSQL for String {
48 fn from_libsql_type(wasm_ptr: i32) -> Self {
49 <&str>::from_libsql_type(wasm_ptr).to_owned()
50 }
51}
52
53impl IntoLibSQL for String {
54 fn into_libsql_type(self) -> i32 {
55 self.as_str().into_libsql_type()
56 }
57}
58
59impl FromLibSQL for &mut [u8] {
60 fn from_libsql_type(wasm_ptr: i32) -> Self {
61 let raw_ptr = wasm_ptr as *const c_void;
62 if unsafe { *(raw_ptr as *const c_char) != SQLITE_BLOB as c_char } {
63 &mut []
64 } else {
65 let size = unsafe {
66 u32::from_be_bytes(
67 core::slice::from_raw_parts(raw_ptr.offset(1) as *const u8, 4)
68 .try_into()
69 .unwrap_or([0_u8, 0_u8, 0_u8, 0_u8]),
70 )
71 };
72 unsafe { core::slice::from_raw_parts_mut(raw_ptr.offset(5) as *mut u8, size as usize) }
73 }
74 }
75}
76
77impl IntoLibSQL for Vec<u8> {
78 fn into_libsql_type(self) -> i32 {
79 let mut mem: Vec<u8> = vec![0; self.len() + 5];
80 mem[0] = SQLITE_BLOB;
81 mem[1..5].copy_from_slice(&u32::to_be_bytes(self.len() as u32));
82 mem[5..].copy_from_slice(&self);
83 let ptr = mem.as_ptr() as i32;
84 std::mem::forget(mem);
85 ptr
86 }
87}
88
89impl<T: FromLibSQL> FromLibSQL for Option<T> {
90 fn from_libsql_type(wasm_ptr: i32) -> Self {
91 let raw_ptr = wasm_ptr as *const c_char;
92 unsafe {
93 if *raw_ptr == SQLITE_NULL as c_char {
94 None
95 } else {
96 Some(<T>::from_libsql_type(wasm_ptr))
97 }
98 }
99 }
100}
101
102#[no_mangle]
103pub unsafe extern "C" fn libsql_malloc(size: usize) -> usize {
104 let buffer = Vec::<u8>::with_capacity(size);
105 let ptr = Vec::leak(buffer);
106 ptr.as_ptr() as usize
107}