dcbor_pattern/pattern/value/
known_value_pattern.rs1use dcbor::prelude::*;
2use known_values::{KNOWN_VALUES, KnownValue};
3
4use crate::pattern::{Matcher, Path, Pattern, vm::Instr};
5
6const KNOWN_VALUE_TAG: Tag = Tag::with_value(40000);
8
9#[derive(Debug, Clone)]
11pub enum KnownValuePattern {
12 Any,
14 Value(KnownValue),
16 Name(String),
18 Regex(regex::Regex),
20}
21
22impl PartialEq for KnownValuePattern {
23 fn eq(&self, other: &Self) -> bool {
24 match (self, other) {
25 (KnownValuePattern::Any, KnownValuePattern::Any) => true,
26 (KnownValuePattern::Value(a), KnownValuePattern::Value(b)) => {
27 a == b
28 }
29 (KnownValuePattern::Name(a), KnownValuePattern::Name(b)) => {
30 a == b
31 }
32 (KnownValuePattern::Regex(a), KnownValuePattern::Regex(b)) => {
33 a.as_str() == b.as_str()
34 }
35 _ => false,
36 }
37 }
38}
39
40impl Eq for KnownValuePattern {}
41
42impl std::hash::Hash for KnownValuePattern {
43 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
44 match self {
45 KnownValuePattern::Any => {
46 0u8.hash(state);
47 }
48 KnownValuePattern::Value(s) => {
49 1u8.hash(state);
50 s.hash(state);
51 }
52 KnownValuePattern::Name(name) => {
53 2u8.hash(state);
54 name.hash(state);
55 }
56 KnownValuePattern::Regex(regex) => {
57 3u8.hash(state);
58 regex.as_str().hash(state);
60 }
61 }
62 }
63}
64
65impl KnownValuePattern {
66 pub fn any() -> Self { KnownValuePattern::Any }
68
69 pub fn value(value: KnownValue) -> Self { KnownValuePattern::Value(value) }
71
72 pub fn named(name: impl Into<String>) -> Self {
74 KnownValuePattern::Name(name.into())
75 }
76
77 pub fn regex(regex: regex::Regex) -> Self {
80 KnownValuePattern::Regex(regex)
81 }
82}
83
84impl Matcher for KnownValuePattern {
85 fn paths(&self, haystack: &CBOR) -> Vec<Path> {
86 if let CBORCase::Tagged(tag, content) = haystack.as_case() {
88 if *tag == KNOWN_VALUE_TAG {
89 if let CBORCase::Unsigned(value) = content.as_case() {
90 let known_value = KnownValue::new(*value);
91 match self {
92 KnownValuePattern::Any => vec![vec![haystack.clone()]],
93 KnownValuePattern::Value(expected) => {
94 if known_value == *expected {
95 vec![vec![haystack.clone()]]
96 } else {
97 vec![]
98 }
99 }
100 KnownValuePattern::Name(name) => {
101 let binding = KNOWN_VALUES.get();
104 if let Some(known_values_store) = binding.as_ref() {
105 if let Some(expected_value) =
106 known_values_store.known_value_named(name)
107 {
108 if known_value == *expected_value {
109 vec![vec![haystack.clone()]]
110 } else {
111 vec![]
112 }
113 } else {
114 vec![]
116 }
117 } else {
118 vec![]
120 }
121 }
122 KnownValuePattern::Regex(regex) => {
123 let name = {
126 let binding = KNOWN_VALUES.get();
127 if let Some(known_values_store) =
128 binding.as_ref()
129 {
130 known_values_store.name(known_value.clone())
131 } else {
132 known_value.name()
133 }
134 };
135
136 if regex.is_match(&name) {
137 vec![vec![haystack.clone()]]
138 } else {
139 vec![]
140 }
141 }
142 }
143 } else {
144 vec![]
145 }
146 } else {
147 vec![]
148 }
149 } else {
150 vec![]
151 }
152 }
153
154 fn compile(
155 &self,
156 code: &mut Vec<Instr>,
157 literals: &mut Vec<Pattern>,
158 _captures: &mut Vec<String>,
159 ) {
160 let idx = literals.len();
161 literals.push(Pattern::Value(
162 crate::pattern::ValuePattern::KnownValue(self.clone()),
163 ));
164 code.push(Instr::MatchPredicate(idx));
165 }
166}
167
168impl std::fmt::Display for KnownValuePattern {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 match self {
171 KnownValuePattern::Any => write!(f, "known"),
172 KnownValuePattern::Value(value) => {
173 write!(f, "'{}'", value.name())
174 }
175 KnownValuePattern::Name(name) => write!(f, "'{}'", name),
176 KnownValuePattern::Regex(regex) => {
177 write!(f, "'/{}/'", regex.as_str())
178 }
179 }
180 }
181}