litcheck_filecheck/pattern/
prefix.rs1use crate::{
2 ast::{Match, RegexPattern},
3 common::*,
4};
5
6#[derive(Debug)]
7pub enum PatternPrefix<'a> {
8 Literal {
10 id: usize,
11 prefix: Span<Cow<'a, str>>,
12 },
13 Substring {
15 id: usize,
16 prefix: Span<Cow<'a, str>>,
17 },
18 Regex { id: usize, prefix: RegexPattern<'a> },
20 Dynamic {
23 id: usize,
24 prefix: Cow<'a, Match<'a>>,
25 },
26}
27impl<'a> PatternPrefix<'a> {
28 pub fn id(&self) -> usize {
29 match self {
30 Self::Literal { id, .. }
31 | Self::Substring { id, .. }
32 | Self::Regex { id, .. }
33 | Self::Dynamic { id, .. } => *id,
34 }
35 }
36
37 pub fn span(&self) -> SourceSpan {
38 match self {
39 Self::Literal { prefix, .. } | Self::Substring { prefix, .. } => prefix.span(),
40 Self::Regex { prefix, .. } => prefix.span(),
41 Self::Dynamic { prefix, .. } => prefix.span(),
42 }
43 }
44
45 pub fn as_str(&self) -> Option<&str> {
46 match self {
47 Self::Literal { prefix, .. } | Self::Substring { prefix, .. } => {
48 Some(prefix.inner().as_ref())
49 }
50 Self::Regex { prefix, .. } => Some(prefix.as_ref()),
51 Self::Dynamic { .. } => None,
52 }
53 }
54
55 pub fn to_str(&self) -> Option<Span<Cow<'a, str>>> {
56 match self {
57 Self::Literal { prefix, .. } | Self::Substring { prefix, .. } => Some(prefix.clone()),
58 Self::Regex { prefix, .. } => Some(prefix.pattern.clone()),
59 Self::Dynamic { .. } => None,
60 }
61 }
62
63 pub fn into_str(self) -> Option<Span<Cow<'a, str>>> {
64 match self {
65 Self::Literal { prefix, .. } | Self::Substring { prefix, .. } => Some(prefix),
66 Self::Regex { prefix, .. } => Some(prefix.pattern),
67 Self::Dynamic { .. } => None,
68 }
69 }
70
71 pub fn into_regex_pattern(self) -> Option<RegexPattern<'a>> {
72 match self {
73 Self::Literal { prefix, .. } | Self::Substring { prefix, .. } => Some(
74 RegexPattern::new(prefix.map(|s| Cow::Owned(regex::escape(s.as_ref())))),
75 ),
76 Self::Regex { prefix, .. } => Some(prefix),
77 Self::Dynamic { .. } => None,
78 }
79 }
80
81 pub fn is_regex(&self) -> bool {
82 matches!(self, Self::Regex { .. })
83 }
84
85 pub fn is_regex_compatible(&self) -> bool {
86 matches!(
87 self,
88 Self::Regex { .. } | Self::Literal { .. } | Self::Substring { .. }
89 )
90 }
91
92 pub fn is_dynamic(&self) -> bool {
93 matches!(self, Self::Dynamic { .. })
94 }
95
96 pub fn is_capturing(&self) -> bool {
97 match self {
98 Self::Regex { prefix, .. } if !prefix.captures.is_empty() => true,
99 Self::Dynamic { .. } => true,
100 _ => false,
101 }
102 }
103
104 pub fn overlaps(&self, prefix: &str) -> bool {
106 self.as_str()
107 .map(|p| p.starts_with(prefix))
108 .unwrap_or(false)
109 }
110
111 pub fn is_overlapped_by(&self, prefix: &str) -> bool {
113 self.as_str()
114 .map(|p| prefix.starts_with(p))
115 .unwrap_or(false)
116 }
117
118 pub fn is_duplicate_prefix(&self, prefix: &str) -> bool {
120 self.as_str().map(|p| p == prefix).unwrap_or(false)
121 }
122}