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