rusqlite/types/
value_ref.rs1use super::{Type, Value};
2use crate::types::{FromSqlError, FromSqlResult};
3
4#[derive(Copy, Clone, Debug, PartialEq)]
9pub enum ValueRef<'a> {
10 Null,
12 Integer(i64),
14 Real(f64),
16 Text(&'a [u8]),
18 Blob(&'a [u8]),
20}
21
22impl ValueRef<'_> {
23 #[inline]
25 #[must_use]
26 pub fn data_type(&self) -> Type {
27 match *self {
28 ValueRef::Null => Type::Null,
29 ValueRef::Integer(_) => Type::Integer,
30 ValueRef::Real(_) => Type::Real,
31 ValueRef::Text(_) => Type::Text,
32 ValueRef::Blob(_) => Type::Blob,
33 }
34 }
35}
36
37impl<'a> ValueRef<'a> {
38 #[inline]
42 pub fn as_i64(&self) -> FromSqlResult<i64> {
43 match *self {
44 ValueRef::Integer(i) => Ok(i),
45 _ => Err(FromSqlError::InvalidType),
46 }
47 }
48
49 #[inline]
54 pub fn as_i64_or_null(&self) -> FromSqlResult<Option<i64>> {
55 match *self {
56 ValueRef::Null => Ok(None),
57 ValueRef::Integer(i) => Ok(Some(i)),
58 _ => Err(FromSqlError::InvalidType),
59 }
60 }
61
62 #[inline]
66 pub fn as_f64(&self) -> FromSqlResult<f64> {
67 match *self {
68 ValueRef::Real(f) => Ok(f),
69 _ => Err(FromSqlError::InvalidType),
70 }
71 }
72
73 #[inline]
78 pub fn as_f64_or_null(&self) -> FromSqlResult<Option<f64>> {
79 match *self {
80 ValueRef::Null => Ok(None),
81 ValueRef::Real(f) => Ok(Some(f)),
82 _ => Err(FromSqlError::InvalidType),
83 }
84 }
85
86 #[inline]
89 pub fn as_str(&self) -> FromSqlResult<&'a str> {
90 match *self {
91 ValueRef::Text(t) => {
92 std::str::from_utf8(t).map_err(|e| FromSqlError::Other(Box::new(e)))
93 }
94 _ => Err(FromSqlError::InvalidType),
95 }
96 }
97
98 #[inline]
103 pub fn as_str_or_null(&self) -> FromSqlResult<Option<&'a str>> {
104 match *self {
105 ValueRef::Null => Ok(None),
106 ValueRef::Text(t) => std::str::from_utf8(t)
107 .map_err(|e| FromSqlError::Other(Box::new(e)))
108 .map(Some),
109 _ => Err(FromSqlError::InvalidType),
110 }
111 }
112
113 #[inline]
116 pub fn as_blob(&self) -> FromSqlResult<&'a [u8]> {
117 match *self {
118 ValueRef::Blob(b) => Ok(b),
119 _ => Err(FromSqlError::InvalidType),
120 }
121 }
122
123 #[inline]
128 pub fn as_blob_or_null(&self) -> FromSqlResult<Option<&'a [u8]>> {
129 match *self {
130 ValueRef::Null => Ok(None),
131 ValueRef::Blob(b) => Ok(Some(b)),
132 _ => Err(FromSqlError::InvalidType),
133 }
134 }
135
136 #[inline]
139 pub fn as_bytes(&self) -> FromSqlResult<&'a [u8]> {
140 match self {
141 ValueRef::Text(s) | ValueRef::Blob(s) => Ok(s),
142 _ => Err(FromSqlError::InvalidType),
143 }
144 }
145
146 #[inline]
150 pub fn as_bytes_or_null(&self) -> FromSqlResult<Option<&'a [u8]>> {
151 match *self {
152 ValueRef::Null => Ok(None),
153 ValueRef::Text(s) | ValueRef::Blob(s) => Ok(Some(s)),
154 _ => Err(FromSqlError::InvalidType),
155 }
156 }
157}
158
159impl From<ValueRef<'_>> for Value {
160 #[inline]
161 #[track_caller]
162 fn from(borrowed: ValueRef<'_>) -> Value {
163 match borrowed {
164 ValueRef::Null => Value::Null,
165 ValueRef::Integer(i) => Value::Integer(i),
166 ValueRef::Real(r) => Value::Real(r),
167 ValueRef::Text(s) => {
168 let s = std::str::from_utf8(s).expect("invalid UTF-8");
169 Value::Text(s.to_string())
170 }
171 ValueRef::Blob(b) => Value::Blob(b.to_vec()),
172 }
173 }
174}
175
176impl<'a> From<&'a str> for ValueRef<'a> {
177 #[inline]
178 fn from(s: &str) -> ValueRef<'_> {
179 ValueRef::Text(s.as_bytes())
180 }
181}
182
183impl<'a> From<&'a [u8]> for ValueRef<'a> {
184 #[inline]
185 fn from(s: &[u8]) -> ValueRef<'_> {
186 ValueRef::Blob(s)
187 }
188}
189
190impl<'a> From<&'a Value> for ValueRef<'a> {
191 #[inline]
192 fn from(value: &'a Value) -> ValueRef<'a> {
193 match *value {
194 Value::Null => ValueRef::Null,
195 Value::Integer(i) => ValueRef::Integer(i),
196 Value::Real(r) => ValueRef::Real(r),
197 Value::Text(ref s) => ValueRef::Text(s.as_bytes()),
198 Value::Blob(ref b) => ValueRef::Blob(b),
199 }
200 }
201}
202
203impl<'a, T> From<Option<T>> for ValueRef<'a>
204where
205 T: Into<ValueRef<'a>>,
206{
207 #[inline]
208 fn from(s: Option<T>) -> ValueRef<'a> {
209 match s {
210 Some(x) => x.into(),
211 None => ValueRef::Null,
212 }
213 }
214}
215
216#[cfg(any(feature = "functions", feature = "session", feature = "vtab"))]
217impl<'a> ValueRef<'a> {
218 pub(crate) unsafe fn from_value(value: *mut crate::ffi::sqlite3_value) -> ValueRef<'a> {
219 use crate::ffi;
220 use std::slice::from_raw_parts;
221
222 match ffi::sqlite3_value_type(value) {
223 ffi::SQLITE_NULL => ValueRef::Null,
224 ffi::SQLITE_INTEGER => ValueRef::Integer(ffi::sqlite3_value_int64(value)),
225 ffi::SQLITE_FLOAT => ValueRef::Real(ffi::sqlite3_value_double(value)),
226 ffi::SQLITE_TEXT => {
227 let text = ffi::sqlite3_value_text(value);
228 let len = ffi::sqlite3_value_bytes(value);
229 assert!(
230 !text.is_null(),
231 "unexpected SQLITE_TEXT value type with NULL data"
232 );
233 let s = from_raw_parts(text.cast::<u8>(), len as usize);
234 ValueRef::Text(s)
235 }
236 ffi::SQLITE_BLOB => {
237 let (blob, len) = (
238 ffi::sqlite3_value_blob(value),
239 ffi::sqlite3_value_bytes(value),
240 );
241
242 assert!(
243 len >= 0,
244 "unexpected negative return from sqlite3_value_bytes"
245 );
246 if len > 0 {
247 assert!(
248 !blob.is_null(),
249 "unexpected SQLITE_BLOB value type with NULL data"
250 );
251 ValueRef::Blob(from_raw_parts(blob.cast::<u8>(), len as usize))
252 } else {
253 ValueRef::Blob(&[])
256 }
257 }
258 _ => unreachable!("sqlite3_value_type returned invalid value"),
259 }
260 }
261
262 }