Skip to main content

jaq_core/
val.rs

1//! Values that can be processed by jaq.
2//!
3//! To process your own value type with jaq,
4//! you need to implement the [`ValT`] trait.
5
6use crate::box_iter::BoxIter;
7use crate::path::Opt;
8use core::fmt::Display;
9use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
10
11// Makes `f64::from_str` accessible as intra-doc link.
12#[cfg(doc)]
13use core::str::FromStr;
14
15/// Value or eRror.
16pub type ValR<T, V = T> = Result<T, crate::Error<V>>;
17/// Stream of values and eRrors.
18pub type ValRs<'a, T, V = T> = BoxIter<'a, ValR<T, V>>;
19/// Value or eXception.
20///
21/// Use [`unwrap_valr`] to convert to [`ValR`].
22pub type ValX<'a, T, V = T> = Result<T, crate::Exn<'a, V>>;
23/// Stream of values and eXceptions.
24pub type ValXs<'a, T, V = T> = BoxIter<'a, ValX<'a, T, V>>;
25
26/// Convert a value exception [`ValX`] into a value result [`ValR`].
27///
28/// This should always succeed when called on results of a main filter.
29/// For any other filter, this may not succeed, i.e. panic.
30///
31/// If you are writing a native filter, e.g. `f(f1; ...; fn)`,
32/// do not use this function on outputs of `fi`!
33///
34/// This function will exit the current process if
35/// the value exception results from a call to the filter `halt`.
36/// If the `std` feature is disabled, this function panics instead.
37/// In a future jaq 3.0, this function should only be provided if
38/// the `std` feature is enabled.
39pub fn unwrap_valr<T, V>(v: ValX<T, V>) -> ValR<T, V> {
40    #[cfg(feature = "std")]
41    let exit = |exit_code| std::process::exit(exit_code);
42    #[cfg(not(feature = "std"))]
43    let exit = |exit_code| panic!("halt({})", exit_code);
44
45    let halt = |e: crate::Exn<_>| exit(e.get_halt().ok().unwrap());
46    v.map_err(|e| e.get_err().unwrap_or_else(halt))
47}
48
49/// Range of options, used for iteration operations.
50pub type Range<V> = core::ops::Range<Option<V>>;
51
52/// Values that can be processed by jaq.
53///
54/// Implement this trait if you want jaq to process your own type of values.
55pub trait ValT:
56    Clone
57    + Display
58    + From<bool>
59    + From<isize>
60    + From<alloc::string::String>
61    + From<Range<Self>>
62    + FromIterator<Self>
63    + PartialEq
64    + PartialOrd
65    + Add<Output = ValR<Self>>
66    + Sub<Output = ValR<Self>>
67    + Mul<Output = ValR<Self>>
68    + Div<Output = ValR<Self>>
69    + Rem<Output = ValR<Self>>
70    + Neg<Output = ValR<Self>>
71{
72    /// Create a number from a string.
73    ///
74    /// The number should adhere to the format accepted by [`f64::from_str`].
75    fn from_num(n: &str) -> ValR<Self>;
76
77    /// Create an associative map (or object) from a sequence of key-value pairs.
78    ///
79    /// This is used when creating values with the syntax `{k: v}`.
80    fn from_map<I: IntoIterator<Item = (Self, Self)>>(iter: I) -> ValR<Self>;
81
82    /// Yield the key-value pairs of a value.
83    ///
84    /// This is used to collect the paths of `.[]`.
85    /// It should yield any `key` for which `value | .[key]` is defined,
86    /// as well as its output.
87    fn key_values(self) -> BoxIter<'static, ValR<(Self, Self), Self>>;
88
89    /// Yield the children of a value.
90    ///
91    /// This is used by `.[]`.
92    fn values(self) -> alloc::boxed::Box<dyn Iterator<Item = ValR<Self>>>;
93
94    /// Yield the child of a value at the given index.
95    ///
96    /// This is used by `.[k]`.
97    ///
98    /// If `v.index(k)` is `Ok(_)`, then it is contained in `v.values()`.
99    fn index(self, index: &Self) -> ValR<Self>;
100
101    /// Yield a slice of the value with the given range.
102    ///
103    /// This is used by `.[s:e]`, `.[s:]`, and `.[:e]`.
104    fn range(self, range: Range<&Self>) -> ValR<Self>;
105
106    /// Map a function over the children of the value.
107    ///
108    /// This is used by
109    /// - `.[]  |= f` (`opt` = [`Opt::Essential`]) and
110    /// - `.[]? |= f` (`opt` = [`Opt::Optional`]).
111    ///
112    /// If the children of the value are undefined, then:
113    ///
114    /// - If `opt` is [`Opt::Essential`], return an error.
115    /// - If `opt` is [`Opt::Optional`] , return the input value.
116    fn map_values<'a, I: Iterator<Item = ValX<'a, Self>>>(
117        self,
118        opt: Opt,
119        f: impl Fn(Self) -> I,
120    ) -> ValX<'a, Self>;
121
122    /// Map a function over the child of the value at the given index.
123    ///
124    /// This is used by `.[k] |= f`.
125    ///
126    /// See [`Self::map_values`] for the behaviour of `opt`.
127    fn map_index<'a, I: Iterator<Item = ValX<'a, Self>>>(
128        self,
129        index: &Self,
130        opt: Opt,
131        f: impl Fn(Self) -> I,
132    ) -> ValX<'a, Self>;
133
134    /// Map a function over the slice of the value with the given range.
135    ///
136    /// This is used by `.[s:e] |= f`, `.[s:] |= f`, and `.[:e] |= f`.
137    ///
138    /// See [`Self::map_values`] for the behaviour of `opt`.
139    fn map_range<'a, I: Iterator<Item = ValX<'a, Self>>>(
140        self,
141        range: Range<&Self>,
142        opt: Opt,
143        f: impl Fn(Self) -> I,
144    ) -> ValX<'a, Self>;
145
146    /// Return a boolean representation of the value.
147    ///
148    /// This is used by `if v then ...`.
149    fn as_bool(&self) -> bool;
150
151    /// Convert value into a string value.
152    ///
153    /// This is used by `"\(v)"`.
154    fn into_string(self) -> Self;
155}