use std::iter;
use std::slice;
use std::rc::Rc;
use std::sync::Arc;
#[cfg(all(feature = "alloc", not(feature="std")))]
use alloc::boxed::Box;
#[cfg(feature = "std")]
use std::boxed::Box;
#[cfg(all(feature = "alloc", not(feature="std")))]
use alloc::string::{String, FromUtf8Error, FromUtf16Error};
#[cfg(feature = "std")]
use std::string::{String, FromUtf8Error, FromUtf16Error};
#[cfg(all(feature = "alloc", not(feature="std")))]
use alloc::vec::Vec;
#[cfg(feature = "std")]
use std::vec::Vec;
use strategy::*;
use strategy::statics::static_map;
use collection;
use arbitrary::*;
use string::StringParam;
impl Arbitrary for String {
valuetree!();
type Parameters = StringParam;
type Strategy = &'static str;
fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
args.into()
}
}
macro_rules! dst_wrapped {
($($w: ident),*) => {
$(arbitrary!($w<str>, MapInto<StrategyFor<String>, Self>, StringParam;
a => any_with::<String>(a).prop_map_into()
);)*
};
}
dst_wrapped!(Box, Rc, Arc);
lazy_just!(FromUtf16Error, || String::from_utf16(&[0xD800]).unwrap_err());
arbitrary!(FromUtf8Error, SFnPtrMap<BoxedStrategy<Vec<u8>>, Self>;
static_map(not_utf8_bytes(true), |bs| String::from_utf8(bs).unwrap_err())
);
pub(crate) fn not_utf8_bytes(allow_null: bool) -> BoxedStrategy<Vec<u8>> {
let prefix = collection::vec(any::<char>(), ..::std::u16::MAX as usize);
let suffix = gen_el_bytes(allow_null);
(prefix, suffix).prop_map(move |(prefix_bytes, el_bytes)| {
let iter = prefix_bytes.iter();
let string: String = if allow_null {
iter.collect()
} else {
iter.filter(|&&x| x != '\u{0}').collect()
};
let mut bytes = string.into_bytes();
bytes.extend(el_bytes.into_iter());
bytes
}).boxed()
}
#[derive(Debug)]
enum ELBytes {
B1([u8; 1]),
B2([u8; 2]),
B3([u8; 3]),
B4([u8; 4])
}
impl<'a> IntoIterator for &'a ELBytes {
type Item = u8;
type IntoIter = iter::Map<slice::Iter<'a, u8>, fn(&u8) -> u8>;
fn into_iter(self) -> Self::IntoIter {
use self::ELBytes::*;
(match *self {
B1(ref a) => a.iter(),
B2(ref a) => a.iter(),
B3(ref a) => a.iter(),
B4(ref a) => a.iter(),
}).map(|x| *x)
}
}
fn gen_el_bytes(allow_null: bool) -> BoxedStrategy<ELBytes> {
fn b1(a: u8) -> ELBytes { ELBytes::B1([a]) }
fn b2(a: (u8, u8)) -> ELBytes { ELBytes::B2([a.0, a.1]) }
fn b3(a: ((u8, u8), u8)) -> ELBytes { ELBytes::B3([(a.0).0, (a.0).1, a.1]) }
fn b4(a: ((u8, u8), u8, u8)) -> ELBytes {
ELBytes::B4([(a.0).0, (a.0).1, a.1, a.2])
}
let succ_byte = 0x80u8..0xC0u8;
let start_byte = if allow_null { 0x00u8 } else { 0x01u8 };
let fail_byte = prop_oneof![start_byte..0x7Fu8, 0xC1u8..];
let byte0_w0 = prop_oneof![0x80u8..0xC0u8, 0xF5u8..];
let byte0_w2 = 0xC2u8..0xE0u8;
let byte0_w3 = 0xE0u8..0xF0u8;
let byte0_w4 = 0xF0u8..0xF5u8;
let byte01_w3 = byte0_w3.clone().prop_flat_map(|x| (Just(x), match x {
0xE0u8 => 0xA0u8..0xC0u8,
0xE1u8...0xECu8 => 0x80u8..0xC0u8,
0xEDu8 => 0x80u8..0xA0u8,
0xEEu8...0xEFu8 => 0x80u8..0xA0u8,
_ => panic!(),
}));
let byte01_w3_e1 = byte0_w3.clone().prop_flat_map(move |x| (Just(x), match x {
0xE0u8 => prop_oneof![start_byte..0xA0u8, 0xC0u8..],
0xE1u8...0xECu8 => prop_oneof![start_byte..0x80u8, 0xC0u8..],
0xEDu8 => prop_oneof![start_byte..0x80u8, 0xA0u8..],
0xEEu8...0xEFu8 => prop_oneof![start_byte..0x80u8, 0xA0u8..],
_ => panic!(),
}));
let byte01_w4_e1 = byte0_w4.clone().prop_flat_map(move |x| (Just(x), match x {
0xF0u8 => prop_oneof![start_byte..0x90u8, 0xA0u8..],
0xF1u8...0xF3u8 => prop_oneof![start_byte..0x80u8, 0xA0u8..],
0xF4u8 => prop_oneof![start_byte..0x80u8, 0x90u8..],
_ => panic!()
}));
let byte01_w4 = byte0_w4.clone().prop_flat_map(|x| (Just(x), match x {
0xF0u8 => 0x90u8..0xA0u8,
0xF1u8...0xF3u8 => 0x80u8..0xA0u8,
0xF4u8 => 0x80u8..0x90u8,
_ => panic!()
}));
prop_oneof![
prop_oneof![
static_map(byte0_w2.clone(), b1),
static_map(byte0_w3, b1),
static_map(byte01_w3.clone(), b2),
static_map(byte0_w4, b1),
static_map(byte01_w4.clone(), b2),
static_map((byte01_w4.clone(), succ_byte.clone()), b3),
],
prop_oneof![
static_map(byte0_w0, b1),
static_map((byte0_w2, fail_byte.clone()), b2),
static_map(byte01_w3_e1, b2),
static_map(byte01_w4_e1, b2),
],
static_map(prop_oneof![
(byte01_w3, fail_byte.clone()),
(byte01_w4.clone(), fail_byte.clone())
], b3),
static_map((byte01_w4, succ_byte, fail_byte), b4),
].boxed()
}
#[cfg(test)]
mod test {
no_panic_test!(
string => String,
str_box => Box<str>,
str_rc => Rc<str>,
str_arc => Arc<str>,
from_utf16_error => FromUtf16Error,
from_utf8_error => FromUtf8Error
);
}