use std::collections::HashMap;
use CallResult;
use serde;
use super::{Reason, CallError};
pub type Dict = HashMap<String, Value>;
pub type List = Vec<Value>;
#[derive(Debug, PartialEq, Clone, Hash, Eq)]
pub struct URI {
pub uri: String
}
impl URI {
pub fn new(uri: &str) -> URI {
URI {
uri: uri.to_string()
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Value {
Dict(Dict),
Integer(i64),
String(String),
List(List),
Boolean(bool)
}
struct URIVisitor;
struct ValueVisitor;
pub trait ArgList {
fn get_int(&self, index: usize) -> CallResult<Option<i64>>;
fn get_string<'a>(&'a self, index: usize) -> CallResult<Option<&'a str>>;
fn verify_len(&self, expected_len: usize) -> CallResult<()>;
}
pub trait ArgDict {
fn get_int(&self, key: &str) -> CallResult<Option<i64>>;
fn get_string<'a>(&'a self, key: &str) -> CallResult<Option<&'a str>>;
}
impl ArgList for List {
fn get_int(&self, index: usize) -> CallResult<Option<i64>> {
let value = self.get(index);
match value {
Some(value) => {
if let &Value::Integer(value) = value {
Ok(Some(value))
} else {
Err(CallError::new(Reason::InvalidArgument, Some(vec![Value::String(format!("Expected integer, got {}", value.summarize()))]), None))
}
},
None => {
Ok(None)
}
}
}
fn get_string<'a>(&'a self, index: usize) -> CallResult<Option<&'a str>> {
let value = self.get(index);
match value {
Some(value) => {
if let &Value::String(ref value) = value {
Ok(Some(value))
} else {
Err(CallError::new(Reason::InvalidArgument, Some(vec![Value::String(format!("Expected string, got {}", value.summarize()))]), None))
}
},
None => {
Ok(None)
}
}
}
fn verify_len(&self, expected_len: usize) -> CallResult<()> {
if self.len() >= expected_len {
Ok(())
} else {
Err(CallError::new(Reason::InvalidArgument, Some(vec![Value::String(format!("Expected {} arguments, got {}", expected_len, self.len()))]), None))
}
}
}
impl ArgDict for Dict {
fn get_int(&self, key: &str) -> CallResult<Option<i64>> {
let value = self.get(key);
match value {
Some(value) => {
if let &Value::Integer(value) = value {
Ok(Some(value))
} else {
Err(CallError::new(Reason::InvalidArgument, Some(vec![Value::String(format!("Expected integer, got {}", value.summarize()))]), None))
}
},
None => {
Ok(None)
}
}
}
fn get_string<'a>(&'a self, key: &str) -> CallResult<Option<&'a str>> {
let value = self.get(key);
match value {
Some(value) => {
if let &Value::String(ref value) = value {
Ok(Some(value))
} else {
Err(CallError::new(Reason::InvalidArgument, Some(vec![Value::String(format!("Expected string, got {}", value.summarize()))]), None))
}
},
None => {
Ok(None)
}
}
}
}
impl Value {
pub fn summarize(&self) -> String {
match self {
&Value::Dict(ref d) => {
let mut result = String::new();
result.push('{');
result.push_str(&d.iter().take(50).map(|(key, value)| format!("{}:{}", key, value.summarize())).collect::<Vec<_>>().join(","));
result.push('}');
result
},
&Value::Integer(i) => {
i.to_string()
},
&Value::String(ref s) => {
if s.len() > 50 {
s[..50].to_string()
} else {
s.clone()
}
}
&Value::List(ref l) => {
let mut result = String::new();
result.push('[');
result.push_str(&l.iter().take(50).map(|element| element.summarize()).collect::<Vec<_>>().join(","));
result.push(']');
result
}
&Value::Boolean(b) => {
b.to_string()
}
}
}
}
impl serde::de::Visitor for ValueVisitor {
type Value = Value;
#[inline]
fn visit_str<E>(&mut self, value: &str) -> Result<Value, E>
where E: serde::de::Error {
Ok(Value::String(value.to_string()))
}
#[inline]
fn visit_i64<E>(&mut self, value: i64) -> Result<Value, E>
where E: serde::de::Error {
Ok(Value::Integer(value))
}
#[inline]
fn visit_u64<E>(&mut self, value: u64) -> Result<Value, E>
where E: serde::de::Error {
Ok(Value::Integer(value as i64))
}
#[inline]
fn visit_bool<E>(&mut self, value: bool) -> Result<Value, E>
where E: serde::de::Error {
Ok(Value::Boolean(value))
}
#[inline]
fn visit_map<Visitor>(&mut self, mut visitor: Visitor) -> Result<Value, Visitor::Error>
where Visitor: serde::de::MapVisitor,
{
let mut values = HashMap::with_capacity(visitor.size_hint().0);
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(Value::Dict(values))
}
#[inline]
fn visit_seq<Visitor>(&mut self, mut visitor: Visitor) -> Result<Value, Visitor::Error>
where Visitor: serde::de::SeqVisitor,
{
let mut values = Vec::with_capacity(visitor.size_hint().0);;
while let Some(value) = try!(visitor.visit()) {
values.push(value);
}
try!(visitor.end());
Ok(Value::List(values))
}
}
impl serde::Serialize for Value {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::ser::Serializer,
{
match *self {
Value::Dict(ref dict) => dict.serialize(serializer),
Value::String(ref s) => serializer.serialize_str(s),
Value::Integer(i) => serializer.serialize_i64(i),
Value::List(ref list) => list.serialize(serializer),
Value::Boolean(b) => serializer.serialize_bool(b)
}
}
}
impl serde::Deserialize for Value {
fn deserialize<D>(deserializer: &mut D) -> Result<Value, D::Error>
where D: serde::Deserializer,
{
deserializer.deserialize(ValueVisitor)
}
}
impl serde::Serialize for URI {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::ser::Serializer,
{
serializer.serialize_str(&self.uri)
}
}
impl serde::Deserialize for URI {
fn deserialize<D>(deserializer: &mut D) -> Result<URI, D::Error>
where D: serde::Deserializer,
{
deserializer.deserialize(URIVisitor)
}
}
impl serde::de::Visitor for URIVisitor {
type Value = URI;
#[inline]
fn visit_str<E>(&mut self, value: &str) -> Result<URI, E>
where E: serde::de::Error,
{
Ok(URI {
uri: value.to_string()
})
}
}