1use std::fmt::Display;
2
3#[repr(C)]
6#[derive(Debug, PartialEq, Eq, Clone, Copy)]
7pub enum ResultCode {
8 OK = 0,
9 Error = 1,
10 InvalidArgs = 2,
11 Unknown = 3,
12 OoM = 4,
13 Corrupt = 5,
14 NotFound = 6,
15 AlreadyExists = 7,
16 PermissionDenied = 8,
17 Aborted = 9,
18 OutOfRange = 10,
19 Unimplemented = 11,
20 Internal = 12,
21 Unavailable = 13,
22 CustomError = 14,
23 EOF = 15,
24 ReadOnly = 16,
25 RowID = 17,
26 Row = 18,
27 Interrupt = 19,
28 Busy = 20,
29}
30
31impl ResultCode {
32 pub fn is_ok(&self) -> bool {
33 matches!(self, Self::OK)
34 }
35
36 pub fn is_error(&self) -> bool {
37 !matches!(self, Self::OK | Self::RowID | Self::EOF)
38 }
39
40 pub fn has_error_set(&self) -> bool {
41 matches!(self, Self::CustomError)
42 }
43}
44
45impl Display for ResultCode {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 match self {
48 ResultCode::OK => write!(f, "OK"),
49 ResultCode::Error => write!(f, "Error"),
50 ResultCode::InvalidArgs => write!(f, "Invalid Argument"),
51 ResultCode::Unknown => write!(f, "Unknown"),
52 ResultCode::OoM => write!(f, "Out of Memory"),
53 ResultCode::Corrupt => write!(f, "Corrupt"),
54 ResultCode::NotFound => write!(f, "Not Found"),
55 ResultCode::AlreadyExists => write!(f, "Already Exists"),
56 ResultCode::PermissionDenied => write!(f, "Permission Denied"),
57 ResultCode::Aborted => write!(f, "Aborted"),
58 ResultCode::OutOfRange => write!(f, "Out of Range"),
59 ResultCode::Unimplemented => write!(f, "Unimplemented"),
60 ResultCode::Internal => write!(f, "Internal Error"),
61 ResultCode::Unavailable => write!(f, "Unavailable"),
62 ResultCode::CustomError => write!(f, "Error "),
63 ResultCode::EOF => write!(f, "EOF"),
64 ResultCode::ReadOnly => write!(f, "Read Only"),
65 ResultCode::RowID => write!(f, "RowID"),
66 ResultCode::Row => write!(f, "Row"),
67 ResultCode::Interrupt => write!(f, "Interrupt"),
68 ResultCode::Busy => write!(f, "Busy"),
69 }
70 }
71}
72#[repr(C)]
73#[derive(PartialEq, Debug, Eq, Clone, Copy)]
74pub enum StepResult {
78 Error,
79 Row,
80 Done,
81 Interrupt,
82 Busy,
83}
84
85impl From<ResultCode> for StepResult {
86 fn from(code: ResultCode) -> Self {
87 match code {
88 ResultCode::Error => StepResult::Error,
89 ResultCode::Row => StepResult::Row,
90 ResultCode::EOF => StepResult::Done,
91 ResultCode::Interrupt => StepResult::Interrupt,
92 ResultCode::Busy => StepResult::Busy,
93 _ => StepResult::Error,
94 }
95 }
96}
97
98#[repr(C)]
99#[derive(PartialEq, Debug, Eq, Clone, Copy)]
100pub enum ValueType {
101 Null,
102 Integer,
103 Float,
104 Text,
105 Blob,
106 Error,
107}
108
109#[repr(C)]
110pub struct Value {
111 value_type: ValueType,
112 value: ValueData,
113}
114impl Default for Value {
115 fn default() -> Self {
116 Self::null()
117 }
118}
119
120#[repr(C)]
121union ValueData {
122 int: i64,
123 float: f64,
124 text: *const TextValue,
125 blob: *const Blob,
126 error: *const ErrValue,
127}
128
129#[repr(C)]
130#[derive(PartialEq, Clone, Copy, Debug)]
131enum TextSubtype {
132 Text,
133 Json,
134}
135
136impl std::fmt::Debug for Value {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 match self.value_type {
139 ValueType::Null => write!(f, "Value {{ Null }}"),
140 ValueType::Integer => write!(
141 f,
142 "Value {{ Integer: {} }}",
143 self.to_integer().unwrap_or_default()
144 ),
145 ValueType::Float => write!(
146 f,
147 "Value {{ Float: {} }}",
148 self.to_float().unwrap_or_default()
149 ),
150 ValueType::Text => write!(f, "Value {{ Text: {:?} }}", self.to_text()),
151 ValueType::Blob => write!(f, "Value {{ Blob: {:?} }}", self.to_blob()),
152 ValueType::Error => write!(f, "Value {{ Error }}"),
153 }
154 }
155}
156
157#[repr(C)]
158pub struct TextValue {
159 _type: TextSubtype,
160 text: *const u8,
161 len: u32,
162}
163
164impl std::fmt::Debug for TextValue {
165 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166 write!(
167 f,
168 "TextValue {{ text: {:?}, len: {} }}",
169 self.text, self.len
170 )
171 }
172}
173
174impl Default for TextValue {
175 fn default() -> Self {
176 Self {
177 _type: TextSubtype::Text,
178 text: std::ptr::null(),
179 len: 0,
180 }
181 }
182}
183
184impl TextValue {
185 fn new(text: *const u8, len: usize) -> Self {
186 Self {
187 _type: TextSubtype::Text,
188 text,
189 len: len as u32,
190 }
191 }
192
193 fn new_boxed(s: String, sub: TextSubtype) -> Box<Self> {
194 let len = s.len();
195 let buffer = s.into_boxed_str();
196 let strbox = Box::into_raw(buffer);
197 Box::new(Self {
198 _type: sub,
199 text: strbox as *const u8,
200 len: len as u32,
201 })
202 }
203
204 #[cfg(feature = "core_only")]
205 fn free(self) {
206 if !self.text.is_null() {
207 let _ = unsafe { Box::from_raw(self.text as *mut u8) };
208 }
209 }
210
211 fn as_str(&self) -> &str {
212 if self.text.is_null() {
213 return "";
214 }
215 unsafe {
216 std::str::from_utf8_unchecked(std::slice::from_raw_parts(self.text, self.len as usize))
217 }
218 }
219}
220
221#[repr(C)]
222struct ErrValue {
223 code: ResultCode,
224 message: *mut TextValue,
225}
226
227impl ErrValue {
228 fn new(code: ResultCode) -> Self {
229 Self {
230 code,
231 message: std::ptr::null_mut(),
232 }
233 }
234
235 fn new_with_message(code: ResultCode, message: String) -> Self {
236 let buffer = message.into_boxed_str();
237 let ptr = buffer.as_ptr();
238 let len = buffer.len();
239 std::mem::forget(buffer);
240 let text_value = TextValue::new(ptr, len);
241 Self {
242 code,
243 message: Box::into_raw(Box::new(text_value)),
244 }
245 }
246}
247
248#[repr(C)]
249struct Blob {
250 data: *const u8,
251 size: u64,
252}
253
254impl std::fmt::Debug for Blob {
255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 write!(f, "Blob {{ data: {:?}, size: {} }}", self.data, self.size)
257 }
258}
259
260impl Blob {
261 pub fn new(data: *const u8, size: u64) -> Self {
262 Self { data, size }
263 }
264
265 pub fn as_bytes(&self) -> &[u8] {
266 if self.data.is_null() {
267 return &[];
268 }
269 unsafe { std::slice::from_raw_parts(self.data, self.size as usize) }
270 }
271 #[cfg(feature = "core_only")]
272 fn free(self) {
273 if !self.data.is_null() {
274 let _ = unsafe { Box::from_raw(self.data as *mut u8) };
275 }
276 }
277}
278
279impl Value {
280 pub fn null() -> Self {
282 Self {
283 value_type: ValueType::Null,
284 value: ValueData { int: 0 },
285 }
286 }
287
288 pub fn value_type(&self) -> ValueType {
290 self.value_type
291 }
292
293 pub fn to_float(&self) -> Option<f64> {
295 match self.value_type {
296 ValueType::Float => Some(unsafe { self.value.float }),
297 ValueType::Integer => Some(unsafe { self.value.int } as f64),
298 ValueType::Text => {
299 let txt = self.to_text().unwrap_or_default();
300 txt.parse().ok()
301 }
302 _ => None,
303 }
304 }
305
306 pub fn to_text(&self) -> Option<&str> {
308 unsafe {
309 if self.value_type == ValueType::Text && !self.value.text.is_null() {
310 let txt = &*self.value.text;
311 Some(txt.as_str())
312 } else {
313 None
314 }
315 }
316 }
317
318 pub fn is_json(&self) -> bool {
319 unsafe {
320 if self.value_type == ValueType::Text && !self.value.text.is_null() {
321 let txt = &*self.value.text;
322 return txt._type == TextSubtype::Json;
323 }
324 }
325 false
326 }
327
328 pub fn to_blob(&self) -> Option<Vec<u8>> {
330 match self.value_type {
331 ValueType::Blob => {
332 if unsafe { self.value.blob.is_null() } {
333 return None;
334 }
335 let blob = unsafe { &*(self.value.blob) };
336 let slice = unsafe { std::slice::from_raw_parts(blob.data, blob.size as usize) };
337 Some(slice.to_vec())
338 }
339 ValueType::Text => {
340 let txt = self.to_text().unwrap_or_default();
341 Some(txt.as_bytes().to_vec())
342 }
343 _ => None,
344 }
345 }
346
347 pub fn to_integer(&self) -> Option<i64> {
349 match self.value_type() {
350 ValueType::Integer => Some(unsafe { self.value.int }),
351 ValueType::Float => Some(unsafe { self.value.float } as i64),
352 ValueType::Text => self
353 .to_text()
354 .map(|txt| txt.parse::<i64>().unwrap_or_default()),
355 _ => None,
356 }
357 }
358
359 pub fn to_error(&self) -> Option<ResultCode> {
361 if self.value_type != ValueType::Error {
362 return None;
363 }
364 if unsafe { self.value.error.is_null() } {
365 return None;
366 }
367 let err = unsafe { &*self.value.error };
368 Some(err.code)
369 }
370
371 pub fn to_error_details(&self) -> Option<(ResultCode, Option<String>)> {
373 if self.value_type != ValueType::Error || unsafe { self.value.error.is_null() } {
374 return None;
375 }
376 let err_val = unsafe { &*(self.value.error) };
377 let code = err_val.code;
378
379 if err_val.message.is_null() {
380 Some((code, None))
381 } else {
382 let txt = unsafe { &*(err_val.message as *const TextValue) };
383 let msg = txt.as_str().to_owned();
384 Some((code, Some(msg)))
385 }
386 }
387
388 pub fn as_bytes(&self) -> Vec<u8> {
390 let mut bytes = vec![];
391 unsafe {
392 match self.value_type {
393 ValueType::Integer => bytes.extend_from_slice(&self.value.int.to_le_bytes()),
394 ValueType::Float => bytes.extend_from_slice(&self.value.float.to_le_bytes()),
395 ValueType::Text => {
396 let text = self.value.text.as_ref().expect("Invalid text pointer");
397 bytes.extend_from_slice(text.as_str().as_bytes());
398 }
399 ValueType::Blob => {
400 let blob = self.value.blob.as_ref().expect("Invalid blob pointer");
401 bytes.extend_from_slice(blob.as_bytes());
402 }
403 ValueType::Error | ValueType::Null => {}
404 }
405 }
406
407 bytes
408 }
409
410 pub fn from_integer(i: i64) -> Self {
412 Self {
413 value_type: ValueType::Integer,
414 value: ValueData { int: i },
415 }
416 }
417
418 pub fn from_float(value: f64) -> Self {
420 Self {
421 value_type: ValueType::Float,
422 value: ValueData { float: value },
423 }
424 }
425
426 pub fn from_text(s: String) -> Self {
428 let txt_value = TextValue::new_boxed(s, TextSubtype::Text);
429 let ptr = Box::into_raw(txt_value);
430 Self {
431 value_type: ValueType::Text,
432 value: ValueData { text: ptr },
433 }
434 }
435
436 pub fn from_json(s: String) -> Self {
437 let txt_value = TextValue::new_boxed(s, TextSubtype::Json);
438 let ptr = Box::into_raw(txt_value);
439 Self {
440 value_type: ValueType::Text,
441 value: ValueData { text: ptr },
442 }
443 }
444
445 pub fn error(code: ResultCode) -> Self {
447 let err_val = ErrValue::new(code);
448 Self {
449 value_type: ValueType::Error,
450 value: ValueData {
451 error: Box::into_raw(Box::new(err_val)) as *const ErrValue,
452 },
453 }
454 }
455
456 pub fn error_with_message(message: String) -> Self {
458 let err_value = ErrValue::new_with_message(ResultCode::CustomError, message);
459 let err_box = Box::new(err_value);
460 Self {
461 value_type: ValueType::Error,
462 value: ValueData {
463 error: Box::into_raw(err_box) as *const ErrValue,
464 },
465 }
466 }
467
468 pub fn from_blob(value: Vec<u8>) -> Self {
470 let len = value.len();
471 let boxed_data = value.into_boxed_slice();
472 let ptr = Box::into_raw(boxed_data) as *const u8;
473 let boxed_blob = Box::new(Blob::new(ptr, len as u64));
474 Self {
475 value_type: ValueType::Blob,
476 value: ValueData {
477 blob: Box::into_raw(boxed_blob) as *const Blob,
478 },
479 }
480 }
481
482 #[cfg(feature = "core_only")]
489 pub unsafe fn __free_internal_type(self) {
490 match self.value_type {
491 ValueType::Text => {
492 let txt = Box::from_raw(self.value.text as *mut TextValue);
493 txt.free();
494 }
495 ValueType::Blob => {
496 let blob = Box::from_raw(self.value.blob as *mut Blob);
497 blob.free();
498 }
499 ValueType::Error => {
500 let err_val = Box::from_raw(self.value.error as *mut ErrValue);
501 if !err_val.message.is_null() {
502 let _ = Box::from_raw(err_val.message);
503 }
504 }
505 _ => {}
506 }
507 }
508}