1use serde::{Deserialize, Serialize};
8use std::collections::BTreeMap;
9use std::fmt;
10use std::hash::{Hash, Hasher};
11use std::sync::Arc;
12
13use super::Timestamp;
14
15#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
20pub struct PropertyKey(Arc<str>);
21
22impl PropertyKey {
23 #[must_use]
25 pub fn new(s: impl Into<Arc<str>>) -> Self {
26 Self(s.into())
27 }
28
29 #[must_use]
31 pub fn as_str(&self) -> &str {
32 &self.0
33 }
34}
35
36impl fmt::Debug for PropertyKey {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 write!(f, "PropertyKey({:?})", self.0)
39 }
40}
41
42impl fmt::Display for PropertyKey {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 write!(f, "{}", self.0)
45 }
46}
47
48impl From<&str> for PropertyKey {
49 fn from(s: &str) -> Self {
50 Self::new(s)
51 }
52}
53
54impl From<String> for PropertyKey {
55 fn from(s: String) -> Self {
56 Self::new(s)
57 }
58}
59
60impl AsRef<str> for PropertyKey {
61 fn as_ref(&self) -> &str {
62 &self.0
63 }
64}
65
66#[derive(Clone, PartialEq, Serialize, Deserialize)]
86pub enum Value {
87 Null,
89
90 Bool(bool),
92
93 Int64(i64),
95
96 Float64(f64),
98
99 String(Arc<str>),
101
102 Bytes(Arc<[u8]>),
104
105 Timestamp(Timestamp),
107
108 List(Arc<[Value]>),
110
111 Map(Arc<BTreeMap<PropertyKey, Value>>),
113}
114
115impl Value {
116 #[inline]
118 #[must_use]
119 pub const fn is_null(&self) -> bool {
120 matches!(self, Value::Null)
121 }
122
123 #[inline]
125 #[must_use]
126 pub const fn as_bool(&self) -> Option<bool> {
127 match self {
128 Value::Bool(b) => Some(*b),
129 _ => None,
130 }
131 }
132
133 #[inline]
135 #[must_use]
136 pub const fn as_int64(&self) -> Option<i64> {
137 match self {
138 Value::Int64(i) => Some(*i),
139 _ => None,
140 }
141 }
142
143 #[inline]
145 #[must_use]
146 pub const fn as_float64(&self) -> Option<f64> {
147 match self {
148 Value::Float64(f) => Some(*f),
149 _ => None,
150 }
151 }
152
153 #[inline]
155 #[must_use]
156 pub fn as_str(&self) -> Option<&str> {
157 match self {
158 Value::String(s) => Some(s),
159 _ => None,
160 }
161 }
162
163 #[inline]
165 #[must_use]
166 pub fn as_bytes(&self) -> Option<&[u8]> {
167 match self {
168 Value::Bytes(b) => Some(b),
169 _ => None,
170 }
171 }
172
173 #[inline]
175 #[must_use]
176 pub const fn as_timestamp(&self) -> Option<Timestamp> {
177 match self {
178 Value::Timestamp(t) => Some(*t),
179 _ => None,
180 }
181 }
182
183 #[inline]
185 #[must_use]
186 pub fn as_list(&self) -> Option<&[Value]> {
187 match self {
188 Value::List(l) => Some(l),
189 _ => None,
190 }
191 }
192
193 #[inline]
195 #[must_use]
196 pub fn as_map(&self) -> Option<&BTreeMap<PropertyKey, Value>> {
197 match self {
198 Value::Map(m) => Some(m),
199 _ => None,
200 }
201 }
202
203 #[must_use]
205 pub const fn type_name(&self) -> &'static str {
206 match self {
207 Value::Null => "NULL",
208 Value::Bool(_) => "BOOL",
209 Value::Int64(_) => "INT64",
210 Value::Float64(_) => "FLOAT64",
211 Value::String(_) => "STRING",
212 Value::Bytes(_) => "BYTES",
213 Value::Timestamp(_) => "TIMESTAMP",
214 Value::List(_) => "LIST",
215 Value::Map(_) => "MAP",
216 }
217 }
218
219 #[must_use]
221 pub fn serialize(&self) -> Vec<u8> {
222 bincode::serde::encode_to_vec(self, bincode::config::standard())
223 .expect("Value serialization should not fail")
224 }
225
226 pub fn deserialize(bytes: &[u8]) -> Result<Self, bincode::error::DecodeError> {
232 let (value, _) = bincode::serde::decode_from_slice(bytes, bincode::config::standard())?;
233 Ok(value)
234 }
235}
236
237impl fmt::Debug for Value {
238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 match self {
240 Value::Null => write!(f, "Null"),
241 Value::Bool(b) => write!(f, "Bool({b})"),
242 Value::Int64(i) => write!(f, "Int64({i})"),
243 Value::Float64(fl) => write!(f, "Float64({fl})"),
244 Value::String(s) => write!(f, "String({s:?})"),
245 Value::Bytes(b) => write!(f, "Bytes([{}; {} bytes])", b.first().unwrap_or(&0), b.len()),
246 Value::Timestamp(t) => write!(f, "Timestamp({t:?})"),
247 Value::List(l) => write!(f, "List({l:?})"),
248 Value::Map(m) => write!(f, "Map({m:?})"),
249 }
250 }
251}
252
253impl fmt::Display for Value {
254 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255 match self {
256 Value::Null => write!(f, "NULL"),
257 Value::Bool(b) => write!(f, "{b}"),
258 Value::Int64(i) => write!(f, "{i}"),
259 Value::Float64(fl) => write!(f, "{fl}"),
260 Value::String(s) => write!(f, "{s:?}"),
261 Value::Bytes(b) => write!(f, "<bytes: {} bytes>", b.len()),
262 Value::Timestamp(t) => write!(f, "{t}"),
263 Value::List(l) => {
264 write!(f, "[")?;
265 for (i, v) in l.iter().enumerate() {
266 if i > 0 {
267 write!(f, ", ")?;
268 }
269 write!(f, "{v}")?;
270 }
271 write!(f, "]")
272 }
273 Value::Map(m) => {
274 write!(f, "{{")?;
275 for (i, (k, v)) in m.iter().enumerate() {
276 if i > 0 {
277 write!(f, ", ")?;
278 }
279 write!(f, "{k}: {v}")?;
280 }
281 write!(f, "}}")
282 }
283 }
284 }
285}
286
287impl From<bool> for Value {
289 fn from(b: bool) -> Self {
290 Value::Bool(b)
291 }
292}
293
294impl From<i64> for Value {
295 fn from(i: i64) -> Self {
296 Value::Int64(i)
297 }
298}
299
300impl From<i32> for Value {
301 fn from(i: i32) -> Self {
302 Value::Int64(i64::from(i))
303 }
304}
305
306impl From<f64> for Value {
307 fn from(f: f64) -> Self {
308 Value::Float64(f)
309 }
310}
311
312impl From<f32> for Value {
313 fn from(f: f32) -> Self {
314 Value::Float64(f64::from(f))
315 }
316}
317
318impl From<&str> for Value {
319 fn from(s: &str) -> Self {
320 Value::String(s.into())
321 }
322}
323
324impl From<String> for Value {
325 fn from(s: String) -> Self {
326 Value::String(s.into())
327 }
328}
329
330impl From<Arc<str>> for Value {
331 fn from(s: Arc<str>) -> Self {
332 Value::String(s)
333 }
334}
335
336impl From<Vec<u8>> for Value {
337 fn from(b: Vec<u8>) -> Self {
338 Value::Bytes(b.into())
339 }
340}
341
342impl From<&[u8]> for Value {
343 fn from(b: &[u8]) -> Self {
344 Value::Bytes(b.into())
345 }
346}
347
348impl From<Timestamp> for Value {
349 fn from(t: Timestamp) -> Self {
350 Value::Timestamp(t)
351 }
352}
353
354impl<T: Into<Value>> From<Vec<T>> for Value {
355 fn from(v: Vec<T>) -> Self {
356 Value::List(v.into_iter().map(Into::into).collect())
357 }
358}
359
360impl<T: Into<Value>> From<Option<T>> for Value {
361 fn from(opt: Option<T>) -> Self {
362 match opt {
363 Some(v) => v.into(),
364 None => Value::Null,
365 }
366 }
367}
368
369#[derive(Clone, Debug)]
381pub struct HashableValue(pub Value);
382
383impl HashableValue {
384 #[must_use]
386 pub fn new(value: Value) -> Self {
387 Self(value)
388 }
389
390 #[must_use]
392 pub fn inner(&self) -> &Value {
393 &self.0
394 }
395
396 #[must_use]
398 pub fn into_inner(self) -> Value {
399 self.0
400 }
401}
402
403impl Hash for HashableValue {
404 fn hash<H: Hasher>(&self, state: &mut H) {
405 std::mem::discriminant(&self.0).hash(state);
407
408 match &self.0 {
409 Value::Null => {}
410 Value::Bool(b) => b.hash(state),
411 Value::Int64(i) => i.hash(state),
412 Value::Float64(f) => {
413 f.to_bits().hash(state);
415 }
416 Value::String(s) => s.hash(state),
417 Value::Bytes(b) => b.hash(state),
418 Value::Timestamp(t) => t.hash(state),
419 Value::List(l) => {
420 l.len().hash(state);
421 for v in l.iter() {
422 HashableValue(v.clone()).hash(state);
423 }
424 }
425 Value::Map(m) => {
426 m.len().hash(state);
427 for (k, v) in m.iter() {
428 k.hash(state);
429 HashableValue(v.clone()).hash(state);
430 }
431 }
432 }
433 }
434}
435
436impl PartialEq for HashableValue {
437 fn eq(&self, other: &Self) -> bool {
438 match (&self.0, &other.0) {
439 (Value::Float64(a), Value::Float64(b)) => {
440 a.to_bits() == b.to_bits()
442 }
443 (Value::List(a), Value::List(b)) => {
444 if a.len() != b.len() {
445 return false;
446 }
447 a.iter()
448 .zip(b.iter())
449 .all(|(x, y)| HashableValue(x.clone()) == HashableValue(y.clone()))
450 }
451 (Value::Map(a), Value::Map(b)) => {
452 if a.len() != b.len() {
453 return false;
454 }
455 a.iter().all(|(k, v)| {
456 b.get(k)
457 .is_some_and(|bv| HashableValue(v.clone()) == HashableValue(bv.clone()))
458 })
459 }
460 _ => self.0 == other.0,
462 }
463 }
464}
465
466impl Eq for HashableValue {}
467
468impl From<Value> for HashableValue {
469 fn from(value: Value) -> Self {
470 Self(value)
471 }
472}
473
474impl From<HashableValue> for Value {
475 fn from(hv: HashableValue) -> Self {
476 hv.0
477 }
478}
479
480#[cfg(test)]
481mod tests {
482 use super::*;
483
484 #[test]
485 fn test_value_type_checks() {
486 assert!(Value::Null.is_null());
487 assert!(!Value::Bool(true).is_null());
488
489 assert_eq!(Value::Bool(true).as_bool(), Some(true));
490 assert_eq!(Value::Bool(false).as_bool(), Some(false));
491 assert_eq!(Value::Int64(42).as_bool(), None);
492
493 assert_eq!(Value::Int64(42).as_int64(), Some(42));
494 assert_eq!(Value::String("test".into()).as_int64(), None);
495
496 assert_eq!(Value::Float64(1.234).as_float64(), Some(1.234));
497 assert_eq!(Value::String("hello".into()).as_str(), Some("hello"));
498 }
499
500 #[test]
501 fn test_value_from_conversions() {
502 let v: Value = true.into();
503 assert_eq!(v.as_bool(), Some(true));
504
505 let v: Value = 42i64.into();
506 assert_eq!(v.as_int64(), Some(42));
507
508 let v: Value = 1.234f64.into();
509 assert_eq!(v.as_float64(), Some(1.234));
510
511 let v: Value = "hello".into();
512 assert_eq!(v.as_str(), Some("hello"));
513
514 let v: Value = vec![1u8, 2, 3].into();
515 assert_eq!(v.as_bytes(), Some(&[1u8, 2, 3][..]));
516 }
517
518 #[test]
519 fn test_value_serialization_roundtrip() {
520 let values = vec![
521 Value::Null,
522 Value::Bool(true),
523 Value::Int64(i64::MAX),
524 Value::Float64(std::f64::consts::PI),
525 Value::String("hello world".into()),
526 Value::Bytes(vec![0, 1, 2, 255].into()),
527 Value::List(vec![Value::Int64(1), Value::Int64(2)].into()),
528 ];
529
530 for v in values {
531 let bytes = v.serialize();
532 let decoded = Value::deserialize(&bytes).unwrap();
533 assert_eq!(v, decoded);
534 }
535 }
536
537 #[test]
538 fn test_property_key() {
539 let key = PropertyKey::new("name");
540 assert_eq!(key.as_str(), "name");
541
542 let key2: PropertyKey = "age".into();
543 assert_eq!(key2.as_str(), "age");
544
545 assert!(key2 < key);
547 }
548
549 #[test]
550 fn test_value_type_name() {
551 assert_eq!(Value::Null.type_name(), "NULL");
552 assert_eq!(Value::Bool(true).type_name(), "BOOL");
553 assert_eq!(Value::Int64(0).type_name(), "INT64");
554 assert_eq!(Value::Float64(0.0).type_name(), "FLOAT64");
555 assert_eq!(Value::String("".into()).type_name(), "STRING");
556 assert_eq!(Value::Bytes(vec![].into()).type_name(), "BYTES");
557 assert_eq!(Value::List(vec![].into()).type_name(), "LIST");
558 assert_eq!(Value::Map(BTreeMap::new().into()).type_name(), "MAP");
559 }
560
561 #[test]
562 fn test_hashable_value_basic() {
563 use std::collections::HashMap;
564
565 let mut map: HashMap<HashableValue, i32> = HashMap::new();
566
567 map.insert(HashableValue::new(Value::Int64(42)), 1);
569 map.insert(HashableValue::new(Value::String("test".into())), 2);
570 map.insert(HashableValue::new(Value::Bool(true)), 3);
571 map.insert(HashableValue::new(Value::Float64(3.14)), 4);
572
573 assert_eq!(map.get(&HashableValue::new(Value::Int64(42))), Some(&1));
574 assert_eq!(
575 map.get(&HashableValue::new(Value::String("test".into()))),
576 Some(&2)
577 );
578 assert_eq!(map.get(&HashableValue::new(Value::Bool(true))), Some(&3));
579 assert_eq!(map.get(&HashableValue::new(Value::Float64(3.14))), Some(&4));
580 }
581
582 #[test]
583 fn test_hashable_value_float_edge_cases() {
584 use std::collections::HashMap;
585
586 let mut map: HashMap<HashableValue, i32> = HashMap::new();
587
588 let nan = f64::NAN;
590 map.insert(HashableValue::new(Value::Float64(nan)), 1);
591 assert_eq!(map.get(&HashableValue::new(Value::Float64(nan))), Some(&1));
592
593 let pos_zero = 0.0f64;
595 let neg_zero = -0.0f64;
596 map.insert(HashableValue::new(Value::Float64(pos_zero)), 2);
597 map.insert(HashableValue::new(Value::Float64(neg_zero)), 3);
598 assert_eq!(
599 map.get(&HashableValue::new(Value::Float64(pos_zero))),
600 Some(&2)
601 );
602 assert_eq!(
603 map.get(&HashableValue::new(Value::Float64(neg_zero))),
604 Some(&3)
605 );
606 }
607
608 #[test]
609 fn test_hashable_value_equality() {
610 let v1 = HashableValue::new(Value::Int64(42));
611 let v2 = HashableValue::new(Value::Int64(42));
612 let v3 = HashableValue::new(Value::Int64(43));
613
614 assert_eq!(v1, v2);
615 assert_ne!(v1, v3);
616 }
617
618 #[test]
619 fn test_hashable_value_inner() {
620 let hv = HashableValue::new(Value::String("hello".into()));
621 assert_eq!(hv.inner().as_str(), Some("hello"));
622
623 let v = hv.into_inner();
624 assert_eq!(v.as_str(), Some("hello"));
625 }
626
627 #[test]
628 fn test_hashable_value_conversions() {
629 let v = Value::Int64(42);
630 let hv: HashableValue = v.clone().into();
631 let v2: Value = hv.into();
632 assert_eq!(v, v2);
633 }
634}