1use bumpalo::Bump;
8
9use crate::model::number::{int_to_f64, whole_to_i64};
10use crate::model::value::{KindName, Map, Ref, RefKey, Value, ValueKind};
11
12#[derive(Debug, Clone, Copy, PartialEq)]
14pub enum ValueRef<'a> {
15 Null,
17 Bool(bool),
19 Int(i64),
21 Float(f64),
23 Str(&'a str),
25 List(&'a [ValueRef<'a>]),
27 Map(MapRef<'a>),
29 Ref {
32 kind: KindName,
34 id: &'a str,
36 },
37 Bytes(&'a [u8]),
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Default)]
43pub struct MapRef<'a>(pub &'a [(&'a str, ValueRef<'a>)]);
44
45impl<'a> MapRef<'a> {
46 #[must_use]
48 pub fn get(self, key: &str) -> Option<&'a ValueRef<'a>> {
49 self.0.iter().find(|(k, _)| *k == key).map(|(_, v)| v)
50 }
51
52 #[must_use = "an iterator does nothing until it is consumed"]
54 pub fn iter(self) -> impl ExactSizeIterator<Item = (&'a str, &'a ValueRef<'a>)> + 'a {
55 self.0.iter().map(|(k, v)| (*k, v))
56 }
57
58 #[must_use = "an iterator does nothing until it is consumed"]
60 pub fn keys(self) -> impl ExactSizeIterator<Item = &'a str> + 'a {
61 self.0.iter().map(|(k, _)| *k)
62 }
63
64 #[must_use]
66 pub fn len(self) -> usize {
67 self.0.len()
68 }
69
70 #[must_use]
72 pub fn is_empty(self) -> bool {
73 self.0.is_empty()
74 }
75}
76
77impl<'a> ValueRef<'a> {
78 #[must_use]
80 pub fn kind(&self) -> ValueKind {
81 match self {
82 ValueRef::Null => ValueKind::Null,
83 ValueRef::Bool(_) => ValueKind::Bool,
84 ValueRef::Int(_) => ValueKind::Int,
85 ValueRef::Float(_) => ValueKind::Float,
86 ValueRef::Str(_) => ValueKind::Str,
87 ValueRef::List(_) => ValueKind::List,
88 ValueRef::Map(_) => ValueKind::Map,
89 ValueRef::Ref { .. } => ValueKind::Ref,
90 ValueRef::Bytes(_) => ValueKind::Bytes,
91 }
92 }
93
94 #[must_use]
96 pub fn is_null(&self) -> bool {
97 matches!(self, ValueRef::Null)
98 }
99
100 #[must_use]
102 pub fn as_bool(&self) -> Option<bool> {
103 match self {
104 ValueRef::Bool(b) => Some(*b),
105 _ => None,
106 }
107 }
108
109 #[must_use]
111 pub fn as_i64(&self) -> Option<i64> {
112 match self {
113 ValueRef::Int(n) => Some(*n),
114 ValueRef::Float(f) => whole_to_i64(*f),
115 _ => None,
116 }
117 }
118
119 #[must_use]
121 pub fn as_f64(&self) -> Option<f64> {
122 match self {
123 ValueRef::Int(n) => Some(int_to_f64(*n)),
124 ValueRef::Float(f) => Some(*f),
125 _ => None,
126 }
127 }
128
129 #[must_use]
131 pub fn as_str(&self) -> Option<&'a str> {
132 match self {
133 ValueRef::Str(s) => Some(s),
134 _ => None,
135 }
136 }
137
138 #[must_use]
140 pub fn as_list(&self) -> Option<&'a [ValueRef<'a>]> {
141 match self {
142 ValueRef::List(l) => Some(l),
143 _ => None,
144 }
145 }
146
147 #[must_use]
149 pub fn as_map(&self) -> Option<MapRef<'a>> {
150 match self {
151 ValueRef::Map(m) => Some(*m),
152 _ => None,
153 }
154 }
155
156 #[must_use]
158 pub fn get(&self, key: &str) -> Option<&'a ValueRef<'a>> {
159 self.as_map()?.get(key)
160 }
161
162 #[must_use]
164 pub fn to_value(self) -> Value {
165 match self {
166 ValueRef::Null => Value::Null,
167 ValueRef::Bool(b) => Value::Bool(b),
168 ValueRef::Int(n) => Value::Int(n),
169 ValueRef::Float(f) => Value::Float(f),
170 ValueRef::Str(s) => Value::Str(s.to_string()),
171 ValueRef::List(l) => Value::List(l.iter().map(|v| v.to_value()).collect()),
172 ValueRef::Map(m) => {
173 let mut out = Map::with_capacity(m.len());
174 for (k, v) in m.iter() {
175 out.insert(k, v.to_value());
176 }
177 Value::Map(out)
178 }
179 ValueRef::Ref { kind, id } => Value::Ref(Ref::new(kind, RefKey::spelled(id))),
180 ValueRef::Bytes(b) => Value::Bytes(b.to_vec()),
181 }
182 }
183
184 #[must_use]
186 pub fn to_ref(self) -> Option<Ref> {
187 match self {
188 ValueRef::Ref { kind, id } => Some(Ref::new(kind, RefKey::spelled(id))),
189 _ => None,
190 }
191 }
192}
193
194impl Value {
195 pub fn borrow<'a>(&'a self, arena: &'a Bump) -> ValueRef<'a> {
197 match self {
198 Value::Null => ValueRef::Null,
199 Value::Bool(b) => ValueRef::Bool(*b),
200 Value::Int(n) => ValueRef::Int(*n),
201 Value::Float(f) => ValueRef::Float(*f),
202 Value::Str(s) => ValueRef::Str(s),
203 Value::List(l) => {
204 ValueRef::List(arena.alloc_slice_fill_iter(l.iter().map(|v| v.borrow(arena))))
205 }
206 Value::Map(m) => ValueRef::Map(MapRef(
207 arena.alloc_slice_fill_iter(m.iter().map(|(k, v)| (k, v.borrow(arena)))),
208 )),
209 Value::Ref(r) => ValueRef::Ref {
210 kind: r.kind,
211 id: r.id.as_str(),
212 },
213 Value::Bytes(b) => ValueRef::Bytes(b),
214 }
215 }
216}