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