//! Support for configurable generation of arbitrary nix values use proptest::{prelude::*, strategy::BoxedStrategy}; use std::{ffi::OsString, rc::Rc}; use super::{NixAttrs, NixList, NixString, Value}; #[derive(Clone)] pub enum Parameters { Strategy(BoxedStrategy), Parameters { generate_internal_values: bool, generate_functions: bool, generate_nested: bool, }, } impl Default for Parameters { fn default() -> Self { Self::Parameters { generate_internal_values: false, generate_functions: false, generate_nested: true, } } } impl Arbitrary for Value { type Parameters = Parameters; type Strategy = BoxedStrategy; fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { match args { Parameters::Strategy(s) => s, Parameters::Parameters { generate_internal_values, generate_functions, generate_nested, } => { if generate_internal_values || generate_functions { todo!("Generating internal values and functions not implemented yet") } else if generate_nested { non_internal_value().boxed() } else { leaf_value().boxed() } } } } } fn leaf_value() -> impl Strategy { use Value::*; prop_oneof![ Just(Null), any::().prop_map(Bool), any::().prop_map(Integer), any::().prop_map(Float), any::().prop_map(String), any::().prop_map(|s| Path(s.into())), ] } fn non_internal_value() -> impl Strategy { leaf_value().prop_recursive(10, 256, 10, |inner| { prop_oneof![ any_with::(( Default::default(), Default::default(), Parameters::Strategy(inner.clone()) )) .prop_map(|a| Value::Attrs(Rc::new(a))), any_with::((Default::default(), Parameters::Strategy(inner))) .prop_map(Value::List) ] }) }