Skip to main content

objectiveai_sdk/functions/check/example_inputs/
object.rs

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