Skip to main content

jasn_core/
value.rs

1use std::{borrow::Cow, collections::BTreeMap};
2
3mod binary;
4pub use binary::Binary;
5mod timestamp;
6pub use timestamp::Timestamp;
7
8#[cfg(feature = "serde")]
9pub mod de;
10#[cfg(feature = "serde")]
11pub mod ser;
12
13/// Represents a valid JASN value.
14#[derive(Debug, Clone, PartialEq, Default)]
15pub enum Value {
16    /// Null value.
17    #[default]
18    Null,
19    /// Boolean value (true or false).
20    Bool(bool),
21    /// 64-bit signed integer.
22    Int(i64),
23    /// 64-bit floating-point number.
24    Float(f64),
25    /// UTF-8 string.
26    String(String),
27    /// Binary data (byte array).
28    Binary(Binary),
29    /// Timestamp with timezone (ISO8601/RFC3339 compatible).
30    Timestamp(Timestamp),
31    /// Ordered list of values.
32    List(Vec<Value>),
33    /// Map of string keys to values.
34    Map(BTreeMap<String, Value>),
35}
36
37/// Display implementation for Value using debug formatting.
38///
39/// For proper JASN formatting, use the `jasn` crate's formatting functions.
40impl std::fmt::Display for Value {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        write!(f, "{:?}", self)
43    }
44}
45
46impl Value {
47    /// Returns true if the value is [`Self::Null`].
48    pub fn is_null(&self) -> bool {
49        matches!(self, Value::Null)
50    }
51
52    /// Returns true if the value is [`Self::Bool`].
53    pub fn is_bool(&self) -> bool {
54        matches!(self, Value::Bool(_))
55    }
56
57    /// Returns true if the value is [`Self::Int`].
58    pub fn is_int(&self) -> bool {
59        matches!(self, Value::Int(_))
60    }
61
62    /// Returns true if the value is [`Self::Float`].
63    pub fn is_float(&self) -> bool {
64        matches!(self, Value::Float(_))
65    }
66
67    /// Returns true if the value is [`Self::String`].
68    pub fn is_string(&self) -> bool {
69        matches!(self, Value::String(_))
70    }
71
72    /// Returns true if the value is [`Self::Binary`].
73    pub fn is_binary(&self) -> bool {
74        matches!(self, Value::Binary(_))
75    }
76
77    /// Returns true if the value is [`Self::Timestamp`].
78    pub fn is_timestamp(&self) -> bool {
79        matches!(self, Value::Timestamp(_))
80    }
81
82    /// Returns true if the value is [`Self::List`].
83    pub fn is_list(&self) -> bool {
84        matches!(self, Value::List(_))
85    }
86
87    /// Returns true if the value is [`Self::Map`].
88    pub fn is_map(&self) -> bool {
89        matches!(self, Value::Map(_))
90    }
91
92    /// Returns the [`bool`] value if this is a [`Self::Bool`], otherwise `None`.
93    pub fn as_bool(&self) -> Option<bool> {
94        match self {
95            Value::Bool(b) => Some(*b),
96            _ => None,
97        }
98    }
99
100    /// Returns the [`i64`] value if this is a [`Self::Int`], otherwise `None`.
101    pub fn as_int(&self) -> Option<i64> {
102        match self {
103            Value::Int(i) => Some(*i),
104            _ => None,
105        }
106    }
107
108    /// Returns the [`f64`] value if this is a [`Self::Float`], otherwise `None`.
109    pub fn as_float(&self) -> Option<f64> {
110        match self {
111            Value::Float(f) => Some(*f),
112            _ => None,
113        }
114    }
115
116    /// Returns the [`str`] if this is a [`Self::String`], otherwise `None`.
117    pub fn as_string(&self) -> Option<&str> {
118        match self {
119            Value::String(s) => Some(s),
120            _ => None,
121        }
122    }
123
124    /// Returns the [`Binary`] if this is a [`Self::Binary`], otherwise `None`.
125    pub fn as_binary(&self) -> Option<&Binary> {
126        match self {
127            Value::Binary(b) => Some(b),
128            _ => None,
129        }
130    }
131
132    /// Returns the [`Timestamp`] value if this is a [`Self::Timestamp`], otherwise `None`.
133    pub fn as_timestamp(&self) -> Option<&Timestamp> {
134        match self {
135            Value::Timestamp(t) => Some(t),
136            _ => None,
137        }
138    }
139
140    /// Returns the list of values if this is a [`Self::List`], otherwise `None`.
141    pub fn as_list(&self) -> Option<&[Value]> {
142        match self {
143            Value::List(l) => Some(l),
144            _ => None,
145        }
146    }
147
148    /// Returns the map of key-value pairs if this is a [`Self::Map`], otherwise `None`.
149    pub fn as_map(&self) -> Option<&BTreeMap<String, Value>> {
150        match self {
151            Value::Map(m) => Some(m),
152            _ => None,
153        }
154    }
155
156    /// Returns a mutable reference to the list of values if this is a [`Self::List`], otherwise `None`.
157    pub fn as_list_mut(&mut self) -> Option<&mut Vec<Value>> {
158        match self {
159            Value::List(l) => Some(l),
160            _ => None,
161        }
162    }
163
164    /// Returns a mutable reference to the map of key-value pairs if this is a [`Self::Map`], otherwise `None`.
165    pub fn as_map_mut(&mut self) -> Option<&mut BTreeMap<String, Value>> {
166        match self {
167            Value::Map(m) => Some(m),
168            _ => None,
169        }
170    }
171
172    /// Takes the value, leaving [`Self::Null`] in its place.
173    pub fn take(&mut self) -> Value {
174        std::mem::replace(self, Value::Null)
175    }
176}
177
178impl From<()> for Value {
179    fn from(_: ()) -> Self {
180        Value::Null
181    }
182}
183
184impl From<bool> for Value {
185    fn from(value: bool) -> Self {
186        Value::Bool(value)
187    }
188}
189
190impl From<i64> for Value {
191    fn from(value: i64) -> Self {
192        Value::Int(value)
193    }
194}
195
196impl From<f64> for Value {
197    fn from(value: f64) -> Self {
198        Value::Float(value)
199    }
200}
201
202impl From<String> for Value {
203    fn from(value: String) -> Self {
204        Value::String(value)
205    }
206}
207
208impl From<&str> for Value {
209    fn from(value: &str) -> Self {
210        Value::String(value.to_string())
211    }
212}
213
214impl<'a> From<Cow<'a, str>> for Value {
215    fn from(value: Cow<'a, str>) -> Self {
216        Value::String(value.into_owned())
217    }
218}
219
220impl From<Binary> for Value {
221    fn from(value: Binary) -> Self {
222        Value::Binary(value)
223    }
224}
225
226impl From<Timestamp> for Value {
227    fn from(value: Timestamp) -> Self {
228        Value::Timestamp(value)
229    }
230}
231
232impl<V> From<Vec<V>> for Value
233where
234    V: Into<Value>,
235{
236    fn from(vec: Vec<V>) -> Self {
237        vec.into_iter().collect()
238    }
239}
240
241impl<V> From<&[V]> for Value
242where
243    V: Into<Value> + Clone,
244{
245    fn from(slice: &[V]) -> Self {
246        slice.iter().cloned().collect()
247    }
248}
249
250impl<V, const N: usize> From<[V; N]> for Value
251where
252    V: Into<Value>,
253{
254    fn from(arr: [V; N]) -> Self {
255        arr.into_iter().collect()
256    }
257}
258
259impl<V, const N: usize> From<&[V; N]> for Value
260where
261    V: Into<Value> + Clone,
262{
263    fn from(arr: &[V; N]) -> Self {
264        arr.iter().cloned().collect()
265    }
266}
267
268impl<V> FromIterator<V> for Value
269where
270    V: Into<Value>,
271{
272    fn from_iter<I: IntoIterator<Item = V>>(iter: I) -> Self {
273        Value::List(iter.into_iter().map(Into::into).collect())
274    }
275}
276
277impl<K, V> FromIterator<(K, V)> for Value
278where
279    K: Into<String>,
280    V: Into<Value>,
281{
282    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
283        Value::Map(
284            iter.into_iter()
285                .map(|(k, v)| (k.into(), v.into()))
286                .collect(),
287        )
288    }
289}
290
291impl<K, V> From<&[(K, V)]> for Value
292where
293    K: Into<String> + Clone,
294    V: Into<Value> + Clone,
295{
296    fn from(slice: &[(K, V)]) -> Self {
297        slice.iter().cloned().collect()
298    }
299}
300
301impl<K, V, const N: usize> From<[(K, V); N]> for Value
302where
303    K: Into<String>,
304    V: Into<Value>,
305{
306    fn from(arr: [(K, V); N]) -> Self {
307        arr.into_iter().collect()
308    }
309}
310
311impl<K, V, const N: usize> From<&[(K, V); N]> for Value
312where
313    K: Into<String> + Clone,
314    V: Into<Value> + Clone,
315{
316    fn from(arr: &[(K, V); N]) -> Self {
317        arr.iter().cloned().collect()
318    }
319}
320
321impl<V> From<Option<V>> for Value
322where
323    V: Into<Value>,
324{
325    fn from(opt: Option<V>) -> Self {
326        match opt {
327            Some(v) => v.into(),
328            None => Value::Null,
329        }
330    }
331}
332
333impl PartialEq<str> for Value {
334    fn eq(&self, other: &str) -> bool {
335        self.as_string() == Some(other)
336    }
337}
338
339impl PartialEq<&str> for Value {
340    fn eq(&self, other: &&str) -> bool {
341        self.as_string() == Some(*other)
342    }
343}
344
345impl PartialEq<String> for Value {
346    fn eq(&self, other: &String) -> bool {
347        self.as_string() == Some(other.as_str())
348    }
349}
350
351impl PartialEq<i64> for Value {
352    fn eq(&self, other: &i64) -> bool {
353        self.as_int() == Some(*other)
354    }
355}
356
357impl PartialEq<f64> for Value {
358    fn eq(&self, other: &f64) -> bool {
359        self.as_float() == Some(*other)
360    }
361}
362
363impl PartialEq<bool> for Value {
364    fn eq(&self, other: &bool) -> bool {
365        self.as_bool() == Some(*other)
366    }
367}
368
369#[cfg(test)]
370mod tests {
371    use rstest::rstest;
372
373    use super::*;
374
375    #[rstest]
376    #[case(Value::Null, "null")]
377    #[case(Value::Bool(true), "bool")]
378    #[case(Value::Int(42), "int")]
379    #[case(Value::Float(2.5), "float")]
380    #[case(Value::String("hello".to_string()), "string")]
381    #[case(Value::Binary(Binary(vec![1, 2, 3])), "binary")]
382    #[case(Value::Timestamp(Timestamp::from_unix_timestamp(1234567890).unwrap()), "timestamp")]
383    #[case(Value::List(vec![Value::Null]), "list")]
384    #[case(Value::Map(BTreeMap::new()), "map")]
385    fn test_is_methods(#[case] value: Value, #[case] value_type: &str) {
386        assert_eq!(value.is_null(), value_type == "null");
387        assert_eq!(value.is_bool(), value_type == "bool");
388        assert_eq!(value.is_int(), value_type == "int");
389        assert_eq!(value.is_float(), value_type == "float");
390        assert_eq!(value.is_string(), value_type == "string");
391        assert_eq!(value.is_binary(), value_type == "binary");
392        assert_eq!(value.is_timestamp(), value_type == "timestamp");
393        assert_eq!(value.is_list(), value_type == "list");
394        assert_eq!(value.is_map(), value_type == "map");
395    }
396
397    #[test]
398    fn test_as_bool() {
399        assert_eq!(Value::Bool(true).as_bool(), Some(true));
400        assert_eq!(Value::Null.as_bool(), None);
401    }
402
403    #[test]
404    fn test_as_int() {
405        assert_eq!(Value::Int(42).as_int(), Some(42));
406        assert_eq!(Value::Float(2.5).as_int(), None);
407    }
408
409    #[test]
410    fn test_as_float() {
411        assert_eq!(Value::Float(2.5).as_float(), Some(2.5));
412        assert_eq!(Value::Int(42).as_float(), None);
413    }
414
415    #[test]
416    fn test_as_string() {
417        assert_eq!(
418            Value::String("hello".to_string()).as_string(),
419            Some("hello")
420        );
421        assert_eq!(Value::Null.as_string(), None);
422    }
423
424    #[test]
425    fn test_as_binary() {
426        let binary = Binary(vec![1, 2, 3]);
427        let binary_val = Value::Binary(binary.clone());
428        assert_eq!(binary_val.as_binary(), Some(&binary));
429        assert_eq!(Value::Null.as_binary(), None);
430    }
431
432    #[test]
433    fn test_as_timestamp() {
434        let ts = Timestamp::from_unix_timestamp(1234567890).unwrap();
435        let ts_val = Value::Timestamp(ts);
436        assert_eq!(ts_val.as_timestamp(), Some(&ts));
437        assert_eq!(Value::Int(42).as_timestamp(), None);
438    }
439
440    #[test]
441    fn test_as_list() {
442        let list = vec![Value::Int(1), Value::Int(2)];
443        let list_val = Value::List(list.clone());
444        assert_eq!(list_val.as_list(), Some(list.as_slice()));
445        assert_eq!(Value::Null.as_list(), None);
446    }
447
448    #[test]
449    fn test_as_map() {
450        let mut map = BTreeMap::new();
451        map.insert("key".to_string(), Value::Int(42));
452        let map_val = Value::Map(map.clone());
453        assert_eq!(map_val.as_map(), Some(&map));
454        assert_eq!(Value::Null.as_map(), None);
455    }
456
457    #[rstest]
458    #[case(Value::from(()), Value::Null)]
459    #[case(Value::from(true), Value::Bool(true))]
460    #[case(Value::from(42i64), Value::Int(42))]
461    #[case(Value::from(2.5f64), Value::Float(2.5))]
462    #[case(Value::from("hello".to_string()), Value::String("hello".to_string()))]
463    #[case(Value::from("world"), Value::String("world".to_string()))]
464    fn test_from_primitives(#[case] actual: Value, #[case] expected: Value) {
465        assert_eq!(actual, expected);
466    }
467
468    #[test]
469    fn test_from_conversions() {
470        // From primitives - tested via rstest above
471
472        // From Cow
473        let owned: Cow<str> = Cow::Owned("owned".to_string());
474        assert_eq!(Value::from(owned), Value::String("owned".to_string()));
475        let borrowed: Cow<str> = Cow::Borrowed("borrowed");
476        assert_eq!(Value::from(borrowed), Value::String("borrowed".to_string()));
477
478        // From Binary
479        let binary = Binary(vec![1, 2, 3]);
480        assert_eq!(Value::from(binary.clone()), Value::Binary(binary));
481
482        // From Timestamp
483        let dt = Timestamp::from_unix_timestamp(1234567890).unwrap();
484        assert_eq!(Value::from(dt), Value::Timestamp(dt));
485
486        // Value::Binary from byte literal
487        let value = Value::Binary(b"data".into());
488        assert_eq!(value, Value::Binary(Binary(b"data".to_vec())));
489
490        // From Vec
491        let vec = vec![1i64, 2, 3];
492        let list_val = Value::from(vec);
493        assert_eq!(
494            list_val,
495            Value::List(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
496        );
497
498        // From &[V]
499        let slice: &[i64] = &[1, 2, 3];
500        let list_val = Value::from(slice);
501        assert_eq!(
502            list_val,
503            Value::List(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
504        );
505
506        // FromIterator for List
507        let list_val: Value = vec![1i64, 2, 3].into_iter().collect();
508        assert_eq!(
509            list_val,
510            Value::List(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
511        );
512
513        // FromIterator for Map
514        let map_val: Value = vec![("a", 1i64), ("b", 2)].into_iter().collect();
515        let mut expected_map = BTreeMap::new();
516        expected_map.insert("a".to_string(), Value::Int(1));
517        expected_map.insert("b".to_string(), Value::Int(2));
518        assert_eq!(map_val, Value::Map(expected_map));
519
520        // From &[(K, V)]
521        let slice: &[(&str, i64)] = &[("x", 10), ("y", 20)];
522        let map_val = Value::from(slice);
523        let mut expected_map = BTreeMap::new();
524        expected_map.insert("x".to_string(), Value::Int(10));
525        expected_map.insert("y".to_string(), Value::Int(20));
526        assert_eq!(map_val, Value::Map(expected_map));
527
528        // From [V; N] - owned array to List
529        let list_val = Value::from([1i64, 2, 3]);
530        assert_eq!(
531            list_val,
532            Value::List(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
533        );
534
535        // From &[V; N] - array reference to List
536        let arr = [4i64, 5, 6];
537        let list_val = Value::from(&arr);
538        assert_eq!(
539            list_val,
540            Value::List(vec![Value::Int(4), Value::Int(5), Value::Int(6)])
541        );
542
543        // From [(K, V); N] - owned array to Map
544        let map_val = Value::from([("a", 1i64), ("b", 2)]);
545        let mut expected_map = BTreeMap::new();
546        expected_map.insert("a".to_string(), Value::Int(1));
547        expected_map.insert("b".to_string(), Value::Int(2));
548        assert_eq!(map_val, Value::Map(expected_map));
549
550        // From &[(K, V); N] - array reference to Map
551        let arr = [("c", 3i64), ("d", 4)];
552        let map_val = Value::from(&arr);
553        let mut expected_map = BTreeMap::new();
554        expected_map.insert("c".to_string(), Value::Int(3));
555        expected_map.insert("d".to_string(), Value::Int(4));
556        assert_eq!(map_val, Value::Map(expected_map));
557
558        // From Option
559        assert_eq!(Value::from(Some(42i64)), Value::Int(42));
560        assert_eq!(Value::from(None::<i64>), Value::Null);
561    }
562
563    #[test]
564    fn test_default() {
565        assert_eq!(Value::default(), Value::Null);
566    }
567
568    #[test]
569    fn test_mutable_accessors() {
570        // as_list_mut
571        let mut list_val = Value::List(vec![Value::Int(1), Value::Int(2)]);
572        if let Some(list) = list_val.as_list_mut() {
573            list.push(Value::Int(3));
574            list[0] = Value::Int(10);
575        }
576        assert_eq!(
577            list_val,
578            Value::List(vec![Value::Int(10), Value::Int(2), Value::Int(3)])
579        );
580
581        // as_list_mut returns None for non-list
582        let mut int_val = Value::Int(42);
583        assert_eq!(int_val.as_list_mut(), None);
584
585        // as_map_mut
586        let mut map_val = Value::Map(BTreeMap::new());
587        if let Some(map) = map_val.as_map_mut() {
588            map.insert("key".to_string(), Value::Int(42));
589            if let Some(value) = map.get_mut("key") {
590                *value = Value::Int(99);
591            }
592        }
593        let mut expected = BTreeMap::new();
594        expected.insert("key".to_string(), Value::Int(99));
595        assert_eq!(map_val, Value::Map(expected));
596
597        // as_map_mut returns None for non-map
598        assert_eq!(int_val.as_map_mut(), None);
599    }
600
601    #[test]
602    fn test_take() {
603        let mut value = Value::Int(42);
604        let taken = value.take();
605        assert_eq!(taken, Value::Int(42));
606        assert_eq!(value, Value::Null);
607
608        let mut list = Value::List(vec![Value::Int(1), Value::Int(2)]);
609        let taken = list.take();
610        assert_eq!(taken, Value::List(vec![Value::Int(1), Value::Int(2)]));
611        assert_eq!(list, Value::Null);
612
613        // Taking from Null leaves Null
614        let mut null = Value::Null;
615        let taken = null.take();
616        assert_eq!(taken, Value::Null);
617        assert_eq!(null, Value::Null);
618    }
619
620    #[test]
621    fn test_partial_eq_string() {
622        let string_val = Value::String("hello".to_string());
623        assert_eq!(string_val, "hello");
624        assert_eq!(string_val, "hello".to_string());
625        assert_ne!(string_val, "world");
626    }
627
628    #[test]
629    fn test_partial_eq_int() {
630        let int_val = Value::Int(42);
631        assert_eq!(int_val, 42i64);
632        assert_ne!(int_val, 43i64);
633    }
634
635    #[test]
636    fn test_partial_eq_float() {
637        let float_val = Value::Float(2.5);
638        assert_eq!(float_val, 2.5f64);
639        assert_ne!(float_val, 1.5f64);
640    }
641
642    #[test]
643    fn test_partial_eq_bool() {
644        let bool_val = Value::Bool(true);
645        assert_eq!(bool_val, true);
646        assert_ne!(bool_val, false);
647    }
648
649    #[test]
650    fn test_partial_eq_mismatched_types() {
651        let int_val = Value::Int(42);
652        let string_val = Value::String("hello".to_string());
653        assert_ne!(int_val, "42");
654        assert_ne!(string_val, 42i64);
655    }
656}