use arbitrary::Error::IncorrectFormat;
use arbitrary::{Arbitrary, Result, Unstructured};
use crate::encoder::model::StagedLayer;
use crate::encoder::optimizer::Presence;
use crate::encoder::{StagedId, StagedProperty, StagedSharedDict, StagedStrings};
impl Arbitrary<'_> for StagedId {
fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> {
let count = u.int_in_range(0..=64u8)? as usize;
let values: Vec<Option<u64>> = (0..count).map(|_| u.arbitrary()).collect::<Result<_>>()?;
Ok(Self::from_optional(values))
}
}
impl Arbitrary<'_> for StagedLayer {
fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> {
let name_len = u.int_in_range(0..=32u8)? as usize;
let name: String = (0..name_len)
.map(|_| u.arbitrary::<char>())
.collect::<Result<_>>()?;
let extent: u32 = u.arbitrary()?;
let geometry: crate::decoder::GeometryValues = u.arbitrary()?;
let fc = geometry.vector_types().len();
let id = if u.arbitrary::<bool>()? {
let ids: Vec<Option<u64>> = (0..fc)
.map(|_| -> Result<_> {
if u.arbitrary::<bool>()? {
Ok(Some(u.arbitrary::<u64>()?))
} else {
Ok(None)
}
})
.collect::<Result<_>>()?;
StagedId::from_optional(ids)
} else {
StagedId::None
};
let prop_count = u.int_in_range(0..=4u8)? as usize;
let properties: Vec<StagedProperty> = (0..prop_count)
.map(|_| {
let values: Vec<Option<u32>> =
(0..fc).map(|_| u.arbitrary()).collect::<Result<_>>()?;
Ok(StagedProperty::opt_u32("prop", values))
})
.collect::<Result<_>>()?;
Ok(Self {
name,
extent,
id,
geometry,
properties,
})
}
}
impl<'a> Arbitrary<'a> for StagedSharedDict {
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
let item_count = u.int_in_range(0..=8u8)? as usize;
let items_raw: Vec<(String, Vec<Option<String>>, Presence)> = (0..item_count)
.map(|_| {
let values = generate_strings(u)?;
let presence = if values.iter().all(Option::is_some) {
Presence::AllPresent
} else {
Presence::Mixed
};
Ok((bounded_string(u, 32)?, values, presence))
})
.collect::<Result<_>>()?;
if items_raw.is_empty() {
return Ok(Self {
prefix: bounded_string(u, 32)?,
data: String::new(),
items: Vec::new(),
});
}
let prefix = bounded_string(u, 32)?;
Self::new(prefix, items_raw).map_err(|_| IncorrectFormat)
}
}
impl Arbitrary<'_> for StagedProperty {
fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> {
let count = u.int_in_range(0..=64u8)? as usize;
let values: Vec<Option<u32>> = (0..count).map(|_| u.arbitrary()).collect::<Result<_>>()?;
Ok(Self::opt_u32("prop", values))
}
}
impl Arbitrary<'_> for StagedStrings {
fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> {
Ok(Self::from_optional(
bounded_string(u, 32)?,
generate_strings(u)?,
))
}
}
pub fn bounded_string(u: &mut Unstructured<'_>, max_len: u8) -> Result<String> {
let len = u.int_in_range(0..=max_len)? as usize;
(0..len)
.map(|_| u.arbitrary::<char>())
.collect::<Result<_>>()
}
fn generate_strings(u: &mut Unstructured) -> Result<Vec<Option<String>>> {
let val_count = u.int_in_range(0..=16u8)? as usize;
let values: Vec<Option<String>> = (0..val_count)
.map(|_| -> Result<_> {
if u.arbitrary()? {
Ok(Some(bounded_string(u, 64)?))
} else {
Ok(None)
}
})
.collect::<Result<_>>()?;
Ok(values)
}