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
383#[derive(Clone, Debug)]
415pub enum OrderableValue {
416 Int64(i64),
418 Float64(OrderedFloat64),
420 String(Arc<str>),
422 Bool(bool),
424 Timestamp(Timestamp),
426}
427
428#[derive(Clone, Copy, Debug)]
433pub struct OrderedFloat64(pub f64);
434
435impl OrderedFloat64 {
436 #[must_use]
438 pub const fn new(f: f64) -> Self {
439 Self(f)
440 }
441
442 #[must_use]
444 pub const fn get(&self) -> f64 {
445 self.0
446 }
447}
448
449impl PartialEq for OrderedFloat64 {
450 fn eq(&self, other: &Self) -> bool {
451 match (self.0.is_nan(), other.0.is_nan()) {
453 (true, true) => true,
454 (true, false) | (false, true) => false,
455 (false, false) => self.0 == other.0,
456 }
457 }
458}
459
460impl Eq for OrderedFloat64 {}
461
462impl PartialOrd for OrderedFloat64 {
463 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
464 Some(self.cmp(other))
465 }
466}
467
468impl Ord for OrderedFloat64 {
469 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
470 match (self.0.is_nan(), other.0.is_nan()) {
472 (true, true) => std::cmp::Ordering::Equal,
473 (true, false) => std::cmp::Ordering::Greater,
474 (false, true) => std::cmp::Ordering::Less,
475 (false, false) => {
476 self.0
478 .partial_cmp(&other.0)
479 .unwrap_or(std::cmp::Ordering::Equal)
480 }
481 }
482 }
483}
484
485impl Hash for OrderedFloat64 {
486 fn hash<H: Hasher>(&self, state: &mut H) {
487 self.0.to_bits().hash(state);
488 }
489}
490
491impl From<f64> for OrderedFloat64 {
492 fn from(f: f64) -> Self {
493 Self(f)
494 }
495}
496
497impl OrderableValue {
498 #[must_use]
503 pub fn try_from(value: &Value) -> Option<Self> {
504 match value {
505 Value::Int64(i) => Some(Self::Int64(*i)),
506 Value::Float64(f) => Some(Self::Float64(OrderedFloat64(*f))),
507 Value::String(s) => Some(Self::String(s.clone())),
508 Value::Bool(b) => Some(Self::Bool(*b)),
509 Value::Timestamp(t) => Some(Self::Timestamp(*t)),
510 Value::Null | Value::Bytes(_) | Value::List(_) | Value::Map(_) => None,
511 }
512 }
513
514 #[must_use]
516 pub fn into_value(self) -> Value {
517 match self {
518 Self::Int64(i) => Value::Int64(i),
519 Self::Float64(f) => Value::Float64(f.0),
520 Self::String(s) => Value::String(s),
521 Self::Bool(b) => Value::Bool(b),
522 Self::Timestamp(t) => Value::Timestamp(t),
523 }
524 }
525
526 #[must_use]
528 pub const fn as_i64(&self) -> Option<i64> {
529 match self {
530 Self::Int64(i) => Some(*i),
531 _ => None,
532 }
533 }
534
535 #[must_use]
537 pub const fn as_f64(&self) -> Option<f64> {
538 match self {
539 Self::Float64(f) => Some(f.0),
540 _ => None,
541 }
542 }
543
544 #[must_use]
546 pub fn as_str(&self) -> Option<&str> {
547 match self {
548 Self::String(s) => Some(s),
549 _ => None,
550 }
551 }
552}
553
554impl PartialEq for OrderableValue {
555 fn eq(&self, other: &Self) -> bool {
556 match (self, other) {
557 (Self::Int64(a), Self::Int64(b)) => a == b,
558 (Self::Float64(a), Self::Float64(b)) => a == b,
559 (Self::String(a), Self::String(b)) => a == b,
560 (Self::Bool(a), Self::Bool(b)) => a == b,
561 (Self::Timestamp(a), Self::Timestamp(b)) => a == b,
562 (Self::Int64(a), Self::Float64(b)) => (*a as f64) == b.0,
564 (Self::Float64(a), Self::Int64(b)) => a.0 == (*b as f64),
565 _ => false,
566 }
567 }
568}
569
570impl Eq for OrderableValue {}
571
572impl PartialOrd for OrderableValue {
573 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
574 Some(self.cmp(other))
575 }
576}
577
578impl Ord for OrderableValue {
579 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
580 match (self, other) {
581 (Self::Int64(a), Self::Int64(b)) => a.cmp(b),
582 (Self::Float64(a), Self::Float64(b)) => a.cmp(b),
583 (Self::String(a), Self::String(b)) => a.cmp(b),
584 (Self::Bool(a), Self::Bool(b)) => a.cmp(b),
585 (Self::Timestamp(a), Self::Timestamp(b)) => a.cmp(b),
586 (Self::Int64(a), Self::Float64(b)) => OrderedFloat64(*a as f64).cmp(b),
588 (Self::Float64(a), Self::Int64(b)) => a.cmp(&OrderedFloat64(*b as f64)),
589 _ => self.type_ordinal().cmp(&other.type_ordinal()),
592 }
593 }
594}
595
596impl OrderableValue {
597 const fn type_ordinal(&self) -> u8 {
599 match self {
600 Self::Bool(_) => 0,
601 Self::Int64(_) => 1,
602 Self::Float64(_) => 2,
603 Self::String(_) => 3,
604 Self::Timestamp(_) => 4,
605 }
606 }
607}
608
609impl Hash for OrderableValue {
610 fn hash<H: Hasher>(&self, state: &mut H) {
611 std::mem::discriminant(self).hash(state);
612 match self {
613 Self::Int64(i) => i.hash(state),
614 Self::Float64(f) => f.hash(state),
615 Self::String(s) => s.hash(state),
616 Self::Bool(b) => b.hash(state),
617 Self::Timestamp(t) => t.hash(state),
618 }
619 }
620}
621
622impl HashableValue {
623 #[must_use]
625 pub fn new(value: Value) -> Self {
626 Self(value)
627 }
628
629 #[must_use]
631 pub fn inner(&self) -> &Value {
632 &self.0
633 }
634
635 #[must_use]
637 pub fn into_inner(self) -> Value {
638 self.0
639 }
640}
641
642impl Hash for HashableValue {
643 fn hash<H: Hasher>(&self, state: &mut H) {
644 std::mem::discriminant(&self.0).hash(state);
646
647 match &self.0 {
648 Value::Null => {}
649 Value::Bool(b) => b.hash(state),
650 Value::Int64(i) => i.hash(state),
651 Value::Float64(f) => {
652 f.to_bits().hash(state);
654 }
655 Value::String(s) => s.hash(state),
656 Value::Bytes(b) => b.hash(state),
657 Value::Timestamp(t) => t.hash(state),
658 Value::List(l) => {
659 l.len().hash(state);
660 for v in l.iter() {
661 HashableValue(v.clone()).hash(state);
662 }
663 }
664 Value::Map(m) => {
665 m.len().hash(state);
666 for (k, v) in m.iter() {
667 k.hash(state);
668 HashableValue(v.clone()).hash(state);
669 }
670 }
671 }
672 }
673}
674
675impl PartialEq for HashableValue {
676 fn eq(&self, other: &Self) -> bool {
677 match (&self.0, &other.0) {
678 (Value::Float64(a), Value::Float64(b)) => {
679 a.to_bits() == b.to_bits()
681 }
682 (Value::List(a), Value::List(b)) => {
683 if a.len() != b.len() {
684 return false;
685 }
686 a.iter()
687 .zip(b.iter())
688 .all(|(x, y)| HashableValue(x.clone()) == HashableValue(y.clone()))
689 }
690 (Value::Map(a), Value::Map(b)) => {
691 if a.len() != b.len() {
692 return false;
693 }
694 a.iter().all(|(k, v)| {
695 b.get(k)
696 .is_some_and(|bv| HashableValue(v.clone()) == HashableValue(bv.clone()))
697 })
698 }
699 _ => self.0 == other.0,
701 }
702 }
703}
704
705impl Eq for HashableValue {}
706
707impl From<Value> for HashableValue {
708 fn from(value: Value) -> Self {
709 Self(value)
710 }
711}
712
713impl From<HashableValue> for Value {
714 fn from(hv: HashableValue) -> Self {
715 hv.0
716 }
717}
718
719#[cfg(test)]
720mod tests {
721 use super::*;
722
723 #[test]
724 fn test_value_type_checks() {
725 assert!(Value::Null.is_null());
726 assert!(!Value::Bool(true).is_null());
727
728 assert_eq!(Value::Bool(true).as_bool(), Some(true));
729 assert_eq!(Value::Bool(false).as_bool(), Some(false));
730 assert_eq!(Value::Int64(42).as_bool(), None);
731
732 assert_eq!(Value::Int64(42).as_int64(), Some(42));
733 assert_eq!(Value::String("test".into()).as_int64(), None);
734
735 assert_eq!(Value::Float64(1.234).as_float64(), Some(1.234));
736 assert_eq!(Value::String("hello".into()).as_str(), Some("hello"));
737 }
738
739 #[test]
740 fn test_value_from_conversions() {
741 let v: Value = true.into();
742 assert_eq!(v.as_bool(), Some(true));
743
744 let v: Value = 42i64.into();
745 assert_eq!(v.as_int64(), Some(42));
746
747 let v: Value = 1.234f64.into();
748 assert_eq!(v.as_float64(), Some(1.234));
749
750 let v: Value = "hello".into();
751 assert_eq!(v.as_str(), Some("hello"));
752
753 let v: Value = vec![1u8, 2, 3].into();
754 assert_eq!(v.as_bytes(), Some(&[1u8, 2, 3][..]));
755 }
756
757 #[test]
758 fn test_value_serialization_roundtrip() {
759 let values = vec![
760 Value::Null,
761 Value::Bool(true),
762 Value::Int64(i64::MAX),
763 Value::Float64(std::f64::consts::PI),
764 Value::String("hello world".into()),
765 Value::Bytes(vec![0, 1, 2, 255].into()),
766 Value::List(vec![Value::Int64(1), Value::Int64(2)].into()),
767 ];
768
769 for v in values {
770 let bytes = v.serialize();
771 let decoded = Value::deserialize(&bytes).unwrap();
772 assert_eq!(v, decoded);
773 }
774 }
775
776 #[test]
777 fn test_property_key() {
778 let key = PropertyKey::new("name");
779 assert_eq!(key.as_str(), "name");
780
781 let key2: PropertyKey = "age".into();
782 assert_eq!(key2.as_str(), "age");
783
784 assert!(key2 < key);
786 }
787
788 #[test]
789 fn test_value_type_name() {
790 assert_eq!(Value::Null.type_name(), "NULL");
791 assert_eq!(Value::Bool(true).type_name(), "BOOL");
792 assert_eq!(Value::Int64(0).type_name(), "INT64");
793 assert_eq!(Value::Float64(0.0).type_name(), "FLOAT64");
794 assert_eq!(Value::String("".into()).type_name(), "STRING");
795 assert_eq!(Value::Bytes(vec![].into()).type_name(), "BYTES");
796 assert_eq!(Value::List(vec![].into()).type_name(), "LIST");
797 assert_eq!(Value::Map(BTreeMap::new().into()).type_name(), "MAP");
798 }
799
800 #[test]
801 fn test_hashable_value_basic() {
802 use std::collections::HashMap;
803
804 let mut map: HashMap<HashableValue, i32> = HashMap::new();
805
806 map.insert(HashableValue::new(Value::Int64(42)), 1);
808 map.insert(HashableValue::new(Value::String("test".into())), 2);
809 map.insert(HashableValue::new(Value::Bool(true)), 3);
810 map.insert(HashableValue::new(Value::Float64(3.14)), 4);
811
812 assert_eq!(map.get(&HashableValue::new(Value::Int64(42))), Some(&1));
813 assert_eq!(
814 map.get(&HashableValue::new(Value::String("test".into()))),
815 Some(&2)
816 );
817 assert_eq!(map.get(&HashableValue::new(Value::Bool(true))), Some(&3));
818 assert_eq!(map.get(&HashableValue::new(Value::Float64(3.14))), Some(&4));
819 }
820
821 #[test]
822 fn test_hashable_value_float_edge_cases() {
823 use std::collections::HashMap;
824
825 let mut map: HashMap<HashableValue, i32> = HashMap::new();
826
827 let nan = f64::NAN;
829 map.insert(HashableValue::new(Value::Float64(nan)), 1);
830 assert_eq!(map.get(&HashableValue::new(Value::Float64(nan))), Some(&1));
831
832 let pos_zero = 0.0f64;
834 let neg_zero = -0.0f64;
835 map.insert(HashableValue::new(Value::Float64(pos_zero)), 2);
836 map.insert(HashableValue::new(Value::Float64(neg_zero)), 3);
837 assert_eq!(
838 map.get(&HashableValue::new(Value::Float64(pos_zero))),
839 Some(&2)
840 );
841 assert_eq!(
842 map.get(&HashableValue::new(Value::Float64(neg_zero))),
843 Some(&3)
844 );
845 }
846
847 #[test]
848 fn test_hashable_value_equality() {
849 let v1 = HashableValue::new(Value::Int64(42));
850 let v2 = HashableValue::new(Value::Int64(42));
851 let v3 = HashableValue::new(Value::Int64(43));
852
853 assert_eq!(v1, v2);
854 assert_ne!(v1, v3);
855 }
856
857 #[test]
858 fn test_hashable_value_inner() {
859 let hv = HashableValue::new(Value::String("hello".into()));
860 assert_eq!(hv.inner().as_str(), Some("hello"));
861
862 let v = hv.into_inner();
863 assert_eq!(v.as_str(), Some("hello"));
864 }
865
866 #[test]
867 fn test_hashable_value_conversions() {
868 let v = Value::Int64(42);
869 let hv: HashableValue = v.clone().into();
870 let v2: Value = hv.into();
871 assert_eq!(v, v2);
872 }
873
874 #[test]
875 fn test_orderable_value_try_from() {
876 assert!(OrderableValue::try_from(&Value::Int64(42)).is_some());
878 assert!(OrderableValue::try_from(&Value::Float64(3.14)).is_some());
879 assert!(OrderableValue::try_from(&Value::String("test".into())).is_some());
880 assert!(OrderableValue::try_from(&Value::Bool(true)).is_some());
881 assert!(OrderableValue::try_from(&Value::Timestamp(Timestamp::from_secs(1000))).is_some());
882
883 assert!(OrderableValue::try_from(&Value::Null).is_none());
885 assert!(OrderableValue::try_from(&Value::Bytes(vec![1, 2, 3].into())).is_none());
886 assert!(OrderableValue::try_from(&Value::List(vec![].into())).is_none());
887 assert!(OrderableValue::try_from(&Value::Map(BTreeMap::new().into())).is_none());
888 }
889
890 #[test]
891 fn test_orderable_value_ordering() {
892 use std::collections::BTreeSet;
893
894 let mut set = BTreeSet::new();
896 set.insert(OrderableValue::try_from(&Value::Int64(30)).unwrap());
897 set.insert(OrderableValue::try_from(&Value::Int64(10)).unwrap());
898 set.insert(OrderableValue::try_from(&Value::Int64(20)).unwrap());
899
900 let values: Vec<_> = set.iter().filter_map(|v| v.as_i64()).collect();
901 assert_eq!(values, vec![10, 20, 30]);
902 }
903
904 #[test]
905 fn test_orderable_value_float_ordering() {
906 let v1 = OrderableValue::try_from(&Value::Float64(1.0)).unwrap();
907 let v2 = OrderableValue::try_from(&Value::Float64(2.0)).unwrap();
908 let v_nan = OrderableValue::try_from(&Value::Float64(f64::NAN)).unwrap();
909 let v_inf = OrderableValue::try_from(&Value::Float64(f64::INFINITY)).unwrap();
910
911 assert!(v1 < v2);
912 assert!(v2 < v_inf);
913 assert!(v_inf < v_nan); assert!(v_nan == v_nan); }
916
917 #[test]
918 fn test_orderable_value_string_ordering() {
919 let a = OrderableValue::try_from(&Value::String("apple".into())).unwrap();
920 let b = OrderableValue::try_from(&Value::String("banana".into())).unwrap();
921 let c = OrderableValue::try_from(&Value::String("cherry".into())).unwrap();
922
923 assert!(a < b);
924 assert!(b < c);
925 }
926
927 #[test]
928 fn test_orderable_value_into_value() {
929 let original = Value::Int64(42);
930 let orderable = OrderableValue::try_from(&original).unwrap();
931 let back = orderable.into_value();
932 assert_eq!(original, back);
933
934 let original = Value::Float64(3.14);
935 let orderable = OrderableValue::try_from(&original).unwrap();
936 let back = orderable.into_value();
937 assert_eq!(original, back);
938
939 let original = Value::String("test".into());
940 let orderable = OrderableValue::try_from(&original).unwrap();
941 let back = orderable.into_value();
942 assert_eq!(original, back);
943 }
944
945 #[test]
946 fn test_orderable_value_cross_type_numeric() {
947 let i = OrderableValue::try_from(&Value::Int64(10)).unwrap();
949 let f = OrderableValue::try_from(&Value::Float64(10.0)).unwrap();
950
951 assert_eq!(i, f);
953
954 let f2 = OrderableValue::try_from(&Value::Float64(10.5)).unwrap();
955 assert!(i < f2);
956 }
957
958 #[test]
959 fn test_ordered_float64_nan_handling() {
960 let nan1 = OrderedFloat64::new(f64::NAN);
961 let nan2 = OrderedFloat64::new(f64::NAN);
962 let inf = OrderedFloat64::new(f64::INFINITY);
963 let neg_inf = OrderedFloat64::new(f64::NEG_INFINITY);
964 let zero = OrderedFloat64::new(0.0);
965
966 assert_eq!(nan1, nan2);
968
969 assert!(neg_inf < zero);
971 assert!(zero < inf);
972 assert!(inf < nan1);
973 }
974}