cel_cxx_ffi/
checker.rs

1use std::pin::Pin;
2
3use crate::absl::{Status, StringView};
4use crate::common::{Ast, FunctionDecl, Source, Type, VariableDecl};
5
6#[cxx::bridge]
7mod ffi {
8    #[namespace = "absl"]
9    unsafe extern "C++" {
10        include!(<absl/status/status.h>);
11        type Status = super::Status;
12        
13        include!(<absl/strings/string_view.h>);
14        type string_view<'a> = super::StringView<'a>;
15    }
16
17    #[namespace = "cel"]
18    unsafe extern "C++" {
19        include!(<checker/type_checker_builder.h>);
20        include!(<checker/checker_options.h>);
21        type Type<'a> = super::Type<'a>;
22        type Ast = super::Ast;
23        type Source = super::Source;
24        type VariableDecl<'a> = super::VariableDecl<'a>;
25        type FunctionDecl<'a> = super::FunctionDecl<'a>;
26
27        type CheckerOptions;
28        type CheckerLibrary;
29        type TypeCheckerSubset;
30
31        type TypeChecker;
32
33        type TypeCheckerBuilderConfigurer;
34        type TypeCheckerBuilder<'a>;
35        #[rust_name = "add_variable"]
36        fn AddVariable<'a>(
37            self: Pin<&mut TypeCheckerBuilder<'a>>,
38            decl: &VariableDecl<'a>,
39        ) -> Status;
40        #[rust_name = "add_or_replace_variable"]
41        fn AddOrReplaceVariable<'a>(
42            self: Pin<&mut TypeCheckerBuilder<'a>>,
43            decl: &VariableDecl<'a>,
44        ) -> Status;
45        #[rust_name = "add_context_declaration"]
46        fn AddContextDeclaration<'a>(
47            self: Pin<&mut TypeCheckerBuilder<'a>>,
48            type_name: string_view<'_>,
49        ) -> Status;
50        #[rust_name = "add_function"]
51        fn AddFunction<'a>(
52            self: Pin<&mut TypeCheckerBuilder<'a>>,
53            decl: &FunctionDecl<'a>,
54        ) -> Status;
55        #[rust_name = "merge_function"]
56        fn MergeFunction<'a>(
57            self: Pin<&mut TypeCheckerBuilder<'a>>,
58            decl: &FunctionDecl<'a>,
59        ) -> Status;
60        #[rust_name = "set_expected_type"]
61        fn SetExpectedType<'a>(self: Pin<&mut TypeCheckerBuilder<'a>>, expected_type: &Type<'a>);
62        fn set_container<'a>(self: Pin<&mut TypeCheckerBuilder<'a>>, container: string_view<'_>);
63        fn options<'this, 'a>(self: &'this TypeCheckerBuilder<'a>) -> &'this CheckerOptions;
64
65        type TypeCheckIssue;
66        fn severity(self: &TypeCheckIssue) -> Severity;
67
68        type ValidationResult;
69        #[rust_name = "is_valid"]
70        fn IsValid(self: &ValidationResult) -> bool;
71    }
72
73    #[namespace = "rust::cel_cxx"]
74    unsafe extern "C++" {
75        include!(<cel-cxx-ffi/include/absl.h>);
76        include!(<cel-cxx-ffi/include/checker.h>);
77        type Severity = super::Severity;
78        type FunctionPredicate;
79
80        // CheckerLibrary
81        fn CheckerLibrary_new(
82            id: &CxxString,
83            configurer: UniquePtr<TypeCheckerBuilderConfigurer>,
84        ) -> UniquePtr<CheckerLibrary>;
85        fn CheckerLibrary_new_optional() -> UniquePtr<CheckerLibrary>;
86        fn CheckerLibrary_new_standard() -> UniquePtr<CheckerLibrary>;
87        fn CheckerLibrary_id<'a>(checker_library: &'a CheckerLibrary) -> &'a CxxString;
88
89        // FunctionPredicate
90        fn FunctionPredicate_new(
91            ffi_predicate: Box<AnyFfiFunctionPredicate>
92        ) -> UniquePtr<FunctionPredicate>;
93
94        // TypeCheckerSubset
95        fn TypeCheckerSubset_new(
96            library_id: &CxxString,
97            should_include_overload: UniquePtr<FunctionPredicate>,
98        ) -> UniquePtr<TypeCheckerSubset>;
99        fn TypeCheckerSubset_library_id<'a>(type_checker_subset: &'a TypeCheckerSubset) -> &'a CxxString;
100
101        // CheckerOptions
102        fn CheckerOptions_new() -> UniquePtr<CheckerOptions>;
103
104        // CheckerOptions getters and setters
105        fn CheckerOptions_enable_cross_numeric_comparisons(
106            checker_options: &CheckerOptions,
107        ) -> bool;
108        fn CheckerOptions_enable_cross_numeric_comparisons_mut(
109            checker_options: Pin<&mut CheckerOptions>,
110        ) -> &mut bool;
111        fn CheckerOptions_enable_legacy_null_assignment(checker_options: &CheckerOptions) -> bool;
112        fn CheckerOptions_enable_legacy_null_assignment_mut(
113            checker_options: Pin<&mut CheckerOptions>,
114        ) -> &mut bool;
115        fn CheckerOptions_update_struct_type_names(checker_options: &CheckerOptions) -> bool;
116        fn CheckerOptions_update_struct_type_names_mut(
117            checker_options: Pin<&mut CheckerOptions>,
118        ) -> &mut bool;
119        fn CheckerOptions_allow_well_known_type_context_declarations(
120            checker_options: &CheckerOptions,
121        ) -> bool;
122        fn CheckerOptions_allow_well_known_type_context_declarations_mut(
123            checker_options: Pin<&mut CheckerOptions>,
124        ) -> &mut bool;
125        fn CheckerOptions_max_expression_node_count(checker_options: &CheckerOptions) -> i32;
126        fn CheckerOptions_max_expression_node_count_mut(
127            checker_options: Pin<&mut CheckerOptions>,
128        ) -> &mut i32;
129        fn CheckerOptions_max_error_issues(checker_options: &CheckerOptions) -> i32;
130        fn CheckerOptions_max_error_issues_mut(
131            checker_options: Pin<&mut CheckerOptions>,
132        ) -> &mut i32;
133
134        // TypeCheckerBuilderConfigurer
135        fn TypeCheckerBuilderConfigurer_new(
136            ffi_configurer: Box<AnyFfiTypeCheckerBuilderConfigurer>,
137        ) -> UniquePtr<TypeCheckerBuilderConfigurer>;
138
139        // TypeCheckerBuilder
140        fn TypeCheckerBuilder_add_library<'a>(
141            type_checker_builder: Pin<&mut TypeCheckerBuilder<'a>>,
142            library: UniquePtr<CheckerLibrary>,
143        ) -> Status;
144        fn TypeCheckerBuilder_add_library_subset<'a>(
145            type_checker_builder: Pin<&mut TypeCheckerBuilder<'a>>,
146            library_subset: UniquePtr<TypeCheckerSubset>,
147        ) -> Status;
148
149        // TypeCheckIssue
150        fn TypeCheckIssue_to_display_string(
151            type_check_issue: &TypeCheckIssue,
152            source: &Source,
153        ) -> String;
154
155        // ValidationResult
156        unsafe fn ValidationResult_get_ast(validation_result: &ValidationResult) -> *const Ast;
157        fn ValidationResult_release_ast(
158            validation_result: Pin<&mut ValidationResult>,
159            result: &mut UniquePtr<Ast>,
160        ) -> Status;
161
162        fn ValidationResult_format_error(validation_result: &ValidationResult) -> String;
163    }
164
165    #[namespace = "rust::cel_cxx"]
166    extern "Rust" {
167        #[derive(ExternType)]
168        type AnyFfiTypeCheckerBuilderConfigurer<'f>;
169        #[cxx_name = "Call"]
170        unsafe fn call<'f>(
171            self: &AnyFfiTypeCheckerBuilderConfigurer<'f>,
172            type_checker_builder: Pin<&mut TypeCheckerBuilder<'_>>,
173        ) -> Status;
174
175        #[derive(ExternType)]
176        type AnyFfiFunctionPredicate<'f>;
177        #[cxx_name = "Call"]
178        unsafe fn call<'f>(
179            self: &AnyFfiFunctionPredicate<'f>,
180            function_name: string_view<'_>,
181            overload_id: string_view<'_>,
182        ) -> bool;
183    }
184
185    impl UniquePtr<ValidationResult> {}
186}
187
188// TypeCheckerBuilderConfigurer
189pub use ffi::TypeCheckerBuilderConfigurer;
190unsafe impl Send for TypeCheckerBuilderConfigurer {}
191unsafe impl Sync for TypeCheckerBuilderConfigurer {}
192
193impl TypeCheckerBuilderConfigurer {
194    pub fn new<F: FfiTypeCheckerBuilderConfigurer + 'static>(configurer: F) -> cxx::UniquePtr<Self> {
195        ffi::TypeCheckerBuilderConfigurer_new(Box::new(AnyFfiTypeCheckerBuilderConfigurer::new(configurer)))
196    }
197}
198
199pub trait FfiTypeCheckerBuilderConfigurer: Fn(Pin<&mut TypeCheckerBuilder<'_>>) -> Status {}
200impl<'f, F> FfiTypeCheckerBuilderConfigurer for F where
201    F: 'f + Fn(Pin<&mut TypeCheckerBuilder<'_>>) -> Status {}
202
203struct AnyFfiTypeCheckerBuilderConfigurer<'f>(Box<dyn FfiTypeCheckerBuilderConfigurer + 'f>);
204impl<'f> AnyFfiTypeCheckerBuilderConfigurer<'f> {
205    fn new<T: FfiTypeCheckerBuilderConfigurer + 'f>(configurer: T) -> Self {
206        Self(Box::new(configurer))
207    }
208
209    fn call(&self, type_checker_builder: Pin<&mut TypeCheckerBuilder<'_>>) -> Status {
210        (self.0)(type_checker_builder)
211    }
212}
213
214// CheckerLibrary
215pub type TypeCheckerLibrary = CheckerLibrary;
216
217pub use ffi::CheckerLibrary;
218unsafe impl Send for CheckerLibrary {}
219unsafe impl Sync for CheckerLibrary {}
220
221impl CheckerLibrary {
222    pub fn new(id: &cxx::CxxString, configurer: cxx::UniquePtr<TypeCheckerBuilderConfigurer>) -> cxx::UniquePtr<Self> {
223        ffi::CheckerLibrary_new(id, configurer)
224    }
225
226    pub fn new_optional() -> cxx::UniquePtr<Self> {
227        ffi::CheckerLibrary_new_optional()
228    }
229
230    pub fn new_standard() -> cxx::UniquePtr<Self> {
231        ffi::CheckerLibrary_new_standard()
232    }
233
234    pub fn id(&self) -> &cxx::CxxString {
235        ffi::CheckerLibrary_id(&self)
236    }
237}
238
239// FunctionPredicate
240pub use ffi::FunctionPredicate;
241unsafe impl Send for FunctionPredicate {}
242unsafe impl Sync for FunctionPredicate {}
243
244impl FunctionPredicate {
245    pub fn new<F: FfiFunctionPredicate + 'static>(predicate: F) -> cxx::UniquePtr<Self> {
246        ffi::FunctionPredicate_new(Box::new(AnyFfiFunctionPredicate::new(predicate)))
247    }
248}
249
250pub trait FfiFunctionPredicate: Fn(StringView<'_>, StringView<'_>) -> bool {}
251impl<'f, F> FfiFunctionPredicate for F where
252    F: 'f + Fn(StringView<'_>, StringView<'_>) -> bool {}
253
254struct AnyFfiFunctionPredicate<'f>(Box<dyn FfiFunctionPredicate + 'f>);
255impl<'f> AnyFfiFunctionPredicate<'f> {
256    fn new<T: FfiFunctionPredicate + 'f>(predicate: T) -> Self {
257        Self(Box::new(predicate))
258    }
259
260    fn call(&self, function_name: StringView<'_>, overload_id: StringView<'_>) -> bool {
261        (self.0)(function_name, overload_id)
262    }
263}
264
265// CheckerLibrarySubset
266pub type TypeCheckerLibrarySubset = TypeCheckerSubset;
267
268pub use ffi::TypeCheckerSubset;
269unsafe impl Send for TypeCheckerSubset {}
270unsafe impl Sync for TypeCheckerSubset {}
271
272impl TypeCheckerSubset {
273    pub fn new(library_id: &cxx::CxxString, should_include_overload: cxx::UniquePtr<FunctionPredicate>) -> cxx::UniquePtr<Self> {
274        ffi::TypeCheckerSubset_new(library_id, should_include_overload)
275    }
276
277    pub fn library_id(&self) -> &cxx::CxxString {
278        ffi::TypeCheckerSubset_library_id(&self)
279    }
280}
281
282// CheckerOptions
283pub type TypeCheckerOptions = CheckerOptions;
284
285pub use ffi::CheckerOptions;
286unsafe impl Send for CheckerOptions {}
287unsafe impl Sync for CheckerOptions {}
288
289impl CheckerOptions {
290    pub fn new() -> cxx::UniquePtr<Self> {
291        ffi::CheckerOptions_new()
292    }
293
294    pub fn enable_cross_numeric_comparisons(&self) -> bool {
295        ffi::CheckerOptions_enable_cross_numeric_comparisons(self)
296    }
297
298    pub fn enable_cross_numeric_comparisons_mut<'a>(self: Pin<&'a mut Self>) -> &'a mut bool {
299        ffi::CheckerOptions_enable_cross_numeric_comparisons_mut(self)
300    }
301
302    pub fn enable_legacy_null_assignment(&self) -> bool {
303        ffi::CheckerOptions_enable_legacy_null_assignment(self)
304    }
305
306    pub fn enable_legacy_null_assignment_mut<'a>(self: Pin<&'a mut Self>) -> &'a mut bool {
307        ffi::CheckerOptions_enable_legacy_null_assignment_mut(self)
308    }
309
310    pub fn update_struct_type_names(&self) -> bool {
311        ffi::CheckerOptions_update_struct_type_names(self)
312    }
313
314    pub fn update_struct_type_names_mut<'a>(self: Pin<&'a mut Self>) -> &'a mut bool {
315        ffi::CheckerOptions_update_struct_type_names_mut(self)
316    }
317
318    pub fn allow_well_known_type_context_declarations(&self) -> bool {
319        ffi::CheckerOptions_allow_well_known_type_context_declarations(self)
320    }
321
322    pub fn allow_well_known_type_context_declarations_mut<'a>(
323        self: Pin<&'a mut Self>,
324    ) -> &'a mut bool {
325        ffi::CheckerOptions_allow_well_known_type_context_declarations_mut(self)
326    }
327
328    pub fn max_expression_node_count(&self) -> i32 {
329        ffi::CheckerOptions_max_expression_node_count(self)
330    }
331
332    pub fn max_expression_node_count_mut<'a>(self: Pin<&'a mut Self>) -> &'a mut i32 {
333        ffi::CheckerOptions_max_expression_node_count_mut(self)
334    }
335
336    pub fn max_error_issues(&self) -> i32 {
337        ffi::CheckerOptions_max_error_issues(self)
338    }
339
340    pub fn max_error_issues_mut<'a>(self: Pin<&'a mut Self>) -> &'a mut i32 {
341        ffi::CheckerOptions_max_error_issues_mut(self)
342    }
343}
344
345pub use ffi::ValidationResult;
346unsafe impl Send for ValidationResult {}
347unsafe impl Sync for ValidationResult {}
348
349impl ValidationResult {
350    pub fn ast(&self) -> Option<&Ast> {
351        unsafe {
352            let ast = ffi::ValidationResult_get_ast(self);
353            ast.as_ref()
354        }
355    }
356
357    pub fn release_ast(self: Pin<&mut Self>) -> Result<cxx::UniquePtr<Ast>, Status> {
358        let mut result = cxx::UniquePtr::null();
359        let status = ffi::ValidationResult_release_ast(self, &mut result);
360        if status.is_ok() {
361            Ok(result)
362        } else {
363            Err(status)
364        }
365    }
366
367    pub fn format_error(&self) -> String {
368        ffi::ValidationResult_format_error(self)
369    }
370}
371
372// Severity
373#[repr(i32)]
374#[derive(Clone, Copy, PartialEq, Eq, Default)]
375pub enum Severity {
376    #[default]
377    Error,
378    Warning,
379    Information,
380    Deprecated,
381}
382
383unsafe impl cxx::ExternType for Severity {
384    type Id = cxx::type_id!("rust::cel_cxx::Severity");
385    type Kind = cxx::kind::Trivial;
386}
387
388// TypeCheckIssue
389pub use ffi::TypeCheckIssue;
390unsafe impl Send for TypeCheckIssue {}
391unsafe impl Sync for TypeCheckIssue {}
392impl TypeCheckIssue {
393    pub fn to_display_string(&self, source: &Source) -> String {
394        ffi::TypeCheckIssue_to_display_string(self, source)
395    }
396}
397
398// TypeChecker
399pub use ffi::TypeChecker;
400unsafe impl Send for TypeChecker {}
401unsafe impl Sync for TypeChecker {}
402
403impl std::fmt::Debug for TypeChecker {
404    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
405        let ptr = self as *const TypeChecker;
406        write!(f, "TypeChecker {{ ptr: {ptr:p} }}")
407    }
408}
409
410// TypeCheckerBuilder
411pub use ffi::TypeCheckerBuilder;
412unsafe impl<'a> Send for TypeCheckerBuilder<'a> {}
413unsafe impl<'a> Sync for TypeCheckerBuilder<'a> {}
414
415impl<'a> TypeCheckerBuilder<'a> {
416    pub fn add_library(self: Pin<&mut Self>, library: cxx::UniquePtr<CheckerLibrary>) -> Status {
417        ffi::TypeCheckerBuilder_add_library(self, library)
418    }
419
420    pub fn add_library_subset(self: Pin<&mut Self>, library_subset: cxx::UniquePtr<TypeCheckerSubset>) -> Status {
421        ffi::TypeCheckerBuilder_add_library_subset(self, library_subset)
422    }
423}