1use std::{
7 convert::TryFrom,
8 error::Error,
9 fmt::{self, Debug},
10};
11
12pub mod file;
13pub mod mem;
14pub mod owned;
15
16pub trait Context {
21 type String;
23 type I64;
25 type XML;
27}
28
29pub trait ValueMapperMut<TI, TO>
35where
36 TI: Context,
37 TO: Context,
38{
39 fn map_string(&mut self, from: &TI::String) -> TO::String;
41 fn map_i64(&mut self, from: &TI::I64) -> TO::I64;
43 fn map_xml(&mut self, from: &TI::XML) -> TO::XML;
45}
46
47#[derive(Debug)]
52#[cfg_attr(feature = "serde", derive(serde::Serialize))]
53#[cfg_attr(feature = "serde", serde(untagged))]
54pub enum Value<T: Context> {
55 Nothing,
57 Integer(i32),
59 Float(f32),
61 Text(T::String),
63 Boolean(bool),
65 BigInt(T::I64),
67 VarChar(T::XML),
69}
70
71impl<C: Context> fmt::Display for Value<C>
72where
73 C::I64: Debug,
74 C::String: Debug,
75 C::XML: Debug,
76{
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 match self {
79 Self::Nothing => write!(f, "NULL"),
80 Self::Integer(i) => write!(f, "{}", i),
81 Self::Float(v) => write!(f, "{}", v),
82 Self::Text(t) => write!(f, "{:?}", t),
83 Self::Boolean(b) => write!(f, "{}", b),
84 Self::BigInt(i) => write!(f, "{:?}", i),
85 Self::VarChar(v) => write!(f, "{:?}", v),
86 }
87 }
88}
89
90impl<C1: Context, C2: Context> PartialEq<Value<C1>> for Value<C2>
91where
92 C1::I64: PartialEq<C2::I64>,
93 C1::String: PartialEq<C2::String>,
94 C1::XML: PartialEq<C2::XML>,
95{
96 fn eq(&self, other: &Value<C1>) -> bool {
97 match other {
98 Value::Nothing => matches!(self, Self::Nothing),
99 Value::Integer(x) => matches!(self, Self::Integer(y) if x == y),
100 Value::Float(x) => matches!(self, Self::Float(y) if x == y),
101 Value::Text(x) => matches!(self, Self::Text(y) if x == y),
102 Value::Boolean(x) => matches!(self, Self::Boolean(y) if x == y),
103 Value::BigInt(x) => matches!(self, Self::BigInt(y) if x == y),
104 Value::VarChar(x) => matches!(self, Self::VarChar(y) if x == y),
105 }
106 }
107}
108
109impl<T: Context> Clone for Value<T>
110where
111 T::String: Clone,
112 T::XML: Clone,
113 T::I64: Clone,
114{
115 fn clone(&self) -> Self {
116 match self {
117 Value::Nothing => Value::Nothing,
118 Value::Integer(v) => Value::Integer(*v),
119 Value::Float(v) => Value::Float(*v),
120 Value::Text(v) => Value::Text(v.clone()),
121 Value::Boolean(v) => Value::Boolean(*v),
122 Value::BigInt(v) => Value::BigInt(v.clone()),
123 Value::VarChar(v) => Value::VarChar(v.clone()),
124 }
125 }
126}
127
128impl<T: Context> Copy for Value<T>
129where
130 T::String: Copy,
131 T::XML: Copy,
132 T::I64: Copy,
133{
134}
135
136impl<T: Context> Value<T> {
137 pub fn map<O, M>(&self, mapper: &mut M) -> Value<O>
139 where
140 O: Context,
141 M: ValueMapperMut<T, O>,
142 {
143 match self {
144 Value::Nothing => Value::Nothing,
145 Value::Integer(v) => Value::Integer(*v),
146 Value::Float(v) => Value::Float(*v),
147 Value::Text(v) => Value::Text(mapper.map_string(v)),
148 Value::Boolean(v) => Value::Boolean(*v),
149 Value::BigInt(v) => Value::BigInt(mapper.map_i64(v)),
150 Value::VarChar(v) => Value::VarChar(mapper.map_xml(v)),
151 }
152 }
153
154 pub fn into_opt_integer(self) -> Option<i32> {
156 if let Self::Integer(value) = self {
157 Some(value)
158 } else {
159 None
160 }
161 }
162
163 pub fn into_opt_float(self) -> Option<f32> {
165 if let Self::Float(value) = self {
166 Some(value)
167 } else {
168 None
169 }
170 }
171
172 pub fn into_opt_text(self) -> Option<T::String> {
174 if let Self::Text(value) = self {
175 Some(value)
176 } else {
177 None
178 }
179 }
180
181 pub fn into_opt_boolean(self) -> Option<bool> {
183 if let Self::Boolean(value) = self {
184 Some(value)
185 } else {
186 None
187 }
188 }
189
190 pub fn into_opt_big_int(self) -> Option<T::I64> {
192 if let Self::BigInt(value) = self {
193 Some(value)
194 } else {
195 None
196 }
197 }
198
199 pub fn into_opt_varchar(self) -> Option<T::XML> {
201 if let Self::VarChar(value) = self {
202 Some(value)
203 } else {
204 None
205 }
206 }
207}
208
209impl<T: Context> From<&Value<T>> for ValueType {
210 fn from(val: &Value<T>) -> Self {
211 match val {
212 Value::Nothing => ValueType::Nothing,
213 Value::Integer(_) => ValueType::Integer,
214 Value::Float(_) => ValueType::Float,
215 Value::Text(_) => ValueType::Text,
216 Value::Boolean(_) => ValueType::Boolean,
217 Value::BigInt(_) => ValueType::BigInt,
218 Value::VarChar(_) => ValueType::VarChar,
219 }
220 }
221}
222
223#[derive(Debug, Copy, Clone, PartialEq, Eq)]
225#[cfg_attr(feature = "serde", derive(serde::Serialize))]
226pub enum ValueType {
227 Nothing,
229 Integer,
231 Float,
233 Text,
235 Boolean,
237 BigInt,
239 VarChar,
241}
242
243impl ValueType {
244 pub fn static_name(&self) -> &'static str {
246 match self {
247 ValueType::Nothing => "NULL",
248 ValueType::Integer => "INTEGER",
249 ValueType::Float => "FLOAT",
250 ValueType::Text => "TEXT",
251 ValueType::Boolean => "BOOLEAN",
252 ValueType::BigInt => "BIGINT",
253 ValueType::VarChar => "VARCHAR",
254 }
255 }
256
257 pub fn to_sqlite_type(self) -> &'static str {
259 match self {
260 ValueType::Nothing => "BLOB_NONE",
261 ValueType::Integer => "INT32",
262 ValueType::Float => "REAL",
263 ValueType::Text => "TEXT4",
264 ValueType::Boolean => "INT_BOOL",
265 ValueType::BigInt => "INT64",
266 ValueType::VarChar => "TEXT_XML",
267 }
268 }
269
270 pub fn from_sqlite_type(decl_type: &str) -> Option<Self> {
300 match decl_type {
301 "BLOB_NONE" | "blob_none" | "none" | "NULL" => Some(ValueType::Nothing),
302 "INT32" | "int32" | "TINYINT" | "SMALLINT" => Some(ValueType::Integer),
303 "real" | "REAL" | "FLOAT" => Some(ValueType::Float),
304 "TEXT4" | "text_4" | "TEXT" => Some(ValueType::Text),
305 "BIT" | "INT_BOOL" | "int_bool" => Some(ValueType::Boolean),
306 "INT64" | "int64" | "BIGINT" | "INTEGER" => Some(ValueType::BigInt),
307 "XML" | "TEXT_XML" | "xml" | "text_8" | "text_xml" | "VARCHAR" => {
308 Some(ValueType::VarChar)
309 }
310 _ => None,
311 }
312 }
313}
314
315impl fmt::Display for ValueType {
316 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
317 write!(f, "{}", self.static_name())
318 }
319}
320
321impl From<ValueType> for u8 {
322 fn from(value_type: ValueType) -> u8 {
323 match value_type {
324 ValueType::Nothing => 0,
325 ValueType::Integer => 1,
326 ValueType::Float => 3,
327 ValueType::Text => 4,
328 ValueType::Boolean => 5,
329 ValueType::BigInt => 6,
330 ValueType::VarChar => 8,
331 }
332 }
333}
334
335impl From<ValueType> for u32 {
336 fn from(value_type: ValueType) -> u32 {
337 u8::from(value_type).into()
338 }
339}
340
341#[derive(Debug, PartialEq, Eq)]
343pub struct UnknownValueType(u32);
344
345impl UnknownValueType {
346 pub fn value(&self) -> u32 {
348 self.0
349 }
350}
351
352impl Error for UnknownValueType {}
353impl fmt::Display for UnknownValueType {
354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355 write!(f, "Unknown FDB value type {}", self.0)
356 }
357}
358
359impl TryFrom<u32> for ValueType {
360 type Error = UnknownValueType;
361
362 fn try_from(value_type: u32) -> Result<ValueType, Self::Error> {
363 match value_type {
364 0 => Ok(ValueType::Nothing),
365 1 => Ok(ValueType::Integer),
366 3 => Ok(ValueType::Float),
367 4 => Ok(ValueType::Text),
368 5 => Ok(ValueType::Boolean),
369 6 => Ok(ValueType::BigInt),
370 8 => Ok(ValueType::VarChar),
371 _ => Err(UnknownValueType(value_type)),
372 }
373 }
374}