use std::ops::Range;
use std::slice::Iter;
use bstr::{BStr, ByteSlice};
use serde::ser::SerializeStruct;
use serde::{Deserialize, Serialize, Serializer};
use crate::compiler::{IdentId, PatternId, PatternInfo, RuleInfo};
use crate::scanner::{ScanContext, ScanState};
use crate::{Rules, compiler, scanner};
#[derive(Serialize, Deserialize, Clone, Copy)]
pub enum PatternKind {
Text,
Hex,
Regexp,
}
pub struct Rule<'a, 'r> {
pub(crate) ctx: Option<&'a ScanContext<'r, 'a>>,
pub(crate) rules: &'r Rules,
pub(crate) rule_info: &'r RuleInfo,
}
impl<'a, 'r> Rule<'a, 'r> {
pub fn identifier(&self) -> &'r str {
self.rules.ident_pool().get(self.rule_info.ident_id).unwrap()
}
pub fn namespace(&self) -> &'r str {
self.rules.ident_pool().get(self.rule_info.namespace_ident_id).unwrap()
}
pub fn metadata(&self) -> Metadata<'a, 'r> {
Metadata {
rules: self.rules,
iterator: self.rule_info.metadata.iter(),
len: self.rule_info.metadata.len(),
}
}
pub fn is_global(&self) -> bool {
self.rule_info.is_global
}
pub fn is_private(&self) -> bool {
self.rule_info.is_private
}
pub fn tags(&self) -> Tags<'a, 'r> {
Tags {
rules: self.rules,
iterator: self.rule_info.tags.iter(),
len: self.rule_info.tags.len(),
}
}
pub fn patterns(&self) -> Patterns<'a, 'r> {
Patterns {
ctx: self.ctx,
rules: self.rules,
include_private: false,
iterator: self.rule_info.patterns.iter(),
len_non_private: self.rule_info.patterns.len()
- self.rule_info.num_private_patterns,
len_private: self.rule_info.num_private_patterns,
}
}
}
impl Serialize for Rule<'_, '_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut s = serializer.serialize_struct("rule", 7)?;
s.serialize_field("identifier", &self.identifier())?;
s.serialize_field("namespace", &self.namespace())?;
s.serialize_field("is_global", &self.is_global())?;
s.serialize_field("is_private", &self.is_private())?;
let metadata: Vec<_> = self.metadata().collect();
s.serialize_field("metadata", &metadata)?;
let tags: Vec<_> = self.tags().collect();
s.serialize_field("tags", &tags)?;
let patterns: Vec<_> = self.patterns().include_private(true).collect();
s.serialize_field("patterns", &patterns)?;
s.end()
}
}
#[derive(Debug, PartialEq, Serialize)]
#[serde(untagged)]
pub enum MetaValue<'r> {
Integer(i64),
Float(f64),
Bool(bool),
String(&'r str),
Bytes(&'r BStr),
}
pub struct Metadata<'a, 'r> {
rules: &'r Rules,
iterator: Iter<'a, (IdentId, compiler::MetaValue)>,
len: usize,
}
impl<'r> Metadata<'_, 'r> {
pub fn into_json(self) -> serde_json::Value {
let v: Vec<(&'r str, MetaValue<'r>)> = self.collect();
serde_json::value::to_value(v).unwrap()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.iterator.len() == 0
}
}
impl<'r> Iterator for Metadata<'_, 'r> {
type Item = (&'r str, MetaValue<'r>);
fn next(&mut self) -> Option<Self::Item> {
let (ident_id, value) = self.iterator.next()?;
let ident = self.rules.ident_pool().get(*ident_id).unwrap();
let value = match value {
compiler::MetaValue::Bool(b) => MetaValue::Bool(*b),
compiler::MetaValue::Integer(i) => MetaValue::Integer(*i),
compiler::MetaValue::Float(f) => MetaValue::Float(*f),
compiler::MetaValue::String(id) => {
let s = self.rules.lit_pool().get(*id).unwrap();
let s = unsafe { s.to_str_unchecked() };
MetaValue::String(s)
}
compiler::MetaValue::Bytes(id) => {
MetaValue::Bytes(self.rules.lit_pool().get(*id).unwrap())
}
};
Some((ident, value))
}
}
impl ExactSizeIterator for Metadata<'_, '_> {
#[inline]
fn len(&self) -> usize {
self.len
}
}
pub struct Tags<'a, 'r> {
rules: &'r Rules,
iterator: Iter<'a, IdentId>,
len: usize,
}
impl Tags<'_, '_> {
#[inline]
pub fn is_empty(&self) -> bool {
self.iterator.len() == 0
}
}
impl<'r> Iterator for Tags<'_, 'r> {
type Item = Tag<'r>;
fn next(&mut self) -> Option<Self::Item> {
let ident_id = self.iterator.next()?;
Some(Tag { rules: self.rules, ident_id: *ident_id })
}
}
impl ExactSizeIterator for Tags<'_, '_> {
#[inline]
fn len(&self) -> usize {
self.len
}
}
pub struct Tag<'r> {
rules: &'r Rules,
ident_id: IdentId,
}
impl<'r> Tag<'r> {
pub fn identifier(&self) -> &'r str {
self.rules.ident_pool().get(self.ident_id).unwrap()
}
}
impl<'r> Serialize for Tag<'r> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.identifier())
}
}
pub struct Patterns<'a, 'r> {
ctx: Option<&'a ScanContext<'r, 'a>>,
rules: &'r Rules,
iterator: Iter<'a, PatternInfo>,
include_private: bool,
len_private: usize,
len_non_private: usize,
}
impl Patterns<'_, '_> {
pub fn include_private(mut self, yes: bool) -> Self {
self.include_private = yes;
self
}
}
impl ExactSizeIterator for Patterns<'_, '_> {
#[inline]
fn len(&self) -> usize {
if self.include_private {
self.len_non_private + self.len_private
} else {
self.len_non_private
}
}
}
impl<'a, 'r> Iterator for Patterns<'a, 'r> {
type Item = Pattern<'a, 'r>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let pattern = self.iterator.next()?;
if pattern.is_private {
self.len_private -= 1;
} else {
self.len_non_private -= 1;
}
if self.include_private || !pattern.is_private {
return Some(Pattern {
ctx: self.ctx,
rules: self.rules,
ident_id: pattern.ident_id,
pattern_id: pattern.pattern_id,
kind: pattern.kind,
is_private: pattern.is_private,
});
}
}
}
}
pub struct Pattern<'a, 'r> {
ctx: Option<&'a ScanContext<'r, 'a>>,
rules: &'r Rules,
ident_id: IdentId,
pattern_id: PatternId,
kind: PatternKind,
is_private: bool,
}
impl<'a, 'r> Pattern<'a, 'r> {
pub fn identifier(&self) -> &'r str {
self.rules.ident_pool().get(self.ident_id).unwrap()
}
#[inline]
pub fn kind(&self) -> PatternKind {
self.kind
}
#[inline]
pub fn is_private(&self) -> bool {
self.is_private
}
pub fn matches(&self) -> Matches<'a, 'r> {
Matches {
ctx: self.ctx,
iterator: self.ctx.and_then(|ctx| {
ctx.pattern_matches
.get(self.pattern_id)
.map(|matches| matches.iter())
}),
}
}
}
impl<'a, 'r> Serialize for Pattern<'a, 'r> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut s = serializer.serialize_struct("pattern", 4)?;
s.serialize_field("identifier", &self.identifier())?;
s.serialize_field("kind", &self.kind())?;
s.serialize_field("is_private", &self.is_private())?;
let matches: Vec<_> = self.matches().collect();
s.serialize_field("matches", &matches)?;
s.end()
}
}
pub struct Matches<'a, 'r> {
ctx: Option<&'a ScanContext<'r, 'a>>,
iterator: Option<Iter<'a, scanner::Match>>,
}
impl<'a, 'r> Iterator for Matches<'a, 'r> {
type Item = Match<'a, 'r>;
fn next(&mut self) -> Option<Self::Item> {
let iter = self.iterator.as_mut()?;
Some(Match { ctx: self.ctx?, inner: iter.next()? })
}
}
impl ExactSizeIterator for Matches<'_, '_> {
fn len(&self) -> usize {
self.iterator.as_ref().map_or(0, |it| it.len())
}
}
pub struct Match<'a, 'r> {
ctx: &'a ScanContext<'r, 'a>,
inner: &'a scanner::Match,
}
impl<'a> Match<'a, '_> {
#[inline]
pub fn range(&self) -> Range<usize> {
self.inner.range.clone()
}
#[inline]
pub fn data(&self) -> &'a [u8] {
let data = match &self.ctx.scan_state {
ScanState::Finished(snippets) => snippets.get(self.range()),
_ => None,
};
data.unwrap()
}
#[inline]
pub fn xor_key(&self) -> Option<u8> {
self.inner.xor_key
}
}
impl<'a, 'r> Serialize for Match<'a, 'r> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut s = serializer.serialize_struct("match", 2)?;
s.serialize_field("range", &self.range())?;
s.serialize_field("xor_key", &self.xor_key())?;
s.end()
}
}