use mpack::{self, Value, ValueMap};
use std::convert;
use std::error;
use std::fmt;
pub struct Metadata {
pub buffer_id: i64,
pub window_id: i64,
pub tabpage_id: i64,
}
#[derive(Debug)]
pub enum GetMetadataError {
NotAMap,
NoTypeInformation,
Missing(String),
Invalid(String),
ReadError(mpack::ReadError),
}
impl fmt::Display for GetMetadataError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", self)
}
}
impl error::Error for GetMetadataError {
fn description(&self) -> &str {
match *self {
GetMetadataError::NotAMap => "not a map",
GetMetadataError::NoTypeInformation => "no type information",
GetMetadataError::Invalid(_) => "invalid id",
GetMetadataError::Missing(_) => "missing id",
GetMetadataError::ReadError(_) => "read error",
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
GetMetadataError::ReadError(ref e) => Some(e as &error::Error),
_ => None,
}
}
}
impl convert::From<mpack::ReadError> for GetMetadataError {
fn from(err: mpack::ReadError) -> GetMetadataError {
GetMetadataError::ReadError(err)
}
}
impl Metadata {
pub fn new(metadata: Value) -> Result<Metadata, GetMetadataError> {
let metadata = match metadata.map() {
Ok(m) => m,
Err(_) => return Err(GetMetadataError::NotAMap),
};
let types = match metadata.get("types") {
Some(t) => t.clone().map().unwrap(),
None => return Err(GetMetadataError::NoTypeInformation),
};
fn get_id(types: &ValueMap, name: &'static str) -> Result<i64, GetMetadataError> {
let ob = match types.get(name) {
Some(v) => match v.clone().map() {
Ok(ob) => ob,
Err(_) => return Err(GetMetadataError::Missing(format!("{}.id", name))),
},
None => return Err(GetMetadataError::Missing(format!("{}.id", name))),
};
match ob.get("id") {
Some(id) => Ok(id.clone().int().unwrap()),
None => return Err(GetMetadataError::Invalid(format!("{}.id", name))),
}
}
Ok(Metadata {
buffer_id: try!(get_id(&types, "Buffer")),
window_id: try!(get_id(&types, "Window")),
tabpage_id: try!(get_id(&types, "Tabpage")),
})
}
}