objectiveai_sdk/functions/check/example_inputs/
object.rs1use 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 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}