surrealdb_types/kind/
literal.rs1use std::collections::BTreeMap;
2use std::hash;
3
4use rust_decimal::Decimal;
5use serde::{Deserialize, Serialize};
6
7use crate::sql::fmt_sql_comma_separated;
8use crate::utils::escape::QuoteStr;
9use crate::{Duration, Kind, SqlFormat, ToSql, Value};
10
11#[derive(Clone, Debug, Serialize, Deserialize)]
17pub enum KindLiteral {
18 String(String),
20 Integer(i64),
22 Float(f64),
24 Decimal(Decimal),
26 Duration(Duration),
28 Array(Vec<Kind>),
30 Object(BTreeMap<String, Kind>),
32 Bool(bool),
34}
35
36impl KindLiteral {
37 pub fn matches(&self, value: &Value) -> bool {
39 match self {
40 KindLiteral::String(s) => {
41 if let Value::String(v) = value {
42 s == v
43 } else {
44 false
45 }
46 }
47 KindLiteral::Integer(i) => {
48 if let Value::Number(crate::Number::Int(v)) = value {
49 i == v
50 } else {
51 false
52 }
53 }
54 KindLiteral::Float(f) => {
55 if let Value::Number(crate::Number::Float(v)) = value {
56 f.to_bits() == v.to_bits()
57 } else {
58 false
59 }
60 }
61 KindLiteral::Decimal(d) => {
62 if let Value::Number(crate::Number::Decimal(v)) = value {
63 d == v
64 } else {
65 false
66 }
67 }
68 KindLiteral::Duration(d) => {
69 if let Value::Duration(v) = value {
70 d == v
71 } else {
72 false
73 }
74 }
75 KindLiteral::Array(kinds) => {
76 if let Value::Array(arr) = value {
77 if kinds.len() != arr.len() {
78 return false;
79 }
80 kinds.iter().zip(arr.iter()).all(|(kind, val)| val.is_kind(kind))
81 } else {
82 false
83 }
84 }
85 KindLiteral::Object(kinds) => {
86 if let Value::Object(obj) = value {
87 if kinds.len() != obj.len() {
88 return false;
89 }
90 kinds.iter().all(|(key, kind)| {
91 obj.get(key).map(|val| val.is_kind(kind)).unwrap_or(false)
92 })
93 } else {
94 false
95 }
96 }
97 KindLiteral::Bool(b) => {
98 if let Value::Bool(v) = value {
99 b == v
100 } else {
101 false
102 }
103 }
104 }
105 }
106}
107
108impl Eq for KindLiteral {}
109impl PartialEq for KindLiteral {
110 fn eq(&self, other: &Self) -> bool {
111 match self {
112 KindLiteral::String(strand) => {
113 if let KindLiteral::String(other) = other {
114 strand == other
115 } else {
116 false
117 }
118 }
119 KindLiteral::Integer(x) => {
120 if let KindLiteral::Integer(other) = other {
121 x == other
122 } else {
123 false
124 }
125 }
126 KindLiteral::Float(x) => {
127 if let KindLiteral::Float(other) = other {
128 x.to_bits() == other.to_bits()
129 } else {
130 false
131 }
132 }
133 KindLiteral::Decimal(decimal) => {
134 if let KindLiteral::Decimal(other) = other {
135 decimal == other
136 } else {
137 false
138 }
139 }
140 KindLiteral::Duration(duration) => {
141 if let KindLiteral::Duration(other) = other {
142 duration == other
143 } else {
144 false
145 }
146 }
147 KindLiteral::Array(kinds) => {
148 if let KindLiteral::Array(other) = other {
149 kinds == other
150 } else {
151 false
152 }
153 }
154 KindLiteral::Object(btree_map) => {
155 if let KindLiteral::Object(other) = other {
156 btree_map == other
157 } else {
158 false
159 }
160 }
161 KindLiteral::Bool(a) => {
162 if let KindLiteral::Bool(b) = other {
163 a == b
164 } else {
165 false
166 }
167 }
168 }
169 }
170}
171
172impl hash::Hash for KindLiteral {
173 fn hash<H: hash::Hasher>(&self, state: &mut H) {
174 std::mem::discriminant(self).hash(state);
175 match self {
176 KindLiteral::String(strand) => strand.hash(state),
177 KindLiteral::Integer(x) => x.hash(state),
178 KindLiteral::Float(x) => x.to_bits().hash(state),
179 KindLiteral::Decimal(decimal) => decimal.hash(state),
180 KindLiteral::Duration(duration) => duration.hash(state),
181 KindLiteral::Array(kinds) => kinds.hash(state),
182 KindLiteral::Object(btree_map) => btree_map.hash(state),
183 KindLiteral::Bool(x) => x.hash(state),
184 }
185 }
186}
187
188impl ToSql for KindLiteral {
189 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
190 match self {
191 KindLiteral::String(string) => QuoteStr(string).fmt_sql(f, fmt),
192 KindLiteral::Integer(x) => x.fmt_sql(f, fmt),
193 KindLiteral::Float(v) => {
194 if v.is_finite() {
195 v.fmt_sql(f, fmt);
197 f.push('f');
198 } else {
199 v.fmt_sql(f, fmt);
201 }
202 }
203 KindLiteral::Decimal(v) => {
204 v.fmt_sql(f, fmt);
205 f.push_str("dec");
206 }
207 KindLiteral::Duration(duration) => duration.fmt_sql_internal(f),
208 KindLiteral::Array(kinds) => {
209 f.push('[');
210 fmt_sql_comma_separated(kinds, f, fmt);
211 f.push(']');
212 }
213 KindLiteral::Object(btree_map) => {
214 f.push('{');
215 let items = btree_map
216 .iter()
217 .map(|(k, v)| format!("{}: {}", k.to_sql(), v.to_sql()))
218 .collect::<Vec<String>>();
219 fmt_sql_comma_separated(&items, f, fmt);
220 f.push('}');
221 }
222 KindLiteral::Bool(x) => x.fmt_sql(f, fmt),
223 }
224 }
225}