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)) => a == b,
30 (KnownValuePattern::Regex(a), KnownValuePattern::Regex(b)) => {
31 a.as_str() == b.as_str()
32 }
33 _ => false,
34 }
35 }
36}
37
38impl Eq for KnownValuePattern {}
39
40impl std::hash::Hash for KnownValuePattern {
41 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
42 match self {
43 KnownValuePattern::Any => {
44 0u8.hash(state);
45 }
46 KnownValuePattern::Value(s) => {
47 1u8.hash(state);
48 s.hash(state);
49 }
50 KnownValuePattern::Name(name) => {
51 2u8.hash(state);
52 name.hash(state);
53 }
54 KnownValuePattern::Regex(regex) => {
55 3u8.hash(state);
56 regex.as_str().hash(state);
58 }
59 }
60 }
61}
62
63impl KnownValuePattern {
64 pub fn any() -> Self { KnownValuePattern::Any }
66
67 pub fn value(value: KnownValue) -> Self { KnownValuePattern::Value(value) }
69
70 pub fn named(name: impl Into<String>) -> Self {
72 KnownValuePattern::Name(name.into())
73 }
74
75 pub fn regex(regex: regex::Regex) -> Self {
78 KnownValuePattern::Regex(regex)
79 }
80}
81
82impl Matcher for KnownValuePattern {
83 fn paths(&self, haystack: &CBOR) -> Vec<Path> {
84 if let CBORCase::Tagged(tag, content) = haystack.as_case() {
86 if *tag == KNOWN_VALUE_TAG {
87 if let CBORCase::Unsigned(value) = content.as_case() {
88 let known_value = KnownValue::new(*value);
89 match self {
90 KnownValuePattern::Any => vec![vec![haystack.clone()]],
91 KnownValuePattern::Value(expected) => {
92 if known_value == *expected {
93 vec![vec![haystack.clone()]]
94 } else {
95 vec![]
96 }
97 }
98 KnownValuePattern::Name(name) => {
99 let binding = KNOWN_VALUES.get();
102 if let Some(known_values_store) = binding.as_ref() {
103 if let Some(expected_value) =
104 known_values_store.known_value_named(name)
105 {
106 if known_value == *expected_value {
107 vec![vec![haystack.clone()]]
108 } else {
109 vec![]
110 }
111 } else {
112 vec![]
114 }
115 } else {
116 vec![]
118 }
119 }
120 KnownValuePattern::Regex(regex) => {
121 let name = {
124 let binding = KNOWN_VALUES.get();
125 if let Some(known_values_store) =
126 binding.as_ref()
127 {
128 known_values_store.name(known_value.clone())
129 } else {
130 known_value.name()
131 }
132 };
133
134 if regex.is_match(&name) {
135 vec![vec![haystack.clone()]]
136 } else {
137 vec![]
138 }
139 }
140 }
141 } else {
142 vec![]
143 }
144 } else {
145 vec![]
146 }
147 } else {
148 vec![]
149 }
150 }
151
152 fn compile(
153 &self,
154 code: &mut Vec<Instr>,
155 literals: &mut Vec<Pattern>,
156 _captures: &mut Vec<String>,
157 ) {
158 let idx = literals.len();
159 literals.push(Pattern::Value(
160 crate::pattern::ValuePattern::KnownValue(self.clone()),
161 ));
162 code.push(Instr::MatchPredicate(idx));
163 }
164}
165
166impl std::fmt::Display for KnownValuePattern {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 match self {
169 KnownValuePattern::Any => write!(f, "known"),
170 KnownValuePattern::Value(value) => {
171 write!(f, "'{}'", value.name())
172 }
173 KnownValuePattern::Name(name) => write!(f, "'{}'", name),
174 KnownValuePattern::Regex(regex) => {
175 write!(f, "'/{}/'", regex.as_str())
176 }
177 }
178 }
179}