jaq_syn/
path.rs

1//! Value access and iteration.
2use alloc::vec::Vec;
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6/// A path such as `.[].a?[1:]`.
7pub type Path<T> = Vec<(Part<crate::Spanned<T>>, Opt)>;
8
9/// A part of a path, such as `[]`, `a`, and `[1:]` in `.[].a?[1:]`.
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11#[derive(Clone, Debug)]
12pub enum Part<I> {
13    /// Access arrays with integer and objects with string indices
14    Index(I),
15    /// Iterate over arrays with optional range bounds and over objects without bounds
16    Range(Option<I>, Option<I>),
17}
18
19impl<I> Default for Part<I> {
20    fn default() -> Self {
21        Self::Range(None, None)
22    }
23}
24
25/// Optionality of a path part, i.e. whether `?` is present.
26///
27/// For example, `[] | .a` fails with an error, while `[] | .a?` returns nothing.
28/// By default, path parts are *essential*, meaning that they fail.
29/// Annotating them with `?` makes them *optional*.
30#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
31#[derive(Copy, Clone, Debug)]
32pub enum Opt {
33    /// Return nothing if the input cannot be accessed with the path
34    Optional,
35    /// Fail if the input cannot be accessed with the path
36    Essential,
37}
38
39impl<I> Part<I> {
40    /// Apply a function to the contained indices.
41    pub fn map<J>(self, mut f: impl FnMut(I) -> J) -> Part<J> {
42        match self {
43            Self::Index(i) => Part::Index(f(i)),
44            Self::Range(l, h) => Part::Range(l.map(&mut f), h.map(f)),
45        }
46    }
47}
48
49impl Opt {
50    /// If `self` is optional, return `x`, else fail with `f(x)`.
51    pub fn fail<T, E>(self, x: T, f: impl FnOnce(T) -> E) -> Result<T, E> {
52        match self {
53            Self::Optional => Ok(x),
54            Self::Essential => Err(f(x)),
55        }
56    }
57
58    /// If `self` is optional, return all items of the iterator that are `Ok` and succeed,
59    /// else return all items of the iterator and fail if any is `Err`.
60    pub fn collect<T, E>(self, iter: impl Iterator<Item = Result<T, E>>) -> Result<Vec<T>, E> {
61        match self {
62            Self::Optional => Ok(iter.filter_map(|x| x.ok()).collect()),
63            Self::Essential => iter.collect(),
64        }
65    }
66}