use std::i64;
use num_bigint::BigInt;
use quickcheck::{Arbitrary, Gen, empty_shrinker};
use rand::Rng;
use crate::{Value, HashableValue};
const MAX_DEPTH: u32 = 1;
fn gen_value<G: Gen>(g: &mut G, depth: u32) -> Value {
let upper = if depth > 0 { 12 } else { 7 };
match g.gen_range(0, upper) {
0 => Value::None,
1 => Value::Bool(Arbitrary::arbitrary(g)),
2 => Value::I64(Arbitrary::arbitrary(g)),
3 => Value::Int(gen_bigint(g)),
4 => Value::F64(Arbitrary::arbitrary(g)),
5 => Value::Bytes(Arbitrary::arbitrary(g)),
6 => Value::String(Arbitrary::arbitrary(g)),
7 => Value::List(gen_vec(g, depth - 1)),
8 => Value::Tuple(gen_vec(g, depth - 1)),
9 => Value::Set(gen_hvec(g, depth - 1).into_iter().collect()),
10 => Value::FrozenSet(gen_hvec(g, depth - 1).into_iter().collect()),
11 => { let kvec = gen_hvec(g, depth - 1);
let vvec = gen_vec(g, depth - 1);
Value::Dict(kvec.into_iter().zip(vvec).collect()) },
_ => unreachable!(),
}
}
fn gen_bigint<G: Gen>(g: &mut G) -> BigInt {
let offset = BigInt::from(2) * BigInt::from(if g.gen() { i64::MIN } else { i64::MAX });
offset + BigInt::from(g.gen::<i64>())
}
fn gen_vec<G: Gen>(g: &mut G, depth: u32) -> Vec<Value> {
let size = { let s = g.size(); g.gen_range(0, s) };
(0..size).map(|_| gen_value(g, depth)).collect()
}
fn gen_hvalue<G: Gen>(g: &mut G, depth: u32) -> HashableValue {
let upper = if depth > 0 { 9 } else { 7 };
match g.gen_range(0, upper) {
0 => HashableValue::None,
1 => HashableValue::Bool(Arbitrary::arbitrary(g)),
2 => HashableValue::I64(Arbitrary::arbitrary(g)),
3 => { let val: i64 = Arbitrary::arbitrary(g);
let max = BigInt::from(i64::MAX);
HashableValue::Int(BigInt::from(val) + BigInt::from(2) * max) },
4 => HashableValue::F64(Arbitrary::arbitrary(g)),
5 => HashableValue::Bytes(Arbitrary::arbitrary(g)),
6 => HashableValue::String(Arbitrary::arbitrary(g)),
7 => HashableValue::Tuple(gen_hvec(g, depth - 1)),
8 => HashableValue::FrozenSet(gen_hvec(g, depth - 1).into_iter().collect()),
_ => unreachable!(),
}
}
fn gen_hvec<G: Gen>(g: &mut G, depth: u32) -> Vec<HashableValue> {
let size = { let s = g.size(); g.gen_range(0, s) };
(0..size).map(|_| gen_hvalue(g, depth)).collect()
}
impl Arbitrary for Value {
fn arbitrary<G: Gen>(g: &mut G) -> Value {
gen_value(g, MAX_DEPTH)
}
fn shrink(&self) -> Box<dyn Iterator<Item=Value>> {
match *self {
Value::None => empty_shrinker(),
Value::Bool(v) => Box::new(Arbitrary::shrink(&v).map(Value::Bool)),
Value::I64(v) => Box::new(Arbitrary::shrink(&v).map(Value::I64)),
Value::Int(_) => empty_shrinker(),
Value::F64(v) => Box::new(Arbitrary::shrink(&v).map(Value::F64)),
Value::Bytes(ref v) => Box::new(Arbitrary::shrink(v).map(Value::Bytes)),
Value::String(ref v) => Box::new(Arbitrary::shrink(v).map(Value::String)),
Value::List(ref v) => Box::new(Arbitrary::shrink(v).map(Value::List)),
Value::Tuple(ref v) => Box::new(Arbitrary::shrink(v).map(Value::List)),
Value::Set(ref v) => Box::new(Arbitrary::shrink(v).map(Value::Set)),
Value::FrozenSet(ref v) => Box::new(Arbitrary::shrink(v).map(Value::FrozenSet)),
Value::Dict(ref v) => Box::new(Arbitrary::shrink(v).map(Value::Dict)),
}
}
}
impl Arbitrary for HashableValue {
fn arbitrary<G: Gen>(g: &mut G) -> HashableValue {
gen_hvalue(g, MAX_DEPTH)
}
fn shrink(&self) -> Box<dyn Iterator<Item=HashableValue>> {
match *self {
HashableValue::None => empty_shrinker(),
HashableValue::Bool(v) => Box::new(Arbitrary::shrink(&v).map(HashableValue::Bool)),
HashableValue::I64(v) => Box::new(Arbitrary::shrink(&v).map(HashableValue::I64)),
HashableValue::Int(_) => empty_shrinker(),
HashableValue::F64(v) => Box::new(Arbitrary::shrink(&v).map(HashableValue::F64)),
HashableValue::Bytes(ref v) => Box::new(Arbitrary::shrink(v).map(HashableValue::Bytes)),
HashableValue::String(ref v) => Box::new(Arbitrary::shrink(v).map(HashableValue::String)),
HashableValue::Tuple(ref v) => Box::new(Arbitrary::shrink(v).map(HashableValue::Tuple)),
HashableValue::FrozenSet(ref v) => Box::new(Arbitrary::shrink(v).map(HashableValue::FrozenSet)),
}
}
}