libhaystack/haystack/filter/
path.rs

1// Copyright (C) 2020 - 2022, J2 Innovations
2
3//! Haystack filter path
4
5use crate::haystack::encoding::zinc::decode::id::Id;
6use std::fmt::{Display, Formatter, Result};
7use std::ops::Index;
8
9/// A `Filter` `Path` element
10///
11/// Used to resolve indirections such as `siteRef->dis`.
12///
13/// Path elements are name of [Ref](crate::val::Ref) tags in a Dict that would
14/// be resolved to other Dicts that have the same `id` tag as the value of the Ref path element.
15/// This indirection scheme allows chaining multiple dicts in a graph like arrangement.
16#[derive(PartialEq, Eq, PartialOrd, Clone, Debug)]
17pub struct Path {
18    segments: Vec<Id>,
19}
20
21impl Path {
22    /// `True` if this `Path` is empty
23    pub fn is_empty(&self) -> bool {
24        self.segments.is_empty()
25    }
26
27    /// `Path`'s length
28    pub fn len(&self) -> usize {
29        self.segments.len()
30    }
31
32    /// Obtain an `Id` iterator over `Path`s segments
33    pub fn iter(&'_ self) -> std::slice::Iter<'_, Id> {
34        self.segments.iter()
35    }
36}
37
38/// Creates `Path` from `Vec<Id>`
39impl From<Vec<Id>> for Path {
40    fn from(segments: Vec<Id>) -> Self {
41        Path { segments }
42    }
43}
44
45/// Creates `Path` from [Id](haystack::decoding::zinc::Id)
46impl From<Id> for Path {
47    fn from(segment: Id) -> Self {
48        Path {
49            segments: vec![segment],
50        }
51    }
52}
53
54/// Creates `Path` from `&str`
55impl From<&str> for Path {
56    fn from(segment: &str) -> Self {
57        Path::from(Id::from(segment))
58    }
59}
60
61impl Index<usize> for Path {
62    type Output = Id;
63
64    fn index(&self, index: usize) -> &Self::Output {
65        &self.segments[index]
66    }
67}
68
69impl Display for Path {
70    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
71        self.segments
72            .iter()
73            .enumerate()
74            .try_for_each(|(idx, id)| -> Result {
75                f.write_str(&id.to_string())?;
76                if idx < self.segments.len() - 1 {
77                    f.write_str("->")
78                } else {
79                    Ok(())
80                }
81            })
82    }
83}