Skip to main content

objectiveai_sdk/functions/check/example_inputs/
object.rs

1use indexmap::IndexMap;
2use rand::Rng;
3use rand::SeedableRng;
4use rand::rngs::StdRng;
5
6use crate::functions::expression::{
7    InputSchema, InputValue, ObjectInputSchema,
8};
9
10pub fn permutations(schema: &ObjectInputSchema) -> usize {
11    let required = schema.required.as_deref().unwrap_or(&[]);
12    schema
13        .properties
14        .iter()
15        .map(|(key, prop)| {
16            if required.contains(key) {
17                super::optional::inner_permutations(prop)
18            } else {
19                super::optional::permutations(prop)
20            }
21        })
22        .max()
23        .unwrap_or(1)
24}
25
26pub fn generate(schema: &ObjectInputSchema, mut rng: StdRng) -> Generator {
27    let required = schema.required.as_deref().unwrap_or(&[]);
28
29    let fields: Vec<FieldSlot> = schema
30        .properties
31        .iter()
32        .map(|(key, prop)| {
33            let is_optional = !required.contains(key);
34            let sub_rng = StdRng::seed_from_u64(rng.random::<u64>());
35            let source = make_field_source(prop, is_optional, sub_rng);
36            FieldSlot {
37                name: key.clone(),
38                source,
39            }
40        })
41        .collect();
42
43    Generator { fields }
44}
45
46struct FieldSlot {
47    name: String,
48    source: FieldSource,
49}
50
51enum FieldSource {
52    Required(super::multi::Generator),
53    Optional(super::optional::Generator),
54}
55
56impl FieldSource {
57    fn advance(&mut self) -> Option<InputValue> {
58        match self {
59            FieldSource::Required(iter) => Some(iter.next().unwrap()),
60            FieldSource::Optional(iter) => iter.next().unwrap(),
61        }
62    }
63}
64
65fn make_field_source(
66    schema: &InputSchema,
67    is_optional: bool,
68    rng: StdRng,
69) -> FieldSource {
70    if is_optional {
71        FieldSource::Optional(super::optional::generate(schema, rng))
72    } else {
73        FieldSource::Required(super::multi::generate(schema, rng))
74    }
75}
76
77pub struct Generator {
78    fields: Vec<FieldSlot>,
79}
80
81impl Iterator for Generator {
82    type Item = InputValue;
83    fn next(&mut self) -> Option<InputValue> {
84        if self.fields.is_empty() {
85            return Some(InputValue::Object(IndexMap::new()));
86        }
87
88        // Build object: advance each field's iterator
89        let mut map = IndexMap::new();
90        for field in &mut self.fields {
91            let value = field.source.advance();
92            if let Some(v) = value {
93                map.insert(field.name.clone(), v);
94            }
95        }
96        let result = InputValue::Object(map);
97
98        Some(result)
99    }
100}