1use serde::{Deserialize, Serialize};
65use std::collections::HashMap;
66use std::fmt;
67
68use std::cmp::Ordering;
69
70#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
82pub enum PropertyValue {
83 String(String),
84 Integer(i64),
85 Float(f64),
86 Boolean(bool),
87 DateTime(i64), Array(Vec<PropertyValue>),
89 Map(HashMap<String, PropertyValue>),
90 Vector(Vec<f32>),
91 Duration {
93 months: i64,
94 days: i64,
95 seconds: i64,
96 nanos: i32,
97 },
98 Null,
99}
100
101impl Eq for PropertyValue {}
102
103impl PartialOrd for PropertyValue {
104 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
105 Some(self.cmp(other))
106 }
107}
108
109impl Ord for PropertyValue {
110 fn cmp(&self, other: &Self) -> Ordering {
111 use PropertyValue::*;
112 match (self, other) {
113 (Null, Null) => Ordering::Equal,
114 (Null, _) => Ordering::Less,
115 (_, Null) => Ordering::Greater,
116
117 (Boolean(a), Boolean(b)) => a.cmp(b),
118 (Boolean(_), _) => Ordering::Less,
119 (_, Boolean(_)) => Ordering::Greater,
120
121 (Integer(a), Integer(b)) => a.cmp(b),
122 (Integer(_), _) => Ordering::Less,
123 (_, Integer(_)) => Ordering::Greater,
124
125 (Float(a), Float(b)) => a.total_cmp(b),
126 (Float(_), _) => Ordering::Less,
127 (_, Float(_)) => Ordering::Greater,
128
129 (String(a), String(b)) => a.cmp(b),
130 (String(_), _) => Ordering::Less,
131 (_, String(_)) => Ordering::Greater,
132
133 (DateTime(a), DateTime(b)) => a.cmp(b),
134 (DateTime(_), _) => Ordering::Less,
135 (_, DateTime(_)) => Ordering::Greater,
136
137 (Array(a), Array(b)) => a.cmp(b),
138 (Array(_), _) => Ordering::Less,
139 (_, Array(_)) => Ordering::Greater,
140
141 (Map(a), Map(b)) => {
147 let mut keys_a: Vec<_> = a.keys().collect();
148 let mut keys_b: Vec<_> = b.keys().collect();
149 keys_a.sort();
150 keys_b.sort();
151
152 for (ka, kb) in keys_a.iter().zip(keys_b.iter()) {
154 match ka.cmp(kb) {
155 Ordering::Equal => {}
156 ord => return ord,
157 }
158 }
159
160 if keys_a.len() != keys_b.len() {
161 return keys_a.len().cmp(&keys_b.len());
162 }
163
164 for k in keys_a {
166 let va = a.get(k).unwrap();
167 let vb = b.get(k).unwrap();
168 match va.cmp(vb) {
169 Ordering::Equal => {}
170 ord => return ord,
171 }
172 }
173 Ordering::Equal
174 }
175 (Map(_), _) => Ordering::Less,
176 (_, Map(_)) => Ordering::Greater,
177
178 (Vector(a), Vector(b)) => {
179 for (va, vb) in a.iter().zip(b.iter()) {
181 match va.total_cmp(vb) {
182 Ordering::Equal => {}
183 ord => return ord,
184 }
185 }
186 a.len().cmp(&b.len())
187 }
188 (Vector(_), _) => Ordering::Less,
189 (_, Vector(_)) => Ordering::Greater,
190
191 (
192 Duration {
193 months: m1,
194 days: d1,
195 seconds: s1,
196 nanos: n1,
197 },
198 Duration {
199 months: m2,
200 days: d2,
201 seconds: s2,
202 nanos: n2,
203 },
204 ) => m1
205 .cmp(m2)
206 .then(d1.cmp(d2))
207 .then(s1.cmp(s2))
208 .then(n1.cmp(n2)),
209 }
210 }
211}
212
213impl std::hash::Hash for PropertyValue {
214 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
215 match self {
216 PropertyValue::String(s) => {
217 0.hash(state);
218 s.hash(state);
219 }
220 PropertyValue::Integer(i) => {
221 1.hash(state);
222 i.hash(state);
223 }
224 PropertyValue::Float(f) => {
225 2.hash(state);
226 f.to_bits().hash(state);
228 }
229 PropertyValue::Boolean(b) => {
230 3.hash(state);
231 b.hash(state);
232 }
233 PropertyValue::DateTime(dt) => {
234 4.hash(state);
235 dt.hash(state);
236 }
237 PropertyValue::Array(arr) => {
238 5.hash(state);
239 arr.hash(state);
240 }
241 PropertyValue::Map(map) => {
242 6.hash(state);
243 let mut keys: Vec<_> = map.keys().collect();
245 keys.sort();
246 for k in keys {
247 k.hash(state);
248 map.get(k).unwrap().hash(state);
249 }
250 }
251 PropertyValue::Vector(v) => {
252 7.hash(state);
253 for val in v {
254 val.to_bits().hash(state);
255 }
256 }
257 PropertyValue::Duration {
258 months,
259 days,
260 seconds,
261 nanos,
262 } => {
263 8.hash(state);
264 months.hash(state);
265 days.hash(state);
266 seconds.hash(state);
267 nanos.hash(state);
268 }
269 PropertyValue::Null => {
270 9.hash(state);
271 }
272 }
273 }
274}
275
276impl PropertyValue {
277 pub fn is_null(&self) -> bool {
279 matches!(self, PropertyValue::Null)
280 }
281
282 pub fn as_string(&self) -> Option<&str> {
284 match self {
285 PropertyValue::String(s) => Some(s),
286 _ => None,
287 }
288 }
289
290 pub fn as_integer(&self) -> Option<i64> {
292 match self {
293 PropertyValue::Integer(i) => Some(*i),
294 _ => None,
295 }
296 }
297
298 pub fn as_float(&self) -> Option<f64> {
300 match self {
301 PropertyValue::Float(f) => Some(*f),
302 _ => None,
303 }
304 }
305
306 pub fn as_boolean(&self) -> Option<bool> {
308 match self {
309 PropertyValue::Boolean(b) => Some(*b),
310 _ => None,
311 }
312 }
313
314 pub fn as_datetime(&self) -> Option<i64> {
316 match self {
317 PropertyValue::DateTime(dt) => Some(*dt),
318 _ => None,
319 }
320 }
321
322 pub fn as_array(&self) -> Option<&Vec<PropertyValue>> {
324 match self {
325 PropertyValue::Array(arr) => Some(arr),
326 _ => None,
327 }
328 }
329
330 pub fn as_map(&self) -> Option<&HashMap<String, PropertyValue>> {
332 match self {
333 PropertyValue::Map(map) => Some(map),
334 _ => None,
335 }
336 }
337
338 pub fn as_vector(&self) -> Option<&Vec<f32>> {
340 match self {
341 PropertyValue::Vector(v) => Some(v),
342 _ => None,
343 }
344 }
345
346 pub fn type_name(&self) -> &'static str {
348 match self {
349 PropertyValue::String(_) => "String",
350 PropertyValue::Integer(_) => "Integer",
351 PropertyValue::Float(_) => "Float",
352 PropertyValue::Boolean(_) => "Boolean",
353 PropertyValue::DateTime(_) => "DateTime",
354 PropertyValue::Array(_) => "Array",
355 PropertyValue::Map(_) => "Map",
356 PropertyValue::Vector(_) => "Vector",
357 PropertyValue::Duration { .. } => "Duration",
358 PropertyValue::Null => "Null",
359 }
360 }
361
362 pub fn to_json(&self) -> serde_json::Value {
364 use serde_json::json;
365 match self {
366 PropertyValue::String(s) => json!(s),
367 PropertyValue::Integer(i) => json!(i),
368 PropertyValue::Float(f) => json!(f),
369 PropertyValue::Boolean(b) => json!(b),
370 PropertyValue::DateTime(dt) => json!(dt),
371 PropertyValue::Array(arr) => {
372 json!(arr.iter().map(|v| v.to_json()).collect::<Vec<_>>())
373 }
374 PropertyValue::Map(map) => {
375 let mut json_map = serde_json::Map::new();
376 for (k, v) in map {
377 json_map.insert(k.clone(), v.to_json());
378 }
379 serde_json::Value::Object(json_map)
380 }
381 PropertyValue::Vector(v) => json!(v),
382 PropertyValue::Duration {
383 months,
384 days,
385 seconds,
386 nanos,
387 } => {
388 json!({
389 "months": months,
390 "days": days,
391 "seconds": seconds,
392 "nanos": nanos
393 })
394 }
395 PropertyValue::Null => serde_json::Value::Null,
396 }
397 }
398}
399
400impl fmt::Display for PropertyValue {
401 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402 match self {
403 PropertyValue::String(s) => write!(f, "\"{}\"", s),
404 PropertyValue::Integer(i) => write!(f, "{}", i),
405 PropertyValue::Float(fl) => write!(f, "{}", fl),
406 PropertyValue::Boolean(b) => write!(f, "{}", b),
407 PropertyValue::DateTime(dt) => write!(f, "DateTime({})", dt),
408 PropertyValue::Array(arr) => {
409 write!(f, "[")?;
410 for (i, val) in arr.iter().enumerate() {
411 if i > 0 {
412 write!(f, ", ")?;
413 }
414 write!(f, "{}", val)?;
415 }
416 write!(f, "]")
417 }
418 PropertyValue::Map(map) => {
419 write!(f, "{{")?;
420 for (i, (key, val)) in map.iter().enumerate() {
421 if i > 0 {
422 write!(f, ", ")?;
423 }
424 write!(f, "{}: {}", key, val)?;
425 }
426 write!(f, "}}")
427 }
428 PropertyValue::Vector(v) => {
429 write!(f, "Vector([")?;
430 for (i, val) in v.iter().enumerate() {
431 if i > 0 {
432 write!(f, ", ")?;
433 }
434 write!(f, "{}", val)?;
435 }
436 write!(f, "])")
437 }
438 PropertyValue::Duration {
439 months,
440 days,
441 seconds,
442 nanos,
443 } => {
444 write!(f, "P")?;
445 if *months > 0 {
446 let years = months / 12;
447 let rem_months = months % 12;
448 if years > 0 {
449 write!(f, "{}Y", years)?;
450 }
451 if rem_months > 0 {
452 write!(f, "{}M", rem_months)?;
453 }
454 }
455 if *days > 0 {
456 write!(f, "{}D", days)?;
457 }
458 if *seconds > 0 || *nanos > 0 {
459 write!(f, "T")?;
460 let h = seconds / 3600;
461 let m = (seconds % 3600) / 60;
462 let s = seconds % 60;
463 if h > 0 {
464 write!(f, "{}H", h)?;
465 }
466 if m > 0 {
467 write!(f, "{}M", m)?;
468 }
469 if s > 0 || *nanos > 0 {
470 write!(f, "{}S", s)?;
471 }
472 }
473 Ok(())
474 }
475 PropertyValue::Null => write!(f, "null"),
476 }
477 }
478}
479
480impl From<String> for PropertyValue {
482 fn from(s: String) -> Self {
483 PropertyValue::String(s)
484 }
485}
486
487impl From<&str> for PropertyValue {
488 fn from(s: &str) -> Self {
489 PropertyValue::String(s.to_string())
490 }
491}
492
493impl From<i64> for PropertyValue {
494 fn from(i: i64) -> Self {
495 PropertyValue::Integer(i)
496 }
497}
498
499impl From<i32> for PropertyValue {
500 fn from(i: i32) -> Self {
501 PropertyValue::Integer(i as i64)
502 }
503}
504
505impl From<f64> for PropertyValue {
506 fn from(f: f64) -> Self {
507 PropertyValue::Float(f)
508 }
509}
510
511impl From<bool> for PropertyValue {
512 fn from(b: bool) -> Self {
513 PropertyValue::Boolean(b)
514 }
515}
516
517impl From<Vec<PropertyValue>> for PropertyValue {
518 fn from(arr: Vec<PropertyValue>) -> Self {
519 PropertyValue::Array(arr)
520 }
521}
522
523impl From<HashMap<String, PropertyValue>> for PropertyValue {
524 fn from(map: HashMap<String, PropertyValue>) -> Self {
525 PropertyValue::Map(map)
526 }
527}
528
529impl From<Vec<f32>> for PropertyValue {
530 fn from(v: Vec<f32>) -> Self {
531 PropertyValue::Vector(v)
532 }
533}
534
535pub type PropertyMap = HashMap<String, PropertyValue>;
537
538#[cfg(test)]
539mod tests {
540 use super::*;
541
542 #[test]
543 fn test_property_value_types() {
544 assert_eq!(
546 PropertyValue::String("test".to_string()).type_name(),
547 "String"
548 );
549 assert_eq!(PropertyValue::Integer(42).type_name(), "Integer");
550 assert_eq!(PropertyValue::Float(3.14).type_name(), "Float");
551 assert_eq!(PropertyValue::Boolean(true).type_name(), "Boolean");
552 assert_eq!(PropertyValue::DateTime(1234567890).type_name(), "DateTime");
553 assert_eq!(PropertyValue::Array(vec![]).type_name(), "Array");
554 assert_eq!(PropertyValue::Map(HashMap::new()).type_name(), "Map");
555 assert_eq!(PropertyValue::Vector(vec![0.1]).type_name(), "Vector");
556 assert_eq!(PropertyValue::Null.type_name(), "Null");
557 }
558
559 #[test]
560 fn test_property_value_conversions() {
561 let string_prop: PropertyValue = "hello".into();
562 assert_eq!(string_prop.as_string(), Some("hello"));
563
564 let int_prop: PropertyValue = 42i64.into();
565 assert_eq!(int_prop.as_integer(), Some(42));
566
567 let float_prop: PropertyValue = 3.14.into();
568 assert_eq!(float_prop.as_float(), Some(3.14));
569
570 let bool_prop: PropertyValue = true.into();
571 assert_eq!(bool_prop.as_boolean(), Some(true));
572
573 let vector_prop: PropertyValue = vec![1.0f32, 2.0f32].into();
574 assert_eq!(vector_prop.as_vector(), Some(&vec![1.0f32, 2.0f32]));
575 }
576
577 #[test]
578 fn test_property_map() {
579 let mut props = PropertyMap::new();
580 props.insert("name".to_string(), "Alice".into());
581 props.insert("age".to_string(), 30i64.into());
582 props.insert("active".to_string(), true.into());
583
584 assert_eq!(props.get("name").unwrap().as_string(), Some("Alice"));
585 assert_eq!(props.get("age").unwrap().as_integer(), Some(30));
586 assert_eq!(props.get("active").unwrap().as_boolean(), Some(true));
587 }
588
589 #[test]
590 fn test_nested_properties() {
591 let arr = vec![
593 PropertyValue::Integer(1),
594 PropertyValue::Integer(2),
595 PropertyValue::Integer(3),
596 ];
597 let arr_prop = PropertyValue::Array(arr);
598 assert_eq!(arr_prop.as_array().unwrap().len(), 3);
599
600 let mut map = HashMap::new();
602 map.insert(
603 "key".to_string(),
604 PropertyValue::String("value".to_string()),
605 );
606 let map_prop = PropertyValue::Map(map);
607 assert!(map_prop.as_map().unwrap().contains_key("key"));
608 }
609
610 #[test]
613 fn test_ord_null_less_than_everything() {
614 assert!(PropertyValue::Null < PropertyValue::Boolean(false));
615 assert!(PropertyValue::Null < PropertyValue::Integer(0));
616 assert!(PropertyValue::Null < PropertyValue::Float(0.0));
617 assert!(PropertyValue::Null < PropertyValue::String("".to_string()));
618 }
619
620 #[test]
621 fn test_ord_null_equal() {
622 assert_eq!(
623 PropertyValue::Null.cmp(&PropertyValue::Null),
624 std::cmp::Ordering::Equal
625 );
626 }
627
628 #[test]
629 fn test_ord_boolean_less_than_integer() {
630 assert!(PropertyValue::Boolean(true) < PropertyValue::Integer(0));
631 }
632
633 #[test]
634 fn test_ord_boolean_comparison() {
635 assert!(PropertyValue::Boolean(false) < PropertyValue::Boolean(true));
636 }
637
638 #[test]
639 fn test_ord_integer_comparison() {
640 assert!(PropertyValue::Integer(1) < PropertyValue::Integer(2));
641 assert_eq!(
642 PropertyValue::Integer(5).cmp(&PropertyValue::Integer(5)),
643 std::cmp::Ordering::Equal
644 );
645 }
646
647 #[test]
648 fn test_ord_integer_less_than_float() {
649 assert!(PropertyValue::Integer(100) < PropertyValue::Float(0.0));
650 }
651
652 #[test]
653 fn test_ord_float_comparison() {
654 assert!(PropertyValue::Float(1.0) < PropertyValue::Float(2.0));
655 assert_eq!(
656 PropertyValue::Float(3.14).cmp(&PropertyValue::Float(3.14)),
657 std::cmp::Ordering::Equal
658 );
659 }
660
661 #[test]
662 fn test_ord_float_less_than_string() {
663 assert!(PropertyValue::Float(1e100) < PropertyValue::String("a".to_string()));
664 }
665
666 #[test]
667 fn test_ord_string_comparison() {
668 assert!(PropertyValue::String("a".to_string()) < PropertyValue::String("b".to_string()));
669 assert!(PropertyValue::String("abc".to_string()) > PropertyValue::String("ab".to_string()));
670 }
671
672 #[test]
673 fn test_ord_datetime_comparison() {
674 assert!(PropertyValue::DateTime(100) < PropertyValue::DateTime(200));
675 }
676
677 #[test]
678 fn test_ord_array_comparison() {
679 let a1 = PropertyValue::Array(vec![PropertyValue::Integer(1)]);
680 let a2 = PropertyValue::Array(vec![PropertyValue::Integer(2)]);
681 assert!(a1 < a2);
682 }
683
684 #[test]
685 fn test_ord_map_comparison() {
686 let mut m1 = HashMap::new();
687 m1.insert("a".to_string(), PropertyValue::Integer(1));
688 let mut m2 = HashMap::new();
689 m2.insert("a".to_string(), PropertyValue::Integer(2));
690 let pv1 = PropertyValue::Map(m1);
691 let pv2 = PropertyValue::Map(m2);
692 assert!(pv1 < pv2);
693 }
694
695 #[test]
696 fn test_ord_map_different_keys() {
697 let mut m1 = HashMap::new();
698 m1.insert("a".to_string(), PropertyValue::Integer(1));
699 let mut m2 = HashMap::new();
700 m2.insert("b".to_string(), PropertyValue::Integer(1));
701 let pv1 = PropertyValue::Map(m1);
702 let pv2 = PropertyValue::Map(m2);
703 assert!(pv1 < pv2); }
705
706 #[test]
707 fn test_ord_map_different_sizes() {
708 let mut m1 = HashMap::new();
709 m1.insert("a".to_string(), PropertyValue::Integer(1));
710 let mut m2 = HashMap::new();
711 m2.insert("a".to_string(), PropertyValue::Integer(1));
712 m2.insert("b".to_string(), PropertyValue::Integer(2));
713 let pv1 = PropertyValue::Map(m1);
714 let pv2 = PropertyValue::Map(m2);
715 assert!(pv1 < pv2); }
717
718 #[test]
719 fn test_ord_vector_comparison() {
720 let v1 = PropertyValue::Vector(vec![1.0, 2.0]);
721 let v2 = PropertyValue::Vector(vec![1.0, 3.0]);
722 assert!(v1 < v2);
723 }
724
725 #[test]
726 fn test_ord_vector_different_lengths() {
727 let v1 = PropertyValue::Vector(vec![1.0]);
728 let v2 = PropertyValue::Vector(vec![1.0, 2.0]);
729 assert!(v1 < v2);
730 }
731
732 #[test]
733 fn test_ord_duration_comparison() {
734 let d1 = PropertyValue::Duration {
735 months: 1,
736 days: 0,
737 seconds: 0,
738 nanos: 0,
739 };
740 let d2 = PropertyValue::Duration {
741 months: 2,
742 days: 0,
743 seconds: 0,
744 nanos: 0,
745 };
746 assert!(d1 < d2);
747 }
748
749 #[test]
750 fn test_ord_duration_tiebreak_days() {
751 let d1 = PropertyValue::Duration {
752 months: 1,
753 days: 5,
754 seconds: 0,
755 nanos: 0,
756 };
757 let d2 = PropertyValue::Duration {
758 months: 1,
759 days: 10,
760 seconds: 0,
761 nanos: 0,
762 };
763 assert!(d1 < d2);
764 }
765
766 #[test]
767 fn test_ord_duration_tiebreak_seconds() {
768 let d1 = PropertyValue::Duration {
769 months: 1,
770 days: 5,
771 seconds: 100,
772 nanos: 0,
773 };
774 let d2 = PropertyValue::Duration {
775 months: 1,
776 days: 5,
777 seconds: 200,
778 nanos: 0,
779 };
780 assert!(d1 < d2);
781 }
782
783 #[test]
784 fn test_ord_duration_tiebreak_nanos() {
785 let d1 = PropertyValue::Duration {
786 months: 1,
787 days: 5,
788 seconds: 100,
789 nanos: 10,
790 };
791 let d2 = PropertyValue::Duration {
792 months: 1,
793 days: 5,
794 seconds: 100,
795 nanos: 20,
796 };
797 assert!(d1 < d2);
798 }
799
800 #[test]
801 fn test_partial_ord_consistency() {
802 let a = PropertyValue::Integer(42);
803 let b = PropertyValue::Integer(42);
804 assert_eq!(a.partial_cmp(&b), Some(std::cmp::Ordering::Equal));
805 }
806
807 #[test]
810 fn test_hash_deterministic_map() {
811 use std::collections::hash_map::DefaultHasher;
812 use std::hash::{Hash, Hasher};
813
814 let mut m1 = HashMap::new();
815 m1.insert("b".to_string(), PropertyValue::Integer(2));
816 m1.insert("a".to_string(), PropertyValue::Integer(1));
817
818 let mut m2 = HashMap::new();
819 m2.insert("a".to_string(), PropertyValue::Integer(1));
820 m2.insert("b".to_string(), PropertyValue::Integer(2));
821
822 let hash1 = {
823 let mut h = DefaultHasher::new();
824 PropertyValue::Map(m1).hash(&mut h);
825 h.finish()
826 };
827 let hash2 = {
828 let mut h = DefaultHasher::new();
829 PropertyValue::Map(m2).hash(&mut h);
830 h.finish()
831 };
832 assert_eq!(hash1, hash2);
833 }
834
835 #[test]
836 fn test_hash_deterministic_vector() {
837 use std::collections::hash_map::DefaultHasher;
838 use std::hash::{Hash, Hasher};
839
840 let v1 = PropertyValue::Vector(vec![1.0, 2.0, 3.0]);
841 let v2 = PropertyValue::Vector(vec![1.0, 2.0, 3.0]);
842
843 let hash1 = {
844 let mut h = DefaultHasher::new();
845 v1.hash(&mut h);
846 h.finish()
847 };
848 let hash2 = {
849 let mut h = DefaultHasher::new();
850 v2.hash(&mut h);
851 h.finish()
852 };
853 assert_eq!(hash1, hash2);
854 }
855
856 #[test]
857 fn test_hash_deterministic_duration() {
858 use std::collections::hash_map::DefaultHasher;
859 use std::hash::{Hash, Hasher};
860
861 let d1 = PropertyValue::Duration {
862 months: 1,
863 days: 2,
864 seconds: 3,
865 nanos: 4,
866 };
867 let d2 = PropertyValue::Duration {
868 months: 1,
869 days: 2,
870 seconds: 3,
871 nanos: 4,
872 };
873
874 let hash1 = {
875 let mut h = DefaultHasher::new();
876 d1.hash(&mut h);
877 h.finish()
878 };
879 let hash2 = {
880 let mut h = DefaultHasher::new();
881 d2.hash(&mut h);
882 h.finish()
883 };
884 assert_eq!(hash1, hash2);
885 }
886
887 #[test]
888 fn test_hash_different_types_different_hashes() {
889 use std::collections::hash_map::DefaultHasher;
890 use std::hash::{Hash, Hasher};
891
892 let int_hash = {
893 let mut h = DefaultHasher::new();
894 PropertyValue::Integer(42).hash(&mut h);
895 h.finish()
896 };
897 let str_hash = {
898 let mut h = DefaultHasher::new();
899 PropertyValue::String("42".to_string()).hash(&mut h);
900 h.finish()
901 };
902 assert_ne!(int_hash, str_hash);
903 }
904
905 #[test]
906 fn test_hash_null() {
907 use std::collections::hash_map::DefaultHasher;
908 use std::hash::{Hash, Hasher};
909
910 let hash = {
911 let mut h = DefaultHasher::new();
912 PropertyValue::Null.hash(&mut h);
913 h.finish()
914 };
915 assert!(hash > 0 || hash == 0); }
918
919 #[test]
920 fn test_hash_float() {
921 use std::collections::hash_map::DefaultHasher;
922 use std::hash::{Hash, Hasher};
923
924 let hash1 = {
925 let mut h = DefaultHasher::new();
926 PropertyValue::Float(3.14).hash(&mut h);
927 h.finish()
928 };
929 let hash2 = {
930 let mut h = DefaultHasher::new();
931 PropertyValue::Float(3.14).hash(&mut h);
932 h.finish()
933 };
934 assert_eq!(hash1, hash2);
935 }
936
937 #[test]
938 fn test_hash_array() {
939 use std::collections::hash_map::DefaultHasher;
940 use std::hash::{Hash, Hasher};
941
942 let arr = PropertyValue::Array(vec![PropertyValue::Integer(1), PropertyValue::Integer(2)]);
943 let hash = {
944 let mut h = DefaultHasher::new();
945 arr.hash(&mut h);
946 h.finish()
947 };
948 assert!(hash > 0 || hash == 0);
949 }
950
951 #[test]
952 fn test_hash_boolean() {
953 use std::collections::hash_map::DefaultHasher;
954 use std::hash::{Hash, Hasher};
955
956 let hash1 = {
957 let mut h = DefaultHasher::new();
958 PropertyValue::Boolean(true).hash(&mut h);
959 h.finish()
960 };
961 let hash2 = {
962 let mut h = DefaultHasher::new();
963 PropertyValue::Boolean(false).hash(&mut h);
964 h.finish()
965 };
966 assert_ne!(hash1, hash2);
967 }
968
969 #[test]
970 fn test_hash_datetime() {
971 use std::collections::hash_map::DefaultHasher;
972 use std::hash::{Hash, Hasher};
973
974 let hash1 = {
975 let mut h = DefaultHasher::new();
976 PropertyValue::DateTime(12345).hash(&mut h);
977 h.finish()
978 };
979 let hash2 = {
980 let mut h = DefaultHasher::new();
981 PropertyValue::DateTime(12345).hash(&mut h);
982 h.finish()
983 };
984 assert_eq!(hash1, hash2);
985 }
986
987 #[test]
990 fn test_display_string() {
991 assert_eq!(
992 format!("{}", PropertyValue::String("hello".to_string())),
993 "\"hello\""
994 );
995 }
996
997 #[test]
998 fn test_display_integer() {
999 assert_eq!(format!("{}", PropertyValue::Integer(42)), "42");
1000 }
1001
1002 #[test]
1003 fn test_display_float() {
1004 assert_eq!(format!("{}", PropertyValue::Float(3.14)), "3.14");
1005 }
1006
1007 #[test]
1008 fn test_display_boolean() {
1009 assert_eq!(format!("{}", PropertyValue::Boolean(true)), "true");
1010 assert_eq!(format!("{}", PropertyValue::Boolean(false)), "false");
1011 }
1012
1013 #[test]
1014 fn test_display_datetime() {
1015 assert_eq!(
1016 format!("{}", PropertyValue::DateTime(1234567890)),
1017 "DateTime(1234567890)"
1018 );
1019 }
1020
1021 #[test]
1022 fn test_display_array() {
1023 let arr = PropertyValue::Array(vec![PropertyValue::Integer(1), PropertyValue::Integer(2)]);
1024 assert_eq!(format!("{}", arr), "[1, 2]");
1025 }
1026
1027 #[test]
1028 fn test_display_array_empty() {
1029 let arr = PropertyValue::Array(vec![]);
1030 assert_eq!(format!("{}", arr), "[]");
1031 }
1032
1033 #[test]
1034 fn test_display_null() {
1035 assert_eq!(format!("{}", PropertyValue::Null), "null");
1036 }
1037
1038 #[test]
1039 fn test_display_vector() {
1040 let v = PropertyValue::Vector(vec![1.0, 2.5]);
1041 let s = format!("{}", v);
1042 assert!(s.starts_with("Vector(["));
1043 assert!(s.contains("1"));
1044 assert!(s.contains("2.5"));
1045 assert!(s.ends_with("])"));
1046 }
1047
1048 #[test]
1049 fn test_display_map() {
1050 let mut map = HashMap::new();
1051 map.insert("key".to_string(), PropertyValue::Integer(42));
1052 let pv = PropertyValue::Map(map);
1053 let s = format!("{}", pv);
1054 assert!(s.contains("key: 42"));
1055 }
1056
1057 #[test]
1058 fn test_display_duration_years_months() {
1059 let d = PropertyValue::Duration {
1060 months: 14,
1061 days: 0,
1062 seconds: 0,
1063 nanos: 0,
1064 };
1065 let s = format!("{}", d);
1066 assert!(s.contains("1Y"));
1067 assert!(s.contains("2M"));
1068 }
1069
1070 #[test]
1071 fn test_display_duration_days_time() {
1072 let d = PropertyValue::Duration {
1073 months: 0,
1074 days: 5,
1075 seconds: 7261,
1076 nanos: 0,
1077 };
1078 let s = format!("{}", d);
1079 assert!(s.contains("5D"));
1080 assert!(s.contains("T"));
1081 assert!(s.contains("2H"));
1082 assert!(s.contains("1M"));
1083 assert!(s.contains("1S"));
1084 }
1085
1086 #[test]
1087 fn test_display_duration_empty() {
1088 let d = PropertyValue::Duration {
1089 months: 0,
1090 days: 0,
1091 seconds: 0,
1092 nanos: 0,
1093 };
1094 let s = format!("{}", d);
1095 assert_eq!(s, "P");
1096 }
1097
1098 #[test]
1099 fn test_display_duration_nanos_only() {
1100 let d = PropertyValue::Duration {
1101 months: 0,
1102 days: 0,
1103 seconds: 0,
1104 nanos: 100,
1105 };
1106 let s = format!("{}", d);
1107 assert!(s.contains("T"));
1108 assert!(s.contains("0S"));
1109 }
1110
1111 #[test]
1114 fn test_to_json_string() {
1115 let json = PropertyValue::String("hello".to_string()).to_json();
1116 assert_eq!(json, serde_json::json!("hello"));
1117 }
1118
1119 #[test]
1120 fn test_to_json_integer() {
1121 let json = PropertyValue::Integer(42).to_json();
1122 assert_eq!(json, serde_json::json!(42));
1123 }
1124
1125 #[test]
1126 fn test_to_json_float() {
1127 let json = PropertyValue::Float(3.14).to_json();
1128 assert_eq!(json, serde_json::json!(3.14));
1129 }
1130
1131 #[test]
1132 fn test_to_json_boolean() {
1133 let json = PropertyValue::Boolean(true).to_json();
1134 assert_eq!(json, serde_json::json!(true));
1135 }
1136
1137 #[test]
1138 fn test_to_json_null() {
1139 let json = PropertyValue::Null.to_json();
1140 assert!(json.is_null());
1141 }
1142
1143 #[test]
1144 fn test_to_json_datetime() {
1145 let json = PropertyValue::DateTime(1234567890).to_json();
1146 assert_eq!(json, serde_json::json!(1234567890));
1147 }
1148
1149 #[test]
1150 fn test_to_json_array() {
1151 let arr = PropertyValue::Array(vec![
1152 PropertyValue::Integer(1),
1153 PropertyValue::String("x".to_string()),
1154 ]);
1155 let json = arr.to_json();
1156 assert_eq!(json, serde_json::json!([1, "x"]));
1157 }
1158
1159 #[test]
1160 fn test_to_json_map() {
1161 let mut map = HashMap::new();
1162 map.insert(
1163 "name".to_string(),
1164 PropertyValue::String("Alice".to_string()),
1165 );
1166 map.insert("age".to_string(), PropertyValue::Integer(30));
1167 let json = PropertyValue::Map(map).to_json();
1168 assert_eq!(json["name"], serde_json::json!("Alice"));
1169 assert_eq!(json["age"], serde_json::json!(30));
1170 }
1171
1172 #[test]
1173 fn test_to_json_vector() {
1174 let v = PropertyValue::Vector(vec![1.0, 2.0, 3.0]);
1175 let json = v.to_json();
1176 let arr = json.as_array().unwrap();
1177 assert_eq!(arr.len(), 3);
1178 }
1179
1180 #[test]
1181 fn test_to_json_duration() {
1182 let d = PropertyValue::Duration {
1183 months: 1,
1184 days: 2,
1185 seconds: 3,
1186 nanos: 4,
1187 };
1188 let json = d.to_json();
1189 assert_eq!(json["months"], serde_json::json!(1));
1190 assert_eq!(json["days"], serde_json::json!(2));
1191 assert_eq!(json["seconds"], serde_json::json!(3));
1192 assert_eq!(json["nanos"], serde_json::json!(4));
1193 }
1194
1195 #[test]
1198 fn test_is_null_true() {
1199 assert!(PropertyValue::Null.is_null());
1200 }
1201
1202 #[test]
1203 fn test_is_null_false() {
1204 assert!(!PropertyValue::Integer(0).is_null());
1205 assert!(!PropertyValue::String("".to_string()).is_null());
1206 assert!(!PropertyValue::Boolean(false).is_null());
1207 }
1208
1209 #[test]
1212 fn test_as_string_on_non_string() {
1213 assert_eq!(PropertyValue::Integer(42).as_string(), None);
1214 }
1215
1216 #[test]
1217 fn test_as_integer_on_non_integer() {
1218 assert_eq!(PropertyValue::String("x".to_string()).as_integer(), None);
1219 }
1220
1221 #[test]
1222 fn test_as_float_on_non_float() {
1223 assert_eq!(PropertyValue::Integer(1).as_float(), None);
1224 }
1225
1226 #[test]
1227 fn test_as_boolean_on_non_boolean() {
1228 assert_eq!(PropertyValue::Integer(1).as_boolean(), None);
1229 }
1230
1231 #[test]
1232 fn test_as_datetime_on_non_datetime() {
1233 assert_eq!(PropertyValue::Integer(1).as_datetime(), None);
1234 }
1235
1236 #[test]
1237 fn test_as_array_on_non_array() {
1238 assert_eq!(PropertyValue::Integer(1).as_array(), None);
1239 }
1240
1241 #[test]
1242 fn test_as_map_on_non_map() {
1243 assert_eq!(PropertyValue::Integer(1).as_map(), None);
1244 }
1245
1246 #[test]
1247 fn test_as_vector_on_non_vector() {
1248 assert_eq!(PropertyValue::Integer(1).as_vector(), None);
1249 }
1250
1251 #[test]
1254 fn test_from_i32() {
1255 let pv: PropertyValue = 42i32.into();
1256 assert_eq!(pv.as_integer(), Some(42));
1257 }
1258
1259 #[test]
1260 fn test_from_string_owned() {
1261 let pv: PropertyValue = String::from("test").into();
1262 assert_eq!(pv.as_string(), Some("test"));
1263 }
1264
1265 #[test]
1268 fn test_duration_type_name() {
1269 let d = PropertyValue::Duration {
1270 months: 0,
1271 days: 0,
1272 seconds: 0,
1273 nanos: 0,
1274 };
1275 assert_eq!(d.type_name(), "Duration");
1276 }
1277
1278 #[test]
1281 fn test_eq_same_types() {
1282 assert_eq!(PropertyValue::Integer(1), PropertyValue::Integer(1));
1283 assert_ne!(PropertyValue::Integer(1), PropertyValue::Integer(2));
1284 assert_eq!(PropertyValue::Float(1.0), PropertyValue::Float(1.0));
1285 assert_eq!(
1286 PropertyValue::String("a".to_string()),
1287 PropertyValue::String("a".to_string())
1288 );
1289 assert_ne!(
1290 PropertyValue::String("a".to_string()),
1291 PropertyValue::String("b".to_string())
1292 );
1293 }
1294
1295 #[test]
1296 fn test_eq_different_types() {
1297 assert_ne!(PropertyValue::Integer(1), PropertyValue::Float(1.0));
1298 assert_ne!(
1299 PropertyValue::Integer(1),
1300 PropertyValue::String("1".to_string())
1301 );
1302 }
1303
1304 #[test]
1305 fn test_eq_duration() {
1306 let d1 = PropertyValue::Duration {
1307 months: 1,
1308 days: 2,
1309 seconds: 3,
1310 nanos: 4,
1311 };
1312 let d2 = PropertyValue::Duration {
1313 months: 1,
1314 days: 2,
1315 seconds: 3,
1316 nanos: 4,
1317 };
1318 let d3 = PropertyValue::Duration {
1319 months: 1,
1320 days: 2,
1321 seconds: 3,
1322 nanos: 5,
1323 };
1324 assert_eq!(d1, d2);
1325 assert_ne!(d1, d3);
1326 }
1327}