1use std::ops::Range;
2use std::slice::Iter;
3
4use bstr::{BStr, ByteSlice};
5use serde::ser::SerializeStruct;
6use serde::{Deserialize, Serialize, Serializer};
7
8use crate::compiler::{IdentId, PatternId, PatternInfo, RuleInfo};
9use crate::scanner::{ScanContext, ScanState};
10use crate::{Rules, compiler, scanner};
11
12#[derive(Serialize, Deserialize, Clone, Copy)]
14pub enum PatternKind {
15 Text,
17 Hex,
19 Regexp,
21}
22
23pub struct Rule<'a, 'r> {
25 pub(crate) ctx: Option<&'a ScanContext<'r, 'a>>,
26 pub(crate) rules: &'r Rules,
27 pub(crate) rule_info: &'r RuleInfo,
28}
29
30impl<'a, 'r> Rule<'a, 'r> {
31 pub fn identifier(&self) -> &'r str {
33 self.rules.ident_pool().get(self.rule_info.ident_id).unwrap()
34 }
35
36 pub fn namespace(&self) -> &'r str {
38 self.rules.ident_pool().get(self.rule_info.namespace_ident_id).unwrap()
39 }
40
41 pub fn metadata(&self) -> Metadata<'a, 'r> {
43 Metadata {
44 rules: self.rules,
45 iterator: self.rule_info.metadata.iter(),
46 len: self.rule_info.metadata.len(),
47 }
48 }
49
50 pub fn is_global(&self) -> bool {
52 self.rule_info.is_global
53 }
54
55 pub fn is_private(&self) -> bool {
57 self.rule_info.is_private
58 }
59
60 pub fn tags(&self) -> Tags<'a, 'r> {
62 Tags {
63 rules: self.rules,
64 iterator: self.rule_info.tags.iter(),
65 len: self.rule_info.tags.len(),
66 }
67 }
68
69 pub fn patterns(&self) -> Patterns<'a, 'r> {
75 Patterns {
76 ctx: self.ctx,
77 rules: self.rules,
78 include_private: false,
79 iterator: self.rule_info.patterns.iter(),
80 len_non_private: self.rule_info.patterns.len()
81 - self.rule_info.num_private_patterns,
82 len_private: self.rule_info.num_private_patterns,
83 }
84 }
85}
86
87impl Serialize for Rule<'_, '_> {
88 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89 where
90 S: Serializer,
91 {
92 let mut s = serializer.serialize_struct("rule", 7)?;
93
94 s.serialize_field("identifier", &self.identifier())?;
95 s.serialize_field("namespace", &self.namespace())?;
96 s.serialize_field("is_global", &self.is_global())?;
97 s.serialize_field("is_private", &self.is_private())?;
98
99 let metadata: Vec<_> = self.metadata().collect();
100 s.serialize_field("metadata", &metadata)?;
101
102 let tags: Vec<_> = self.tags().collect();
103 s.serialize_field("tags", &tags)?;
104
105 let patterns: Vec<_> = self.patterns().include_private(true).collect();
106 s.serialize_field("patterns", &patterns)?;
107
108 s.end()
109 }
110}
111
112#[derive(Debug, PartialEq, Serialize)]
114#[serde(untagged)]
115pub enum MetaValue<'r> {
116 Integer(i64),
118 Float(f64),
120 Bool(bool),
122 String(&'r str),
124 Bytes(&'r BStr),
127}
128
129pub struct Metadata<'a, 'r> {
134 rules: &'r Rules,
135 iterator: Iter<'a, (IdentId, compiler::MetaValue)>,
136 len: usize,
137}
138
139impl<'r> Metadata<'_, 'r> {
140 pub fn into_json(self) -> serde_json::Value {
181 let v: Vec<(&'r str, MetaValue<'r>)> = self.collect();
182 serde_json::value::to_value(v).unwrap()
183 }
184
185 #[inline]
187 pub fn is_empty(&self) -> bool {
188 self.iterator.len() == 0
189 }
190}
191
192impl<'r> Iterator for Metadata<'_, 'r> {
193 type Item = (&'r str, MetaValue<'r>);
194
195 fn next(&mut self) -> Option<Self::Item> {
196 let (ident_id, value) = self.iterator.next()?;
197
198 let ident = self.rules.ident_pool().get(*ident_id).unwrap();
199
200 let value = match value {
201 compiler::MetaValue::Bool(b) => MetaValue::Bool(*b),
202 compiler::MetaValue::Integer(i) => MetaValue::Integer(*i),
203 compiler::MetaValue::Float(f) => MetaValue::Float(*f),
204 compiler::MetaValue::String(id) => {
205 let s = self.rules.lit_pool().get(*id).unwrap();
206 let s = s.to_str().unwrap();
207 MetaValue::String(s)
208 }
209 compiler::MetaValue::Bytes(id) => {
210 MetaValue::Bytes(self.rules.lit_pool().get(*id).unwrap())
211 }
212 };
213
214 Some((ident, value))
215 }
216}
217
218impl ExactSizeIterator for Metadata<'_, '_> {
219 #[inline]
220 fn len(&self) -> usize {
221 self.len
222 }
223}
224
225pub struct Tags<'a, 'r> {
227 rules: &'r Rules,
228 iterator: Iter<'a, IdentId>,
229 len: usize,
230}
231
232impl Tags<'_, '_> {
233 #[inline]
235 pub fn is_empty(&self) -> bool {
236 self.iterator.len() == 0
237 }
238}
239
240impl<'r> Iterator for Tags<'_, 'r> {
241 type Item = Tag<'r>;
242
243 fn next(&mut self) -> Option<Self::Item> {
244 let ident_id = self.iterator.next()?;
245 Some(Tag { rules: self.rules, ident_id: *ident_id })
246 }
247}
248
249impl ExactSizeIterator for Tags<'_, '_> {
250 #[inline]
251 fn len(&self) -> usize {
252 self.len
253 }
254}
255
256pub struct Tag<'r> {
258 rules: &'r Rules,
259 ident_id: IdentId,
260}
261
262impl<'r> Tag<'r> {
263 pub fn identifier(&self) -> &'r str {
265 self.rules.ident_pool().get(self.ident_id).unwrap()
266 }
267}
268
269impl<'r> Serialize for Tag<'r> {
270 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
271 where
272 S: Serializer,
273 {
274 serializer.serialize_str(self.identifier())
275 }
276}
277
278pub struct Patterns<'a, 'r> {
284 ctx: Option<&'a ScanContext<'r, 'a>>,
285 rules: &'r Rules,
286 iterator: Iter<'a, PatternInfo>,
287 include_private: bool,
291 len_private: usize,
293 len_non_private: usize,
295}
296
297impl Patterns<'_, '_> {
298 pub fn include_private(mut self, yes: bool) -> Self {
303 self.include_private = yes;
304 self
305 }
306}
307
308impl ExactSizeIterator for Patterns<'_, '_> {
309 #[inline]
310 fn len(&self) -> usize {
311 if self.include_private {
312 self.len_non_private + self.len_private
313 } else {
314 self.len_non_private
315 }
316 }
317}
318
319impl<'a, 'r> Iterator for Patterns<'a, 'r> {
320 type Item = Pattern<'a, 'r>;
321
322 fn next(&mut self) -> Option<Self::Item> {
323 loop {
324 let pattern = self.iterator.next()?;
325
326 if pattern.is_private {
327 self.len_private -= 1;
328 } else {
329 self.len_non_private -= 1;
330 }
331
332 if self.include_private || !pattern.is_private {
333 return Some(Pattern {
334 ctx: self.ctx,
335 rules: self.rules,
336 ident_id: pattern.ident_id,
337 pattern_id: pattern.pattern_id,
338 kind: pattern.kind,
339 is_private: pattern.is_private,
340 });
341 }
342 }
343 }
344}
345
346pub struct Pattern<'a, 'r> {
348 ctx: Option<&'a ScanContext<'r, 'a>>,
349 rules: &'r Rules,
350 ident_id: IdentId,
351 pattern_id: PatternId,
352 kind: PatternKind,
353 is_private: bool,
354}
355
356impl<'a, 'r> Pattern<'a, 'r> {
357 pub fn identifier(&self) -> &'r str {
359 self.rules.ident_pool().get(self.ident_id).unwrap()
360 }
361
362 #[inline]
364 pub fn kind(&self) -> PatternKind {
365 self.kind
366 }
367
368 #[inline]
370 pub fn is_private(&self) -> bool {
371 self.is_private
372 }
373
374 pub fn matches(&self) -> Matches<'a, 'r> {
380 Matches {
381 ctx: self.ctx,
382 iterator: self.ctx.and_then(|ctx| {
383 ctx.tracker
384 .pattern_matches
385 .get(self.pattern_id)
386 .map(|matches| matches.iter())
387 }),
388 }
389 }
390}
391
392impl<'a, 'r> Serialize for Pattern<'a, 'r> {
393 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
394 where
395 S: Serializer,
396 {
397 let mut s = serializer.serialize_struct("pattern", 4)?;
398 s.serialize_field("identifier", &self.identifier())?;
399 s.serialize_field("kind", &self.kind())?;
400 s.serialize_field("is_private", &self.is_private())?;
401 let matches: Vec<_> = self.matches().collect();
402 s.serialize_field("matches", &matches)?;
403 s.end()
404 }
405}
406
407pub struct Matches<'a, 'r> {
409 ctx: Option<&'a ScanContext<'r, 'a>>,
410 iterator: Option<Iter<'a, scanner::Match>>,
411}
412
413impl<'a, 'r> Iterator for Matches<'a, 'r> {
414 type Item = Match<'a, 'r>;
415
416 fn next(&mut self) -> Option<Self::Item> {
417 let iter = self.iterator.as_mut()?;
418 Some(Match { ctx: self.ctx?, inner: iter.next()? })
419 }
420}
421
422impl ExactSizeIterator for Matches<'_, '_> {
423 fn len(&self) -> usize {
424 self.iterator.as_ref().map_or(0, |it| it.len())
425 }
426}
427
428pub struct Match<'a, 'r> {
430 ctx: &'a ScanContext<'r, 'a>,
431 inner: &'a scanner::Match,
432}
433
434impl<'a> Match<'a, '_> {
435 #[inline]
437 pub fn range(&self) -> Range<usize> {
438 self.inner.range.clone()
439 }
440
441 #[inline]
443 pub fn data(&self) -> &'a [u8] {
444 match &self.ctx.scan_state {
445 ScanState::Finished(snippets) => {
446 snippets.get(self.range()).unwrap()
447 }
448 _ => panic!("invalid scan state"),
449 }
450 }
451
452 pub fn data_with_context(&self) -> (&'a [u8], Range<usize>) {
461 match &self.ctx.scan_state {
462 ScanState::Finished(snippets) => snippets
463 .get_with_context(self.range(), self.ctx.match_context_size)
464 .unwrap(),
465 _ => panic!("invalid scan state"),
466 }
467 }
468
469 #[inline]
472 pub fn xor_key(&self) -> Option<u8> {
473 self.inner.xor_key
474 }
475}
476
477impl<'a, 'r> Serialize for Match<'a, 'r> {
478 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
479 where
480 S: Serializer,
481 {
482 let mut s = serializer.serialize_struct("match", 2)?;
483 s.serialize_field("range", &self.range())?;
484 s.serialize_field("xor_key", &self.xor_key())?;
485 s.end()
486 }
487}