1use std::ptr::NonNull;
2use std::slice::from_raw_parts;
3use std::str::from_utf8;
4use std::sync::Arc;
5
6use libsqlite3_sys::{
7 sqlite3_value, sqlite3_value_blob, sqlite3_value_bytes, sqlite3_value_double,
8 sqlite3_value_dup, sqlite3_value_free, sqlite3_value_int, sqlite3_value_int64,
9 sqlite3_value_type, SQLITE_NULL,
10};
11
12use crate::type_info::DataType;
13use crate::SqliteTypeInfo;
14use rbdc::error::Error;
15use std::borrow::Cow;
16
17enum SqliteValueData<'r> {
18 Value(&'r SqliteValue),
19}
20
21pub struct SqliteValueRef<'r>(SqliteValueData<'r>);
22
23impl<'r> SqliteValueRef<'r> {
24 pub(crate) fn value(value: &'r SqliteValue) -> Self {
25 Self(SqliteValueData::Value(value))
26 }
27
28 pub(super) fn int(&self) -> i32 {
29 match self.0 {
30 SqliteValueData::Value(v) => v.int(),
31 }
32 }
33
34 pub(super) fn int64(&self) -> i64 {
35 match self.0 {
36 SqliteValueData::Value(v) => v.int64(),
37 }
38 }
39
40 pub(super) fn double(&self) -> f64 {
41 match self.0 {
42 SqliteValueData::Value(v) => v.double(),
43 }
44 }
45
46 pub(super) fn blob(&self) -> &'r [u8] {
47 match self.0 {
48 SqliteValueData::Value(v) => v.blob(),
49 }
50 }
51
52 pub(super) fn text(&self) -> Result<&'r str, Error> {
53 match self.0 {
54 SqliteValueData::Value(v) => v.text(),
55 }
56 }
57}
58
59impl<'r> SqliteValueRef<'r> {
60 pub fn to_owned(&self) -> SqliteValue {
61 match self.0 {
62 SqliteValueData::Value(v) => v.clone(),
63 }
64 }
65
66 pub fn type_info(&self) -> Cow<'_, SqliteTypeInfo> {
67 match self.0 {
68 SqliteValueData::Value(v) => v.type_info(),
69 }
70 }
71
72 pub fn is_null(&self) -> bool {
73 match self.0 {
74 SqliteValueData::Value(v) => v.is_null(),
75 }
76 }
77}
78
79#[derive(Clone, Debug)]
80pub struct SqliteValue {
81 pub(crate) handle: Arc<ValueHandle>,
82 pub(crate) type_info: SqliteTypeInfo,
83}
84
85#[derive(Debug)]
86pub(crate) struct ValueHandle(NonNull<sqlite3_value>);
87
88unsafe impl Send for ValueHandle {}
90unsafe impl Sync for ValueHandle {}
91
92impl SqliteValue {
93 pub(crate) unsafe fn new(value: *mut sqlite3_value, type_info: SqliteTypeInfo) -> Self {
94 debug_assert!(!value.is_null());
95
96 Self {
97 type_info,
98 handle: Arc::new(ValueHandle(NonNull::new_unchecked(sqlite3_value_dup(
99 value,
100 )))),
101 }
102 }
103
104 pub fn type_info_opt(&self) -> Option<SqliteTypeInfo> {
105 let dt = DataType::from_code(unsafe { sqlite3_value_type(self.handle.0.as_ptr()) });
106
107 if let DataType::Null = dt {
108 None
109 } else {
110 Some(SqliteTypeInfo(dt))
111 }
112 }
113
114 pub fn int(&self) -> i32 {
115 unsafe { sqlite3_value_int(self.handle.0.as_ptr()) }
116 }
117
118 pub fn int64(&self) -> i64 {
119 unsafe { sqlite3_value_int64(self.handle.0.as_ptr()) }
120 }
121
122 pub fn double(&self) -> f64 {
123 unsafe { sqlite3_value_double(self.handle.0.as_ptr()) }
124 }
125
126 pub fn blob(&self) -> &[u8] {
127 let len = unsafe { sqlite3_value_bytes(self.handle.0.as_ptr()) } as usize;
128
129 if len == 0 {
130 return &[];
132 }
133
134 let ptr = unsafe { sqlite3_value_blob(self.handle.0.as_ptr()) } as *const u8;
135 debug_assert!(!ptr.is_null());
136
137 unsafe { from_raw_parts(ptr, len) }
138 }
139
140 pub fn text(&self) -> Result<&str, Error> {
141 Ok(from_utf8(self.blob())?)
142 }
143}
144
145impl SqliteValue {
146 pub fn as_ref(&self) -> SqliteValueRef<'_> {
147 SqliteValueRef::value(self)
148 }
149
150 pub fn type_info(&self) -> Cow<'_, SqliteTypeInfo> {
151 self.type_info_opt()
152 .map(Cow::Owned)
153 .unwrap_or(Cow::Borrowed(&self.type_info))
154 }
155
156 pub fn is_null(&self) -> bool {
157 unsafe { sqlite3_value_type(self.handle.0.as_ptr()) == SQLITE_NULL }
158 }
159}
160
161impl Drop for ValueHandle {
162 fn drop(&mut self) {
163 unsafe {
164 sqlite3_value_free(self.0.as_ptr());
165 }
166 }
167}