1use std::ops::Range;
2use std::slice::Iter;
3
4use bstr::{BStr, ByteSlice};
5use serde::{Deserialize, Serialize};
6
7use crate::compiler::{IdentId, PatternId, PatternInfo, RuleInfo};
8use crate::scanner::{ScanContext, ScanState};
9use crate::{compiler, scanner, Rules};
10
11#[derive(Serialize, Deserialize, Clone, Copy)]
13pub enum PatternKind {
14 Text,
16 Hex,
18 Regexp,
20}
21
22pub struct Rule<'a, 'r> {
24 pub(crate) ctx: Option<&'a ScanContext<'r, 'a>>,
25 pub(crate) rules: &'r Rules,
26 pub(crate) rule_info: &'r RuleInfo,
27}
28
29impl<'a, 'r> Rule<'a, 'r> {
30 pub fn identifier(&self) -> &'r str {
32 self.rules.ident_pool().get(self.rule_info.ident_id).unwrap()
33 }
34
35 pub fn namespace(&self) -> &'r str {
37 self.rules.ident_pool().get(self.rule_info.namespace_ident_id).unwrap()
38 }
39
40 pub fn metadata(&self) -> Metadata<'a, 'r> {
42 Metadata {
43 rules: self.rules,
44 iterator: self.rule_info.metadata.iter(),
45 len: self.rule_info.metadata.len(),
46 }
47 }
48
49 pub fn is_global(&self) -> bool {
51 self.rule_info.is_global
52 }
53
54 pub fn is_private(&self) -> bool {
56 self.rule_info.is_private
57 }
58
59 pub fn tags(&self) -> Tags<'a, 'r> {
61 Tags {
62 rules: self.rules,
63 iterator: self.rule_info.tags.iter(),
64 len: self.rule_info.tags.len(),
65 }
66 }
67
68 pub fn patterns(&self) -> Patterns<'a, 'r> {
74 Patterns {
75 ctx: self.ctx,
76 rules: self.rules,
77 include_private: false,
78 iterator: self.rule_info.patterns.iter(),
79 len_non_private: self.rule_info.patterns.len()
80 - self.rule_info.num_private_patterns,
81 len_private: self.rule_info.num_private_patterns,
82 }
83 }
84}
85
86#[derive(Debug, PartialEq, Serialize)]
88#[serde(untagged)]
89pub enum MetaValue<'r> {
90 Integer(i64),
92 Float(f64),
94 Bool(bool),
96 String(&'r str),
98 Bytes(&'r BStr),
101}
102
103pub struct Metadata<'a, 'r> {
108 rules: &'r Rules,
109 iterator: Iter<'a, (IdentId, compiler::MetaValue)>,
110 len: usize,
111}
112
113impl<'r> Metadata<'_, 'r> {
114 pub fn into_json(self) -> serde_json::Value {
155 let v: Vec<(&'r str, MetaValue<'r>)> = self.collect();
156 serde_json::value::to_value(v).unwrap()
157 }
158
159 #[inline]
161 pub fn is_empty(&self) -> bool {
162 self.iterator.len() == 0
163 }
164}
165
166impl<'r> Iterator for Metadata<'_, 'r> {
167 type Item = (&'r str, MetaValue<'r>);
168
169 fn next(&mut self) -> Option<Self::Item> {
170 let (ident_id, value) = self.iterator.next()?;
171
172 let ident = self.rules.ident_pool().get(*ident_id).unwrap();
173
174 let value = match value {
175 compiler::MetaValue::Bool(b) => MetaValue::Bool(*b),
176 compiler::MetaValue::Integer(i) => MetaValue::Integer(*i),
177 compiler::MetaValue::Float(f) => MetaValue::Float(*f),
178 compiler::MetaValue::String(id) => {
179 let s = self.rules.lit_pool().get(*id).unwrap();
180 let s = unsafe { s.to_str_unchecked() };
183 MetaValue::String(s)
184 }
185 compiler::MetaValue::Bytes(id) => {
186 MetaValue::Bytes(self.rules.lit_pool().get(*id).unwrap())
187 }
188 };
189
190 Some((ident, value))
191 }
192}
193
194impl ExactSizeIterator for Metadata<'_, '_> {
195 #[inline]
196 fn len(&self) -> usize {
197 self.len
198 }
199}
200
201pub struct Tags<'a, 'r> {
203 rules: &'r Rules,
204 iterator: Iter<'a, IdentId>,
205 len: usize,
206}
207
208impl Tags<'_, '_> {
209 #[inline]
211 pub fn is_empty(&self) -> bool {
212 self.iterator.len() == 0
213 }
214}
215
216impl<'r> Iterator for Tags<'_, 'r> {
217 type Item = Tag<'r>;
218
219 fn next(&mut self) -> Option<Self::Item> {
220 let ident_id = self.iterator.next()?;
221 Some(Tag { rules: self.rules, ident_id: *ident_id })
222 }
223}
224
225impl ExactSizeIterator for Tags<'_, '_> {
226 #[inline]
227 fn len(&self) -> usize {
228 self.len
229 }
230}
231
232pub struct Tag<'r> {
234 rules: &'r Rules,
235 ident_id: IdentId,
236}
237
238impl<'r> Tag<'r> {
239 pub fn identifier(&self) -> &'r str {
241 self.rules.ident_pool().get(self.ident_id).unwrap()
242 }
243}
244
245pub struct Patterns<'a, 'r> {
251 ctx: Option<&'a ScanContext<'r, 'a>>,
252 rules: &'r Rules,
253 iterator: Iter<'a, PatternInfo>,
254 include_private: bool,
258 len_private: usize,
260 len_non_private: usize,
262}
263
264impl Patterns<'_, '_> {
265 pub fn include_private(mut self, yes: bool) -> Self {
270 self.include_private = yes;
271 self
272 }
273}
274
275impl ExactSizeIterator for Patterns<'_, '_> {
276 #[inline]
277 fn len(&self) -> usize {
278 if self.include_private {
279 self.len_non_private + self.len_private
280 } else {
281 self.len_non_private
282 }
283 }
284}
285
286impl<'a, 'r> Iterator for Patterns<'a, 'r> {
287 type Item = Pattern<'a, 'r>;
288
289 fn next(&mut self) -> Option<Self::Item> {
290 loop {
291 let pattern = self.iterator.next()?;
292
293 if pattern.is_private {
294 self.len_private -= 1;
295 } else {
296 self.len_non_private -= 1;
297 }
298
299 if self.include_private || !pattern.is_private {
300 return Some(Pattern {
301 ctx: self.ctx,
302 rules: self.rules,
303 ident_id: pattern.ident_id,
304 pattern_id: pattern.pattern_id,
305 kind: pattern.kind,
306 is_private: pattern.is_private,
307 });
308 }
309 }
310 }
311}
312
313pub struct Pattern<'a, 'r> {
315 ctx: Option<&'a ScanContext<'r, 'a>>,
316 rules: &'r Rules,
317 ident_id: IdentId,
318 pattern_id: PatternId,
319 kind: PatternKind,
320 is_private: bool,
321}
322
323impl<'a, 'r> Pattern<'a, 'r> {
324 pub fn identifier(&self) -> &'r str {
326 self.rules.ident_pool().get(self.ident_id).unwrap()
327 }
328
329 #[inline]
331 pub fn kind(&self) -> PatternKind {
332 self.kind
333 }
334
335 #[inline]
337 pub fn is_private(&self) -> bool {
338 self.is_private
339 }
340
341 pub fn matches(&self) -> Matches<'a, 'r> {
343 Matches {
344 ctx: self.ctx,
345 iterator: self.ctx.and_then(|ctx| {
346 ctx.pattern_matches
347 .get(self.pattern_id)
348 .map(|matches| matches.iter())
349 }),
350 }
351 }
352}
353
354pub struct Matches<'a, 'r> {
356 ctx: Option<&'a ScanContext<'r, 'a>>,
357 iterator: Option<Iter<'a, scanner::Match>>,
358}
359
360impl<'a, 'r> Iterator for Matches<'a, 'r> {
361 type Item = Match<'a, 'r>;
362
363 fn next(&mut self) -> Option<Self::Item> {
364 let iter = self.iterator.as_mut()?;
365 Some(Match { ctx: self.ctx?, inner: iter.next()? })
366 }
367}
368
369impl ExactSizeIterator for Matches<'_, '_> {
370 fn len(&self) -> usize {
371 self.iterator.as_ref().map_or(0, |it| it.len())
372 }
373}
374
375pub struct Match<'a, 'r> {
377 ctx: &'a ScanContext<'r, 'a>,
378 inner: &'a scanner::Match,
379}
380
381impl<'a> Match<'a, '_> {
382 #[inline]
384 pub fn range(&self) -> Range<usize> {
385 self.inner.range.clone()
386 }
387
388 #[inline]
390 pub fn data(&self) -> &'a [u8] {
391 let data = match &self.ctx.scan_state {
392 ScanState::Finished(snippets) => snippets.get(self.range()),
393 _ => None,
394 };
395
396 data.unwrap()
397 }
398
399 #[inline]
402 pub fn xor_key(&self) -> Option<u8> {
403 self.inner.xor_key
404 }
405}