1use crate::provider::{RawBytes, ValueType};
2
3#[derive(Clone, Debug, PartialEq)]
5pub enum Value {
6 Null,
8 Integer(i64),
10 Float(f64),
12 Text(String),
14 Blob(Vec<u8>),
16}
17
18impl Value {
19 pub fn value_type(&self) -> ValueType {
21 match self {
22 Value::Null => ValueType::Null,
23 Value::Integer(_) => ValueType::Integer,
24 Value::Float(_) => ValueType::Float,
25 Value::Text(_) => ValueType::Text,
26 Value::Blob(_) => ValueType::Blob,
27 }
28 }
29
30 pub fn as_i64(&self) -> Option<i64> {
32 match self {
33 Value::Integer(v) => Some(*v),
34 _ => None,
35 }
36 }
37
38 pub fn as_f64(&self) -> Option<f64> {
40 match self {
41 Value::Float(v) => Some(*v),
42 _ => None,
43 }
44 }
45
46 pub fn as_str(&self) -> Option<&str> {
48 match self {
49 Value::Text(v) => Some(v.as_str()),
50 _ => None,
51 }
52 }
53
54 pub fn as_blob(&self) -> Option<&[u8]> {
56 match self {
57 Value::Blob(v) => Some(v.as_slice()),
58 _ => None,
59 }
60 }
61}
62
63impl From<i64> for Value {
64 fn from(value: i64) -> Self {
65 Value::Integer(value)
66 }
67}
68
69impl From<f64> for Value {
70 fn from(value: f64) -> Self {
71 Value::Float(value)
72 }
73}
74
75impl From<String> for Value {
76 fn from(value: String) -> Self {
77 Value::Text(value)
78 }
79}
80
81impl From<&str> for Value {
82 fn from(value: &str) -> Self {
83 Value::Text(value.to_owned())
84 }
85}
86
87impl From<Vec<u8>> for Value {
88 fn from(value: Vec<u8>) -> Self {
89 Value::Blob(value)
90 }
91}
92
93#[derive(Clone, Copy, Debug, PartialEq)]
95pub enum ValueRef<'a> {
96 Null,
98 Integer(i64),
100 Float(f64),
102 Text(&'a str),
104 Blob(&'a [u8]),
106}
107
108impl<'a> ValueRef<'a> {
109 pub fn value_type(&self) -> ValueType {
111 match self {
112 ValueRef::Null => ValueType::Null,
113 ValueRef::Integer(_) => ValueType::Integer,
114 ValueRef::Float(_) => ValueType::Float,
115 ValueRef::Text(_) => ValueType::Text,
116 ValueRef::Blob(_) => ValueType::Blob,
117 }
118 }
119
120 pub fn as_i64(&self) -> Option<i64> {
122 match self {
123 ValueRef::Integer(v) => Some(*v),
124 _ => None,
125 }
126 }
127
128 pub fn as_f64(&self) -> Option<f64> {
130 match self {
131 ValueRef::Float(v) => Some(*v),
132 _ => None,
133 }
134 }
135
136 pub fn as_str(&self) -> Option<&'a str> {
138 match self {
139 ValueRef::Text(v) => Some(*v),
140 _ => None,
141 }
142 }
143
144 pub fn as_blob(&self) -> Option<&'a [u8]> {
146 match self {
147 ValueRef::Blob(v) => Some(*v),
148 _ => None,
149 }
150 }
151
152 pub fn to_owned(&self) -> Value {
154 match self {
155 ValueRef::Null => Value::Null,
156 ValueRef::Integer(v) => Value::Integer(*v),
157 ValueRef::Float(v) => Value::Float(*v),
158 ValueRef::Text(v) => Value::Text((*v).to_owned()),
159 ValueRef::Blob(v) => Value::Blob((*v).to_vec()),
160 }
161 }
162
163 pub unsafe fn from_raw_text(raw: RawBytes) -> ValueRef<'a> {
169 match unsafe { raw.as_str() } {
170 Some(text) => ValueRef::Text(text),
171 None => ValueRef::Blob(unsafe { raw.as_slice() }),
172 }
173 }
174
175 pub unsafe fn from_raw_blob(raw: RawBytes) -> ValueRef<'a> {
178 ValueRef::Blob(unsafe { raw.as_slice() })
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use crate::provider::RawBytes;
185
186 use super::{Value, ValueRef};
187
188 #[test]
189 fn value_ref_to_owned() {
190 let value = ValueRef::Text("hello");
191 assert_eq!(value.to_owned(), Value::Text("hello".to_owned()));
192 }
193
194 #[test]
195 fn value_ref_from_raw_text_falls_back_to_blob_when_invalid_utf8() {
196 let bytes = [0xff_u8, 0xfe_u8];
197 let raw = RawBytes {
198 ptr: bytes.as_ptr(),
199 len: bytes.len(),
200 };
201 let value = unsafe { ValueRef::from_raw_text(raw) };
202 assert_eq!(value, ValueRef::Blob(&bytes));
203 }
204}