json-codec 0.5.0

JSON Codec implementation
Documentation
extern crate json;
extern crate quickcheck;

use json::{Json, Encoder, Decoder, Config, EncodeResult};
use json::decoder::ReadIter;
use quickcheck::{quickcheck, Arbitrary, Gen};
use std::collections::HashMap;
use std::io::Cursor;

#[test]
pub fn identity_json() {
    fn prop(x: SomeJson) -> bool {
        id(|e| e.encode(&x.0), |mut d| d.decode().map(|y| x.0 == y).unwrap_or(false))
    }
    quickcheck(prop as fn(SomeJson) -> bool)
}

#[test]
pub fn identity_null() {
    fn prop() -> bool {
        id(|e| e.null(), |mut d| d.null().map(|_| true).unwrap_or(false))
    }
    quickcheck(prop as fn() -> bool)
}

#[test]
pub fn identity_bool() {
    fn prop(x: bool) -> bool {
        id(|e| e.bool(x), |mut d| d.bool().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(bool) -> bool)
}

#[test]
pub fn identity_string() {
    fn prop(x: String) -> bool {
        id(|e| e.string(x.as_str()), |mut d| d.string().map(|y| &x == &y).unwrap_or(false))
    }
    quickcheck(prop as fn(String) -> bool)
}

#[test]
pub fn identity_u8() {
    fn prop(x: u8) -> bool {
        id(|e| e.u8(x), |mut d| d.u8().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(u8) -> bool)
}

#[test]
pub fn identity_u16() {
    fn prop(x: u16) -> bool {
        id(|e| e.u16(x), |mut d| d.u16().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(u16) -> bool)
}

#[test]
pub fn identity_u32() {
    fn prop(x: u32) -> bool {
        id(|e| e.u32(x), |mut d| d.u32().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(u32) -> bool)
}

#[test]
pub fn identity_u64() {
    fn prop(x: u64) -> bool {
        id(|e| e.u64(x), |mut d| d.u64().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(u64) -> bool)
}

#[test]
pub fn identity_i8() {
    fn prop(x: i8) -> bool {
        id(|e| e.i8(x), |mut d| d.i8().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(i8) -> bool)
}

#[test]
pub fn identity_i16() {
    fn prop(x: i16) -> bool {
        id(|e| e.i16(x), |mut d| d.i16().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(i16) -> bool)
}

#[test]
pub fn identity_i32() {
    fn prop(x: i32) -> bool {
        id(|e| e.i32(x), |mut d| d.i32().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(i32) -> bool)
}

#[test]
pub fn identity_i64() {
    fn prop(x: i64) -> bool {
        id(|e| e.i64(x), |mut d| d.i64().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(i64) -> bool)
}

#[test]
pub fn identity_f64() {
    fn prop(x: f64) -> bool {
        id(|e| e.f64(x), |mut d| d.f64().map(|y| x == y).unwrap_or(false))
    }
    quickcheck(prop as fn(f64) -> bool)
}

// Helpers //////////////////////////////////////////////////////////////////

fn id<F, G>(enc: F, dec: G) -> bool
    where F: Fn(&mut Encoder<Cursor<Vec<u8>>>) -> EncodeResult<()>,
          G: Fn(Decoder<ReadIter<Cursor<Vec<u8>>>>) -> bool
{
    let mut e = Encoder::new(Cursor::new(Vec::new()));
    match enc(&mut e) {
        Ok(()) => {
            let mut c = e.into_writer();
            c.set_position(0);
            dec(Decoder::new(Config::default(), ReadIter::new(c)))
        }
        Err(err) => panic!("encoder failure: {:?}", err)
    }
}

fn gen_json<G: Gen>(level: u16, g: &mut G) -> Json {
    match g.gen_range(1, 8) {
        1 => Json::Bool(true),
        2 => Json::Bool(false),
        3 => Json::Number(g.gen()),
        4 => Json::String(Arbitrary::arbitrary(g)),
        5 => Json::Array(
            if level > 0 {
                gen_array(level - 1, g)
            } else {
                Vec::new()
            }),
        6 => Json::Object(
            if level > 0 {
                gen_object(level - 1, g)
            } else {
                HashMap::new()
            }),
        _ => Json::Null
    }
}

fn gen_array<G: Gen>(level: u16, g: &mut G) -> Vec<Json> {
    let     len = g.gen_range(0, 64);
    let mut vec = Vec::with_capacity(len);
    for _ in 0 .. len {
        vec.push(gen_json(level, g))
    }
    vec
}

fn gen_object<G: Gen>(level: u16, g: &mut G) -> HashMap<String, Json> {
    let     len = g.gen_range(0, 64);
    let mut obj = HashMap::new();
    for _ in 0 .. len {
        obj.insert(Arbitrary::arbitrary(g), gen_json(level, g));
    }
    obj
}

#[derive(Clone, Debug)]
pub struct SomeJson(pub Json);

impl Arbitrary for SomeJson {
    fn arbitrary<G: Gen>(g: &mut G) -> SomeJson {
        SomeJson(gen_json(1, g))
    }
}