1use std::borrow::Cow;
2
3use crate::any::{Any, AnyTypeInfo, AnyTypeInfoKind};
4use crate::database::Database;
5use crate::error::BoxDynError;
6use crate::types::Type;
7use crate::value::{Value, ValueRef};
8
9#[derive(Clone, Debug)]
10#[non_exhaustive]
11pub enum AnyValueKind<'a> {
12 Null(AnyTypeInfoKind),
13 Bool(bool),
14 SmallInt(i16),
15 Integer(i32),
16 BigInt(i64),
17 Real(f32),
18 Double(f64),
19 Text(Cow<'a, str>),
20 Blob(Cow<'a, [u8]>),
21}
22
23impl AnyValueKind<'_> {
24 fn type_info(&self) -> AnyTypeInfo {
25 AnyTypeInfo {
26 kind: match self {
27 AnyValueKind::Null(_) => AnyTypeInfoKind::Null,
28 AnyValueKind::Bool(_) => AnyTypeInfoKind::Bool,
29 AnyValueKind::SmallInt(_) => AnyTypeInfoKind::SmallInt,
30 AnyValueKind::Integer(_) => AnyTypeInfoKind::Integer,
31 AnyValueKind::BigInt(_) => AnyTypeInfoKind::BigInt,
32 AnyValueKind::Real(_) => AnyTypeInfoKind::Real,
33 AnyValueKind::Double(_) => AnyTypeInfoKind::Double,
34 AnyValueKind::Text(_) => AnyTypeInfoKind::Text,
35 AnyValueKind::Blob(_) => AnyTypeInfoKind::Blob,
36 },
37 }
38 }
39
40 pub(in crate::any) fn unexpected<Expected: Type<Any>>(&self) -> Result<Expected, BoxDynError> {
41 Err(format!("expected {}, got {:?}", Expected::type_info(), self).into())
42 }
43
44 pub(in crate::any) fn try_integer<T>(&self) -> Result<T, BoxDynError>
45 where
46 T: Type<Any> + TryFrom<i16> + TryFrom<i32> + TryFrom<i64>,
47 BoxDynError: From<<T as TryFrom<i16>>::Error>,
48 BoxDynError: From<<T as TryFrom<i32>>::Error>,
49 BoxDynError: From<<T as TryFrom<i64>>::Error>,
50 {
51 Ok(match self {
52 AnyValueKind::SmallInt(i) => (*i).try_into()?,
53 AnyValueKind::Integer(i) => (*i).try_into()?,
54 AnyValueKind::BigInt(i) => (*i).try_into()?,
55 _ => return self.unexpected(),
56 })
57 }
58}
59
60#[derive(Clone, Debug)]
61pub struct AnyValue {
62 #[doc(hidden)]
63 pub kind: AnyValueKind<'static>,
64}
65
66#[derive(Clone, Debug)]
67pub struct AnyValueRef<'a> {
68 pub(crate) kind: AnyValueKind<'a>,
69}
70
71impl Value for AnyValue {
72 type Database = Any;
73
74 fn as_ref(&self) -> <Self::Database as Database>::ValueRef<'_> {
75 AnyValueRef {
76 kind: match &self.kind {
77 AnyValueKind::Null(k) => AnyValueKind::Null(*k),
78 AnyValueKind::Bool(b) => AnyValueKind::Bool(*b),
79 AnyValueKind::SmallInt(i) => AnyValueKind::SmallInt(*i),
80 AnyValueKind::Integer(i) => AnyValueKind::Integer(*i),
81 AnyValueKind::BigInt(i) => AnyValueKind::BigInt(*i),
82 AnyValueKind::Real(r) => AnyValueKind::Real(*r),
83 AnyValueKind::Double(d) => AnyValueKind::Double(*d),
84 AnyValueKind::Text(t) => AnyValueKind::Text(Cow::Borrowed(t)),
85 AnyValueKind::Blob(b) => AnyValueKind::Blob(Cow::Borrowed(b)),
86 },
87 }
88 }
89
90 fn type_info(&self) -> Cow<'_, <Self::Database as Database>::TypeInfo> {
91 Cow::Owned(self.kind.type_info())
92 }
93
94 fn is_null(&self) -> bool {
95 matches!(self.kind, AnyValueKind::Null(_))
96 }
97}
98
99impl<'a> ValueRef<'a> for AnyValueRef<'a> {
100 type Database = Any;
101
102 fn to_owned(&self) -> <Self::Database as Database>::Value {
103 AnyValue {
104 kind: match &self.kind {
105 AnyValueKind::Null(k) => AnyValueKind::Null(*k),
106 AnyValueKind::Bool(b) => AnyValueKind::Bool(*b),
107 AnyValueKind::SmallInt(i) => AnyValueKind::SmallInt(*i),
108 AnyValueKind::Integer(i) => AnyValueKind::Integer(*i),
109 AnyValueKind::BigInt(i) => AnyValueKind::BigInt(*i),
110 AnyValueKind::Real(r) => AnyValueKind::Real(*r),
111 AnyValueKind::Double(d) => AnyValueKind::Double(*d),
112 AnyValueKind::Text(t) => AnyValueKind::Text(Cow::Owned(t.to_string())),
113 AnyValueKind::Blob(b) => AnyValueKind::Blob(Cow::Owned(b.to_vec())),
114 },
115 }
116 }
117
118 fn type_info(&self) -> Cow<'_, <Self::Database as Database>::TypeInfo> {
119 Cow::Owned(self.kind.type_info())
120 }
121
122 fn is_null(&self) -> bool {
123 matches!(self.kind, AnyValueKind::Null(_))
124 }
125}