use std::str::{FromStr, from_utf8};
use nom::{non_empty, space, eof};
use crate::vsl::record::VslIdent;
use crate::maybe_string::MaybeStr;
use super::{
TimeStamp,
Duration,
ByteCount,
BitCount,
FetchMode,
Status,
Port,
FileDescriptor,
AclResult,
CompressionOperation,
CompressionDirection,
};
macro_rules! maybe_str {
($i:expr, $submac:ident!( $($args:tt)* )) => {
map!($i, $submac!($($args)*), MaybeStr::from_bytes)
};
($i:expr, $f:expr) => {
map!($i, call!($f), MaybeStr::from_bytes)
};
}
named!(token<&[u8], &[u8]>, terminated!(is_not!(b" "), alt_complete!(space | eof)));
named!(label<&[u8], &str>, map_res!(terminated!(take_until!(b": "), tag!(b": ")), from_utf8));
named!(symbol<&[u8], &str>, map_res!(token, from_utf8));
named!(header_name<&[u8], &MaybeStr>, maybe_str!(
terminated!(take_until!(b":"), tag!(b":"))));
named!(header_value<&[u8], Option<&MaybeStr> >,
delimited!(opt!(space), opt!(maybe_str!(non_empty)), eof));
macro_rules! named_parsed_symbol {
($name:ident<$parse:ty>) => {
named!($name<&[u8], $parse>, map_res!(symbol, FromStr::from_str));
}
}
named_parsed_symbol!(vsl_ident<VslIdent>);
named_parsed_symbol!(byte_count<ByteCount>);
named_parsed_symbol!(bit_count<BitCount>);
named_parsed_symbol!(fech_mode<FetchMode>);
named_parsed_symbol!(status<Status>);
named_parsed_symbol!(time_stamp<TimeStamp>);
named_parsed_symbol!(duration<Duration>);
named_parsed_symbol!(port<Port>);
named_parsed_symbol!(file_descriptor<FileDescriptor>);
fn map_opt_duration(duration: Duration) -> Option<Duration> {
if duration < 0.0 {
None
} else {
Some(duration)
}
}
named!(opt_duration<&[u8], Option<Duration> >, map!(duration, map_opt_duration));
named!(pub slt_begin<&[u8], (&str, VslIdent, &str)>, tuple!(
symbol, vsl_ident, symbol));
named!(pub slt_timestamp<&[u8], (&str, TimeStamp, Duration, Duration)>, tuple!(
label, time_stamp, duration, duration));
named!(pub slt_req_acct<&[u8], (ByteCount, ByteCount, ByteCount, ByteCount, ByteCount, ByteCount) >, tuple!(
byte_count, byte_count, byte_count, byte_count, byte_count, byte_count));
named!(pub slt_bereq_acct<&[u8], (ByteCount, ByteCount, ByteCount, ByteCount, ByteCount, ByteCount) >, tuple!(
byte_count, byte_count, byte_count, byte_count, byte_count, byte_count));
named!(pub slt_pipe_acct<&[u8], (ByteCount, ByteCount, ByteCount, ByteCount) >, tuple!(
byte_count, byte_count, byte_count, byte_count));
named!(pub slt_method<&[u8], &MaybeStr>, maybe_str!(
non_empty));
named!(pub slt_url<&[u8], &MaybeStr>, maybe_str!(
non_empty));
named!(pub slt_protocol<&[u8], &MaybeStr>, maybe_str!(
non_empty));
named!(pub slt_status<&[u8], Status>, call!(
status));
named!(pub slt_reason<&[u8], &MaybeStr>, maybe_str!(
non_empty));
named!(pub slt_header<&[u8], (&MaybeStr, Option<&MaybeStr>)>, tuple!(
header_name,
header_value));
named!(pub slt_sess_open<&[u8], ((&str, Port), &str, Option<(&str, Port)>, TimeStamp, FileDescriptor)>, tuple!(
tuple!(symbol, port),
symbol, chain!(
some: map!(peek!(tuple!(token, token)), |(ip, port)| { ip != b"-" && port != b"-" }) ~
addr: cond!(some, tuple!(symbol, port)),
|| { addr }),
time_stamp, file_descriptor));
named!(pub slt_proxy<&[u8], (&str, (&str, Port), (&str, Port))>, tuple!(
symbol, tuple!(symbol, port),
tuple!(symbol, port)
));
named!(pub slt_link<&[u8], (&str, VslIdent, &str)>, tuple!(
symbol, vsl_ident, symbol));
named!(pub slt_sess_close<&[u8], (&str, Duration)>, tuple!(
symbol, duration));
named!(pub slt_hit<&[u8], VslIdent>, call!(
vsl_ident));
named!(pub slt_hit_pass<&[u8], VslIdent>, call!(
vsl_ident));
named!(pub slt_hit_miss<&[u8], (VslIdent, Duration)>, tuple!(
vsl_ident, duration));
named!(pub slt_vcl_call<&[u8], &str>, call!(
symbol));
named!(pub slt_vcl_return<&[u8], &str>, call!(
symbol));
named!(pub slt_vcl_acl<&[u8], (AclResult, &str, Option<&MaybeStr>)>, chain!(
mat: terminated!(alt_complete!(tag!(b"NO_MATCH") | tag!(b"MATCH")), space) ~
name: symbol ~ addr: opt!(maybe_str!(non_empty)),
|| (match mat {
b"MATCH" => AclResult::Match,
b"NO_MATCH" => AclResult::NoMatch,
_ => unreachable!()
}, name, addr)));
named!(pub slt_storage<&[u8], (&str, &str)>, tuple!(
symbol, symbol));
named!(pub slt_ttl<&[u8], (&str, Option<Duration>, Option<Duration>, Option<Duration>, TimeStamp,
Option<(TimeStamp, TimeStamp, TimeStamp, Duration)>)>, tuple!(
symbol, opt_duration, opt_duration, opt_duration, time_stamp, opt!(tuple!(
time_stamp, time_stamp, time_stamp, duration ))));
named!(pub slt_fetch_body<&[u8], (FetchMode, &str, bool)>, tuple!(
fech_mode, symbol, terminated!(map!(alt_complete!(tag!(b"stream") | tag!(b"-")),
|s| s == b"stream"
), eof)));
named!(pub slt_gzip<&[u8], Result<(CompressionOperation, CompressionDirection, bool, ByteCount, ByteCount, BitCount, BitCount, BitCount), &MaybeStr> >, alt_complete!(
map!(tuple!(
terminated!(map!(alt!(tag!(b"G") | tag!(b"U") | tag!(b"u")),
|s| if s == b"G" {
CompressionOperation::Gzip
} else if s == b"U" {
CompressionOperation::Gunzip
} else {
CompressionOperation::GunzipTest
}), space),
terminated!(map!(alt!(tag!(b"F") | tag!(b"D")),
|s| if s == b"F" {
CompressionDirection::Fetch
} else {
CompressionDirection::Deliver
}), space),
terminated!(map!(alt!(tag!(b"E") | tag!(b"-")),
|o| o == b"E"
), space),
byte_count,
byte_count,
bit_count,
bit_count,
bit_count), |t| Ok(t)) |
map!(maybe_str!(non_empty), |m| Err(m))));
named!(pub slt_vcl_log<&[u8], &MaybeStr>, maybe_str!(
non_empty));
named!(pub slt_req_start<&[u8], (&str, Port)>, tuple!(
symbol, port));
named!(pub slt_backend_open<&[u8], (FileDescriptor, &str, Option<(&str, Port)>, (&str, Port))>, tuple!(
file_descriptor, symbol, alt!(map!(terminated!(tag!(b"<none> <none>"), space), |_| None) | map!(tuple!(symbol, port), |t| Some(t))), tuple!(symbol, port)));