extern crate url;
#[macro_use]
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate error_chain;
use std::borrow::Cow;
use serde_json::Value;
use err::ErrorKind;
pub mod err {
error_chain! {
errors {
Parse {
description("Couldn't parse input")
}
}
foreign_links {
StdFmt(::std::fmt::Error);
Io(::std::io::Error);
SerdeJson(::serde_json::Error);
}
}
}
mod deserializer;
trait ValueExtensions {
fn find_or_insert_object<I: Into<String>>(&mut self, key: I) -> err::Result<&mut Self>;
fn find_or_insert_array(&mut self) -> err::Result<&mut Self>;
fn collect_pairs<'a>(
&'a self,
pairs: &mut Vec<(String, Cow<'a, str>)>,
buf: String,
) -> err::Result<()>;
fn parse_key(&mut self, key: &str, outside: bool) -> err::Result<&mut Self>;
}
impl ValueExtensions for Value {
fn find_or_insert_object<I: Into<String>>(&mut self, key: I) -> err::Result<&mut Self> {
use serde_json::map::Map;
match *self {
Value::Object(ref mut map) => Ok(map.entry(key.into()).or_insert_with(|| Value::Null)),
Value::Null => {
*self = Value::Object(Map::new());
self.find_or_insert_object(key)
}
_ => Err(ErrorKind::Parse.into()),
}
}
fn find_or_insert_array(&mut self) -> err::Result<&mut Self> {
match *self {
Value::Array(ref mut arr) => {
arr.push(Value::Null);
Ok(arr.last_mut().ok_or_else(|| ErrorKind::Parse)?)
}
Value::Null => {
*self = Value::Array(Vec::new());
self.find_or_insert_array()
}
_ => Err(ErrorKind::Parse.into()),
}
}
fn parse_key(&mut self, key: &str, outside: bool) -> err::Result<&mut Self> {
if outside {
if key.is_empty() {
return Ok(self);
}
let mut iter = key.char_indices();
loop {
match iter.next() {
Some((0, '[')) => {
return self.parse_key(&key[1..], false);
}
Some((idx, '[')) => {
let pre = &key[..idx];
let post = &key[idx + 1..];
let new_node = self.find_or_insert_object(pre)?;
return new_node.parse_key(post, false);
}
None => {
break;
}
_ => {
continue;
}
}
}
Ok(self.find_or_insert_object(key)?)
} else {
if key.is_empty() {
return Err(ErrorKind::Parse.into());
}
let mut iter = key.char_indices();
loop {
match iter.next() {
Some((0, ']')) => {
let post = &key[1..];
let new_node = self.find_or_insert_array()?;
return new_node.parse_key(post, true);
}
Some((idx, ']')) => {
let pre = &key[..idx];
let post = &key[idx + 1..];
let new_node = self.find_or_insert_object(pre)?;
return new_node.parse_key(post, true);
}
None => {
break;
}
_ => {
continue;
}
}
}
Err(ErrorKind::Parse.into())
}
}
fn collect_pairs<'a>(
&'a self,
pairs: &mut Vec<(String, Cow<'a, str>)>,
mut buf: String,
) -> err::Result<()> {
use std::fmt::Write as FmtWrite;
match *self {
Value::Null => {}
Value::Bool(b) => {
pairs.push((buf, b.to_string().into()));
}
Value::Number(ref num) => {
pairs.push((buf, num.to_string().into()));
}
Value::String(ref s) => {
pairs.push((buf, s.as_str().into()));
}
Value::Array(ref arr) => {
write!(&mut buf, "[]")?;
for node in arr {
node.collect_pairs(pairs, buf.clone())?;
}
}
Value::Object(ref map) => {
for (k, node) in map {
let mut buf = buf.clone();
if buf.is_empty() {
write!(&mut buf, "{}", k)?;
} else {
write!(&mut buf, "[{}]", k)?;
}
node.collect_pairs(pairs, buf)?;
}
}
}
Ok(())
}
}
pub fn from_slice<D: ::serde::de::DeserializeOwned>(slice: &[u8]) -> err::Result<D> {
let mut root = Value::Object(::serde_json::map::Map::new());
for (key, value) in ::url::form_urlencoded::parse(slice) {
let node = root.parse_key(key.as_ref(), true)?;
*node = value.into_owned().into();
}
Ok(D::deserialize(deserializer::Deserializer(root))?)
}
pub fn from_bytes<D: ::serde::de::DeserializeOwned>(slice: &[u8]) -> err::Result<D> {
from_slice(slice)
}
pub fn from_str<D: ::serde::de::DeserializeOwned>(s: &str) -> err::Result<D> {
from_slice(s.as_ref())
}
pub fn from_reader<R: ::std::io::Read, D: ::serde::de::DeserializeOwned>(
mut s: R,
) -> err::Result<D> {
let mut buf = Vec::new();
::std::io::Read::read_to_end(&mut s, &mut buf)?;
from_slice(buf.as_ref())
}
pub fn to_string<S: ::serde::Serialize>(s: &S) -> err::Result<String> {
let value = ::serde_json::to_value(s)?;
let mut pairs = Vec::new();
value.collect_pairs(&mut pairs, String::new())?;
let out = ::url::form_urlencoded::Serializer::new(String::new())
.extend_pairs(&pairs)
.finish();
Ok(out)
}