baml/raw_objects/
type_builder.rs

1//! `TypeBuilder` and related types
2//!
3//! These wrap FFI pointers to type builder objects managed by the BAML runtime.
4//! `TypeBuilder` enables dynamic type construction at runtime.
5
6use std::ffi::c_void;
7
8use super::{RawObject, RawObjectTrait};
9use crate::{baml_unreachable, error::BamlError, proto::baml_cffi_v1::BamlObjectType};
10
11// =============================================================================
12// TypeDef - A dynamically constructed BAML type
13// =============================================================================
14
15define_raw_object_wrapper! {
16    /// A dynamically constructed BAML type
17    TypeDef => ObjectType
18}
19
20impl TypeDef {
21    /// Get string representation (never fails)
22    #[must_use]
23    pub fn print(&self) -> String {
24        self.raw.call_method("__display__", ())
25    }
26
27    /// Wrap this type in a list (infallible)
28    #[must_use]
29    pub fn list(&self) -> TypeDef {
30        self.raw
31            .call_method_for_object("list", ())
32            .unwrap_or_else(|e| baml_unreachable!("Failed to create list type: {}", e))
33    }
34
35    /// Make this type optional (infallible)
36    #[must_use]
37    pub fn optional(&self) -> TypeDef {
38        self.raw
39            .call_method_for_object("optional", ())
40            .unwrap_or_else(|e| baml_unreachable!("Failed to create optional type: {}", e))
41    }
42}
43
44// =============================================================================
45// EnumValueBuilder - Builder for enum values
46// =============================================================================
47
48define_raw_object_wrapper! {
49    /// Builder for enum values
50    ///
51    /// **Note**: All methods are fallible because the underlying enum value could be deleted
52    /// while you hold a reference to the builder.
53    EnumValueBuilder => ObjectEnumValueBuilder
54}
55
56impl EnumValueBuilder {
57    /// Get the value name
58    pub fn name(&self) -> Result<String, BamlError> {
59        self.raw.try_call_method("name", ())
60    }
61
62    /// Set description for LLM
63    pub fn set_description(&self, description: &str) -> Result<(), BamlError> {
64        self.raw
65            .try_call_method("set_description", ("description", description))
66    }
67
68    /// Get description (if set)
69    pub fn description(&self) -> Result<Option<String>, BamlError> {
70        self.raw.try_call_method("description", ())
71    }
72
73    /// Set alias for LLM
74    pub fn set_alias(&self, alias: &str) -> Result<(), BamlError> {
75        self.raw.try_call_method("set_alias", ("alias", alias))
76    }
77
78    /// Get alias (if set)
79    pub fn alias(&self) -> Result<Option<String>, BamlError> {
80        self.raw.try_call_method("alias", ())
81    }
82
83    /// Set skip flag
84    pub fn set_skip(&self, skip: bool) -> Result<(), BamlError> {
85        self.raw.try_call_method("set_skip", ("skip", skip))
86    }
87
88    /// Get skip flag
89    pub fn skip(&self) -> Result<bool, BamlError> {
90        self.raw.try_call_method("skip", ())
91    }
92}
93
94// =============================================================================
95// EnumBuilder - Builder for enum types
96// =============================================================================
97
98define_raw_object_wrapper! {
99    /// Builder for enum types
100    ///
101    /// **Note**: All methods are fallible because the underlying enum could be deleted
102    /// while you hold a reference to the builder.
103    EnumBuilder => ObjectEnumBuilder
104}
105
106impl EnumBuilder {
107    /// Add a value to this enum
108    pub fn add_value(&self, value: &str) -> Result<EnumValueBuilder, BamlError> {
109        self.raw
110            .call_method_for_object("add_value", ("value", value))
111    }
112
113    /// Get a value by name (if it exists)
114    pub fn get_value(&self, name: &str) -> Option<EnumValueBuilder> {
115        self.raw
116            .call_method_for_object("value", ("name", name))
117            .ok()
118    }
119
120    /// List all values
121    pub fn list_values(&self) -> Result<Vec<EnumValueBuilder>, BamlError> {
122        self.raw.call_method_for_objects("list_values", ())
123    }
124
125    /// Get this enum as a Type
126    pub fn as_type(&self) -> Result<TypeDef, BamlError> {
127        self.raw.call_method_for_object("type_", ())
128    }
129
130    /// Get the enum name
131    pub fn name(&self) -> Result<String, BamlError> {
132        self.raw.try_call_method("name", ())
133    }
134
135    /// Set description for LLM
136    pub fn set_description(&self, description: &str) -> Result<(), BamlError> {
137        self.raw
138            .try_call_method("set_description", ("description", description))
139    }
140
141    /// Get description (if set)
142    pub fn description(&self) -> Result<Option<String>, BamlError> {
143        self.raw.try_call_method("description", ())
144    }
145
146    /// Set alias for LLM
147    pub fn set_alias(&self, alias: &str) -> Result<(), BamlError> {
148        self.raw.try_call_method("set_alias", ("alias", alias))
149    }
150
151    /// Get alias (if set)
152    pub fn alias(&self) -> Result<Option<String>, BamlError> {
153        self.raw.try_call_method("alias", ())
154    }
155}
156
157// =============================================================================
158// ClassPropertyBuilder - Builder for class properties
159// =============================================================================
160
161define_raw_object_wrapper! {
162    /// Builder for class properties
163    ///
164    /// **Note**: All methods are fallible because the underlying property could be deleted
165    /// while you hold a reference to the builder.
166    ClassPropertyBuilder => ObjectClassPropertyBuilder
167}
168
169impl ClassPropertyBuilder {
170    /// Get the property name
171    pub fn name(&self) -> Result<String, BamlError> {
172        self.raw.try_call_method("name", ())
173    }
174
175    /// Set the property type
176    pub fn set_type(&self, field_type: &TypeDef) -> Result<(), BamlError> {
177        self.raw
178            .try_call_method("set_type", ("field_type", field_type))
179    }
180
181    /// Get the property type
182    pub fn get_type(&self) -> Result<TypeDef, BamlError> {
183        self.raw.call_method_for_object("type_", ())
184    }
185
186    /// Set description for LLM
187    pub fn set_description(&self, description: &str) -> Result<(), BamlError> {
188        self.raw
189            .try_call_method("set_description", ("description", description))
190    }
191
192    /// Get description (if set)
193    pub fn description(&self) -> Result<Option<String>, BamlError> {
194        self.raw.try_call_method("description", ())
195    }
196
197    /// Set alias for LLM
198    pub fn set_alias(&self, alias: &str) -> Result<(), BamlError> {
199        self.raw.try_call_method("set_alias", ("alias", alias))
200    }
201
202    /// Get alias (if set)
203    pub fn alias(&self) -> Result<Option<String>, BamlError> {
204        self.raw.try_call_method("alias", ())
205    }
206}
207
208// =============================================================================
209// ClassBuilder - Builder for class types
210// =============================================================================
211
212define_raw_object_wrapper! {
213    /// Builder for class types
214    ///
215    /// **Note**: All methods are fallible because the underlying class could be deleted
216    /// while you hold a reference to the builder.
217    ClassBuilder => ObjectClassBuilder
218}
219
220impl ClassBuilder {
221    /// Add a property to this class
222    pub fn add_property(
223        &self,
224        name: &str,
225        field_type: &TypeDef,
226    ) -> Result<ClassPropertyBuilder, BamlError> {
227        self.raw
228            .call_method_for_object("add_property", (("name", name), ("field_type", field_type)))
229    }
230
231    /// Get a property by name (if it exists)
232    pub fn get_property(&self, name: &str) -> Option<ClassPropertyBuilder> {
233        self.raw
234            .call_method_for_object("property", ("name", name))
235            .ok()
236    }
237
238    /// List all properties
239    pub fn list_properties(&self) -> Result<Vec<ClassPropertyBuilder>, BamlError> {
240        self.raw.call_method_for_objects("list_properties", ())
241    }
242
243    /// Get this class as a Type
244    pub fn as_type(&self) -> Result<TypeDef, BamlError> {
245        self.raw.call_method_for_object("type_", ())
246    }
247
248    /// Get the class name
249    pub fn name(&self) -> Result<String, BamlError> {
250        self.raw.try_call_method("name", ())
251    }
252
253    /// Set description for LLM
254    pub fn set_description(&self, description: &str) -> Result<(), BamlError> {
255        self.raw
256            .try_call_method("set_description", ("description", description))
257    }
258
259    /// Get description (if set)
260    pub fn description(&self) -> Result<Option<String>, BamlError> {
261        self.raw.try_call_method("description", ())
262    }
263
264    /// Set alias for LLM
265    pub fn set_alias(&self, alias: &str) -> Result<(), BamlError> {
266        self.raw.try_call_method("set_alias", ("alias", alias))
267    }
268
269    /// Get alias (if set)
270    pub fn alias(&self) -> Result<Option<String>, BamlError> {
271        self.raw.try_call_method("alias", ())
272    }
273}
274
275// =============================================================================
276// TypeBuilder - Builder for constructing BAML types at runtime
277// =============================================================================
278
279define_raw_object_wrapper! {
280    /// Builder for constructing BAML types at runtime
281    TypeBuilder => ObjectTypeBuilder
282}
283
284impl TypeBuilder {
285    /// Create a new `TypeBuilder` (infallible)
286    pub fn new(runtime: *const c_void) -> Self {
287        let raw = RawObject::new(runtime, BamlObjectType::ObjectTypeBuilder, ())
288            .unwrap_or_else(|e| baml_unreachable!("Failed to create TypeBuilder: {}", e));
289        Self { raw }
290    }
291
292    // =========================================================================
293    // Primitive types (infallible)
294    // =========================================================================
295
296    /// Get string type
297    pub fn string(&self) -> TypeDef {
298        self.raw
299            .call_method_for_object("string", ())
300            .unwrap_or_else(|e| baml_unreachable!("Failed to get string type: {}", e))
301    }
302
303    /// Get int type
304    pub fn int(&self) -> TypeDef {
305        self.raw
306            .call_method_for_object("int", ())
307            .unwrap_or_else(|e| baml_unreachable!("Failed to get int type: {}", e))
308    }
309
310    /// Get float type
311    pub fn float(&self) -> TypeDef {
312        self.raw
313            .call_method_for_object("float", ())
314            .unwrap_or_else(|e| baml_unreachable!("Failed to get float type: {}", e))
315    }
316
317    /// Get bool type
318    pub fn bool(&self) -> TypeDef {
319        self.raw
320            .call_method_for_object("bool", ())
321            .unwrap_or_else(|e| baml_unreachable!("Failed to get bool type: {}", e))
322    }
323
324    /// Get null type
325    pub fn null(&self) -> TypeDef {
326        self.raw
327            .call_method_for_object("null", ())
328            .unwrap_or_else(|e| baml_unreachable!("Failed to get null type: {}", e))
329    }
330
331    // =========================================================================
332    // Literal types (infallible)
333    // =========================================================================
334
335    /// Get a literal string type
336    pub fn literal_string(&self, value: &str) -> TypeDef {
337        self.raw
338            .call_method_for_object("literal_string", ("value", value))
339            .unwrap_or_else(|e| baml_unreachable!("Failed to get literal string type: {}", e))
340    }
341
342    /// Get a literal int type
343    pub fn literal_int(&self, value: i64) -> TypeDef {
344        self.raw
345            .call_method_for_object("literal_int", ("value", value))
346            .unwrap_or_else(|e| baml_unreachable!("Failed to get literal int type: {}", e))
347    }
348
349    /// Get a literal bool type
350    pub fn literal_bool(&self, value: bool) -> TypeDef {
351        self.raw
352            .call_method_for_object("literal_bool", ("value", value))
353            .unwrap_or_else(|e| baml_unreachable!("Failed to get literal bool type: {}", e))
354    }
355
356    // =========================================================================
357    // Composite types (infallible)
358    // =========================================================================
359
360    /// Get a list type containing the given inner type
361    pub fn list(&self, inner: &TypeDef) -> TypeDef {
362        self.raw
363            .call_method_for_object("list", ("inner", inner))
364            .unwrap_or_else(|e| baml_unreachable!("Failed to get list type: {}", e))
365    }
366
367    /// Get an optional type containing the given inner type
368    pub fn optional(&self, inner: &TypeDef) -> TypeDef {
369        self.raw
370            .call_method_for_object("optional", ("inner", inner))
371            .unwrap_or_else(|e| baml_unreachable!("Failed to get optional type: {}", e))
372    }
373
374    /// Get a map type with the given key and value types
375    pub fn map(&self, key: &TypeDef, value: &TypeDef) -> TypeDef {
376        self.raw
377            .call_method_for_object("map", (("key", key), ("value", value)))
378            .unwrap_or_else(|e| baml_unreachable!("Failed to get map type: {}", e))
379    }
380
381    /// Get a union type of the given types
382    pub fn union(&self, types: &[&TypeDef]) -> TypeDef {
383        self.raw
384            .call_method_for_object("union", ("types", types))
385            .unwrap_or_else(|e| baml_unreachable!("Failed to get union type: {}", e))
386    }
387
388    // =========================================================================
389    // Schema operations (fallible - BAML parsing can fail)
390    // =========================================================================
391
392    /// Parse and add BAML schema definitions
393    pub fn add_baml(&self, baml: &str) -> Result<(), BamlError> {
394        self.raw.try_call_method("add_baml", ("baml", baml))
395    }
396
397    /// Get string representation (never fails)
398    pub fn print(&self) -> String {
399        self.raw.call_method("__display__", ())
400    }
401
402    // =========================================================================
403    // Enum operations
404    // =========================================================================
405
406    /// Add a new enum (fallible - name conflicts, invalid names)
407    pub fn add_enum(&self, name: &str) -> Result<EnumBuilder, BamlError> {
408        self.raw.call_method_for_object("add_enum", ("name", name))
409    }
410
411    /// Get an enum by name (nullable - may not exist)
412    pub fn get_enum(&self, name: &str) -> Option<EnumBuilder> {
413        self.raw
414            .call_method_for_object_optional("enum_", ("name", name))
415            .ok()
416            .flatten()
417    }
418
419    /// List all enums (infallible)
420    pub fn list_enums(&self) -> Vec<EnumBuilder> {
421        self.raw
422            .call_method_for_objects("list_enums", ())
423            .unwrap_or_else(|e| baml_unreachable!("Failed to list enums: {}", e))
424    }
425
426    // =========================================================================
427    // Class operations
428    // =========================================================================
429
430    /// Add a new class (fallible - name conflicts, invalid names)
431    pub fn add_class(&self, name: &str) -> Result<ClassBuilder, BamlError> {
432        self.raw.call_method_for_object("add_class", ("name", name))
433    }
434
435    /// Get a class by name (nullable - may not exist)
436    pub fn get_class(&self, name: &str) -> Option<ClassBuilder> {
437        self.raw
438            .call_method_for_object_optional("class", ("name", name))
439            .ok()
440            .flatten()
441    }
442
443    /// List all classes (infallible)
444    pub fn list_classes(&self) -> Vec<ClassBuilder> {
445        self.raw
446            .call_method_for_objects("list_classes", ())
447            .unwrap_or_else(|e| baml_unreachable!("Failed to list classes: {}", e))
448    }
449}