streamson_lib/matcher/
depth.rs1use std::str::FromStr;
4
5use super::Matcher;
6use crate::{error, path::Path, streamer::ParsedKind};
7
8#[derive(Default, Debug, Clone)]
12pub struct Depth {
13 min: usize,
14 max: Option<usize>,
15}
16
17impl Depth {
18 pub fn new(min: usize, max: Option<usize>) -> Self {
24 Self { min, max }
25 }
26}
27
28impl Matcher for Depth {
29 fn match_path(&self, path: &Path, _kind: ParsedKind) -> bool {
30 let depth = path.depth();
31 if let Some(max) = self.max {
32 self.min <= depth && depth <= max
33 } else {
34 self.min <= depth
35 }
36 }
37}
38
39impl FromStr for Depth {
40 type Err = error::Matcher;
41 fn from_str(s: &str) -> Result<Self, Self::Err> {
42 let splitted: Vec<&str> = s.splitn(2, '-').collect();
43 match splitted.len() {
44 1 => match splitted[0].parse() {
45 Ok(start) => Ok(Self::new(start, Some(start))),
46 Err(_) => Err(error::Matcher::Parse(s.into())),
47 },
48 2 => match (splitted[0].parse(), splitted[1].parse()) {
49 (Ok(start), Ok(end)) => {
50 if start > end {
51 Err(error::Matcher::Parse(s.into()))
52 } else {
53 Ok(Self::new(start, Some(end)))
54 }
55 }
56 (Ok(start), _) if splitted[1].is_empty() => Ok(Self::new(start, None)),
57 _ => Err(error::Matcher::Parse(s.into())),
58 },
59 _ => Err(error::Matcher::Parse(s.into())),
60 }
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::{Depth, Matcher};
67 use crate::{path::Path, streamer::ParsedKind};
68 use std::{convert::TryFrom, str::FromStr};
69
70 #[test]
71 fn match_path() {
72 let depth = Depth::from_str("2-").unwrap();
73
74 assert!(!depth.match_path(&Path::try_from(r#"{"People"}"#).unwrap(), ParsedKind::Arr));
75 assert!(depth.match_path(
76 &Path::try_from(r#"{"People"}[0]"#).unwrap(),
77 ParsedKind::Obj
78 ));
79 assert!(depth.match_path(
80 &Path::try_from(r#"{"People"}[0]{"Age"}"#).unwrap(),
81 ParsedKind::Num
82 ));
83 assert!(depth.match_path(
84 &Path::try_from(r#"{"People"}[0]{"Height"}"#).unwrap(),
85 ParsedKind::Num
86 ));
87 assert!(depth.match_path(
88 &Path::try_from(r#"{"People"}[1]"#).unwrap(),
89 ParsedKind::Obj
90 ));
91 assert!(depth.match_path(
92 &Path::try_from(r#"{"People"}[1]{"Age"}"#).unwrap(),
93 ParsedKind::Num
94 ));
95 assert!(depth.match_path(
96 &Path::try_from(r#"{"People"}[1]{"Height"}"#).unwrap(),
97 ParsedKind::Num
98 ));
99
100 let depth: Depth = "2-2".parse().unwrap();
101 assert!(!depth.match_path(&Path::try_from(r#"{"People"}"#).unwrap(), ParsedKind::Arr));
102 assert!(depth.match_path(
103 &Path::try_from(r#"{"People"}[0]"#).unwrap(),
104 ParsedKind::Obj
105 ));
106 assert!(!depth.match_path(
107 &Path::try_from(r#"{"People"}[0]{"Age"}"#).unwrap(),
108 ParsedKind::Num
109 ));
110 assert!(!depth.match_path(
111 &Path::try_from(r#"{"People"}[0]{"Height"}"#).unwrap(),
112 ParsedKind::Num
113 ));
114 assert!(depth.match_path(
115 &Path::try_from(r#"{"People"}[1]"#).unwrap(),
116 ParsedKind::Obj
117 ));
118 assert!(!depth.match_path(
119 &Path::try_from(r#"{"People"}[1]{"Age"}"#).unwrap(),
120 ParsedKind::Num
121 ));
122 assert!(!depth.match_path(
123 &Path::try_from(r#"{"People"}[1]{"Height"}"#).unwrap(),
124 ParsedKind::Num
125 ));
126
127 let depth: Depth = "2".parse().unwrap();
128 assert!(!depth.match_path(&Path::try_from(r#"{"People"}"#).unwrap(), ParsedKind::Arr));
129 assert!(depth.match_path(
130 &Path::try_from(r#"{"People"}[0]"#).unwrap(),
131 ParsedKind::Obj
132 ));
133 assert!(!depth.match_path(
134 &Path::try_from(r#"{"People"}[0]{"Age"}"#).unwrap(),
135 ParsedKind::Num
136 ));
137 assert!(!depth.match_path(
138 &Path::try_from(r#"{"People"}[0]{"Height"}"#).unwrap(),
139 ParsedKind::Num
140 ));
141 assert!(depth.match_path(
142 &Path::try_from(r#"{"People"}[1]"#).unwrap(),
143 ParsedKind::Obj
144 ));
145 assert!(!depth.match_path(
146 &Path::try_from(r#"{"People"}[1]{"Age"}"#).unwrap(),
147 ParsedKind::Num
148 ));
149 assert!(!depth.match_path(
150 &Path::try_from(r#"{"People"}[1]{"Height"}"#).unwrap(),
151 ParsedKind::Num
152 ));
153 }
154
155 #[test]
156 fn depth_parse() {
157 assert!(Depth::from_str("").is_err());
158 assert!(Depth::from_str("-").is_err());
159 assert!(Depth::from_str("4").is_ok());
160 assert!(Depth::from_str("4-").is_ok());
161 assert!(Depth::from_str("4-5").is_ok());
162 assert!(Depth::from_str("4-4").is_ok());
163 assert!(Depth::from_str("4-3").is_err());
164 assert!(Depth::from_str("4-3x").is_err());
165 }
166}