edn_rs/edn/utils/
index.rs

1use alloc::borrow::ToOwned;
2use alloc::string::{String, ToString};
3use core::convert::TryFrom;
4use core::{fmt, ops};
5
6use crate::edn::{Edn, Map};
7
8/// This is a Copy of [`Serde_json::index`](https://docs.serde.rs/src/serde_json/value/index.rs.html)
9pub trait Index: private::Sealed {
10    fn index_into<'v>(&self, v: &'v Edn) -> Option<&'v Edn>;
11
12    fn index_into_mut<'v>(&self, v: &'v mut Edn) -> Option<&'v mut Edn>;
13
14    fn index_or_insert<'v>(&self, v: &'v mut Edn) -> &'v mut Edn;
15}
16
17impl Index for usize {
18    fn index_into<'v>(&self, v: &'v Edn) -> Option<&'v Edn> {
19        match *v {
20            Edn::Vector(ref vec) => vec.0.get(*self),
21            Edn::List(ref vec) => vec.0.get(*self),
22            Edn::Map(ref map) => map.0.get(&self.to_string()),
23            _ => None,
24        }
25    }
26    fn index_into_mut<'v>(&self, v: &'v mut Edn) -> Option<&'v mut Edn> {
27        match *v {
28            Edn::Vector(ref mut vec) => vec.0.get_mut(*self),
29            Edn::List(ref mut vec) => vec.0.get_mut(*self),
30            Edn::Map(ref mut map) => map.0.get_mut(&self.to_string()),
31            _ => None,
32        }
33    }
34    fn index_or_insert<'v>(&self, v: &'v mut Edn) -> &'v mut Edn {
35        match *v {
36            Edn::Vector(ref mut vec) => {
37                let len = vec.0.len();
38                vec.0.get_mut(*self).unwrap_or_else(|| {
39                    panic!("cannot access index {self} of EDN array of length {len}")
40                })
41            }
42            _ => panic!("cannot access index {} of EDN {}", self, Type(v)),
43        }
44    }
45}
46
47impl Index for str {
48    fn index_into<'v>(&self, v: &'v Edn) -> Option<&'v Edn> {
49        match *v {
50            Edn::Map(ref map) => map.0.get(self),
51            _ => None,
52        }
53    }
54    fn index_into_mut<'v>(&self, v: &'v mut Edn) -> Option<&'v mut Edn> {
55        match *v {
56            Edn::Map(ref mut map) => map.0.get_mut(self),
57            _ => None,
58        }
59    }
60    fn index_or_insert<'v>(&self, v: &'v mut Edn) -> &'v mut Edn {
61        if *v == Edn::Nil {
62            *v = Edn::Map(Map::new(alloc::collections::BTreeMap::new()));
63        }
64        match *v {
65            Edn::Map(ref mut map) => map.0.entry(self.to_owned()).or_insert(Edn::Nil),
66            _ => panic!("cannot access key {:?} in EDN {}", self, Type(v)),
67        }
68    }
69}
70
71impl Index for String {
72    fn index_into<'v>(&self, v: &'v Edn) -> Option<&'v Edn> {
73        self[..].index_into(v)
74    }
75    fn index_into_mut<'v>(&self, v: &'v mut Edn) -> Option<&'v mut Edn> {
76        self[..].index_into_mut(v)
77    }
78    fn index_or_insert<'v>(&self, v: &'v mut Edn) -> &'v mut Edn {
79        self[..].index_or_insert(v)
80    }
81}
82
83impl Index for Edn {
84    fn index_into<'v>(&self, v: &'v Edn) -> Option<&'v Edn> {
85        let key = self.to_string();
86        let index = self.to_uint();
87
88        match (v, index) {
89            (Self::Map(map), _) => map.0.get(&key),
90            (Self::List(_) | Self::Vector(_), Some(idx)) => {
91                // A panic is expected behavior when trying to index beyond usize
92                let idx = usize::try_from(idx).unwrap();
93                idx.index_into(v)
94            }
95            _ => None,
96        }
97    }
98    fn index_into_mut<'v>(&self, _: &'v mut Edn) -> Option<&'v mut Edn> {
99        panic!("index_into_mut not implemented for edn")
100    }
101    fn index_or_insert<'v>(&self, _: &'v mut Edn) -> &'v mut Edn {
102        panic!("index_or_insert not implemented for edn")
103    }
104}
105
106impl<T> Index for &T
107where
108    T: ?Sized + Index,
109{
110    fn index_into<'v>(&self, v: &'v Edn) -> Option<&'v Edn> {
111        (**self).index_into(v)
112    }
113    fn index_into_mut<'v>(&self, v: &'v mut Edn) -> Option<&'v mut Edn> {
114        (**self).index_into_mut(v)
115    }
116    fn index_or_insert<'v>(&self, v: &'v mut Edn) -> &'v mut Edn {
117        (**self).index_or_insert(v)
118    }
119}
120
121// Prevent users from implementing the Index trait.
122mod private {
123    use alloc::string::String;
124
125    use crate::Edn;
126
127    pub trait Sealed {}
128    impl Sealed for usize {}
129    impl Sealed for str {}
130    impl Sealed for String {}
131    impl Sealed for Edn {}
132    impl<T> Sealed for &T where T: ?Sized + Sealed {}
133}
134struct Type<'a>(&'a Edn);
135
136impl fmt::Display for Type<'_> {
137    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
138        match *self.0 {
139            Edn::Empty => formatter.write_str("empty"),
140            Edn::Nil => formatter.write_str("null"),
141            Edn::Bool(_) => formatter.write_str("boolean"),
142            Edn::Int(_) | Edn::UInt(_) => formatter.write_str("integer"),
143            Edn::Str(_) => formatter.write_str("string"),
144            Edn::Vector(_) => formatter.write_str("vector"),
145            #[cfg(feature = "sets")]
146            Edn::Set(_) => formatter.write_str("set"),
147            Edn::List(_) => formatter.write_str("list"),
148            Edn::Map(_) => formatter.write_str("map"),
149            Edn::Key(_) => formatter.write_str("key"),
150            Edn::Char(_) => formatter.write_str("char"),
151            Edn::Symbol(_) => formatter.write_str("symbol"),
152            Edn::Double(_) => formatter.write_str("double"),
153            Edn::Rational(_) => formatter.write_str("rational"),
154            Edn::Tagged(_, _) => formatter.write_str("tagged-element"),
155        }
156    }
157}
158
159impl<I> ops::Index<I> for Edn
160where
161    I: Index,
162{
163    type Output = Self;
164    fn index(&self, index: I) -> &Self {
165        static NULL: Edn = Edn::Nil;
166        index.index_into(self).unwrap_or(&NULL)
167    }
168}
169
170impl<I> ops::IndexMut<I> for Edn
171where
172    I: Index,
173{
174    fn index_mut(&mut self, index: I) -> &mut Self {
175        index.index_or_insert(self)
176    }
177}