Skip to main content

pipa/value/
mod.rs

1// SPDX-FileCopyrightText: Copyright 2026 olav@occy.org
2// SPDX-License-Identifier: MPL-2.0
3
4pub mod bytes;
5pub(crate) mod equivalent;
6pub mod error;
7pub mod format;
8#[doc(hidden)]
9pub mod key;
10#[doc(hidden)]
11pub mod keys;
12pub mod list;
13pub mod map;
14#[doc(hidden)]
15pub mod meta;
16pub(crate) mod number;
17#[doc(hidden)]
18pub mod operation;
19pub mod parse;
20pub(crate) mod print;
21pub mod span;
22#[doc(hidden)]
23pub mod tracer;
24
25use crate::value::number::Number;
26use crate::value::print::Print;
27use crate::value::span::Span;
28use bytes::Bytes;
29use key::Key;
30use keys::Keys;
31use list::List;
32use map::Map;
33use meta::Meta;
34use serde::Deserialize;
35use serde::Serialize;
36use tracer::Tracer;
37
38/// The core value type.
39#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
40#[serde(rename_all = "kebab-case")]
41pub enum Value {
42    /// A list of bytes.
43    Bytes(Bytes),
44    /// A list of values.
45    List(List),
46    /// A map from bytes to values.
47    Map(Map),
48}
49
50impl core::fmt::Display for Value {
51    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
52        f.write_str(&String::from_utf8_lossy(&self.clone().print_syntax()))
53    }
54}
55
56impl Default for Value {
57    fn default() -> Self {
58        Value::Bytes(Bytes::default())
59    }
60}
61
62impl From<Vec<u8>> for Value {
63    fn from(value: Vec<u8>) -> Self {
64        Value::Bytes(Bytes::from(value))
65    }
66}
67
68impl From<&[u8]> for Value {
69    fn from(value: &[u8]) -> Self {
70        Value::from(value.to_vec())
71    }
72}
73
74impl From<String> for Value {
75    fn from(value: String) -> Self {
76        Value::from(value.into_bytes())
77    }
78}
79
80impl From<&str> for Value {
81    fn from(value: &str) -> Self {
82        Value::from(value.to_string())
83    }
84}
85
86impl From<char> for Value {
87    fn from(value: char) -> Self {
88        Value::from(value.to_string())
89    }
90}
91
92impl From<usize> for Value {
93    fn from(value: usize) -> Self {
94        Value::from(value.to_string())
95    }
96}
97
98impl From<isize> for Value {
99    fn from(value: isize) -> Self {
100        Value::from(value.to_string())
101    }
102}
103
104impl From<bool> for Value {
105    fn from(value: bool) -> Self {
106        match value {
107            true => Value::from(value.to_string()),
108            false => Value::default(),
109        }
110    }
111}
112
113impl From<Span> for Value {
114    fn from(value: Span) -> Self {
115        Value::List(List::default().with(value.0).with(value.1))
116    }
117}
118
119impl From<Key> for Value {
120    fn from(value: Key) -> Self {
121        Value::from(Vec::<u8>::from(value))
122    }
123}
124
125impl From<Keys> for Value {
126    fn from(value: Keys) -> Self {
127        Value::List(value.into_vec().into_iter().map(Value::from).collect())
128    }
129}
130
131impl From<Tracer> for Value {
132    fn from(value: Tracer) -> Self {
133        Value::Map(
134            Map::default()
135                .with("source", value.source)
136                .with("span", value.span)
137                .with("keys", value.keys)
138                .with("raw", value.raw),
139        )
140    }
141}
142
143impl From<Bytes> for Value {
144    fn from(value: Bytes) -> Self {
145        Value::Bytes(value)
146    }
147}
148
149impl From<List> for Value {
150    fn from(value: List) -> Self {
151        Value::List(value)
152    }
153}
154
155impl From<Map> for Value {
156    fn from(value: Map) -> Self {
157        Value::Map(value)
158    }
159}
160
161impl<T: Into<Value>> From<Option<T>> for Value {
162    fn from(value: Option<T>) -> Self {
163        value.map(Into::into).unwrap_or_default()
164    }
165}
166
167impl TryFrom<Value> for Bytes {
168    type Error = ();
169
170    fn try_from(value: Value) -> Result<Self, Self::Error> {
171        match value {
172            Value::Bytes(v) => Ok(v),
173            _ => Err(()),
174        }
175    }
176}
177
178impl From<Value> for List {
179    fn from(value: Value) -> Self {
180        vec![value].into()
181    }
182}
183
184impl TryFrom<Value> for Map {
185    type Error = ();
186
187    fn try_from(value: Value) -> Result<Self, Self::Error> {
188        match value {
189            Value::Map(v) => Ok(v),
190            _ => Err(()),
191        }
192    }
193}
194
195impl Value {
196    #[doc(hidden)]
197    pub fn with_data(mut self, other: Value) -> Self {
198        other
199            .append_meta(self.take_meta())
200            .with_tracer(self.take_tracer())
201    }
202
203    #[doc(hidden)]
204    pub fn with_meta<K: Into<Vec<u8>>, V: Into<Vec<u8>>>(mut self, key: K, value: V) -> Self {
205        match &mut self {
206            Value::Bytes(v) => v.meta.push(key, value),
207            Value::List(v) => v.meta.push(key, value),
208            Value::Map(v) => v.meta.push(key, value),
209        }
210
211        self
212    }
213
214    #[doc(hidden)]
215    pub fn without_meta(mut self, key: &[u8]) -> Self {
216        match &mut self {
217            Value::Bytes(v) => v.meta.remove(key),
218            Value::List(v) => v.meta.remove(key),
219            Value::Map(v) => v.meta.remove(key),
220        };
221
222        self
223    }
224
225    #[doc(hidden)]
226    pub fn append_meta(mut self, meta: Meta) -> Self {
227        match &mut self {
228            Value::Bytes(v) => v.meta.append(meta),
229            Value::List(v) => v.meta.append(meta),
230            Value::Map(v) => v.meta.append(meta),
231        }
232
233        self
234    }
235
236    #[doc(hidden)]
237    pub fn with_safe(self) -> Self {
238        self.with_meta("internal-safe", "")
239    }
240
241    #[doc(hidden)]
242    pub fn safe(&self) -> bool {
243        self.meta().contains(b"internal-safe")
244    }
245
246    #[doc(hidden)]
247    pub fn meta(&self) -> &Meta {
248        match self {
249            Value::Bytes(v) => &v.meta,
250            Value::List(v) => &v.meta,
251            Value::Map(v) => &v.meta,
252        }
253    }
254
255    #[doc(hidden)]
256    pub fn take_meta(&mut self) -> Meta {
257        core::mem::take(match self {
258            Value::Bytes(v) => &mut v.meta,
259            Value::List(v) => &mut v.meta,
260            Value::Map(v) => &mut v.meta,
261        })
262    }
263
264    #[doc(hidden)]
265    pub fn meta_mut(&mut self) -> &mut Meta {
266        match self {
267            Value::Bytes(v) => &mut v.meta,
268            Value::List(v) => &mut v.meta,
269            Value::Map(v) => &mut v.meta,
270        }
271    }
272
273    #[doc(hidden)]
274    pub fn with_tracer<T: Into<Tracer>>(mut self, tracer: T) -> Self {
275        self.trace(tracer);
276        self
277    }
278
279    #[doc(hidden)]
280    pub fn take_tracer(&mut self) -> Tracer {
281        core::mem::take(match self {
282            Value::Bytes(v) => &mut v.tracer,
283            Value::List(v) => &mut v.tracer,
284            Value::Map(v) => &mut v.tracer,
285        })
286    }
287
288    #[doc(hidden)]
289    pub fn trace<T: Into<Tracer>>(&mut self, tracer: T) {
290        match self {
291            Value::Bytes(v) => v.trace(tracer),
292            Value::List(v) => v.trace(tracer),
293            Value::Map(v) => v.trace(tracer),
294        }
295    }
296
297    #[doc(hidden)]
298    pub fn tracer(&self) -> &Tracer {
299        match self {
300            Value::Bytes(v) => v.tracer(),
301            Value::List(v) => v.tracer(),
302            Value::Map(v) => v.tracer(),
303        }
304    }
305
306    #[doc(hidden)]
307    pub(crate) fn len(&self) -> usize {
308        match self {
309            Value::Bytes(v) => v.data.len(),
310            Value::List(v) => v.data.len(),
311            Value::Map(v) => v.data.len(),
312        }
313    }
314
315    #[doc(hidden)]
316    pub fn is_empty(&self) -> bool {
317        match self {
318            Value::Bytes(v) => v.is_empty(),
319            Value::List(v) => v.is_empty(),
320            Value::Map(v) => v.is_empty(),
321        }
322    }
323
324    #[doc(hidden)]
325    pub fn as_str(&self) -> Option<&str> {
326        self.as_bytes().map(parse::str).transpose().ok().flatten()
327    }
328
329    pub fn as_usize(&self) -> Option<usize> {
330        self.as_bytes()
331            .and_then(|b| Number::try_from(b).ok())
332            .and_then(|n| n.try_into().ok())
333    }
334
335    #[doc(hidden)]
336    pub fn as_isize(&self) -> Option<isize> {
337        self.as_bytes()
338            .and_then(|b| Number::try_from(b).ok())
339            .and_then(|n| n.try_into().ok())
340    }
341
342    #[doc(hidden)]
343    pub(crate) fn as_number(&self) -> Option<Number> {
344        match self {
345            Value::Bytes(v) => Number::try_from(v.as_bytes()).ok(),
346            _ => None,
347        }
348    }
349
350    #[doc(hidden)]
351    pub fn as_bytes(&self) -> Option<&[u8]> {
352        match self {
353            Value::Bytes(v) => Some(v.as_bytes()),
354            Value::List(_) => None,
355            Value::Map(_) => None,
356        }
357    }
358
359    #[doc(hidden)]
360    pub fn as_list(&self) -> Option<&List> {
361        match self {
362            Value::Bytes(_) => None,
363            Value::List(v) => Some(v),
364            Value::Map(_) => None,
365        }
366    }
367
368    #[doc(hidden)]
369    pub fn as_map(&self) -> Option<&Map> {
370        match self {
371            Value::Bytes(_) => None,
372            Value::List(_) => None,
373            Value::Map(v) => Some(v),
374        }
375    }
376
377    #[doc(hidden)]
378    pub fn into_bytes(mut self) -> Bytes {
379        Bytes {
380            tracer: self.take_tracer(),
381            meta: self.take_meta(),
382            data: self.join(),
383        }
384    }
385
386    #[doc(hidden)]
387    pub fn into_list(self) -> List {
388        match self {
389            Value::Bytes(_) if !self.is_empty() => List::from(self),
390            Value::Bytes(_) => List::default(),
391            Value::List(v) => v,
392            Value::Map(v) => v.data.into_values().collect::<List>(),
393        }
394    }
395
396    #[doc(hidden)]
397    pub fn into_map(self) -> Map {
398        match self {
399            Value::Bytes(v) => Map::from((b"", v)),
400            Value::List(v) => v
401                .into_iter()
402                .enumerate()
403                .map(|(i, v)| (i.to_string().into_bytes(), v))
404                .collect(),
405            Value::Map(v) => v,
406        }
407    }
408
409    #[doc(hidden)]
410    pub fn into_other(self, other: &Value) -> Value {
411        match other {
412            Value::Bytes(_) => self.into_bytes().into(),
413            Value::List(_) => self.into_list().into(),
414            Value::Map(_) => self.into_map().into(),
415        }
416    }
417
418    #[doc(hidden)]
419    pub fn into_parts(self) -> List {
420        match self {
421            Value::Bytes(v) => v.as_chars(),
422            _ => self.into_list(),
423        }
424    }
425
426    #[doc(hidden)]
427    pub(crate) fn into_lists(values: Vec<Value>) -> Vec<List> {
428        values.into_iter().map(Value::into_list).collect()
429    }
430
431    #[doc(hidden)]
432    pub fn into_string(self) -> Option<String> {
433        String::from_utf8(self.join()).ok()
434    }
435
436    #[doc(hidden)]
437    pub fn into_string_lossy(self) -> String {
438        String::from_utf8(self.join())
439            .unwrap_or_else(|e| String::from_utf8_lossy(e.as_bytes()).into())
440    }
441
442    #[doc(hidden)]
443    pub(crate) fn intersection(values: Vec<Value>) -> Value {
444        List::intersection(Value::into_lists(values)).into()
445    }
446
447    #[doc(hidden)]
448    pub(crate) fn union(values: Vec<Value>) -> Value {
449        List::union(Value::into_lists(values)).into()
450    }
451
452    #[doc(hidden)]
453    pub fn flatten(self) -> Self {
454        Value::Bytes(self.into_bytes())
455    }
456
457    #[doc(hidden)]
458    pub fn clear(self) -> Value {
459        match self {
460            Value::Bytes(v) => Value::from(v.clear()),
461            Value::List(v) => Value::from(v.clear()),
462            Value::Map(v) => Value::from(v.clear()),
463        }
464    }
465
466    #[doc(hidden)]
467    pub fn split(self) -> Vec<Value> {
468        match self {
469            Value::Bytes(_) => self
470                .into_string_lossy()
471                .split_whitespace()
472                .filter(|c| !c.is_empty())
473                .map(Value::from)
474                .collect(),
475            Value::List(v) => v.data,
476            Value::Map(v) => v.data.into_values().collect(),
477        }
478    }
479
480    #[doc(hidden)]
481    pub fn join(self) -> Vec<u8> {
482        match self {
483            Value::Bytes(v) => v.join(),
484            Value::List(v) => v.join(),
485            Value::Map(v) => v.join(),
486        }
487    }
488
489    #[doc(hidden)]
490    pub(crate) fn into_first(self) -> Value {
491        match self {
492            Value::Bytes(v) => v.first().into(),
493            Value::List(v) => v.data.first().cloned().unwrap_or_else(Value::default),
494            Value::Map(v) => v
495                .data
496                .first()
497                .map(|(_, v)| v.clone())
498                .unwrap_or_else(Value::default),
499        }
500    }
501
502    #[doc(hidden)]
503    pub(crate) fn into_last(self) -> Value {
504        match self {
505            Value::Bytes(v) => v.last().into(),
506            Value::List(v) => v.data.last().cloned().unwrap_or_else(Value::default),
507            Value::Map(v) => v
508                .data
509                .last()
510                .map(|(_, v)| v.clone())
511                .unwrap_or_else(Value::default),
512        }
513    }
514
515    #[doc(hidden)]
516    pub(crate) fn into_rest(self) -> Value {
517        if self.is_empty() {
518            return self;
519        }
520        match self {
521            Value::Bytes(v) => v.rest().into(),
522            Value::List(mut v) => {
523                v.data.remove(0);
524                v.into()
525            }
526            Value::Map(mut v) => {
527                v.data.shift_remove_index(0);
528                v.into()
529            }
530        }
531    }
532
533    #[doc(hidden)]
534    pub fn fold(&mut self, other: Self) {
535        match (self, other) {
536            (Value::Bytes(a), Value::Bytes(b)) => a.fold(b),
537            (Value::List(a), Value::List(b)) => a.fold(b),
538            (Value::Map(a), Value::Map(b)) => a.fold(b),
539            (a, b) => *a = b,
540        }
541    }
542}
543
544#[cfg(test)]
545mod test {
546    use crate::value::Value;
547    use crate::value::list::List;
548    use crate::value::map::Map;
549
550    #[test]
551    fn test_join() {
552        let bytes = Value::from("a");
553        let map = Value::Map(Map::default().with("b", "c"));
554        let value = Value::List(List::default().with(bytes).with(map));
555        assert_eq!(value.join(), b"ac")
556    }
557
558    #[test]
559    fn test_display() {
560        let bytes = Value::from("a");
561        let map = Value::Map(Map::default().with("b", "c"));
562        let value = Value::List(List::default().with(bytes).with(map));
563        assert_eq!(value.to_string(), r#"["a" {b "c"}]"#)
564    }
565}