1use std::fmt;
4
5use crate::model::number::{int_to_f64, whole_to_i64};
7#[derive(Debug, Clone, PartialEq, Default)]
19pub enum Value {
20 #[default]
22 Null,
23 Bool(bool),
25 Int(i64),
27 Float(f64),
29 Str(String),
31 List(Vec<Value>),
33 Map(Map),
35 Ref(Ref),
37 Bytes(Vec<u8>),
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
47pub struct Ref {
48 pub kind: KindName,
50 pub id: RefKey,
52}
53
54impl Ref {
55 #[must_use]
57 pub fn new(kind: KindName, id: RefKey) -> Self {
58 Self { kind, id }
59 }
60
61 pub fn parse(kind: &str, id: &str) -> Result<Self, crate::typed::TypedError> {
67 let kind = KindName::new(kind)?;
68 let id = RefKey::new(id).map_err(|_| crate::typed::TypedError::BadId {
69 kind: Some(kind),
70 id: id.to_owned(),
71 })?;
72 Ok(Self { kind, id })
73 }
74
75 pub fn of<K: crate::Kind>(id: &K::Id) -> Self {
77 Self {
78 kind: K::kind_name(),
79 id: RefKey::spelled(&crate::schema::RefId::spell(id)),
80 }
81 }
82}
83
84impl fmt::Display for Ref {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 write!(f, "{}{}:{}", crate::names::TYPED, self.kind, self.id)
88 }
89}
90
91pub use super::map::Map;
92pub use super::reference::{KindName, RefKey};
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
97pub enum ValueKind {
98 Null,
100 Bool,
102 Int,
104 Float,
106 Str,
108 List,
110 Map,
112 Ref,
114 Bytes,
116}
117
118impl fmt::Display for ValueKind {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 f.write_str(match self {
121 ValueKind::Null => "null",
122 ValueKind::Bool => "true/false",
123 ValueKind::Int => "an integer",
124 ValueKind::Float => "a number",
125 ValueKind::Str => "a string",
126 ValueKind::List => "a list",
127 ValueKind::Map => "an object",
128 ValueKind::Ref => "a reference",
129 ValueKind::Bytes => "bytes",
130 })
131 }
132}
133
134impl Value {
135 pub fn kind(&self) -> ValueKind {
137 match self {
138 Value::Null => ValueKind::Null,
139 Value::Bool(_) => ValueKind::Bool,
140 Value::Int(_) => ValueKind::Int,
141 Value::Float(_) => ValueKind::Float,
142 Value::Str(_) => ValueKind::Str,
143 Value::List(_) => ValueKind::List,
144 Value::Map(_) => ValueKind::Map,
145 Value::Ref(_) => ValueKind::Ref,
146 Value::Bytes(_) => ValueKind::Bytes,
147 }
148 }
149
150 pub fn is_null(&self) -> bool {
152 matches!(self, Value::Null)
153 }
154
155 pub fn as_bool(&self) -> Option<bool> {
157 match self {
158 Value::Bool(b) => Some(*b),
159 _ => None,
160 }
161 }
162
163 pub fn as_i64(&self) -> Option<i64> {
165 match self {
166 Value::Int(n) => Some(*n),
167 Value::Float(f) => whole_to_i64(*f),
168 _ => None,
169 }
170 }
171
172 pub fn as_f64(&self) -> Option<f64> {
174 match self {
175 Value::Int(n) => Some(int_to_f64(*n)),
176 Value::Float(f) => Some(*f),
177 _ => None,
178 }
179 }
180
181 pub fn as_str(&self) -> Option<&str> {
183 match self {
184 Value::Str(s) => Some(s),
185 _ => None,
186 }
187 }
188
189 pub fn as_list(&self) -> Option<&[Value]> {
191 match self {
192 Value::List(l) => Some(l),
193 _ => None,
194 }
195 }
196
197 pub fn as_map(&self) -> Option<&Map> {
199 match self {
200 Value::Map(m) => Some(m),
201 _ => None,
202 }
203 }
204
205 pub fn get(&self, key: &str) -> Option<&Value> {
207 self.as_map()?.get(key)
208 }
209
210 pub fn at(&self, path: &Path) -> Option<&Value> {
212 let mut v = self;
213 for seg in path.segments() {
214 v = match (seg, v) {
215 (Seg::Key(k), Value::Map(m)) => m.get(k)?,
216 (Seg::Index(i), Value::List(l)) => l.get(*i)?,
217 _ => return None,
218 };
219 }
220 Some(v)
221 }
222
223 pub fn at_mut(&mut self, segs: &[Seg]) -> Option<&mut Value> {
225 let mut v = self;
226 for seg in segs {
227 v = match (seg, v) {
228 (Seg::Key(k), Value::Map(m)) => m.get_mut(k)?,
229 (Seg::Index(i), Value::List(l)) => l.get_mut(*i)?,
230 _ => return None,
231 };
232 }
233 Some(v)
234 }
235}
236
237impl From<bool> for Value {
238 fn from(b: bool) -> Self {
239 Value::Bool(b)
240 }
241}
242impl From<i64> for Value {
243 fn from(n: i64) -> Self {
244 Value::Int(n)
245 }
246}
247impl From<f64> for Value {
248 fn from(f: f64) -> Self {
249 Value::Float(f)
250 }
251}
252impl From<&str> for Value {
253 fn from(s: &str) -> Self {
254 Value::Str(s.to_string())
255 }
256}
257impl From<String> for Value {
258 fn from(s: String) -> Self {
259 Value::Str(s)
260 }
261}
262impl From<Vec<Value>> for Value {
263 fn from(l: Vec<Value>) -> Self {
264 Value::List(l)
265 }
266}
267impl From<Map> for Value {
268 fn from(m: Map) -> Self {
269 Value::Map(m)
270 }
271}
272
273#[derive(Debug, Clone, PartialEq, Eq, Hash, crate::Schema)]
275#[data(tag = "type")]
276pub enum Seg {
277 Key(String),
279 Index(usize),
281}
282
283#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
285pub struct Path(Vec<Seg>);
286
287impl Path {
288 #[must_use]
290 pub fn root() -> Self {
291 Self(Vec::new())
292 }
293
294 #[must_use]
296 pub fn segments(&self) -> &[Seg] {
297 &self.0
298 }
299
300 #[must_use]
302 pub fn is_root(&self) -> bool {
303 self.0.is_empty()
304 }
305
306 pub fn push(&mut self, seg: Seg) {
308 self.0.push(seg);
309 }
310
311 pub fn pop(&mut self) {
313 self.0.pop();
314 }
315
316 #[must_use]
318 pub fn key(&self, key: &str) -> Path {
319 let mut p = self.clone();
320 p.0.push(Seg::Key(key.to_string()));
321 p
322 }
323
324 #[must_use]
326 pub fn then(&self, rest: &Path) -> Path {
327 let mut p = self.clone();
328 p.0.extend(rest.0.iter().cloned());
329 p
330 }
331
332 #[must_use]
334 pub fn index(&self, i: usize) -> Path {
335 let mut p = self.clone();
336 p.0.push(Seg::Index(i));
337 p
338 }
339}
340
341impl crate::Schema for Path {
343 fn shape() -> crate::Shape {
344 Vec::<Seg>::shape()
345 }
346 fn read(v: &crate::ValueRef<'_>, cx: &mut crate::Reader<'_>) -> Option<Self> {
347 Vec::<Seg>::read(v, cx).map(Path)
348 }
349 fn write(&self) -> Value {
350 self.0.write()
351 }
352 fn pack(&self, p: &mut crate::frame::Packer) {
353 self.0.pack(p);
354 }
355 fn unpack(u: &mut crate::frame::Unpacker<'_>) -> Option<Self> {
356 Vec::<Seg>::unpack(u).map(Path)
357 }
358}
359
360impl fmt::Display for Path {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 if self.0.is_empty() {
363 return f.write_str("(root)");
364 }
365 for (i, seg) in self.0.iter().enumerate() {
366 match seg {
367 Seg::Key(k) if is_plain_key(k) => {
368 if i > 0 {
369 f.write_str(".")?;
370 }
371 f.write_str(k)?;
372 }
373 Seg::Key(k) => write!(f, "[{k:?}]")?,
374 Seg::Index(n) => write!(f, "[{n}]")?,
375 }
376 }
377 Ok(())
378 }
379}
380
381fn is_plain_key(k: &str) -> bool {
382 let mut chars = k.chars();
383 chars
384 .next()
385 .is_some_and(|c| c.is_ascii_alphabetic() || c == '_' || c == '$')
386 && chars.all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '$')
387}