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 type_info_opt(&self) -> Option<SqliteTypeInfo> {
73 match self.0 {
74 SqliteValueData::Value(v) => v.type_info_opt(),
75 }
76 }
77
78 pub fn is_null(&self) -> bool {
79 match self.0 {
80 SqliteValueData::Value(v) => v.is_null(),
81 }
82 }
83}
84
85#[derive(Clone, Debug)]
86pub struct SqliteValue {
87 pub(crate) handle: Arc<ValueHandle>,
88 pub(crate) type_info: SqliteTypeInfo,
89}
90
91#[derive(Debug)]
92pub(crate) struct ValueHandle(NonNull<sqlite3_value>);
93
94unsafe impl Send for ValueHandle {}
96unsafe impl Sync for ValueHandle {}
97
98impl SqliteValue {
99 pub(crate) unsafe fn new(value: *mut sqlite3_value, type_info: SqliteTypeInfo) -> Self {
100 debug_assert!(!value.is_null());
101
102 Self {
103 type_info,
104 handle: Arc::new(ValueHandle(NonNull::new_unchecked(sqlite3_value_dup(
105 value,
106 )))),
107 }
108 }
109
110 pub fn type_info_opt(&self) -> Option<SqliteTypeInfo> {
111 let dt = DataType::from_code(unsafe { sqlite3_value_type(self.handle.0.as_ptr()) });
112 if let DataType::Null = dt {
113 None
114 } else {
115 Some(SqliteTypeInfo(dt))
116 }
117 }
118
119 pub fn int(&self) -> i32 {
120 unsafe { sqlite3_value_int(self.handle.0.as_ptr()) }
121 }
122
123 pub fn int64(&self) -> i64 {
124 unsafe { sqlite3_value_int64(self.handle.0.as_ptr()) }
125 }
126
127 pub fn double(&self) -> f64 {
128 unsafe { sqlite3_value_double(self.handle.0.as_ptr()) }
129 }
130
131 pub fn blob(&self) -> &[u8] {
132 let len = unsafe { sqlite3_value_bytes(self.handle.0.as_ptr()) } as usize;
133
134 if len == 0 {
135 return &[];
137 }
138
139 let ptr = unsafe { sqlite3_value_blob(self.handle.0.as_ptr()) } as *const u8;
140 debug_assert!(!ptr.is_null());
141
142 unsafe { from_raw_parts(ptr, len) }
143 }
144
145 pub fn text(&self) -> Result<&str, Error> {
146 Ok(from_utf8(self.blob())?)
147 }
148}
149
150impl SqliteValue {
151 pub fn as_ref(&self) -> SqliteValueRef<'_> {
152 SqliteValueRef::value(self)
153 }
154
155 pub fn type_info(&self) -> Cow<'_, SqliteTypeInfo> {
156 self.type_info_opt()
157 .map(Cow::Owned)
158 .unwrap_or(Cow::Borrowed(&self.type_info))
159 }
160
161 pub fn is_null(&self) -> bool {
162 unsafe { sqlite3_value_type(self.handle.0.as_ptr()) == SQLITE_NULL }
163 }
164}
165
166impl Drop for ValueHandle {
167 fn drop(&mut self) {
168 unsafe {
169 sqlite3_value_free(self.0.as_ptr());
170 }
171 }
172}