tracing_formatters/
index.rs

1use crate::value::Value;
2use core::fmt;
3use core::fmt::Display;
4use std::collections::BTreeMap;
5use std::ops;
6
7pub trait Index: private::Sealed {
8    /// Return None if the key is not already in the array or object.
9    #[doc(hidden)]
10    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
11
12    /// Return None if the key is not already in the array or object.
13    #[doc(hidden)]
14    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
15
16    /// Panic if array index out of bounds. If key is not already in the object,
17    /// insert it with a value of null. Panic if Value is a type that cannot be
18    /// indexed into, except if Value is null then it can be treated as an empty
19    /// object.
20    #[doc(hidden)]
21    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
22}
23
24impl Index for usize {
25    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
26        match v {
27            Value::Array(vec) => vec.get(*self),
28            _ => None,
29        }
30    }
31    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
32        match v {
33            Value::Array(vec) => vec.get_mut(*self),
34            _ => None,
35        }
36    }
37    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
38        match v {
39            Value::Array(vec) => {
40                let len = vec.len();
41                vec.get_mut(*self).unwrap_or_else(|| {
42                    panic!(
43                        "cannot access index {} of JSON array of length {}",
44                        self, len
45                    )
46                })
47            }
48            _ => panic!("cannot access index {} of JSON {}", self, Type(v)),
49        }
50    }
51}
52
53impl Index for str {
54    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
55        match v {
56            Value::Map(map) => map.get(self),
57            _ => None,
58        }
59    }
60    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
61        match v {
62            Value::Map(map) => map.get_mut(self),
63            _ => None,
64        }
65    }
66    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
67        if let Value::Null = v {
68            *v = Value::Map(BTreeMap::new());
69        }
70        match v {
71            Value::Map(map) => map.entry(self.to_owned()).or_insert(Value::Null),
72            _ => panic!("cannot access key {:?} in JSON {}", self, Type(v)),
73        }
74    }
75}
76
77impl Index for String {
78    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
79        self[..].index_into(v)
80    }
81    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
82        self[..].index_into_mut(v)
83    }
84    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
85        self[..].index_or_insert(v)
86    }
87}
88
89impl<'a, T> Index for &'a T
90where
91    T: ?Sized + Index,
92{
93    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
94        (**self).index_into(v)
95    }
96    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
97        (**self).index_into_mut(v)
98    }
99    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
100        (**self).index_or_insert(v)
101    }
102}
103
104// Prevent users from implementing the Index trait.
105mod private {
106    pub trait Sealed {}
107    impl Sealed for usize {}
108    impl Sealed for str {}
109    impl Sealed for alloc::string::String {}
110    impl<'a, T> Sealed for &'a T where T: ?Sized + Sealed {}
111}
112
113/// Used in panic messages.
114struct Type<'a>(&'a Value);
115
116impl<'a> Display for Type<'a> {
117    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
118        match *self.0 {
119            Value::Null => formatter.write_str("null"),
120            Value::Bool(_) => formatter.write_str("boolean"),
121            Value::Int(_) => formatter.write_str("integer"),
122            Value::UInt(_) => formatter.write_str("uinteger"),
123            Value::Float(_) => formatter.write_str("float"),
124            Value::String(_) => formatter.write_str("string"),
125            Value::Array(_) => formatter.write_str("array"),
126            Value::Map(_) => formatter.write_str("object"),
127        }
128    }
129}
130
131impl<I> ops::Index<I> for Value
132where
133    I: Index,
134{
135    type Output = Value;
136
137    fn index(&self, index: I) -> &Value {
138        static NULL: Value = Value::Null;
139        index.index_into(self).unwrap_or(&NULL)
140    }
141}
142
143impl<I> ops::IndexMut<I> for Value
144where
145    I: Index,
146{
147    fn index_mut(&mut self, index: I) -> &mut Value {
148        index.index_or_insert(self)
149    }
150}