json_traits/
path_pattern.rs1pub trait PathPattern {
11 #[doc(alias = "IsSupportedBy")]
23 #[must_use]
24 fn is_supported_by<I, S>(&self, patterns: I) -> bool
25 where
26 I: IntoIterator<Item = S>,
27 S: AsRef<str>;
28
29 #[doc(alias = "IsAPathMatchWith")]
33 #[must_use]
34 fn is_a_path_match_with(&self, path: &str) -> bool;
35}
36
37impl PathPattern for str {
38 fn is_supported_by<I, S>(&self, patterns: I) -> bool
39 where
40 I: IntoIterator<Item = S>,
41 S: AsRef<str>,
42 {
43 patterns
44 .into_iter()
45 .any(|pattern| pattern.as_ref().is_a_path_match_with(self))
46 }
47
48 fn is_a_path_match_with(&self, path: &str) -> bool {
49 if !self.as_bytes().contains(&b'*') {
50 return self == path;
51 }
52 segments_match(self.as_bytes(), path.as_bytes())
53 }
54}
55
56fn segments_match(mut pattern: &[u8], mut path: &[u8]) -> bool {
57 loop {
58 let (pattern_segment, pattern_rest) = split_segment(pattern);
59 let (path_segment, path_rest) = split_segment(path);
60 if pattern_segment != b"*" && pattern_segment != path_segment {
61 return false;
62 }
63 match (pattern_rest, path_rest) {
64 (None, None) => return true,
65 (Some(pattern_rest), Some(path_rest)) => {
66 pattern = pattern_rest;
67 path = path_rest;
68 }
69 _ => return false,
70 }
71 }
72}
73
74fn split_segment(input: &[u8]) -> (&[u8], Option<&[u8]>) {
75 match input.iter().position(|&byte| byte == b'.') {
76 Some(index) => (&input[..index], Some(&input[index + 1..])),
77 None => (input, None),
78 }
79}