summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2015-04-23 10:53:27 +0200
committerYorhel <git@yorhel.nl>2015-04-23 10:53:27 +0200
commit3c66b5f385f49af91ea5467d5ce1b0c10dbf8cfb (patch)
tree3fd0658ef80d99aa650a4d357c7fc4a16c4b34ed
parentcc54b6fbd2d2ac0877d6b33fe5a5280acb4766e4 (diff)
Regex matching
This breaks the tests because Regex doesn't have Eq. Can try something else maybe...
-rw-r--r--Cargo.toml1
-rw-r--r--src/filter.rs71
-rw-r--r--src/main.rs1
3 files changed, 70 insertions, 3 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 6dc672b..563d73d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,3 +7,4 @@ authors = ["Yorhel <git@yorhel.nl>"]
time = "*"
peg = "*"
getopts = "*"
+regex = "*"
diff --git a/src/filter.rs b/src/filter.rs
index f3d2ade..d4ce4bd 100644
--- a/src/filter.rs
+++ b/src/filter.rs
@@ -1,3 +1,6 @@
+use regex::Regex;
+use super::Line;
+
#[derive(Clone,Copy,Debug,PartialEq,Eq)]
pub enum FilterCmp {
Ge,
@@ -8,13 +11,26 @@ pub enum FilterCmp {
Ne,
}
-#[derive(Debug,PartialEq,Eq)]
+#[derive(Clone,Copy,Debug,PartialEq,Eq)]
+pub enum FilterStrField {
+ Host,
+ Ident,
+ User,
+ Method,
+ Path,
+ Proto,
+ Referer,
+ Ua,
+}
+
+#[derive(Debug)]
pub enum Filter {
And(Box<Filter>, Box<Filter>),
Or(Box<Filter>, Box<Filter>),
Not(Box<Filter>),
SizeCmp(FilterCmp, u64),
StatusCmp(FilterCmp, u16),
+ Match(FilterStrField, Regex),
}
@@ -34,10 +50,40 @@ cmp -> super::FilterCmp
/ "=" { super::FilterCmp::Eq }
/ "!=" { super::FilterCmp::Ne }
+strfield -> super::FilterStrField
+ = "host" { super::FilterStrField::Host }
+ / "ident" { super::FilterStrField::Ident }
+ / "user" { super::FilterStrField::User }
+ / "method" { super::FilterStrField::Method }
+ / "path" { super::FilterStrField::Path }
+ / "proto" { super::FilterStrField::Proto }
+ / "referer" { super::FilterStrField::Referer }
+ / "ua" { super::FilterStrField::Ua }
+
unsigned -> u64
= [1-9][0-9]* { match_str.parse().unwrap() }
/ "0" { 0u64 }
+unit_mult -> u64
+ = "G" { 1u64<<30 }
+ / "M" { 1u64<<20 }
+ / "k" { 1u64<<10 }
+ / { 1u64 }
+
+size -> u64
+ = u:unsigned m:unit_mult { u * m }
+
+string_part -> &'input str
+ = [^"\\]+ { match_str }
+ / "\\\"" { "\"" }
+ / "\\\\" { "\\" }
+
+string -> String
+ = "\"" s:string_part* "\"" { s.concat() }
+
+regex -> super::super::regex::Regex
+ = s:string {? match super::super::regex::Regex::new(&s) { Ok(x) => Ok(x), Err(_) => Err("Invalid regular expression") } }
+
ws
= [ ]*
@@ -48,8 +94,9 @@ filter -> super::Filter
/ "!" ws x:filter { super::Filter::Not(Box::new(x)) }
/ "(" ws a:filter "&" ws b:filter ")" ws { super::Filter::And(Box::new(a), Box::new(b)) }
/ "(" ws a:filter "|" ws b:filter ")" ws { super::Filter::Or(Box::new(a), Box::new(b)) }
- / "size" ws c:cmp ws n:unsigned ws { super::Filter::SizeCmp(c, n) }
+ / "size" ws c:cmp ws n:size ws { super::Filter::SizeCmp(c, n) }
/ "status" ws c:cmp ws n:unsigned ws { super::Filter::StatusCmp(c, n as u16) }
+ / f:strfield ws "~" ws r:regex ws { super::Filter::Match(f, r) }
"#);
@@ -68,6 +115,22 @@ impl FilterCmp {
}
+impl FilterStrField {
+ fn getfield<'a>(self, l: &'a Line) -> &'a str {
+ match self {
+ FilterStrField::Host => l.host,
+ FilterStrField::Ident => l.ident,
+ FilterStrField::User => l.user,
+ FilterStrField::Method => l.method,
+ FilterStrField::Path => l.path,
+ FilterStrField::Proto => l.proto,
+ FilterStrField::Referer => l.referer.unwrap_or(""),
+ FilterStrField::Ua => l.ua.unwrap_or(""),
+ }
+ }
+}
+
+
impl Filter {
pub fn new(filter: &str) -> Result<Filter, ()> {
match filterparse::filter(filter) {
@@ -76,13 +139,14 @@ impl Filter {
}
}
- pub fn apply(&self, line: &super::Line) -> bool {
+ pub fn apply(&self, line: &Line) -> bool {
match *self {
Filter::And(ref a, ref b) => a.apply(line) && b.apply(line),
Filter::Or(ref a, ref b) => a.apply(line) || b.apply(line),
Filter::Not(ref a) => !a.apply(line),
Filter::SizeCmp(c, x) => c.apply(x, line.size),
Filter::StatusCmp(c, x) => c.apply(x, line.status),
+ Filter::Match(f, ref r) => r.is_match(f.getfield(&line))
}
}
}
@@ -91,6 +155,7 @@ impl Filter {
#[test]
fn test_parse() {
assert_eq!(Filter::new("size > 1"), Ok(Filter::SizeCmp(FilterCmp::Gt, 1)));
+ assert_eq!(Filter::new("size < 1G"), Ok(Filter::SizeCmp(FilterCmp::Lt, 1024*1024*1024)));
assert_eq!(Filter::new(" ( status >= 1 & status<=10) "),
Ok(Filter::And(
Box::new(Filter::StatusCmp(FilterCmp::Ge, 1)),
diff --git a/src/main.rs b/src/main.rs
index e7b5475..f94107b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,6 +5,7 @@
extern crate test;
extern crate time;
extern crate getopts;
+extern crate regex;
mod line;
mod filter;