Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
#[macro_use]
extern crate nom;
use nom::IResult;
use std::env;
use std::fs::File;
#[derive(Debug)]
struct Request<'a> {
method: &'a [u8],
uri: &'a [u8],
version: &'a [u8],
}
#[derive(Debug)]
struct Header<'a> {
name: &'a [u8],
value: Vec<&'a [u8]>,
}
fn is_token(c: u8) -> bool {
match c {
128...255 => false,
0...31 => false,
b'(' => false,
b')' => false,
b'<' => false,
b'>' => false,
b'@' => false,
b',' => false,
b';' => false,
b':' => false,
b'\\' => false,
b'"' => false,
b'/' => false,
b'[' => false,
b']' => false,
b'?' => false,
b'=' => false,
b'{' => false,
b'}' => false,
b' ' => false,
_ => true,
}
}
fn not_line_ending(c: u8) -> bool {
c != b'\r' && c != b'\n'
}
fn is_space(c: u8) -> bool {
c == b' '
}
fn is_not_space(c: u8) -> bool { c != b' ' }
fn is_horizontal_space(c: u8) -> bool { c == b' ' || c == b'\t' }
fn is_version(c: u8) -> bool {
c >= b'0' && c <= b'9' || c == b'.'
}
named!(line_ending, alt!(tag!("\n") | tag!("\r\n")));
named!(request_line(&[u8]) -> Request, chain!(
method: take_while1!(is_token) ~
take_while1!(is_space) ~
url: take_while1!(is_not_space) ~
take_while1!(is_space) ~
version: http_version ~
line_ending,
|| Request {
method: method,
uri: url,
version: version,
}));
named!(http_version, chain!(
tag!("HTTP/") ~
version: take_while1!(is_version),
|| version));
named!(message_header_value, chain!(
take_while1!(is_horizontal_space) ~
data: take_while1!(not_line_ending) ~
line_ending,
|| data));
named!(message_header(&[u8]) -> Header, chain!(
name: take_while1!(is_token) ~
char!(':') ~
values: many1!(message_header_value),
|| Header {
name: name,
value: values,
}));
named!(request(&[u8]) -> (Request, Vec<Header>), chain!(
req: request_line ~
h: many1!(message_header) ~
line_ending,
|| (req, h)));
fn main() {
let mut contents: Vec<u8> = Vec::new();
{
use std::io::Read;
let mut file = File::open(env::args().nth(1).expect("File to read")).ok().expect("Failed to open file");
let _ = file.read_to_end(&mut contents).unwrap();
}
let mut buf = &contents[..];
let mut i = 0;
loop {
match request(buf) {
IResult::Done(b, _) => {
buf = b;
i = i + 1;
if b.is_empty() {
break;
}
},
IResult::Error(e) => panic!("{:?}", e),
IResult::Incomplete(_) => panic!("Incomplete!"),
}
}
println!("{}", i);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment