1use std::cmp::Ordering;
16use std::collections::BTreeMap;
17use std::fmt::{Display, Formatter};
18use std::hash::{Hash, Hasher};
19use uuid::Uuid;
20
21use crate::{LogicalType, Vector, VectorRef};
22
23#[derive(Debug, Clone)]
24pub enum Value {
25 Null,
26 Bool(bool),
27 Int(i64),
28 Float(f64),
29 String(String),
30 Binary(Vec<u8>),
31 Vector(Vector),
32 Uuid(Uuid),
33 List(Vec<Value>),
34 Map(BTreeMap<String, Value>),
35}
36
37#[derive(Debug, Clone, Copy)]
43pub enum ValueRef<'a> {
44 Null,
45 Bool(bool),
46 Int(i64),
47 Float(f64),
48 String(&'a str),
49 Binary(&'a [u8]),
50 Vector(VectorRef<'a>),
51 Uuid(Uuid),
52 List(&'a [Value]),
53 Map(&'a BTreeMap<String, Value>),
54}
55
56impl PartialEq for Value {
57 fn eq(&self, other: &Self) -> bool {
58 self.cmp(other) == Ordering::Equal
59 }
60}
61
62impl Eq for Value {}
63
64impl PartialOrd for Value {
65 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
66 Some(self.cmp(other))
67 }
68}
69
70impl Ord for Value {
71 fn cmp(&self, other: &Self) -> Ordering {
72 self.kind_rank()
73 .cmp(&other.kind_rank())
74 .then_with(|| match (self, other) {
75 (Value::Null, Value::Null) => Ordering::Equal,
76 (Value::Bool(left), Value::Bool(right)) => left.cmp(right),
77 (Value::Int(left), Value::Int(right)) => left.cmp(right),
78 (Value::Float(left), Value::Float(right)) => left.total_cmp(right),
79 (Value::String(left), Value::String(right)) => left.cmp(right),
80 (Value::Binary(left), Value::Binary(right)) => left.cmp(right),
81 (Value::Vector(left), Value::Vector(right)) => left.cmp(right),
82 (Value::Uuid(left), Value::Uuid(right)) => left.cmp(right),
83 (Value::List(left), Value::List(right)) => left.cmp(right),
84 (Value::Map(left), Value::Map(right)) => left.cmp(right),
85 _ => Ordering::Equal,
86 })
87 }
88}
89
90impl Hash for Value {
91 fn hash<H: Hasher>(&self, state: &mut H) {
92 self.kind_rank().hash(state);
93 match self {
94 Value::Null => {}
95 Value::Bool(value) => value.hash(state),
96 Value::Int(value) => value.hash(state),
97 Value::Float(value) => value.to_bits().hash(state),
98 Value::String(value) => value.hash(state),
99 Value::Binary(value) => value.hash(state),
100 Value::Vector(value) => value.hash(state),
101 Value::Uuid(value) => value.hash(state),
102 Value::List(values) => values.hash(state),
103 Value::Map(values) => values.hash(state),
104 }
105 }
106}
107
108impl Value {
109 pub fn as_ref(&self) -> ValueRef<'_> {
110 self.into()
111 }
112
113 pub fn logical_type(&self) -> Option<LogicalType> {
114 self.as_ref().logical_type()
115 }
116
117 fn kind_rank(&self) -> u8 {
118 match self {
119 Value::Null => 0,
120 Value::Bool(_) => 1,
121 Value::Int(_) => 2,
122 Value::Float(_) => 3,
123 Value::String(_) => 4,
124 Value::Binary(_) => 5,
125 Value::Vector(_) => 9,
126 Value::Uuid(_) => 6,
127 Value::List(_) => 7,
128 Value::Map(_) => 8,
129 }
130 }
131}
132
133impl<'a> ValueRef<'a> {
134 pub const fn is_null(self) -> bool {
135 matches!(self, Self::Null)
136 }
137
138 pub const fn logical_type(self) -> Option<LogicalType> {
139 match self {
140 Self::Null => None,
141 Self::Bool(_) => Some(LogicalType::Boolean),
142 Self::Int(_) => Some(LogicalType::Int64),
143 Self::Float(_) => Some(LogicalType::Float64),
144 Self::String(_) => Some(LogicalType::String),
145 Self::Binary(_) => Some(LogicalType::Binary),
146 Self::Vector(value) => Some(LogicalType::Vector(value.dimension())),
147 Self::Uuid(_) => Some(LogicalType::Uuid),
148 Self::List(_) => Some(LogicalType::List),
149 Self::Map(_) => Some(LogicalType::Map),
150 }
151 }
152
153 pub const fn as_bool(self) -> Option<bool> {
154 match self {
155 Self::Bool(value) => Some(value),
156 _ => None,
157 }
158 }
159
160 pub const fn as_i64(self) -> Option<i64> {
161 match self {
162 Self::Int(value) => Some(value),
163 _ => None,
164 }
165 }
166
167 pub const fn as_f64(self) -> Option<f64> {
168 match self {
169 Self::Float(value) => Some(value),
170 _ => None,
171 }
172 }
173
174 pub const fn as_str(self) -> Option<&'a str> {
175 match self {
176 Self::String(value) => Some(value),
177 _ => None,
178 }
179 }
180
181 pub const fn as_binary(self) -> Option<&'a [u8]> {
182 match self {
183 Self::Binary(value) => Some(value),
184 _ => None,
185 }
186 }
187
188 pub const fn as_uuid(self) -> Option<Uuid> {
189 match self {
190 Self::Uuid(value) => Some(value),
191 _ => None,
192 }
193 }
194
195 pub const fn as_list(self) -> Option<&'a [Value]> {
196 match self {
197 Self::List(value) => Some(value),
198 _ => None,
199 }
200 }
201
202 pub const fn as_map(self) -> Option<&'a BTreeMap<String, Value>> {
203 match self {
204 Self::Map(value) => Some(value),
205 _ => None,
206 }
207 }
208
209 pub fn to_owned_value(self) -> Value {
210 match self {
211 Self::Null => Value::Null,
212 Self::Bool(value) => Value::Bool(value),
213 Self::Int(value) => Value::Int(value),
214 Self::Float(value) => Value::Float(value),
215 Self::String(value) => Value::String(value.to_owned()),
216 Self::Binary(value) => Value::Binary(value.to_vec()),
217 Self::Vector(value) => Value::Vector(value.to_owned()),
218 Self::Uuid(value) => Value::Uuid(value),
219 Self::List(value) => Value::List(value.to_vec()),
220 Self::Map(value) => Value::Map(value.clone()),
221 }
222 }
223
224 const fn kind_rank(self) -> u8 {
225 match self {
226 Self::Null => 0,
227 Self::Bool(_) => 1,
228 Self::Int(_) => 2,
229 Self::Float(_) => 3,
230 Self::String(_) => 4,
231 Self::Binary(_) => 5,
232 Self::Vector(_) => 9,
233 Self::Uuid(_) => 6,
234 Self::List(_) => 7,
235 Self::Map(_) => 8,
236 }
237 }
238}
239
240impl<'a> From<&'a Value> for ValueRef<'a> {
241 fn from(value: &'a Value) -> Self {
242 match value {
243 Value::Null => Self::Null,
244 Value::Bool(value) => Self::Bool(*value),
245 Value::Int(value) => Self::Int(*value),
246 Value::Float(value) => Self::Float(*value),
247 Value::String(value) => Self::String(value),
248 Value::Binary(value) => Self::Binary(value),
249 Value::Vector(value) => Self::Vector(value.as_ref()),
250 Value::Uuid(value) => Self::Uuid(*value),
251 Value::List(value) => Self::List(value),
252 Value::Map(value) => Self::Map(value),
253 }
254 }
255}
256
257impl PartialEq for ValueRef<'_> {
258 fn eq(&self, other: &Self) -> bool {
259 self.cmp(other) == Ordering::Equal
260 }
261}
262
263impl Eq for ValueRef<'_> {}
264
265impl PartialOrd for ValueRef<'_> {
266 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
267 Some(self.cmp(other))
268 }
269}
270
271impl Ord for ValueRef<'_> {
272 fn cmp(&self, other: &Self) -> Ordering {
273 self.kind_rank()
274 .cmp(&other.kind_rank())
275 .then_with(|| match (self, other) {
276 (Self::Null, Self::Null) => Ordering::Equal,
277 (Self::Bool(left), Self::Bool(right)) => left.cmp(right),
278 (Self::Int(left), Self::Int(right)) => left.cmp(right),
279 (Self::Float(left), Self::Float(right)) => left.total_cmp(right),
280 (Self::String(left), Self::String(right)) => left.cmp(right),
281 (Self::Binary(left), Self::Binary(right)) => left.cmp(right),
282 (Self::Vector(left), Self::Vector(right)) => left.cmp(right),
283 (Self::Uuid(left), Self::Uuid(right)) => left.cmp(right),
284 (Self::List(left), Self::List(right)) => left.cmp(right),
285 (Self::Map(left), Self::Map(right)) => left.cmp(right),
286 _ => Ordering::Equal,
287 })
288 }
289}
290
291impl Hash for ValueRef<'_> {
292 fn hash<H: Hasher>(&self, state: &mut H) {
293 self.kind_rank().hash(state);
294 match self {
295 Self::Null => {}
296 Self::Bool(value) => value.hash(state),
297 Self::Int(value) => value.hash(state),
298 Self::Float(value) => value.to_bits().hash(state),
299 Self::String(value) => value.hash(state),
300 Self::Binary(value) => value.hash(state),
301 Self::Vector(value) => value.hash(state),
302 Self::Uuid(value) => value.hash(state),
303 Self::List(value) => value.hash(state),
304 Self::Map(value) => value.hash(state),
305 }
306 }
307}
308
309impl PartialEq<Value> for ValueRef<'_> {
310 fn eq(&self, other: &Value) -> bool {
311 *self == other.as_ref()
312 }
313}
314
315impl PartialEq<&Value> for ValueRef<'_> {
316 fn eq(&self, other: &&Value) -> bool {
317 *self == other.as_ref()
318 }
319}
320
321impl PartialEq<ValueRef<'_>> for Value {
322 fn eq(&self, other: &ValueRef<'_>) -> bool {
323 self.as_ref() == *other
324 }
325}
326
327impl PartialEq<ValueRef<'_>> for &Value {
328 fn eq(&self, other: &ValueRef<'_>) -> bool {
329 self.as_ref() == *other
330 }
331}
332
333impl Display for ValueRef<'_> {
334 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
335 match self {
336 Self::Null => write!(f, "null"),
337 Self::Bool(value) => write!(f, "{value}"),
338 Self::Int(value) => write!(f, "{value}"),
339 Self::Float(value) => write!(f, "{value}"),
340 Self::String(value) => write!(f, "{value}"),
341 Self::Binary(value) => write_binary(f, value),
342 Self::Vector(value) => {
343 f.write_str("VECTOR")?;
344 f.debug_list().entries(value.coordinates()).finish()
345 }
346 Self::Uuid(value) => write!(f, "{value}"),
347 Self::List(values) => {
348 let values = values
349 .iter()
350 .map(ToString::to_string)
351 .collect::<Vec<_>>()
352 .join(", ");
353 write!(f, "[{values}]")
354 }
355 Self::Map(values) => {
356 let values = values
357 .iter()
358 .map(|(key, value)| format!("{key}: {value}"))
359 .collect::<Vec<_>>()
360 .join(", ");
361 write!(f, "{{{values}}}")
362 }
363 }
364 }
365}
366
367impl Display for Value {
368 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
369 match self {
370 Value::Null => write!(f, "null"),
371 Value::Bool(value) => write!(f, "{value}"),
372 Value::Int(value) => write!(f, "{value}"),
373 Value::Float(value) => write!(f, "{value}"),
374 Value::String(value) => write!(f, "{value}"),
375 Value::Binary(value) => write_binary(f, value),
376 Value::Vector(value) => ValueRef::Vector(value.as_ref()).fmt(f),
377 Value::Uuid(value) => write!(f, "{value}"),
378 Value::List(values) => {
379 let values = values
380 .iter()
381 .map(ToString::to_string)
382 .collect::<Vec<_>>()
383 .join(", ");
384 write!(f, "[{values}]")
385 }
386 Value::Map(values) => {
387 let values = values
388 .iter()
389 .map(|(key, value)| format!("{key}: {value}"))
390 .collect::<Vec<_>>()
391 .join(", ");
392 write!(f, "{{{values}}}")
393 }
394 }
395 }
396}
397
398fn write_binary(f: &mut Formatter<'_>, value: &[u8]) -> std::fmt::Result {
399 f.write_str("\\x")?;
400 for byte in value {
401 write!(f, "{byte:02x}")?;
402 }
403 Ok(())
404}
405
406#[cfg(test)]
407mod tests {
408 use super::*;
409
410 #[test]
411 fn value_ref_borrows_variable_width_payloads() {
412 let value = Value::String("borrowed payload".to_string());
413 let reference = value.as_ref();
414
415 assert_eq!(reference.as_str(), Some("borrowed payload"));
416 let Value::String(owned) = &value else {
417 unreachable!();
418 };
419 assert_eq!(reference.as_str().unwrap().as_ptr(), owned.as_ptr());
420 assert_eq!(reference.to_owned_value(), value);
421 }
422
423 #[test]
424 fn value_ref_preserves_owned_value_order_and_hash_semantics() {
425 let values = [
426 Value::Null,
427 Value::Bool(true),
428 Value::Int(1),
429 Value::Float(f64::NAN),
430 Value::String("value".into()),
431 Value::Binary(vec![0, 0xff]),
432 Value::Vector(Vector::new(&[0.0, -0.0]).unwrap()),
433 Value::Vector(Vector::new(&[-0.0, 0.0]).unwrap()),
434 Value::Vector(Vector::new(&[1.0]).unwrap()),
435 Value::List(vec![Value::Int(2)]),
436 Value::Map(BTreeMap::from([("key".into(), Value::Int(3))])),
437 ];
438
439 for left in &values {
440 use std::hash::BuildHasher;
441 let state = std::collections::hash_map::RandomState::new();
442 assert_eq!(state.hash_one(left), state.hash_one(left.as_ref()));
443 for right in &values {
444 assert_eq!(left.cmp(right), left.as_ref().cmp(&right.as_ref()));
445 assert_eq!(left == right, left.as_ref() == *right);
446 }
447 }
448 }
449
450 #[test]
451 fn null_has_no_intrinsic_logical_type() {
452 assert_eq!(Value::Null.logical_type(), None);
453 assert_eq!(Value::Int(42).logical_type(), Some(LogicalType::Int64));
454 assert_eq!(
455 Value::Binary(vec![0, 0xff]).logical_type(),
456 Some(LogicalType::Binary)
457 );
458 }
459
460 #[test]
461 fn binary_value_ref_borrows_and_formats_postgres_hex() {
462 let value = Value::Binary(vec![0, 1, 0xfe, 0xff]);
463 let reference = value.as_ref();
464
465 assert_eq!(reference.as_binary(), Some(&[0, 1, 0xfe, 0xff][..]));
466 let Value::Binary(owned) = &value else {
467 unreachable!();
468 };
469 assert_eq!(reference.as_binary().unwrap().as_ptr(), owned.as_ptr());
470 assert_eq!(reference.to_owned_value(), value);
471 assert_eq!(value.to_string(), "\\x0001feff");
472 }
473}