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 pub fn data_type(&self) -> Type {
26 match *self {
27 ValueRef::Null => Type::Null,
28 ValueRef::Integer(_) => Type::Integer,
29 ValueRef::Real(_) => Type::Real,
30 ValueRef::Text(_) => Type::Text,
31 ValueRef::Blob(_) => Type::Blob,
32 }
33 }
34}
35
36impl<'a> ValueRef<'a> {
37 #[inline]
40 pub fn as_i64(&self) -> FromSqlResult<i64> {
41 match *self {
42 ValueRef::Integer(i) => Ok(i),
43 _ => Err(FromSqlError::InvalidType),
44 }
45 }
46
47 #[inline]
50 pub fn as_f64(&self) -> FromSqlResult<f64> {
51 match *self {
52 ValueRef::Real(f) => Ok(f),
53 _ => Err(FromSqlError::InvalidType),
54 }
55 }
56
57 #[inline]
60 pub fn as_str(&self) -> FromSqlResult<&'a str> {
61 match *self {
62 ValueRef::Text(t) => {
63 std::str::from_utf8(t).map_err(|e| FromSqlError::Other(Box::new(e)))
64 }
65 _ => Err(FromSqlError::InvalidType),
66 }
67 }
68
69 #[inline]
72 pub fn as_blob(&self) -> FromSqlResult<&'a [u8]> {
73 match *self {
74 ValueRef::Blob(b) => Ok(b),
75 _ => Err(FromSqlError::InvalidType),
76 }
77 }
78}
79
80impl From<ValueRef<'_>> for Value {
81 #[inline]
82 fn from(borrowed: ValueRef<'_>) -> Value {
83 match borrowed {
84 ValueRef::Null => Value::Null,
85 ValueRef::Integer(i) => Value::Integer(i),
86 ValueRef::Real(r) => Value::Real(r),
87 ValueRef::Text(s) => {
88 let s = std::str::from_utf8(s).expect("invalid UTF-8");
89 Value::Text(s.to_string())
90 }
91 ValueRef::Blob(b) => Value::Blob(b.to_vec()),
92 }
93 }
94}
95
96impl<'a> From<&'a str> for ValueRef<'a> {
97 #[inline]
98 fn from(s: &str) -> ValueRef<'_> {
99 ValueRef::Text(s.as_bytes())
100 }
101}
102
103impl<'a> From<&'a [u8]> for ValueRef<'a> {
104 #[inline]
105 fn from(s: &[u8]) -> ValueRef<'_> {
106 ValueRef::Blob(s)
107 }
108}
109
110impl<'a> From<&'a Value> for ValueRef<'a> {
111 #[inline]
112 fn from(value: &'a Value) -> ValueRef<'a> {
113 match *value {
114 Value::Null => ValueRef::Null,
115 Value::Integer(i) => ValueRef::Integer(i),
116 Value::Real(r) => ValueRef::Real(r),
117 Value::Text(ref s) => ValueRef::Text(s.as_bytes()),
118 Value::Blob(ref b) => ValueRef::Blob(b),
119 }
120 }
121}
122
123impl<'a, T> From<Option<T>> for ValueRef<'a>
124where
125 T: Into<ValueRef<'a>>,
126{
127 #[inline]
128 fn from(s: Option<T>) -> ValueRef<'a> {
129 match s {
130 Some(x) => x.into(),
131 None => ValueRef::Null,
132 }
133 }
134}
135
136#[cfg(any(feature = "functions", feature = "session", feature = "vtab"))]
137impl<'a> ValueRef<'a> {
138 pub(crate) unsafe fn from_value(value: *mut crate::ffi::sqlite3_value) -> ValueRef<'a> {
139 use crate::ffi;
140 use std::slice::from_raw_parts;
141
142 match ffi::sqlite3_value_type(value) {
143 ffi::SQLITE_NULL => ValueRef::Null,
144 ffi::SQLITE_INTEGER => ValueRef::Integer(ffi::sqlite3_value_int64(value)),
145 ffi::SQLITE_FLOAT => ValueRef::Real(ffi::sqlite3_value_double(value)),
146 ffi::SQLITE_TEXT => {
147 let text = ffi::sqlite3_value_text(value);
148 let len = ffi::sqlite3_value_bytes(value);
149 assert!(
150 !text.is_null(),
151 "unexpected SQLITE_TEXT value type with NULL data"
152 );
153 let s = from_raw_parts(text as *const u8, len as usize);
154 ValueRef::Text(s)
155 }
156 ffi::SQLITE_BLOB => {
157 let (blob, len) = (
158 ffi::sqlite3_value_blob(value),
159 ffi::sqlite3_value_bytes(value),
160 );
161
162 assert!(
163 len >= 0,
164 "unexpected negative return from sqlite3_value_bytes"
165 );
166 if len > 0 {
167 assert!(
168 !blob.is_null(),
169 "unexpected SQLITE_BLOB value type with NULL data"
170 );
171 ValueRef::Blob(from_raw_parts(blob as *const u8, len as usize))
172 } else {
173 ValueRef::Blob(&[])
176 }
177 }
178 _ => unreachable!("sqlite3_value_type returned invalid value"),
179 }
180 }
181}