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 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 fn FunctionPredicate_new(
91 ffi_predicate: Box<AnyFfiFunctionPredicate>
92 ) -> UniquePtr<FunctionPredicate>;
93
94 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 fn CheckerOptions_new() -> UniquePtr<CheckerOptions>;
103
104 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 fn TypeCheckerBuilderConfigurer_new(
136 ffi_configurer: Box<AnyFfiTypeCheckerBuilderConfigurer>,
137 ) -> UniquePtr<TypeCheckerBuilderConfigurer>;
138
139 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 fn TypeCheckIssue_to_display_string(
151 type_check_issue: &TypeCheckIssue,
152 source: &Source,
153 ) -> String;
154
155 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
188pub 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
214pub 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
239pub 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
265pub 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
282pub 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#[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
388pub 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
398pub 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
410pub 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}