use std::collections::HashMap;
use std::fmt;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use uuid::Uuid;
use regex::Regex;
const ID_REGEXP: &'static str =
r"^((?i)[A-F0-9]{8}\-[A-F0-9]{4}\-4[A-F0-9]{3}\-[89AB][A-F0-9]{3}\-[A-F0-9]{12})$";
#[derive(PartialEq, Debug, Eq, Hash, Clone)]
pub struct Id(String);
impl Id {
pub fn random() -> Id {
Id(Uuid::new_v4().to_string())
}
pub fn value(&self) -> &str {
&*self.0
}
}
pub struct IdExtractor(Regex);
impl IdExtractor {
pub fn new() -> IdExtractor {
match Regex::new(ID_REGEXP) {
Ok(regex) => IdExtractor(regex),
_ => unreachable!(), }
}
pub fn parse(&self, s: &str) -> Option<Id> {
let caps = self.0.captures(s);
caps.and_then(|c| c.get(1).map(|r| Id(r.as_str().to_owned())))
}
}
impl Encodable for Id {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_str(&*self.0)
}
}
impl Decodable for Id {
fn decode<S: Decoder>(s: &mut S) -> Result<Id, S::Error> {
s.read_str().map(|s| Id(s.to_owned()))
}
}
impl fmt::Display for Id {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(PartialEq, Debug, Eq, RustcDecodable, RustcEncodable)]
pub struct Request {
pub content_length: Option<u64>,
pub content_type: Option<String>,
pub time: i64,
pub method: String,
pub path: String,
pub body: Option<String>,
pub headers: HashMap<String, Vec<String>>,
pub query_string: HashMap<String, Vec<String>>,
}
#[derive(PartialEq, Debug, Eq, RustcDecodable, RustcEncodable)]
pub struct BinSummary {
pub id: Id,
pub request_count: usize,
}
#[cfg(test)]
mod tests {
use super::*;
use rustc_serialize::json;
#[test]
fn test_idextractor_instantiation() {
let _ = IdExtractor::new();
}
#[test]
fn test_id_json_encoding_decoding() {
let id = Id::random();
let encoded = json::encode(&id).unwrap();
let decoded: Id = json::decode(&*encoded).unwrap();
assert_eq!(decoded, id);
assert_eq!(format!("\"{}\"", id), encoded); }
}