use std::fmt::{Display, Error, Formatter};
use std::result::{Result};
pub const PAIR_SEPARATOR: char = ':';
const UPNP_PREFIX: &'static str = "upnp";
const UUID_PREFIX: &'static str = "uuid";
const URN_PREFIX: &'static str = "urn";
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum FieldMap {
UPnP(Vec<u8>),
UUID(Vec<u8>),
URN(Vec<u8>),
Unknown(Vec<u8>, Vec<u8>)
}
impl FieldMap {
pub fn new(field: &[u8]) -> Option<FieldMap> {
let split_index = match field.iter().position(|&b| b == PAIR_SEPARATOR as u8) {
Some(n) => n,
None => return None
};
let (key, mut value) = field.split_at(split_index);
value = &value[1..];
if key.len() == 0 || value.len() == 0 {
return None
}
if matches_uuid_key(key) {
Some(FieldMap::UUID(value.to_vec()))
} else if matches_urn_key(key) {
Some(FieldMap::URN(value.to_vec()))
} else if matches_upnp_key(key) {
Some(FieldMap::UPnP(value.to_vec()))
} else {
Some(FieldMap::Unknown(key.to_vec(), value.to_vec()))
}
}
}
impl Display for FieldMap {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
let value = match *self {
FieldMap::UPnP(ref v) => { try!(f.write_str(UPNP_PREFIX)); v },
FieldMap::UUID(ref v) => { try!(f.write_str(UUID_PREFIX)); v },
FieldMap::URN(ref v) => { try!(f.write_str(URN_PREFIX)); v },
FieldMap::Unknown(ref k, ref v) => {
let key = String::from_utf8_lossy(k);
try!(Display::fmt(&key, f));
v
}
};
try!(f.write_fmt(format_args!("{}", PAIR_SEPARATOR)));
let cow_value = String::from_utf8_lossy(value);
try!(Display::fmt(&cow_value, f));
Ok(())
}
}
fn matches_uuid_key(key: &[u8]) -> bool {
UUID_PREFIX.as_bytes() == key
}
fn matches_urn_key(key: &[u8]) -> bool {
URN_PREFIX.as_bytes() == key
}
fn matches_upnp_key(key: &[u8]) -> bool {
UPNP_PREFIX.as_bytes() == key
}
#[cfg(test)]
mod tests {
use super::{FieldMap};
#[test]
fn positive_upnp() {
let upnp_pair = FieldMap::new(&b"upnp:some_value_\x80"[..]).unwrap();
assert_eq!(upnp_pair, FieldMap::UPnP(b"some_value_\x80".to_vec()));
}
#[test]
fn positive_uuid() {
let uuid_pair = FieldMap::new(&b"uuid:some_value_\x80"[..]).unwrap();
assert_eq!(uuid_pair, FieldMap::UUID(b"some_value_\x80".to_vec()));
}
#[test]
fn positive_urn() {
let urn_pair = FieldMap::new(&b"urn:some_value_\x80"[..]).unwrap();
assert_eq!(urn_pair, FieldMap::URN(b"some_value_\x80".to_vec()));
}
#[test]
fn positive_unknown() {
let unknown_pair = FieldMap::new(&b"some_key\x80:some_value_\x80"[..]).unwrap();
assert_eq!(unknown_pair, FieldMap::Unknown(b"some_key\x80".to_vec(), b"some_value_\x80".to_vec()));
}
#[test]
#[should_panic]
fn negative_no_colon() {
FieldMap::new(&b"upnpsome_value_\x80"[..]).unwrap();
}
}