<commit_before>use std::collections::BTreeMap;
use std::default::Default;
use rustc_serialize::json::{Json,ToJson};

use util::*;
use util::Presence::*;
use self::RequestMethod::*;
use contact::PartialContact;

#[derive(Clone, PartialEq, Debug)]
pub struct GetRequestArgs {
    pub ids:         Presence<Vec<String>>,
    pub properties:  Presence<Vec<String>>,
    pub since_state: Presence<String>,
}

impl Default for GetRequestArgs {
    fn default() -> GetRequestArgs {
        GetRequestArgs {
            ids:         Absent,
            properties:  Absent,
            since_state: Absent,
        }
    }
}

impl ToJson for GetRequestArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.ids.to_json_field(&mut d, "ids");
        self.properties.to_json_field(&mut d, "properties");
        self.since_state.to_json_field(&mut d, "sinceState");
        Json::Object(d)
    }
}

impl FromJson for GetRequestArgs {
    fn from_json(json: &Json) -> Result<GetRequestArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = GetRequestArgs::default();
                args.ids         = try!(FromJsonField::from_json_field(o, "ids"));
                args.properties  = try!(FromJsonField::from_json_field(o, "properties"));
                args.since_state = try!(FromJsonField::from_json_field(o, "sinceState"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("GetRequestArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct GetResponseArgs {
    pub state:     String,
    pub ids:       Option<Vec<PartialContact>>,
    pub not_found: Option<Vec<String>>,
}

impl Default for GetResponseArgs {
    fn default() -> GetResponseArgs {
        GetResponseArgs {
            state:     "".to_string(),
            ids:       None,
            not_found: None,
        }
    }
}

impl ToJson for GetResponseArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.state.to_json_field(&mut d, "state");
        self.ids.to_json_field(&mut d, "ids");
        self.not_found.to_json_field(&mut d, "notFound");
        Json::Object(d)
    }
}

impl FromJson for GetResponseArgs {
    fn from_json(json: &Json) -> Result<GetResponseArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = GetResponseArgs::default();
                args.state       = try!(FromJsonField::from_json_field(o, "state"));
                args.ids         = try!(FromJsonField::from_json_field(o, "ids"));
                args.not_found   = try!(FromJsonField::from_json_field(o, "notFound"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("GetResponseArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct GetUpdatesRequestArgs {
    pub since_state:             String,
    pub max_changes:             Presence<u64>,
    pub fetch_records:           Presence<bool>,
    pub fetch_record_properties: Presence<Vec<String>>,
}

impl Default for GetUpdatesRequestArgs {
    fn default() -> GetUpdatesRequestArgs {
        GetUpdatesRequestArgs {
            since_state:             "".to_string(),
            max_changes:             Absent,
            fetch_records:           Absent,
            fetch_record_properties: Absent,
        }
    }
}

impl ToJson for GetUpdatesRequestArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.since_state.to_json_field(&mut d, "sinceState");
        self.max_changes.to_json_field(&mut d, "maxChanges");
        self.fetch_records.to_json_field(&mut d, "fetchRecords");
        self.fetch_record_properties.to_json_field(&mut d, "fetchRecordProperties");
        Json::Object(d)
    }
}

impl FromJson for GetUpdatesRequestArgs {
    fn from_json(json: &Json) -> Result<GetUpdatesRequestArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = GetUpdatesRequestArgs::default();
                args.since_state             = try!(FromJsonField::from_json_field(o, "sinceState"));
                args.max_changes             = try!(FromJsonField::from_json_field(o, "maxChanges"));
                args.fetch_records           = try!(FromJsonField::from_json_field(o, "fetchRecords"));
                args.fetch_record_properties = try!(FromJsonField::from_json_field(o, "fetchRecordProperties"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("GetUpdatesRequestArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct GetUpdatesResponseArgs {
    pub old_state: String,
    pub new_state: String,
    pub changed:   Vec<String>,
    pub removed:   Vec<String>,
}

impl Default for GetUpdatesResponseArgs {
    fn default() -> GetUpdatesResponseArgs {
        GetUpdatesResponseArgs {
            old_state: "".to_string(),
            new_state: "".to_string(),
            changed:   vec!(),
            removed:   vec!(),
        }
    }
}

impl ToJson for GetUpdatesResponseArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.old_state.to_json_field(&mut d, "oldState");
        self.new_state.to_json_field(&mut d, "newState");
        self.changed.to_json_field(&mut d, "changed");
        self.removed.to_json_field(&mut d, "removed");
        Json::Object(d)
    }
}

impl FromJson for GetUpdatesResponseArgs {
    fn from_json(json: &Json) -> Result<GetUpdatesResponseArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = GetUpdatesResponseArgs::default();
                args.old_state = try!(FromJsonField::from_json_field(o, "oldState"));
                args.new_state = try!(FromJsonField::from_json_field(o, "newState"));
                args.changed   = try!(FromJsonField::from_json_field(o, "changed"));
                args.removed   = try!(FromJsonField::from_json_field(o, "removed"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("GetUpdatesResponseArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct SetRequestArgs {
    pub if_in_state: Presence<String>,
    pub create:      Presence<BTreeMap<String,PartialContact>>,
    pub update:      Presence<BTreeMap<String,PartialContact>>,
    pub destroy:     Presence<Vec<String>>,
}

impl Default for SetRequestArgs {
    fn default() -> SetRequestArgs {
        SetRequestArgs {
            if_in_state: Absent,
            create:      Absent,
            update:      Absent,
            destroy:     Absent,
        }
    }
}

impl ToJson for SetRequestArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.if_in_state.to_json_field(&mut d, "ifInState");
        self.create.to_json_field(&mut d, "create");
        self.update.to_json_field(&mut d, "update");
        self.destroy.to_json_field(&mut d, "destroy");
        Json::Object(d)
    }
}

impl FromJson for SetRequestArgs {
    fn from_json(json: &Json) -> Result<SetRequestArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = SetRequestArgs::default();
                args.if_in_state = try!(FromJsonField::from_json_field(o, "ifInState"));
                args.create      = try!(FromJsonField::from_json_field(o, "create"));
                args.update      = try!(FromJsonField::from_json_field(o, "update"));
                args.destroy     = try!(FromJsonField::from_json_field(o, "destroy"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("SetRequestArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct SetResponseArgs {
    pub old_state:     Option<String>,
    pub new_state:     String,
    pub created:       BTreeMap<String,PartialContact>,
    pub updated:       Vec<String>,
    pub destroyed:     Vec<String>,
    pub not_created:   BTreeMap<String,SetError>,
    pub not_updated:   BTreeMap<String,SetError>,
    pub not_destroyed: BTreeMap<String,SetError>,
}

impl Default for SetResponseArgs {
    fn default() -> SetResponseArgs {
        SetResponseArgs {
            old_state:     None,
            new_state:     "".to_string(),
            created:       BTreeMap::new(),
            updated:       vec!(),
            destroyed:     vec!(),
            not_created:   BTreeMap::new(),
            not_updated:   BTreeMap::new(),
            not_destroyed: BTreeMap::new(),
        }
    }
}

impl ToJson for SetResponseArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.old_state.to_json_field(&mut d, "oldState");
        self.new_state.to_json_field(&mut d, "newState");
        self.created.to_json_field(&mut d, "created");
        self.updated.to_json_field(&mut d, "updated");
        self.destroyed.to_json_field(&mut d, "destroyed");
        self.not_created.to_json_field(&mut d, "notCreated");
        self.not_updated.to_json_field(&mut d, "notUpdated");
        self.not_destroyed.to_json_field(&mut d, "notDestroyed");
        Json::Object(d)
    }
}

impl FromJson for SetResponseArgs {
    fn from_json(json: &Json) -> Result<SetResponseArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = SetResponseArgs::default();
                args.old_state     = try!(FromJsonField::from_json_field(o, "oldState"));
                args.new_state     = try!(FromJsonField::from_json_field(o, "newState"));
                args.created       = try!(FromJsonField::from_json_field(o, "created"));
                args.updated       = try!(FromJsonField::from_json_field(o, "updated"));
                args.destroyed     = try!(FromJsonField::from_json_field(o, "destroyed"));
                args.not_created   = try!(FromJsonField::from_json_field(o, "notCreated"));
                args.not_updated   = try!(FromJsonField::from_json_field(o, "notUpdated"));
                args.not_destroyed = try!(FromJsonField::from_json_field(o, "notDestroyed"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("SetResponseArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct SetError {
    pub typ:         String,
    pub description: Option<String>,
}

impl Default for SetError {
    fn default() -> SetError {
        SetError {
            typ:         "".to_string(),
            description: None,
        }
    }
}

impl ToJson for SetError {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.typ.to_json_field(&mut d, "type");
        self.description.to_json_field(&mut d, "description");
        Json::Object(d)
    }
}

impl FromJson for SetError {
    fn from_json(json: &Json) -> Result<SetError,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut se = SetError::default();
                se.typ         = try!(FromJsonField::from_json_field(o, "type"));
                se.description = try!(FromJsonField::from_json_field(o, "description"));
                Ok(se)
            },
            _ => Err(ParseError::InvalidJsonType("SetError".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub enum RequestMethod {
    GetContacts(GetRequestArgs, String),
    GetContactUpdates(GetUpdatesRequestArgs, String),
    SetContacts(SetRequestArgs, String),
}

impl ToJson for RequestMethod {
    fn to_json(&self) -> Json {
        Json::Array(
            match *self {
                GetContacts(ref args, ref client_id) =>
                    vec!("getContacts".to_json(), args.to_json(), client_id.to_json()),
                GetContactUpdates(ref args, ref client_id) =>
                    vec!("getContactUpdates".to_json(), args.to_json(), client_id.to_json()),
                SetContacts(ref args, ref client_id) =>
                    vec!("setContacts".to_json(), args.to_json(), client_id.to_json()),
            }
        )
    }
}

impl FromJson for RequestMethod {
    fn from_json(json: &Json) -> Result<RequestMethod,ParseError> {
        match *json {
            Json::Array(ref a) => {
                if let false = a.len() == 3 {
                    return Err(ParseError::InvalidStructure("RequestMethod".to_string()));
                }
                let method = try!(String::from_json(&a[0]));
                let client_id = try!(String::from_json(&a[2]));
                match method.as_ref() {
                    "getContacts" =>
                        Ok(GetContacts(try!(GetRequestArgs::from_json(&a[1])), client_id)),
                    "getContactUpdates" =>
                        Ok(GetContactUpdates(try!(GetUpdatesRequestArgs::from_json(&a[1])), client_id)),
                    "setContacts" =>
                        Ok(SetContacts(try!(SetRequestArgs::from_json(&a[1])), client_id)),
                    _ => Err(ParseError::UnknownMethod(method)),
                }
            },
            _ => Err(ParseError::InvalidJsonType("RequestMethod".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct RequestBatch(pub Vec<RequestMethod>);

impl Default for RequestBatch {
    fn default() -> RequestBatch {
        RequestBatch(vec!())
    }
}

impl ToJson for RequestBatch {
    fn to_json(&self) -> Json {
        self.0.to_json()
    }
}

impl FromJson for RequestBatch {
    fn from_json(json: &Json) -> Result<RequestBatch,ParseError> {
        match Vec::<RequestMethod>::from_json(json) {
            Ok(v) => Ok(RequestBatch(v)),
            Err(e) => Err(e),
        }
    }
}
<commit_msg>Response methods and batches<commit_after>use std::collections::BTreeMap;
use std::default::Default;
use rustc_serialize::json::{Json,ToJson};

use util::*;
use util::Presence::*;
use self::RequestMethod::*;
use self::ResponseMethod::*;
use contact::PartialContact;

#[derive(Clone, PartialEq, Debug)]
pub struct GetRequestArgs {
    pub ids:         Presence<Vec<String>>,
    pub properties:  Presence<Vec<String>>,
    pub since_state: Presence<String>,
}

impl Default for GetRequestArgs {
    fn default() -> GetRequestArgs {
        GetRequestArgs {
            ids:         Absent,
            properties:  Absent,
            since_state: Absent,
        }
    }
}

impl ToJson for GetRequestArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.ids.to_json_field(&mut d, "ids");
        self.properties.to_json_field(&mut d, "properties");
        self.since_state.to_json_field(&mut d, "sinceState");
        Json::Object(d)
    }
}

impl FromJson for GetRequestArgs {
    fn from_json(json: &Json) -> Result<GetRequestArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = GetRequestArgs::default();
                args.ids         = try!(FromJsonField::from_json_field(o, "ids"));
                args.properties  = try!(FromJsonField::from_json_field(o, "properties"));
                args.since_state = try!(FromJsonField::from_json_field(o, "sinceState"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("GetRequestArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct GetResponseArgs {
    pub state:     String,
    pub ids:       Option<Vec<PartialContact>>,
    pub not_found: Option<Vec<String>>,
}

impl Default for GetResponseArgs {
    fn default() -> GetResponseArgs {
        GetResponseArgs {
            state:     "".to_string(),
            ids:       None,
            not_found: None,
        }
    }
}

impl ToJson for GetResponseArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.state.to_json_field(&mut d, "state");
        self.ids.to_json_field(&mut d, "ids");
        self.not_found.to_json_field(&mut d, "notFound");
        Json::Object(d)
    }
}

impl FromJson for GetResponseArgs {
    fn from_json(json: &Json) -> Result<GetResponseArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = GetResponseArgs::default();
                args.state       = try!(FromJsonField::from_json_field(o, "state"));
                args.ids         = try!(FromJsonField::from_json_field(o, "ids"));
                args.not_found   = try!(FromJsonField::from_json_field(o, "notFound"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("GetResponseArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct GetUpdatesRequestArgs {
    pub since_state:             String,
    pub max_changes:             Presence<u64>,
    pub fetch_records:           Presence<bool>,
    pub fetch_record_properties: Presence<Vec<String>>,
}

impl Default for GetUpdatesRequestArgs {
    fn default() -> GetUpdatesRequestArgs {
        GetUpdatesRequestArgs {
            since_state:             "".to_string(),
            max_changes:             Absent,
            fetch_records:           Absent,
            fetch_record_properties: Absent,
        }
    }
}

impl ToJson for GetUpdatesRequestArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.since_state.to_json_field(&mut d, "sinceState");
        self.max_changes.to_json_field(&mut d, "maxChanges");
        self.fetch_records.to_json_field(&mut d, "fetchRecords");
        self.fetch_record_properties.to_json_field(&mut d, "fetchRecordProperties");
        Json::Object(d)
    }
}

impl FromJson for GetUpdatesRequestArgs {
    fn from_json(json: &Json) -> Result<GetUpdatesRequestArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = GetUpdatesRequestArgs::default();
                args.since_state             = try!(FromJsonField::from_json_field(o, "sinceState"));
                args.max_changes             = try!(FromJsonField::from_json_field(o, "maxChanges"));
                args.fetch_records           = try!(FromJsonField::from_json_field(o, "fetchRecords"));
                args.fetch_record_properties = try!(FromJsonField::from_json_field(o, "fetchRecordProperties"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("GetUpdatesRequestArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct GetUpdatesResponseArgs {
    pub old_state: String,
    pub new_state: String,
    pub changed:   Vec<String>,
    pub removed:   Vec<String>,
}

impl Default for GetUpdatesResponseArgs {
    fn default() -> GetUpdatesResponseArgs {
        GetUpdatesResponseArgs {
            old_state: "".to_string(),
            new_state: "".to_string(),
            changed:   vec!(),
            removed:   vec!(),
        }
    }
}

impl ToJson for GetUpdatesResponseArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.old_state.to_json_field(&mut d, "oldState");
        self.new_state.to_json_field(&mut d, "newState");
        self.changed.to_json_field(&mut d, "changed");
        self.removed.to_json_field(&mut d, "removed");
        Json::Object(d)
    }
}

impl FromJson for GetUpdatesResponseArgs {
    fn from_json(json: &Json) -> Result<GetUpdatesResponseArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = GetUpdatesResponseArgs::default();
                args.old_state = try!(FromJsonField::from_json_field(o, "oldState"));
                args.new_state = try!(FromJsonField::from_json_field(o, "newState"));
                args.changed   = try!(FromJsonField::from_json_field(o, "changed"));
                args.removed   = try!(FromJsonField::from_json_field(o, "removed"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("GetUpdatesResponseArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct SetRequestArgs {
    pub if_in_state: Presence<String>,
    pub create:      Presence<BTreeMap<String,PartialContact>>,
    pub update:      Presence<BTreeMap<String,PartialContact>>,
    pub destroy:     Presence<Vec<String>>,
}

impl Default for SetRequestArgs {
    fn default() -> SetRequestArgs {
        SetRequestArgs {
            if_in_state: Absent,
            create:      Absent,
            update:      Absent,
            destroy:     Absent,
        }
    }
}

impl ToJson for SetRequestArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.if_in_state.to_json_field(&mut d, "ifInState");
        self.create.to_json_field(&mut d, "create");
        self.update.to_json_field(&mut d, "update");
        self.destroy.to_json_field(&mut d, "destroy");
        Json::Object(d)
    }
}

impl FromJson for SetRequestArgs {
    fn from_json(json: &Json) -> Result<SetRequestArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = SetRequestArgs::default();
                args.if_in_state = try!(FromJsonField::from_json_field(o, "ifInState"));
                args.create      = try!(FromJsonField::from_json_field(o, "create"));
                args.update      = try!(FromJsonField::from_json_field(o, "update"));
                args.destroy     = try!(FromJsonField::from_json_field(o, "destroy"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("SetRequestArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct SetResponseArgs {
    pub old_state:     Option<String>,
    pub new_state:     String,
    pub created:       BTreeMap<String,PartialContact>,
    pub updated:       Vec<String>,
    pub destroyed:     Vec<String>,
    pub not_created:   BTreeMap<String,SetError>,
    pub not_updated:   BTreeMap<String,SetError>,
    pub not_destroyed: BTreeMap<String,SetError>,
}

impl Default for SetResponseArgs {
    fn default() -> SetResponseArgs {
        SetResponseArgs {
            old_state:     None,
            new_state:     "".to_string(),
            created:       BTreeMap::new(),
            updated:       vec!(),
            destroyed:     vec!(),
            not_created:   BTreeMap::new(),
            not_updated:   BTreeMap::new(),
            not_destroyed: BTreeMap::new(),
        }
    }
}

impl ToJson for SetResponseArgs {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.old_state.to_json_field(&mut d, "oldState");
        self.new_state.to_json_field(&mut d, "newState");
        self.created.to_json_field(&mut d, "created");
        self.updated.to_json_field(&mut d, "updated");
        self.destroyed.to_json_field(&mut d, "destroyed");
        self.not_created.to_json_field(&mut d, "notCreated");
        self.not_updated.to_json_field(&mut d, "notUpdated");
        self.not_destroyed.to_json_field(&mut d, "notDestroyed");
        Json::Object(d)
    }
}

impl FromJson for SetResponseArgs {
    fn from_json(json: &Json) -> Result<SetResponseArgs,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut args = SetResponseArgs::default();
                args.old_state     = try!(FromJsonField::from_json_field(o, "oldState"));
                args.new_state     = try!(FromJsonField::from_json_field(o, "newState"));
                args.created       = try!(FromJsonField::from_json_field(o, "created"));
                args.updated       = try!(FromJsonField::from_json_field(o, "updated"));
                args.destroyed     = try!(FromJsonField::from_json_field(o, "destroyed"));
                args.not_created   = try!(FromJsonField::from_json_field(o, "notCreated"));
                args.not_updated   = try!(FromJsonField::from_json_field(o, "notUpdated"));
                args.not_destroyed = try!(FromJsonField::from_json_field(o, "notDestroyed"));
                Ok(args)
            },
            _ => Err(ParseError::InvalidJsonType("SetResponseArgs".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct SetError {
    pub typ:         String,
    pub description: Option<String>,
}

impl Default for SetError {
    fn default() -> SetError {
        SetError {
            typ:         "".to_string(),
            description: None,
        }
    }
}

impl ToJson for SetError {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        self.typ.to_json_field(&mut d, "type");
        self.description.to_json_field(&mut d, "description");
        Json::Object(d)
    }
}

impl FromJson for SetError {
    fn from_json(json: &Json) -> Result<SetError,ParseError> {
        match *json {
            Json::Object(ref o) => {
                let mut se = SetError::default();
                se.typ         = try!(FromJsonField::from_json_field(o, "type"));
                se.description = try!(FromJsonField::from_json_field(o, "description"));
                Ok(se)
            },
            _ => Err(ParseError::InvalidJsonType("SetError".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub enum RequestMethod {
    GetContacts(GetRequestArgs, String),
    GetContactUpdates(GetUpdatesRequestArgs, String),
    SetContacts(SetRequestArgs, String),
}

impl ToJson for RequestMethod {
    fn to_json(&self) -> Json {
        Json::Array(
            match *self {
                GetContacts(ref args, ref client_id) =>
                    vec!("getContacts".to_json(), args.to_json(), client_id.to_json()),
                GetContactUpdates(ref args, ref client_id) =>
                    vec!("getContactUpdates".to_json(), args.to_json(), client_id.to_json()),
                SetContacts(ref args, ref client_id) =>
                    vec!("setContacts".to_json(), args.to_json(), client_id.to_json()),
            }
        )
    }
}

impl FromJson for RequestMethod {
    fn from_json(json: &Json) -> Result<RequestMethod,ParseError> {
        match *json {
            Json::Array(ref a) => {
                if let false = a.len() == 3 {
                    return Err(ParseError::InvalidStructure("RequestMethod".to_string()));
                }
                let method = try!(String::from_json(&a[0]));
                let client_id = try!(String::from_json(&a[2]));
                match method.as_ref() {
                    "getContacts" =>
                        Ok(GetContacts(try!(GetRequestArgs::from_json(&a[1])), client_id)),
                    "getContactUpdates" =>
                        Ok(GetContactUpdates(try!(GetUpdatesRequestArgs::from_json(&a[1])), client_id)),
                    "setContacts" =>
                        Ok(SetContacts(try!(SetRequestArgs::from_json(&a[1])), client_id)),
                    _ => Err(ParseError::UnknownMethod(method)),
                }
            },
            _ => Err(ParseError::InvalidJsonType("RequestMethod".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub enum ResponseMethod {
    Contacts(GetResponseArgs, String),
    ContactUpdates(GetUpdatesResponseArgs, String),
    ContactsSet(SetResponseArgs, String),
}

impl ToJson for ResponseMethod {
    fn to_json(&self) -> Json {
        Json::Array(
            match *self {
                Contacts(ref args, ref client_id) =>
                    vec!("contacts".to_json(), args.to_json(), client_id.to_json()),
                ContactUpdates(ref args, ref client_id) =>
                    vec!("contactUpdates".to_json(), args.to_json(), client_id.to_json()),
                ContactsSet(ref args, ref client_id) =>
                    vec!("contactsSet".to_json(), args.to_json(), client_id.to_json()),
            }
        )
    }
}

impl FromJson for ResponseMethod {
    fn from_json(json: &Json) -> Result<ResponseMethod,ParseError> {
        match *json {
            Json::Array(ref a) => {
                if let false = a.len() == 3 {
                    return Err(ParseError::InvalidStructure("ResponseMethod".to_string()));
                }
                let method = try!(String::from_json(&a[0]));
                let client_id = try!(String::from_json(&a[2]));
                match method.as_ref() {
                    "contacts" =>
                        Ok(Contacts(try!(GetResponseArgs::from_json(&a[1])), client_id)),
                    "contactUpdates" =>
                        Ok(ContactUpdates(try!(GetUpdatesResponseArgs::from_json(&a[1])), client_id)),
                    "contactsSet" =>
                        Ok(ContactsSet(try!(SetResponseArgs::from_json(&a[1])), client_id)),
                    _ => Err(ParseError::UnknownMethod(method)),
                }
            },
            _ => Err(ParseError::InvalidJsonType("ResponseMethod".to_string())),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct RequestBatch(pub Vec<RequestMethod>);

impl Default for RequestBatch {
    fn default() -> RequestBatch {
        RequestBatch(vec!())
    }
}

impl ToJson for RequestBatch {
    fn to_json(&self) -> Json {
        self.0.to_json()
    }
}

impl FromJson for RequestBatch {
    fn from_json(json: &Json) -> Result<RequestBatch,ParseError> {
        match Vec::<RequestMethod>::from_json(json) {
            Ok(v) => Ok(RequestBatch(v)),
            Err(e) => Err(e),
        }
    }
}

#[derive(Clone, PartialEq, Debug)]
pub struct ResponseBatch(pub Vec<ResponseMethod>);

impl Default for ResponseBatch {
    fn default() -> ResponseBatch {
        ResponseBatch(vec!())
    }
}

impl ToJson for ResponseBatch {
    fn to_json(&self) -> Json {
        self.0.to_json()
    }
}

impl FromJson for ResponseBatch {
    fn from_json(json: &Json) -> Result<ResponseBatch,ParseError> {
        match Vec::<ResponseMethod>::from_json(json) {
            Ok(v) => Ok(ResponseBatch(v)),
            Err(e) => Err(e),
        }
    }
}
<|endoftext|>


<commit_before>extern mod std;
use std::hashmap::HashMap;
use sexpr;

// A very simple LISP-like language
// Globally scoped, no closures

/// Our value types
#[deriving(Clone)]
pub enum LispValue {
	List(~[LispValue]),
	Atom(~str),
	Str(~str),
	Num(float),
	Fn(~[~str], ~LispValue), // args, body
	BIF(~str, ~[~str], extern fn(@mut HashMap<~str, ~LispValue>, ~[~LispValue])->~LispValue) // built-in function (args, closure)
}

// XXX: this is ugly but it won't automatically derive Eq because of the extern fn
impl Eq for LispValue {
	fn eq(&self, other: &LispValue) -> bool {
		match (self.clone(), other.clone()) {
			(BIF(ref x, _, _), BIF(ref y, _, _)) if *x == *y => true,
			(Str(ref x), Str(ref y)) if *x == *y => true,
			(Num(ref x), Num(ref y)) if *x == *y => true,
			(Atom(ref x), Atom(ref y)) if *x == *y => true,
			(List(ref x), List(ref y)) if *x == *y => true,
			(Fn(ref x, ref x2), Fn(ref y, ref y2)) if *x == *y && *x2 == *y2 => true,
			_ => false
		}
	}
}

fn from_sexpr(sexpr: &sexpr::Value) -> ~LispValue {
	match *sexpr {
		sexpr::List(ref v) => ~List(v.map(|x| *from_sexpr(x))),
		sexpr::Num(v) => ~Num(v),
		sexpr::Str(ref v) => ~Str(v.clone()),
		sexpr::Atom(ref v) => ~Atom(v.clone())
	}
}

/// The type of the global symbol table (string to a value mapping).
type SymbolTable = HashMap<~str, ~LispValue>;

/// Returns a value representing the empty list
#[inline]
pub fn nil() -> ~LispValue {
	~List(~[])
}

/// Creates a new symbol table and returns it
pub fn new_symt() -> SymbolTable {
	HashMap::new()
}

/// Binds a symbol in the symbol table. Replaces if it already exists.
pub fn bind(symt: @mut SymbolTable, name: ~str, value: ~LispValue) {
	symt.insert(name, value);
}

/// Look up a symbol in the symbol table. Fails if not found.
pub fn lookup(symt: @mut SymbolTable, name: ~str) -> ~LispValue {
	match symt.find(&name) {
		Some(v) => v.clone(),
		None => fail!("couldn't find symbol: %s", name)
	}
}

/// Identity function
fn id_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue { v[0] }

fn cons_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	match v {
		[~a, ~b, .._] => ~List(~[a, b]),
		_ => fail!("cons: requires two arguments")
	}
}

fn car_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	match v[0] {
		~List(v_) => ~v_[0],
		_ => fail!("car: need a list")
	}
}

fn cdr_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	match v[0] {
		~List(v_) => ~v_[1],
		_ => fail!("cdr: need a list")
	}
}

// Print function
fn print_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	match v[0] {
		~Str(s) => printfln!("%s", s),
		_ => fail!("print takes an str")
	}
	nil()
}

/// Initializes standard library functions
pub fn init_std(symt: @mut SymbolTable) {
	bind(symt, ~"id", ~BIF(~"id", ~[~"x"], id_));
	bind(symt, ~"print", ~BIF(~"print", ~[~"msg"], print_));
	bind(symt, ~"cons", ~BIF(~"cons", ~[~"x", ~"y"], cons_));
	bind(symt, ~"car", ~BIF(~"car", ~[~"x"], car_));
	bind(symt, ~"cdr", ~BIF(~"cdr", ~[~"x"], cdr_));
}

fn apply(symt: @mut SymbolTable, f: ~LispValue, args: ~[~LispValue]) -> ~LispValue {
	match *f {
		BIF(name, fnargs, bif) => {
			// apply built-in function
			if fnargs.len() != args.len() {
				fail!("function '%s' requires %u arguments, but it received %u arguments",
					name, fnargs.len(), args.len())
			}

			bif(symt, args)
		}

		_ => fail!("apply: need function")
	}
}

/// Evaluates an s-expression and returns a value.
pub fn eval(symt: @mut SymbolTable, input: sexpr::Value) -> ~LispValue {
	match input {
		sexpr::List(v) => {
			if(v.len() == 0) {
				fail!("eval given empty list")
			}

			// evaluate a list as a function call
			match v {
				[sexpr::Atom(sym), ..args] => {
					let f = lookup(symt, sym);
					let xargs = args.map(|x| eval(symt, x.clone())); // eval'd args
					apply(symt, f, xargs)
				}
				_ => fail!("function calls take an atom"),
			}

		}
		_ => from_sexpr(&input) // return non-list values as they are
	}
}

#[cfg(test)]
mod test {
	use super::*;
	use sexpr;
	use sexpr::from_str;

	fn read(input: &str) -> sexpr::Value {
		from_str(input).unwrap()
	}

	#[test]
	fn test_eval() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("123")), ~Num(123.0));
		assert_eq!(eval(symt, read("(id 123)")), ~Num(123.0));
		assert_eq!(eval(symt, read("(id (id (id 123)))")), ~Num(123.0));
		// should fail: assert_eq!(eval(&mut symt, read("(1 2 3)")), ~List(~[Num(1.0), Num(2.0), Num(3.0)]));
	}

	#[test]
	fn test_str() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("(id \"hi\")")), ~Str(~"hi"));
		assert_eq!(eval(symt, read("(car (cons \"a\" \"b\"))")), ~Str(~"a"));
	}

	#[test]
	fn test_cons() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("(cons 1 2)")), ~List(~[Num(1.0), Num(2.0)]));
		assert_eq!(eval(symt, read("(cons 1 (cons 2 3))")), ~List(~[Num(1.0),
			List(~[Num(2.0), Num(3.0)])]));
	}

	#[test]
	fn test_car() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("(car (cons 1 2))")), ~Num(1.0));
	}

	#[test]
	fn test_cdr() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("(cdr (cons 1 2))")), ~Num(2.0));
		assert_eq!(eval(symt, read("(cdr (cons 1 (cons 2 3)))")), ~List(~[Num(2.0), Num(3.0)]));
	}
}<commit_msg>Implement + and *<commit_after>extern mod std;
use std::hashmap::HashMap;
use sexpr;

// A very simple LISP-like language
// Globally scoped, no closures

/// Our value types
#[deriving(Clone)]
pub enum LispValue {
	List(~[LispValue]),
	Atom(~str),
	Str(~str),
	Num(float),
	Fn(~[~str], ~LispValue), // args, body
	BIF(~str, ~[~str], extern fn(@mut HashMap<~str, ~LispValue>, ~[~LispValue])->~LispValue) // built-in function (args, closure)
}

// XXX: this is ugly but it won't automatically derive Eq because of the extern fn
impl Eq for LispValue {
	fn eq(&self, other: &LispValue) -> bool {
		match (self.clone(), other.clone()) {
			(BIF(ref x, _, _), BIF(ref y, _, _)) if *x == *y => true,
			(Str(ref x), Str(ref y)) if *x == *y => true,
			(Num(ref x), Num(ref y)) if *x == *y => true,
			(Atom(ref x), Atom(ref y)) if *x == *y => true,
			(List(ref x), List(ref y)) if *x == *y => true,
			(Fn(ref x, ref x2), Fn(ref y, ref y2)) if *x == *y && *x2 == *y2 => true,
			_ => false
		}
	}
}

fn from_sexpr(sexpr: &sexpr::Value) -> ~LispValue {
	match *sexpr {
		sexpr::List(ref v) => ~List(v.map(|x| *from_sexpr(x))),
		sexpr::Num(v) => ~Num(v),
		sexpr::Str(ref v) => ~Str(v.clone()),
		sexpr::Atom(ref v) => ~Atom(v.clone())
	}
}

/// The type of the global symbol table (string to a value mapping).
type SymbolTable = HashMap<~str, ~LispValue>;

/// Returns a value representing the empty list
#[inline]
pub fn nil() -> ~LispValue {
	~List(~[])
}

/// Creates a new symbol table and returns it
pub fn new_symt() -> SymbolTable {
	HashMap::new()
}

/// Binds a symbol in the symbol table. Replaces if it already exists.
pub fn bind(symt: @mut SymbolTable, name: ~str, value: ~LispValue) {
	symt.insert(name, value);
}

/// Look up a symbol in the symbol table. Fails if not found.
pub fn lookup(symt: @mut SymbolTable, name: ~str) -> ~LispValue {
	match symt.find(&name) {
		Some(v) => v.clone(),
		None => fail!("couldn't find symbol: %s", name)
	}
}

/// Identity function
fn id_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue { v[0] }

fn cons_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	match v {
		[~a, ~b, .._] => ~List(~[a, b]),
		_ => fail!("cons: requires two arguments")
	}
}

fn car_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	match v[0] {
		~List(v_) => ~v_[0],
		_ => fail!("car: need a list")
	}
}

fn cdr_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	match v[0] {
		~List(v_) => ~v_[1],
		_ => fail!("cdr: need a list")
	}
}

// Print function
fn print_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	match v[0] {
		~Str(s) => printfln!("%s", s),
		_ => fail!("print takes an str")
	}
	nil()
}

// There are several bugs in the macroing system (#8853, or, #8852 and #8851)
// that prevent us from making these functions macros. In addition, we can't
// return a closure because the type needs to be `extern "Rust" fn`, which
// closures aren't. So we have a little bit of code duplication.
//
// So later, we'll just implement `-` and `/` in terms of `+` and `*`.

fn plus_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	if(v.len() == 0) { fail!("+ needs operands"); }
	else if(v.len() == 1) {
		return v[0];
	}

	let add = |acc: ~LispValue, b: &~LispValue| {
		match (*acc, b) {
			(Num(ref x), &~Num(ref y)) => ~Num(x.clone() + y.clone()),
			(Str(ref x), &~Str(ref y)) => ~Str(x.clone() + y.clone()),
			_ => fail!("invalid operands to +")
		}
	};

	v.iter().skip(1).fold(v[0].clone(), add)
}

fn mul_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	if(v.len() == 0) { fail!("+ needs operands"); }
	else if(v.len() == 1) {
		return v[0];
	}

	let add = |acc: ~LispValue, b: &~LispValue| {
		match (*acc, b) {
			(Num(ref x), &~Num(ref y)) => ~Num(x.clone() * y.clone()),
			_ => fail!("invalid operands to +")
		}
	};

	v.iter().skip(1).fold(v[0].clone(), add)
}

/// Initializes standard library functions
pub fn init_std(symt: @mut SymbolTable) {
	bind(symt, ~"id", ~BIF(~"id", ~[~"x"], id_));
	bind(symt, ~"print", ~BIF(~"print", ~[~"msg"], print_));
	bind(symt, ~"cons", ~BIF(~"cons", ~[~"x", ~"y"], cons_));
	bind(symt, ~"car", ~BIF(~"car", ~[~"x"], car_));
	bind(symt, ~"cdr", ~BIF(~"cdr", ~[~"x"], cdr_));
	bind(symt, ~"+", ~BIF(~"+", ~[~"x"], plus_));
	bind(symt, ~"*", ~BIF(~"*", ~[~"x"], mul_));
}

fn apply(symt: @mut SymbolTable, f: ~LispValue, args: ~[~LispValue]) -> ~LispValue {
	match *f {
		BIF(name, fnargs, bif) => {
			// apply built-in function
			if fnargs.len() != args.len() {
				fail!("function '%s' requires %u arguments, but it received %u arguments",
					name, fnargs.len(), args.len())
			}

			bif(symt, args)
		}

		_ => fail!("apply: need function")
	}
}

/// Evaluates an s-expression and returns a value.
pub fn eval(symt: @mut SymbolTable, input: sexpr::Value) -> ~LispValue {
	match input {
		sexpr::List(v) => {
			if(v.len() == 0) {
				fail!("eval given empty list")
			}

			// evaluate a list as a function call
			match v {
				[sexpr::Atom(sym), ..args] => {
					let f = lookup(symt, sym);
					let xargs = args.map(|x| eval(symt, x.clone())); // eval'd args
					apply(symt, f, xargs)
				}
				_ => fail!("function calls take an atom"),
			}

		}
		_ => from_sexpr(&input) // return non-list values as they are
	}
}

#[cfg(test)]
mod test {
	use super::*;
	use sexpr;
	use sexpr::from_str;

	fn read(input: &str) -> sexpr::Value {
		from_str(input).unwrap()
	}

	#[test]
	fn test_eval() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("123")), ~Num(123.0));
		assert_eq!(eval(symt, read("(id 123)")), ~Num(123.0));
		assert_eq!(eval(symt, read("(id (id (id 123)))")), ~Num(123.0));
		// should fail: assert_eq!(eval(&mut symt, read("(1 2 3)")), ~List(~[Num(1.0), Num(2.0), Num(3.0)]));
	}

	#[test]
	fn test_str() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("(id \"hi\")")), ~Str(~"hi"));
		assert_eq!(eval(symt, read("(car (cons \"a\" \"b\"))")), ~Str(~"a"));
	}

	#[test]
	fn test_cons() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("(cons 1 2)")), ~List(~[Num(1.0), Num(2.0)]));
		assert_eq!(eval(symt, read("(cons 1 (cons 2 3))")), ~List(~[Num(1.0),
			List(~[Num(2.0), Num(3.0)])]));
	}

	#[test]
	fn test_car() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("(car (cons 1 2))")), ~Num(1.0));
	}

	#[test]
	fn test_cdr() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("(cdr (cons 1 2))")), ~Num(2.0));
		assert_eq!(eval(symt, read("(cdr (cons 1 (cons 2 3)))")), ~List(~[Num(2.0), Num(3.0)]));
	}

	#[test]
	fn test_arithmetic() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("(+ 1 3)")), ~Num(5.0));
		assert_eq!(eval(symt, read("(+ 1.5 3)")), ~Num(4.5));
		assert_eq!(eval(symt, read("(+ 5 -3)")), ~Num(2.0));

		assert_eq!(eval(symt, read("(- 5 3)")), ~Num(2.0));
		assert_eq!(eval(symt, read("(- 3 5)")), ~Num(-2.0));
		assert_eq!(eval(symt, read("(- 5 -3)")), ~Num(8.0));
	}
}<|endoftext|>


<commit_before>/// # Models
///
/// Here lies the data structures that a rocket league replay is decoded into. All of the models
/// are contained in this one file because of serde.
///
/// For serde, we only care about serialization, JSON serialization. Deserialization is not
/// implemented from our JSON output because it is lossy (JSON isn't the best with different
/// numeric/string types). Asking "why JSON" would be next logical step, and that's due to other
/// rocket league replay parsers (like Octane) using JSON; however, the output of this library is
/// not compatible with that of other rocket league replay parsers.
use crate::network::Frame;
use serde::ser::{SerializeMap, SerializeSeq};
use serde::{Serialize, Serializer};
use std::collections::HashMap;

/// The structure that a rocket league replay is parsed into.
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct Replay {
    pub header_size: i32,
    pub header_crc: u32,
    pub major_version: i32,
    pub minor_version: i32,
    pub net_version: Option<i32>,
    pub game_type: String,

    /// Could use a map to represent properties but I don't want to assume that duplicate keys
    /// can't exist, so to be safe, use a traditional vector.
    #[serde(serialize_with = "pair_vec")]
    pub properties: Vec<(String, HeaderProp)>,
    pub content_size: i32,
    pub content_crc: u32,
    pub network_frames: Option<NetworkFrames>,
    pub levels: Vec<String>,
    pub keyframes: Vec<KeyFrame>,
    pub debug_info: Vec<DebugInfo>,
    pub tick_marks: Vec<TickMark>,
    pub packages: Vec<String>,
    pub objects: Vec<String>,
    pub names: Vec<String>,
    pub class_indices: Vec<ClassIndex>,
    pub net_cache: Vec<ClassNetCache>,
}

/// The frames decoded from the network data
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct NetworkFrames {
    pub frames: Vec<Frame>,
}

/// In Rocket league replays, there are tickmarks that typically represent a significant event in
/// the game (eg. a goal). The tick mark is placed before the event happens so there is a ramp-up
/// time. For instance, a tickmark could be at frame 396 for a goal at frame 441. At 30 fps, this
/// would be 1.5 seconds of ramp up time.
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct TickMark {
    pub description: String,
    pub frame: i32,
}

/// Keyframes as defined by the video compression section in the [wikipedia][] article, are the
/// main frames that are derived from in the following frame data. The key frames decoded will
/// match up with the frames decoded from the network data.
///
/// [wikipedia]: https://en.wikipedia.org/wiki/Key_frame#Video_compression
#[derive(Serialize, PartialEq, Debug, Clone, Copy)]
pub struct KeyFrame {
    pub time: f32,
    pub frame: i32,
    pub position: i32,
}

/// All the interesting data are stored as properties in the header, properties such as:
///
/// - When and who scored a goal
/// - Player stats (goals, assists, score, etc).
/// - Date and level played on
///
/// A property can be a number, string, or a more complex object such as an array containing
/// additional properties.
#[derive(PartialEq, Debug, Clone)]
pub enum HeaderProp {
    Array(Vec<Vec<(String, HeaderProp)>>),
    Bool(bool),
    Byte,
    Float(f32),
    Int(i32),
    Name(String),
    QWord(u64),
    Str(String),
}

/// Debugging info stored in the replay if debugging is enabled.
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct DebugInfo {
    pub frame: i32,
    pub user: String,
    pub text: String,
}

/// A mapping between an object's name and its index. Largely redundant
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct ClassIndex {
    /// Should be equivalent to `Replay::objects(self.index)`
    pub class: String,

    /// The index that the object appears in the `Replay::objects`
    pub index: i32,
}

/// A mapping between an object (that's an attribute)'s index and what its id will be when encoded
/// in the network data
#[derive(Serialize, PartialEq, Debug, Clone, Copy)]
pub struct CacheProp {
    /// The index that the object appears in the `Replay::objects`
    pub object_ind: i32,

    /// An attribute / property id that appears in the network data. Stream ids are often re-used
    /// between multiple different properties
    pub stream_id: i32,
}

/// Contains useful information when decoding the network stream
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct ClassNetCache {
    /// The index that the object appears in the `Replay::objects`
    pub object_ind: i32,

    /// The cache id of the parent. The child class inherits all the parent's properties.
    pub parent_id: i32,

    /// The cache id of the object
    pub cache_id: i32,

    /// List of properties that is on the object.
    pub properties: Vec<CacheProp>,
}

/// Serialize a vector of key value tuples into a map. This is useful when the data we're ingesting
/// (rocket league replay data) doesn't have a defined spec, so it may be assuming too much to
/// store it into an associative array, so it's stored as a normal sequence. Here we serialize as a
/// map structure because most replay parser do this, so we should be compliant and the data format
/// doesn't dictate that the keys in a sequence of key value pairs must be distinct. It's true,
/// JSON doesn't need the keys to be unique: <http://stackoverflow.com/q/21832701/433785>
fn pair_vec<K, V, S>(inp: &[(K, V)], serializer: S) -> Result<S::Ok, S::Error>
where
    K: Serialize,
    V: Serialize,
    S: Serializer,
{
    let mut state = serializer.serialize_map(Some(inp.len()))?;
    for &(ref key, ref val) in inp.iter() {
        state.serialize_key(key)?;
        state.serialize_value(val)?;
    }
    state.end()
}

/// By default serde will generate a serialization method that writes out the enum as well as the
/// enum value. Since header values are self describing in JSON, we do not need to serialize the
/// enum type. This is slightly lossy as in the serialized format it will be ambiguous if a value
/// is a `Name` or `Str`, as well as `Byte`, `Float`, `Int`, or `QWord`.
impl Serialize for HeaderProp {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match *self {
            HeaderProp::Array(ref x) => {
                let mut state = serializer.serialize_seq(Some(x.len()))?;
                for inner in x {
                    // Look for a better way to do this instead of allocating the intermediate map
                    let mut els = HashMap::new();
                    for (key, val) in inner.iter() {
                        els.insert(key, val);
                    }
                    state.serialize_element(&els)?;
                }
                state.end()
            }
            HeaderProp::Bool(ref x) => serializer.serialize_bool(*x),
            HeaderProp::Byte => serializer.serialize_u8(0),
            HeaderProp::Float(ref x) => serializer.serialize_f32(*x),
            HeaderProp::Int(ref x) => serializer.serialize_i32(*x),
            HeaderProp::QWord(ref x) => serializer.collect_str(x),
            HeaderProp::Name(ref x) | HeaderProp::Str(ref x) => serializer.serialize_str(x),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn to_json<T: serde::Serialize>(input: &T) -> std::string::String {
        serde_json::to_string(input).unwrap()
    }

    #[test]
    fn serialize_header_array() {
        let data = vec![
            vec![
                (String::from("frame"), HeaderProp::Int(441)),
                (
                    String::from("PlayerName"),
                    HeaderProp::Str(String::from("rust is awesome")),
                ),
            ],
            vec![
                (String::from("frame"), HeaderProp::Int(1738)),
                (String::from("PlayerName"), HeaderProp::Str(String::from("rusty"))),
            ],
        ];
        let actual = to_json(&HeaderProp::Array(data));
        assert!(actual.contains("\"PlayerName\":\"rust is awesome\""));
        assert!(actual.contains("\"PlayerName\":\"rusty\""));
        assert!(actual.contains("\"frame\":441"));
        assert!(actual.contains("\"frame\":1738"));
    }

    #[test]
    fn serialize_header_bool() {
        assert_eq!(to_json(&HeaderProp::Bool(false)), "false");
        assert_eq!(to_json(&HeaderProp::Bool(true)), "true");
    }

    #[test]
    fn serialize_header_numbers() {
        assert_eq!(to_json(&HeaderProp::Byte), "0");
        assert_eq!(to_json(&HeaderProp::QWord(10)), "\"10\"");
        assert_eq!(to_json(&HeaderProp::Float(10.2)), "10.2");
        assert_eq!(to_json(&HeaderProp::Int(11)), "11");
    }

    #[test]
    fn serialize_header_str() {
        let val = "hello world";
        assert_eq!(
            to_json(&HeaderProp::Str(String::from(val))),
            "\"hello world\""
        );
        assert_eq!(
            to_json(&HeaderProp::Name(String::from(val))),
            "\"hello world\""
        );
    }
}
<commit_msg>Add convenience functions around header properties<commit_after>/// # Models
///
/// Here lies the data structures that a rocket league replay is decoded into. All of the models
/// are contained in this one file because of serde.
///
/// For serde, we only care about serialization, JSON serialization. Deserialization is not
/// implemented from our JSON output because it is lossy (JSON isn't the best with different
/// numeric/string types). Asking "why JSON" would be next logical step, and that's due to other
/// rocket league replay parsers (like Octane) using JSON; however, the output of this library is
/// not compatible with that of other rocket league replay parsers.
use crate::network::Frame;
use serde::ser::{SerializeMap, SerializeSeq};
use serde::{Serialize, Serializer};
use std::collections::HashMap;

/// The structure that a rocket league replay is parsed into.
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct Replay {
    pub header_size: i32,
    pub header_crc: u32,
    pub major_version: i32,
    pub minor_version: i32,
    pub net_version: Option<i32>,
    pub game_type: String,

    /// Could use a map to represent properties but I don't want to assume that duplicate keys
    /// can't exist, so to be safe, use a traditional vector.
    #[serde(serialize_with = "pair_vec")]
    pub properties: Vec<(String, HeaderProp)>,
    pub content_size: i32,
    pub content_crc: u32,
    pub network_frames: Option<NetworkFrames>,
    pub levels: Vec<String>,
    pub keyframes: Vec<KeyFrame>,
    pub debug_info: Vec<DebugInfo>,
    pub tick_marks: Vec<TickMark>,
    pub packages: Vec<String>,
    pub objects: Vec<String>,
    pub names: Vec<String>,
    pub class_indices: Vec<ClassIndex>,
    pub net_cache: Vec<ClassNetCache>,
}

/// The frames decoded from the network data
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct NetworkFrames {
    pub frames: Vec<Frame>,
}

/// In Rocket league replays, there are tickmarks that typically represent a significant event in
/// the game (eg. a goal). The tick mark is placed before the event happens so there is a ramp-up
/// time. For instance, a tickmark could be at frame 396 for a goal at frame 441. At 30 fps, this
/// would be 1.5 seconds of ramp up time.
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct TickMark {
    pub description: String,
    pub frame: i32,
}

/// Keyframes as defined by the video compression section in the [wikipedia][] article, are the
/// main frames that are derived from in the following frame data. The key frames decoded will
/// match up with the frames decoded from the network data.
///
/// [wikipedia]: https://en.wikipedia.org/wiki/Key_frame#Video_compression
#[derive(Serialize, PartialEq, Debug, Clone, Copy)]
pub struct KeyFrame {
    pub time: f32,
    pub frame: i32,
    pub position: i32,
}

/// All the interesting data are stored as properties in the header, properties such as:
///
/// - When and who scored a goal
/// - Player stats (goals, assists, score, etc).
/// - Date and level played on
///
/// A property can be a number, string, or a more complex object such as an array containing
/// additional properties.
#[derive(PartialEq, Debug, Clone)]
pub enum HeaderProp {
    Array(Vec<Vec<(String, HeaderProp)>>),
    Bool(bool),
    Byte,
    Float(f32),
    Int(i32),
    Name(String),
    QWord(u64),
    Str(String),
}

impl HeaderProp {
    /// If the `HeaderProp` is an array of properties, returns the array
    /// ```
    /// # use boxcars::HeaderProp;
    /// let v = HeaderProp::Array(vec![
    ///     vec![("abc".to_string(), HeaderProp::Byte)]
    /// ]);
    ///
    /// assert_eq!(v.as_array().unwrap().len(), 1);
    /// assert_eq!(v.as_array().unwrap()[0][0].1.as_array(), None);
    /// ```
    pub fn as_array(&self) -> Option<&Vec<Vec<(String, HeaderProp)>>> {
        if let HeaderProp::Array(arr) = self {
            Some(arr)
        } else {
            None
        }
    }

    /// If the `HeaderProp` is a boolean, returns the value
    /// ```
    /// # use boxcars::HeaderProp;
    /// let v = HeaderProp::Bool(true);
    /// let b = HeaderProp::Byte;
    ///
    /// assert_eq!(v.as_bool(), Some(true));
    /// assert_eq!(b.as_bool(), None);
    /// ```
    pub fn as_bool(&self) -> Option<bool> {
        if let HeaderProp::Bool(val) = self {
            Some(*val)
        } else {
            None
        }
    }

    /// If the `HeaderProp` is a float, returns the value
    /// ```
    /// # use boxcars::HeaderProp;
    /// let v = HeaderProp::Float(2.50);
    /// let b = HeaderProp::Byte;
    ///
    /// assert_eq!(v.as_float(), Some(2.50));
    /// assert_eq!(b.as_float(), None);
    /// ```
    pub fn as_float(&self) -> Option<f32> {
        if let HeaderProp::Float(val) = self {
            Some(*val)
        } else {
            None
        }
    }

    /// If the `HeaderProp` is a QWord, returns the value
    /// ```
    /// # use boxcars::HeaderProp;
    /// let v = HeaderProp::QWord(250);
    /// let b = HeaderProp::Byte;
    ///
    /// assert_eq!(v.as_u64(), Some(250));
    /// assert_eq!(b.as_u64(), None);
    /// ```
    pub fn as_u64(&self) -> Option<u64> {
        if let HeaderProp::QWord(val) = self {
            Some(*val)
        } else {
            None
        }
    }

    /// If the `HeaderProp` is an int, returns the value
    /// ```
    /// # use boxcars::HeaderProp;
    /// let v = HeaderProp::Int(-250);
    /// let b = HeaderProp::Byte;
    ///
    /// assert_eq!(v.as_i32(), Some(-250));
    /// assert_eq!(b.as_i32(), None);
    /// ```
    pub fn as_i32(&self) -> Option<i32> {
        if let HeaderProp::Int(val) = self {
            Some(*val)
        } else {
            None
        }
    }

    /// If the `HeaderProp` is an string, returns the value
    /// ```
    /// # use boxcars::HeaderProp;
    /// let v = HeaderProp::Name("abc".to_string());
    /// let x = HeaderProp::Str("def".to_string());
    /// let b = HeaderProp::Byte;
    ///
    /// assert_eq!(v.as_string(), Some("abc"));
    /// assert_eq!(x.as_string(), Some("def"));
    /// assert_eq!(b.as_i32(), None);
    /// ```
    pub fn as_string(&self) -> Option<&str> {
        match self {
            HeaderProp::Name(val) => Some(val.as_str()),
            HeaderProp::Str(val) => Some(val.as_str()),
            _ => None,
        }
    }

    /// Returns if the `HeaderProp` is a byte
    /// ```
    /// # use boxcars::HeaderProp;
    /// let v = HeaderProp::Name("abc".to_string());
    /// let b = HeaderProp::Byte;
    ///
    /// assert_eq!(v.is_byte(), false);
    /// assert_eq!(b.is_byte(), true);
    /// ```
    pub fn is_byte(&self) -> bool {
        if let HeaderProp::Byte = self {
            true
        } else {
            false
        }
    }
}

/// Debugging info stored in the replay if debugging is enabled.
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct DebugInfo {
    pub frame: i32,
    pub user: String,
    pub text: String,
}

/// A mapping between an object's name and its index. Largely redundant
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct ClassIndex {
    /// Should be equivalent to `Replay::objects(self.index)`
    pub class: String,

    /// The index that the object appears in the `Replay::objects`
    pub index: i32,
}

/// A mapping between an object (that's an attribute)'s index and what its id will be when encoded
/// in the network data
#[derive(Serialize, PartialEq, Debug, Clone, Copy)]
pub struct CacheProp {
    /// The index that the object appears in the `Replay::objects`
    pub object_ind: i32,

    /// An attribute / property id that appears in the network data. Stream ids are often re-used
    /// between multiple different properties
    pub stream_id: i32,
}

/// Contains useful information when decoding the network stream
#[derive(Serialize, PartialEq, Debug, Clone)]
pub struct ClassNetCache {
    /// The index that the object appears in the `Replay::objects`
    pub object_ind: i32,

    /// The cache id of the parent. The child class inherits all the parent's properties.
    pub parent_id: i32,

    /// The cache id of the object
    pub cache_id: i32,

    /// List of properties that is on the object.
    pub properties: Vec<CacheProp>,
}

/// Serialize a vector of key value tuples into a map. This is useful when the data we're ingesting
/// (rocket league replay data) doesn't have a defined spec, so it may be assuming too much to
/// store it into an associative array, so it's stored as a normal sequence. Here we serialize as a
/// map structure because most replay parser do this, so we should be compliant and the data format
/// doesn't dictate that the keys in a sequence of key value pairs must be distinct. It's true,
/// JSON doesn't need the keys to be unique: <http://stackoverflow.com/q/21832701/433785>
fn pair_vec<K, V, S>(inp: &[(K, V)], serializer: S) -> Result<S::Ok, S::Error>
where
    K: Serialize,
    V: Serialize,
    S: Serializer,
{
    let mut state = serializer.serialize_map(Some(inp.len()))?;
    for &(ref key, ref val) in inp.iter() {
        state.serialize_key(key)?;
        state.serialize_value(val)?;
    }
    state.end()
}

/// By default serde will generate a serialization method that writes out the enum as well as the
/// enum value. Since header values are self describing in JSON, we do not need to serialize the
/// enum type. This is slightly lossy as in the serialized format it will be ambiguous if a value
/// is a `Name` or `Str`, as well as `Byte`, `Float`, `Int`, or `QWord`.
impl Serialize for HeaderProp {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match *self {
            HeaderProp::Array(ref x) => {
                let mut state = serializer.serialize_seq(Some(x.len()))?;
                for inner in x {
                    // Look for a better way to do this instead of allocating the intermediate map
                    let mut els = HashMap::new();
                    for (key, val) in inner.iter() {
                        els.insert(key, val);
                    }
                    state.serialize_element(&els)?;
                }
                state.end()
            }
            HeaderProp::Bool(ref x) => serializer.serialize_bool(*x),
            HeaderProp::Byte => serializer.serialize_u8(0),
            HeaderProp::Float(ref x) => serializer.serialize_f32(*x),
            HeaderProp::Int(ref x) => serializer.serialize_i32(*x),
            HeaderProp::QWord(ref x) => serializer.collect_str(x),
            HeaderProp::Name(ref x) | HeaderProp::Str(ref x) => serializer.serialize_str(x),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn to_json<T: serde::Serialize>(input: &T) -> std::string::String {
        serde_json::to_string(input).unwrap()
    }

    #[test]
    fn serialize_header_array() {
        let data = vec![
            vec![
                (String::from("frame"), HeaderProp::Int(441)),
                (
                    String::from("PlayerName"),
                    HeaderProp::Str(String::from("rust is awesome")),
                ),
            ],
            vec![
                (String::from("frame"), HeaderProp::Int(1738)),
                (String::from("PlayerName"), HeaderProp::Str(String::from("rusty"))),
            ],
        ];
        let actual = to_json(&HeaderProp::Array(data));
        assert!(actual.contains("\"PlayerName\":\"rust is awesome\""));
        assert!(actual.contains("\"PlayerName\":\"rusty\""));
        assert!(actual.contains("\"frame\":441"));
        assert!(actual.contains("\"frame\":1738"));
    }

    #[test]
    fn serialize_header_bool() {
        assert_eq!(to_json(&HeaderProp::Bool(false)), "false");
        assert_eq!(to_json(&HeaderProp::Bool(true)), "true");
    }

    #[test]
    fn serialize_header_numbers() {
        assert_eq!(to_json(&HeaderProp::Byte), "0");
        assert_eq!(to_json(&HeaderProp::QWord(10)), "\"10\"");
        assert_eq!(to_json(&HeaderProp::Float(10.2)), "10.2");
        assert_eq!(to_json(&HeaderProp::Int(11)), "11");
    }

    #[test]
    fn serialize_header_str() {
        let val = "hello world";
        assert_eq!(
            to_json(&HeaderProp::Str(String::from(val))),
            "\"hello world\""
        );
        assert_eq!(
            to_json(&HeaderProp::Name(String::from(val))),
            "\"hello world\""
        );
    }
}
<|endoftext|>


<commit_before>use nom::{be_u8,be_u16,IResult};

/// Hash algorithms, as defined in [RFC5246]
#[derive(Debug, PartialEq, Eq)]
pub struct HashAlgorithm(u8);

newtype_enum! {
impl display HashAlgorithm {
    None = 0,
    Md5 = 1,
    Sha1 = 2,
    Sha224 = 3,
    Sha256 = 4,
    Sha384 = 5,
    Sha512 = 6,
}
}

/// Signature algorithms, as defined in [RFC5246]
#[derive(Debug, PartialEq, Eq)]
pub struct SignAlgorithm(u8);

newtype_enum! {
impl display SignAlgorithm {
    Anonymous = 0,
    Rsa = 1,
    Dsa = 2,
    Ecdsa = 3,
}
}

#[derive(PartialEq)]
pub struct SignatureAndHashAlgorithm {
    pub hash: HashAlgorithm,
    pub sign: SignAlgorithm,
}

/// Signature algorithms, as defined in [RFC8446] 4.2.3
#[derive(Debug, PartialEq, Eq)]
pub struct SignatureScheme(pub u16);

newtype_enum! {
impl display SignatureScheme {
    /* RSASSA-PKCS1-v1_5 algorithms */
    rsa_pkcs1_sha256 = 0x0401,
    rsa_pkcs1_sha384 = 0x0501,
    rsa_pkcs1_sha512 = 0x0601,

    /* ECDSA algorithms */
    ecdsa_secp256r1_sha256 = 0x0403,
    ecdsa_secp384r1_sha384 = 0x0503,
    ecdsa_secp521r1_sha512 = 0x0603,

    /* RSASSA-PSS algorithms with public key OID rsaEncryption */
    rsa_pss_rsae_sha256 = 0x0804,
    rsa_pss_rsae_sha384 = 0x0805,
    rsa_pss_rsae_sha512 = 0x0806,

    /* EdDSA algorithms */
    ed25519 = 0x0807,
    ed448 = 0x0808,

    /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
    rsa_pss_pss_sha256 = 0x0809,
    rsa_pss_pss_sha384 = 0x080a,
    rsa_pss_pss_sha512 = 0x080b,

    /* Legacy algorithms */
    rsa_pkcs1_sha1 = 0x0201,
    ecdsa_sha1 = 0x0203,
}
}

impl SignatureScheme {
    pub fn is_reserved(&self) -> bool {
        self.0 >= 0xfe00 && self.0 < 0xff00
    }

    /// Get Hash algorithm (for tls <= 1.2) for legacy extension format
    pub fn hash_alg(&self) -> u8 {
        ((self.0 >> 8) & 0xff) as u8
    }

    /// Get Signature algorithm (for tls <= 1.2) for legacy extension format
    pub fn sign_alg(&self) -> u8 {
        (self.0 & 0xff) as u8
    }
}

/// DigitallySigned structure from [RFC2246] section 4.7
/// has no algorithm definition.
/// This should be deprecated in favor if
/// DigitallySigned structure from [RFC5246] section 4.7
#[derive(PartialEq)]
pub struct DigitallySigned<'a> {
    pub alg: Option<SignatureAndHashAlgorithm>,
    // pub alg: Option<u16>, // SignatureScheme
    pub data: &'a[u8],
}

named!(pub parse_digitally_signed_old<DigitallySigned>,
    map!(
        length_bytes!(be_u16),
        |d| { DigitallySigned{ alg:None, data:d } }
    )
);

named!(pub parse_digitally_signed<DigitallySigned>,
    do_parse!(
        h: be_u8 >>
        s: be_u8 >>
        d: length_bytes!(be_u16) >>
        ( DigitallySigned{
            alg: Some( SignatureAndHashAlgorithm{ hash:HashAlgorithm(h), sign:SignAlgorithm(s) } ),
            data: d,
        })
    )
);

/// Parse DigitallySigned object, depending on the `ext` parameter which should
/// be true if the TLS client has sent the `signature_algorithms` extension
pub fn parse_content_and_signature<'a,F,T:'a>(i: &'a[u8], fun: F, ext: bool) -> IResult<&'a[u8],(T,DigitallySigned)>
  where F: Fn(&'a[u8]) -> IResult<&[u8],T>
{
    if ext {
        pair!(i,fun,parse_digitally_signed)
    } else {
        pair!(i,fun,parse_digitally_signed_old)
    }
}
<commit_msg>Update Hash and Sign algorithms (RFC8422)<commit_after>use nom::{be_u8,be_u16,IResult};

/// Hash algorithms, as defined in [RFC5246]
#[derive(Debug, PartialEq, Eq)]
pub struct HashAlgorithm(u8);

newtype_enum! {
impl display HashAlgorithm {
    None = 0,
    Md5 = 1,
    Sha1 = 2,
    Sha224 = 3,
    Sha256 = 4,
    Sha384 = 5,
    Sha512 = 6,
    Intrinsic = 8, // [RFC8422]
}
}

/// Signature algorithms, as defined in [RFC5246]
#[derive(Debug, PartialEq, Eq)]
pub struct SignAlgorithm(u8);

newtype_enum! {
impl display SignAlgorithm {
    Anonymous = 0,
    Rsa = 1,
    Dsa = 2,
    Ecdsa = 3,
    Ed25519 = 7, // [RFC8422]
    Ed448 = 8, // [RFC8422]
}
}

#[derive(PartialEq)]
pub struct SignatureAndHashAlgorithm {
    pub hash: HashAlgorithm,
    pub sign: SignAlgorithm,
}

/// Signature algorithms, as defined in [RFC8446] 4.2.3
#[derive(Debug, PartialEq, Eq)]
pub struct SignatureScheme(pub u16);

newtype_enum! {
impl display SignatureScheme {
    /* RSASSA-PKCS1-v1_5 algorithms */
    rsa_pkcs1_sha256 = 0x0401,
    rsa_pkcs1_sha384 = 0x0501,
    rsa_pkcs1_sha512 = 0x0601,

    /* ECDSA algorithms */
    ecdsa_secp256r1_sha256 = 0x0403,
    ecdsa_secp384r1_sha384 = 0x0503,
    ecdsa_secp521r1_sha512 = 0x0603,

    /* RSASSA-PSS algorithms with public key OID rsaEncryption */
    rsa_pss_rsae_sha256 = 0x0804,
    rsa_pss_rsae_sha384 = 0x0805,
    rsa_pss_rsae_sha512 = 0x0806,

    /* EdDSA algorithms */
    ed25519 = 0x0807,
    ed448 = 0x0808,

    /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
    rsa_pss_pss_sha256 = 0x0809,
    rsa_pss_pss_sha384 = 0x080a,
    rsa_pss_pss_sha512 = 0x080b,

    /* Legacy algorithms */
    rsa_pkcs1_sha1 = 0x0201,
    ecdsa_sha1 = 0x0203,
}
}

impl SignatureScheme {
    pub fn is_reserved(&self) -> bool {
        self.0 >= 0xfe00 && self.0 < 0xff00
    }

    /// Get Hash algorithm (for tls <= 1.2) for legacy extension format
    pub fn hash_alg(&self) -> u8 {
        ((self.0 >> 8) & 0xff) as u8
    }

    /// Get Signature algorithm (for tls <= 1.2) for legacy extension format
    pub fn sign_alg(&self) -> u8 {
        (self.0 & 0xff) as u8
    }
}

/// DigitallySigned structure from [RFC2246] section 4.7
/// has no algorithm definition.
/// This should be deprecated in favor if
/// DigitallySigned structure from [RFC5246] section 4.7
#[derive(PartialEq)]
pub struct DigitallySigned<'a> {
    pub alg: Option<SignatureAndHashAlgorithm>,
    // pub alg: Option<u16>, // SignatureScheme
    pub data: &'a[u8],
}

named!(pub parse_digitally_signed_old<DigitallySigned>,
    map!(
        length_bytes!(be_u16),
        |d| { DigitallySigned{ alg:None, data:d } }
    )
);

named!(pub parse_digitally_signed<DigitallySigned>,
    do_parse!(
        h: be_u8 >>
        s: be_u8 >>
        d: length_bytes!(be_u16) >>
        ( DigitallySigned{
            alg: Some( SignatureAndHashAlgorithm{ hash:HashAlgorithm(h), sign:SignAlgorithm(s) } ),
            data: d,
        })
    )
);

/// Parse DigitallySigned object, depending on the `ext` parameter which should
/// be true if the TLS client has sent the `signature_algorithms` extension
pub fn parse_content_and_signature<'a,F,T:'a>(i: &'a[u8], fun: F, ext: bool) -> IResult<&'a[u8],(T,DigitallySigned)>
  where F: Fn(&'a[u8]) -> IResult<&[u8],T>
{
    if ext {
        pair!(i,fun,parse_digitally_signed)
    } else {
        pair!(i,fun,parse_digitally_signed_old)
    }
}
<|endoftext|>


<commit_before>use nom::{IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::ErrorKind),
  Incomplete(usize),
  Continue,
  EndOfInput,
  Unknown,
  // Parser Error
  HeaderParser,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T, E>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, E> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(_)      => Err(ErrorKind::Unknown),
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T, E>(buffer: &Buffer, result: IResult<&[u8], T, E>)
                      -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(_)      => Err(ErrorKind::Unknown),
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T, E>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, E> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg>Add new custom error types<commit_after>use nom::{IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::ErrorKind),
  Incomplete(usize),
  Continue,
  EndOfInput,
  Unknown,
  // Parser Error
  HeaderParser,
  MetadataHeaderParser,
  StreamInfoParser,
  PaddingParser,
  ApplicationParser,
  SeekTableParser,
  VorbisCommentParser,
  CueSheetParser,
  PictureParser,
  UnknowParser,
  // Invalid Error
  InvalidBlockType,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T, E>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, E> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(_)      => Err(ErrorKind::Unknown),
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T, E>(buffer: &Buffer, result: IResult<&[u8], T, E>)
                      -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(_)      => Err(ErrorKind::Unknown),
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T, E>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, E> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>