1use std::fmt;
16use std::hash::{Hash, Hasher};
17
18use regex::Regex;
19
20use crate::parser::lex::is_label;
21use crate::parser::token::{token_display, TokenId, T_EQL, T_EQL_REGEX, T_NEQ, T_NEQ_REGEX};
22use crate::util::join_vector;
23
24const LABEL_METRIC_NAME: &str = "__name__";
25
26#[derive(Debug, Clone)]
27pub enum MatchOp {
28 Equal,
29 NotEqual,
30 Re(Regex),
32 NotRe(Regex),
33}
34
35impl fmt::Display for MatchOp {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self {
38 MatchOp::Equal => write!(f, "="),
39 MatchOp::NotEqual => write!(f, "!="),
40 MatchOp::Re(_reg) => write!(f, "=~"),
41 MatchOp::NotRe(_reg) => write!(f, "!~"),
42 }
43 }
44}
45
46impl PartialEq for MatchOp {
47 fn eq(&self, other: &Self) -> bool {
48 match (self, other) {
49 (MatchOp::Equal, MatchOp::Equal) => true,
50 (MatchOp::NotEqual, MatchOp::NotEqual) => true,
51 (MatchOp::Re(s), MatchOp::Re(o)) => s.as_str().eq(o.as_str()),
52 (MatchOp::NotRe(s), MatchOp::NotRe(o)) => s.as_str().eq(o.as_str()),
53 _ => false,
54 }
55 }
56}
57
58impl Eq for MatchOp {}
59
60impl Hash for MatchOp {
61 fn hash<H: Hasher>(&self, state: &mut H) {
62 match self {
63 MatchOp::Equal => "eq".hash(state),
64 MatchOp::NotEqual => "ne".hash(state),
65 MatchOp::Re(s) => format!("re:{}", s.as_str()).hash(state),
66 MatchOp::NotRe(s) => format!("nre:{}", s.as_str()).hash(state),
67 }
68 }
69}
70
71#[cfg(feature = "ser")]
72impl serde::Serialize for MatchOp {
73 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
74 where
75 S: serde::Serializer,
76 {
77 serializer.serialize_str(&self.to_string())
78 }
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, Hash)]
83#[cfg_attr(feature = "ser", derive(serde::Serialize))]
84pub struct Matcher {
85 #[cfg_attr(feature = "ser", serde(rename = "type"))]
86 pub op: MatchOp,
87 pub name: String,
88 pub value: String,
89}
90
91impl Matcher {
92 pub fn new(op: MatchOp, name: &str, value: &str) -> Self {
93 Self {
94 op,
95 name: name.into(),
96 value: value.into(),
97 }
98 }
99
100 pub fn is_match(&self, s: &str) -> bool {
102 match &self.op {
103 MatchOp::Equal => self.value.eq(s),
104 MatchOp::NotEqual => self.value.ne(s),
105 MatchOp::Re(r) => r.is_match(s),
106 MatchOp::NotRe(r) => !r.is_match(s),
107 }
108 }
109
110 fn try_parse_re(original_re: &str) -> Result<Regex, String> {
119 let re = format!("^(?:{})$", original_re);
120 Regex::new(&re)
121 .or_else(|_| Regex::new(&try_escape_for_repeat_re(&re)))
122 .map_err(|_| format!("illegal regex for {original_re}",))
123 }
124
125 pub fn new_matcher(id: TokenId, name: String, value: String) -> Result<Matcher, String> {
126 let op = Self::find_matcher_op(id, &value)?;
127 op.map(|op| Matcher::new(op, name.as_str(), value.as_str()))
128 }
129
130 pub fn new_metric_name_matcher(name: String) -> Result<Matcher, String> {
131 Ok(Matcher::new(
132 MatchOp::Equal,
133 LABEL_METRIC_NAME,
134 name.as_str(),
135 ))
136 }
137
138 fn find_matcher_op(id: TokenId, value: &str) -> Result<Result<MatchOp, String>, String> {
139 let op = match id {
140 T_EQL => Ok(MatchOp::Equal),
141 T_NEQ => Ok(MatchOp::NotEqual),
142 T_EQL_REGEX => Ok(MatchOp::Re(Matcher::try_parse_re(value)?)),
143 T_NEQ_REGEX => Ok(MatchOp::NotRe(Matcher::try_parse_re(value)?)),
144 _ => Err(format!("invalid match op {}", token_display(id))),
145 };
146 Ok(op)
147 }
148}
149
150impl fmt::Display for Matcher {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 let name = if is_label(&self.name) {
153 self.name.clone()
154 } else {
155 format!("\"{}\"", self.name)
156 };
157 write!(f, "{}{}\"{}\"", name, self.op, self.value)
158 }
159}
160
161fn try_escape_for_repeat_re(re: &str) -> String {
166 fn is_repeat(chars: &mut std::str::Chars<'_>) -> (bool, String) {
167 let mut buf = String::new();
168 let mut comma_seen = false;
169 for c in chars.by_ref() {
170 buf.push(c);
171 match c {
172 ',' if comma_seen => {
173 return (false, buf); }
175 ',' if buf == "," => {
176 return (false, buf); }
178 ',' if !comma_seen => comma_seen = true,
179 '}' if buf == "}" => {
180 return (false, buf); }
182 '}' => {
183 return (true, buf);
184 }
185 _ if c.is_ascii_digit() => continue,
186 _ => {
187 return (false, buf); }
189 }
190 }
191 (false, buf) }
193
194 let mut result = String::with_capacity(re.len() + 1);
195 let mut chars = re.chars();
196
197 while let Some(c) = chars.next() {
198 match c {
199 '\\' => {
200 if let Some(cc) = chars.next() {
201 result.push(c);
202 result.push(cc);
203 }
204 }
205 '{' => {
206 let (is, s) = is_repeat(&mut chars);
207 if !is {
208 result.push('\\');
209 }
210 result.push(c);
211 result.push_str(&s);
212 }
213 _ => result.push(c),
214 }
215 }
216 result
217}
218
219#[derive(Debug, Clone, PartialEq, Eq)]
220#[cfg_attr(feature = "ser", derive(serde::Serialize))]
221pub struct Matchers {
222 pub matchers: Vec<Matcher>,
223 #[cfg_attr(feature = "ser", serde(skip_serializing_if = "<[_]>::is_empty"))]
224 pub or_matchers: Vec<Vec<Matcher>>,
225}
226
227impl Matchers {
228 pub fn empty() -> Self {
229 Self {
230 matchers: vec![],
231 or_matchers: vec![],
232 }
233 }
234
235 pub fn one(matcher: Matcher) -> Self {
236 let matchers = vec![matcher];
237 Self {
238 matchers,
239 or_matchers: vec![],
240 }
241 }
242
243 pub fn new(matchers: Vec<Matcher>) -> Self {
244 Self {
245 matchers,
246 or_matchers: vec![],
247 }
248 }
249
250 pub fn with_or_matchers(mut self, or_matchers: Vec<Vec<Matcher>>) -> Self {
251 self.or_matchers = or_matchers;
252 self
253 }
254
255 pub fn append(mut self, matcher: Matcher) -> Self {
256 let last_or_matcher = self.or_matchers.last_mut();
259 if let Some(last_or_matcher) = last_or_matcher {
260 last_or_matcher.push(matcher);
261 } else {
262 self.matchers.push(matcher);
263 }
264 self
265 }
266
267 pub fn append_or(mut self, matcher: Matcher) -> Self {
268 if !self.matchers.is_empty() {
269 let last_matchers = std::mem::take(&mut self.matchers);
272 self.or_matchers.push(last_matchers);
273 }
274 let new_or_matchers = vec![matcher];
275 self.or_matchers.push(new_or_matchers);
276 self
277 }
278
279 pub fn is_empty_matchers(&self) -> bool {
285 (self.matchers.is_empty() && self.or_matchers.is_empty())
286 || self
287 .matchers
288 .iter()
289 .chain(self.or_matchers.iter().flatten())
290 .all(|m| m.is_match(""))
291 }
292
293 pub(crate) fn find_matcher_value(&self, name: &str) -> Option<String> {
296 self.matchers
297 .iter()
298 .chain(self.or_matchers.iter().flatten())
299 .find(|m| m.name.eq(name))
300 .map(|m| m.value.clone())
301 }
302
303 pub fn find_matchers(&self, name: &str) -> Vec<Matcher> {
305 self.matchers
306 .iter()
307 .chain(self.or_matchers.iter().flatten())
308 .filter(|m| m.name.eq(name))
309 .cloned()
310 .collect()
311 }
312}
313
314impl fmt::Display for Matchers {
315 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316 let simple_matchers = &self.matchers;
317 let or_matchers = &self.or_matchers;
318 if or_matchers.is_empty() {
319 write!(f, "{}", join_vector(simple_matchers, ",", true))
320 } else {
321 let or_matchers_string =
322 self.or_matchers
323 .iter()
324 .fold(String::new(), |or_matchers_str, pair| {
325 format!("{} or {}", or_matchers_str, join_vector(pair, ", ", false))
326 });
327 let or_matchers_string = or_matchers_string.trim_start_matches(" or").trim();
328 write!(f, "{or_matchers_string}")
329 }
330 }
331}
332
333#[cfg(test)]
334mod tests {
335 use super::*;
336 use crate::parser::token;
337 use std::collections::hash_map::DefaultHasher;
338
339 fn hash<H>(op: H) -> u64
340 where
341 H: Hash,
342 {
343 let mut hasher = DefaultHasher::new();
344 op.hash(&mut hasher);
345 hasher.finish()
346 }
347
348 #[test]
349 fn test_new_matcher() {
350 assert_eq!(
351 Matcher::new_matcher(token::T_ADD, "".into(), "".into()),
352 Err(format!("invalid match op {}", token_display(token::T_ADD)))
353 )
354 }
355
356 #[test]
357 fn test_matcher_op_eq() {
358 assert_eq!(MatchOp::Equal, MatchOp::Equal);
359 assert_eq!(MatchOp::NotEqual, MatchOp::NotEqual);
360 assert_eq!(
361 MatchOp::Re(Regex::new("\\s+").unwrap()),
362 MatchOp::Re(Regex::new("\\s+").unwrap())
363 );
364 assert_eq!(
365 MatchOp::NotRe(Regex::new("\\s+").unwrap()),
366 MatchOp::NotRe(Regex::new("\\s+").unwrap())
367 );
368
369 assert_ne!(MatchOp::Equal, MatchOp::NotEqual);
370 assert_ne!(
371 MatchOp::NotEqual,
372 MatchOp::NotRe(Regex::new("\\s+").unwrap())
373 );
374 assert_ne!(
375 MatchOp::Re(Regex::new("\\s+").unwrap()),
376 MatchOp::NotRe(Regex::new("\\s+").unwrap())
377 );
378 }
379
380 #[test]
381 fn test_matchop_hash() {
382 assert_eq!(hash(MatchOp::Equal), hash(MatchOp::Equal));
383 assert_eq!(hash(MatchOp::NotEqual), hash(MatchOp::NotEqual));
384 assert_eq!(
385 hash(MatchOp::Re(Regex::new("\\s+").unwrap())),
386 hash(MatchOp::Re(Regex::new("\\s+").unwrap()))
387 );
388 assert_eq!(
389 hash(MatchOp::NotRe(Regex::new("\\s+").unwrap())),
390 hash(MatchOp::NotRe(Regex::new("\\s+").unwrap()))
391 );
392
393 assert_ne!(hash(MatchOp::Equal), hash(MatchOp::NotEqual));
394 assert_ne!(
395 hash(MatchOp::NotEqual),
396 hash(MatchOp::NotRe(Regex::new("\\s+").unwrap()))
397 );
398 assert_ne!(
399 hash(MatchOp::Re(Regex::new("\\s+").unwrap())),
400 hash(MatchOp::NotRe(Regex::new("\\s+").unwrap()))
401 );
402 }
403
404 #[test]
405 fn test_matcher_hash() {
406 assert_eq!(
407 hash(Matcher::new(MatchOp::Equal, "name", "value")),
408 hash(Matcher::new(MatchOp::Equal, "name", "value")),
409 );
410
411 assert_eq!(
412 hash(Matcher::new(MatchOp::NotEqual, "name", "value")),
413 hash(Matcher::new(MatchOp::NotEqual, "name", "value")),
414 );
415
416 assert_eq!(
417 hash(Matcher::new(
418 MatchOp::Re(Regex::new("\\s+").unwrap()),
419 "name",
420 "\\s+"
421 )),
422 hash(Matcher::new(
423 MatchOp::Re(Regex::new("\\s+").unwrap()),
424 "name",
425 "\\s+"
426 )),
427 );
428
429 assert_eq!(
430 hash(Matcher::new(
431 MatchOp::NotRe(Regex::new("\\s+").unwrap()),
432 "name",
433 "\\s+"
434 )),
435 hash(Matcher::new(
436 MatchOp::NotRe(Regex::new("\\s+").unwrap()),
437 "name",
438 "\\s+"
439 )),
440 );
441
442 assert_ne!(
443 hash(Matcher::new(MatchOp::Equal, "name", "value")),
444 hash(Matcher::new(MatchOp::NotEqual, "name", "value")),
445 );
446
447 assert_ne!(
448 hash(Matcher::new(
449 MatchOp::Re(Regex::new("\\s+").unwrap()),
450 "name",
451 "\\s+"
452 )),
453 hash(Matcher::new(
454 MatchOp::NotRe(Regex::new("\\s+").unwrap()),
455 "name",
456 "\\s+"
457 )),
458 );
459 }
460
461 #[test]
462 fn test_matcher_eq_ne() {
463 let op = MatchOp::Equal;
464 let matcher = Matcher::new(op, "name", "up");
465 assert!(matcher.is_match("up"));
466 assert!(!matcher.is_match("down"));
467
468 let op = MatchOp::NotEqual;
469 let matcher = Matcher::new(op, "name", "up");
470 assert!(matcher.is_match("foo"));
471 assert!(matcher.is_match("bar"));
472 assert!(!matcher.is_match("up"));
473 }
474
475 #[test]
476 fn test_matcher_re() {
477 let value = "api/v1/.*";
478 let re = Regex::new(value).unwrap();
479 let op = MatchOp::Re(re);
480 let matcher = Matcher::new(op, "name", value);
481 assert!(matcher.is_match("api/v1/query"));
482 assert!(matcher.is_match("api/v1/range_query"));
483 assert!(!matcher.is_match("api/v2"));
484 }
485
486 #[test]
487 fn test_eq_matcher_equality() {
488 assert_eq!(
489 Matcher::new(MatchOp::Equal, "code", "200"),
490 Matcher::new(MatchOp::Equal, "code", "200")
491 );
492
493 assert_ne!(
494 Matcher::new(MatchOp::Equal, "code", "200"),
495 Matcher::new(MatchOp::Equal, "code", "201")
496 );
497
498 assert_ne!(
499 Matcher::new(MatchOp::Equal, "code", "200"),
500 Matcher::new(MatchOp::NotEqual, "code", "200")
501 );
502 }
503
504 #[test]
505 fn test_ne_matcher_equality() {
506 assert_eq!(
507 Matcher::new(MatchOp::NotEqual, "code", "200"),
508 Matcher::new(MatchOp::NotEqual, "code", "200")
509 );
510
511 assert_ne!(
512 Matcher::new(MatchOp::NotEqual, "code", "200"),
513 Matcher::new(MatchOp::NotEqual, "code", "201")
514 );
515
516 assert_ne!(
517 Matcher::new(MatchOp::NotEqual, "code", "200"),
518 Matcher::new(MatchOp::Equal, "code", "200")
519 );
520 }
521
522 #[test]
523 fn test_re_matcher_equality() {
524 assert_eq!(
525 Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2??",),
526 Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2??",)
527 );
528
529 assert_ne!(
530 Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2??",),
531 Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2*?",)
532 );
533
534 assert_ne!(
535 Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2??",),
536 Matcher::new(MatchOp::Equal, "code", "2??")
537 );
538
539 let matcher = Matcher::new(
541 MatchOp::Re(Matcher::try_parse_re("abc.*").unwrap()),
542 "code",
543 "abc.*",
544 );
545 assert!(matcher.is_match("abc123"));
546 assert!(!matcher.is_match("xabc123"));
547
548 let matcher = Matcher::new(
549 MatchOp::Re(Matcher::try_parse_re(".*xyz$").unwrap()),
550 "code",
551 ".*xyz",
552 );
553 assert!(matcher.is_match("123xyz"));
554 assert!(!matcher.is_match("123xyzx"));
555
556 let matcher = Matcher::new(
557 MatchOp::Re(Matcher::try_parse_re("abc").unwrap()),
558 "code",
559 "abc",
560 );
561 assert!(matcher.is_match("abc"));
562 assert!(!matcher.is_match("xabc"));
563 assert!(!matcher.is_match("abcx"));
564
565 let matcher = Matcher::new(
566 MatchOp::Re(Matcher::try_parse_re("127.0.0.1").unwrap()),
567 "code",
568 "127.0.0.1",
569 );
570 assert!(matcher.is_match("127.0.0.1"));
571 assert!(!matcher.is_match("x127.0.0.1"));
572 assert!(!matcher.is_match("127.0.0.2"));
573
574 let raw_input = r#"127\.0\.0\.1"#;
575 let matcher = Matcher::new(
576 MatchOp::Re(Matcher::try_parse_re(raw_input).unwrap()),
577 "code",
578 raw_input,
579 );
580 assert!(matcher.is_match("127.0.0.1"));
581 assert!(!matcher.is_match("x127.0.0.1"));
582 assert!(!matcher.is_match("127.0.0.2"));
583 let re = Matcher::try_parse_re(raw_input).unwrap();
585 let new_re = Regex::new(re.as_str()).unwrap();
586 assert_eq!(re.as_str(), new_re.as_str());
587 }
588
589 #[test]
590 fn test_not_re_matcher_equality() {
591 assert_eq!(
592 Matcher::new(MatchOp::NotRe(Regex::new("2??").unwrap()), "code", "2??",),
593 Matcher::new(MatchOp::NotRe(Regex::new("2??").unwrap()), "code", "2??",)
594 );
595
596 assert_ne!(
597 Matcher::new(MatchOp::NotRe(Regex::new("2??").unwrap()), "code", "2??",),
598 Matcher::new(MatchOp::NotRe(Regex::new("2?*").unwrap()), "code", "2*?",)
599 );
600
601 assert_ne!(
602 Matcher::new(MatchOp::NotRe(Regex::new("2??").unwrap()), "code", "2??",),
603 Matcher::new(MatchOp::Equal, "code", "2??")
604 );
605
606 let matcher = Matcher::new(
608 MatchOp::NotRe(Matcher::try_parse_re("abc.*").unwrap()),
609 "code",
610 "abc.*",
611 );
612 assert!(!matcher.is_match("abc123"));
613 assert!(matcher.is_match("xabc123")); let matcher = Matcher::new(
616 MatchOp::NotRe(Matcher::try_parse_re(".*xyz$").unwrap()),
617 "code",
618 ".*xyz",
619 );
620 assert!(!matcher.is_match("123xyz"));
621 assert!(matcher.is_match("123xyzx")); }
623
624 #[test]
625 fn test_matchers_equality() {
626 assert_eq!(
627 Matchers::empty()
628 .append(Matcher::new(MatchOp::Equal, "name1", "val1"))
629 .append(Matcher::new(MatchOp::Equal, "name2", "val2")),
630 Matchers::empty()
631 .append(Matcher::new(MatchOp::Equal, "name1", "val1"))
632 .append(Matcher::new(MatchOp::Equal, "name2", "val2"))
633 );
634
635 assert_ne!(
636 Matchers::empty().append(Matcher::new(MatchOp::Equal, "name1", "val1")),
637 Matchers::empty().append(Matcher::new(MatchOp::Equal, "name2", "val2"))
638 );
639
640 assert_ne!(
641 Matchers::empty().append(Matcher::new(MatchOp::Equal, "name1", "val1")),
642 Matchers::empty().append(Matcher::new(MatchOp::NotEqual, "name1", "val1"))
643 );
644
645 assert_eq!(
646 Matchers::empty()
647 .append(Matcher::new(MatchOp::Equal, "name1", "val1"))
648 .append(Matcher::new(MatchOp::NotEqual, "name2", "val2"))
649 .append(Matcher::new(
650 MatchOp::Re(Regex::new("\\d+").unwrap()),
651 "name2",
652 "\\d+"
653 ))
654 .append(Matcher::new(
655 MatchOp::NotRe(Regex::new("\\d+").unwrap()),
656 "name2",
657 "\\d+"
658 )),
659 Matchers::empty()
660 .append(Matcher::new(MatchOp::Equal, "name1", "val1"))
661 .append(Matcher::new(MatchOp::NotEqual, "name2", "val2"))
662 .append(Matcher::new(
663 MatchOp::Re(Regex::new("\\d+").unwrap()),
664 "name2",
665 "\\d+"
666 ))
667 .append(Matcher::new(
668 MatchOp::NotRe(Regex::new("\\d+").unwrap()),
669 "name2",
670 "\\d+"
671 ))
672 );
673 }
674
675 #[test]
676 fn test_find_matchers() {
677 let matchers = Matchers::empty()
678 .append(Matcher::new(MatchOp::Equal, "foo", "bar"))
679 .append(Matcher::new(MatchOp::NotEqual, "foo", "bar"))
680 .append(Matcher::new_matcher(T_EQL_REGEX, "foo".into(), "bar".into()).unwrap())
681 .append(Matcher::new_matcher(T_NEQ_REGEX, "foo".into(), "bar".into()).unwrap())
682 .append(Matcher::new(MatchOp::Equal, "FOO", "bar"))
683 .append(Matcher::new(MatchOp::NotEqual, "bar", "bar"));
684
685 let ms = matchers.find_matchers("foo");
686 assert_eq!(4, ms.len());
687 }
688
689 #[test]
690 fn test_convert_re() {
691 assert_eq!(try_escape_for_repeat_re("abc{}"), r"abc\{}");
692 assert_eq!(try_escape_for_repeat_re("abc{def}"), r"abc\{def}");
693 assert_eq!(try_escape_for_repeat_re("abc{def"), r"abc\{def");
694 assert_eq!(try_escape_for_repeat_re("abc{1}"), "abc{1}");
695 assert_eq!(try_escape_for_repeat_re("abc{1,}"), "abc{1,}");
696 assert_eq!(try_escape_for_repeat_re("abc{1,2}"), "abc{1,2}");
697 assert_eq!(try_escape_for_repeat_re("abc{,2}"), r"abc\{,2}");
698 assert_eq!(try_escape_for_repeat_re("abc{{1,2}}"), r"abc\{{1,2}}");
699 assert_eq!(try_escape_for_repeat_re(r"abc\{abc"), r"abc\{abc");
700 assert_eq!(try_escape_for_repeat_re("abc{1a}"), r"abc\{1a}");
701 assert_eq!(try_escape_for_repeat_re("abc{1,a}"), r"abc\{1,a}");
702 assert_eq!(try_escape_for_repeat_re("abc{1,2a}"), r"abc\{1,2a}");
703 assert_eq!(try_escape_for_repeat_re("abc{1,2,3}"), r"abc\{1,2,3}");
704 assert_eq!(try_escape_for_repeat_re("abc{1,,2}"), r"abc\{1,,2}");
705 }
706}