cel_cxx_ffi/
compiler.rs

1use crate::absl::Status;
2use crate::checker::{CheckerLibrary, CheckerOptions};
3use crate::checker::{TypeChecker, TypeCheckerBuilder, ValidationResult};
4use crate::parser::ParserOptions;
5use crate::parser::{Parser, ParserBuilder};
6use crate::protobuf::DescriptorPool;
7use std::pin::Pin;
8
9#[cxx::bridge]
10mod ffi {
11    #[namespace = "absl"]
12    unsafe extern "C++" {
13        include!(<absl/status/status.h>);
14        type Status = super::Status;
15    }
16
17    #[namespace = "google::protobuf"]
18    unsafe extern "C++" {
19        include!(<google/protobuf/descriptor.h>);
20        type DescriptorPool = super::DescriptorPool;
21    }
22
23    #[namespace = "cel"]
24    unsafe extern "C++" {
25        include!(<compiler/compiler.h>);
26        type ParserOptions = super::ParserOptions;
27        type CheckerOptions = super::CheckerOptions;
28        type ParserBuilder = super::ParserBuilder;
29        type CheckerLibrary = super::CheckerLibrary;
30        type TypeChecker = super::TypeChecker;
31        type Parser = super::Parser;
32        type TypeCheckerBuilder<'a> = super::TypeCheckerBuilder<'a>;
33        type ValidationResult = super::ValidationResult;
34
35        type Compiler<'a>;
36        #[rust_name = "type_checker"]
37        fn GetTypeChecker<'a>(self: &Compiler<'a>) -> &TypeChecker;
38        #[rust_name = "parser"]
39        fn GetParser<'a>(self: &Compiler<'a>) -> &Parser;
40
41        type CompilerBuilder<'a>;
42        #[rust_name = "checker_builder"]
43        fn GetCheckerBuilder<'a>(
44            self: Pin<&mut CompilerBuilder<'a>>,
45        ) -> Pin<&mut TypeCheckerBuilder<'a>>;
46        #[rust_name = "parser_builder"]
47        fn GetParserBuilder<'a>(self: Pin<&mut CompilerBuilder<'a>>) -> Pin<&mut ParserBuilder>;
48
49        type CompilerLibrary;
50        type CompilerOptions;
51    }
52
53    #[namespace = "rust::cel_cxx"]
54    unsafe extern "C++" {
55        include!(<cel-cxx-ffi/include/absl.h>);
56        include!(<cel-cxx-ffi/include/compiler.h>);
57
58        // Compiler
59        fn Compiler_compile(
60            compiler: &Compiler,
61            source: &[u8],
62            description: &str,
63            result: &mut UniquePtr<ValidationResult>,
64        ) -> Status;
65
66        // CompilerBuilder
67        fn CompilerBuilder_new<'a>(
68            descriptor_pool: SharedPtr<DescriptorPool>,
69            options: &CompilerOptions,
70            result: &mut UniquePtr<CompilerBuilder<'a>>,
71        ) -> Status;
72
73        fn CompilerBuilder_add_library<'a>(
74            compiler_builder: Pin<&mut CompilerBuilder<'a>>,
75            library: UniquePtr<CompilerLibrary>,
76        ) -> Status;
77
78        fn CompilerBuilder_build<'a>(
79            compiler_builder: Pin<&mut CompilerBuilder<'a>>,
80            result: &mut UniquePtr<Compiler<'a>>,
81        ) -> Status;
82
83        // CompilerLibrary
84        fn CompilerLibrary_new_standard() -> UniquePtr<CompilerLibrary>;
85        fn CompilerLibrary_new_optional() -> UniquePtr<CompilerLibrary>;
86        fn CompilerLibrary_from_checker_library(
87            checker_library: UniquePtr<CheckerLibrary>,
88        ) -> UniquePtr<CompilerLibrary>;
89
90        // CompilerOptions
91        fn CompilerOptions_new() -> UniquePtr<CompilerOptions>;
92
93        // CompilerOptions getters and setters
94        fn CompilerOptions_parser_options(compiler_options: &CompilerOptions) -> &ParserOptions;
95        fn CompilerOptions_parser_options_mut(
96            compiler_options: Pin<&mut CompilerOptions>,
97        ) -> Pin<&mut ParserOptions>;
98        fn CompilerOptions_checker_options(compiler_options: &CompilerOptions) -> &CheckerOptions;
99        fn CompilerOptions_checker_options_mut(
100            compiler_options: Pin<&mut CompilerOptions>,
101        ) -> Pin<&mut CheckerOptions>;
102    }
103}
104
105pub use ffi::Compiler;
106unsafe impl<'a> Send for Compiler<'a> {}
107unsafe impl<'a> Sync for Compiler<'a> {}
108
109impl<'a> Compiler<'a> {
110    pub fn compile(
111        &self,
112        source: &[u8],
113        description: Option<&str>,
114    ) -> Result<cxx::UniquePtr<ValidationResult>, Status> {
115        let description = description.unwrap_or("<input>");
116        let mut result = cxx::UniquePtr::null();
117        let status = ffi::Compiler_compile(self, source, description, &mut result);
118        if status.is_ok() {
119            Ok(result)
120        } else {
121            Err(status)
122        }
123    }
124}
125
126impl<'a> std::fmt::Debug for Compiler<'a> {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        write!(
129            f,
130            "Compiler {{ type_checker: {:?}, parser: {:?} }}",
131            self.type_checker(),
132            self.parser(),
133        )
134    }
135}
136
137pub use ffi::CompilerBuilder;
138unsafe impl<'a> Send for CompilerBuilder<'a> {}
139unsafe impl<'a> Sync for CompilerBuilder<'a> {}
140
141impl<'a> CompilerBuilder<'a> {
142    pub fn new(
143        descriptor_pool: cxx::SharedPtr<DescriptorPool>,
144        options: &CompilerOptions,
145    ) -> Result<cxx::UniquePtr<Self>, Status> {
146        let mut result = cxx::UniquePtr::null();
147        let status = ffi::CompilerBuilder_new(descriptor_pool, options, &mut result);
148        if status.is_ok() {
149            Ok(result)
150        } else {
151            Err(status)
152        }
153    }
154
155    pub fn add_library(
156        self: Pin<&mut Self>,
157        library: cxx::UniquePtr<CompilerLibrary>,
158    ) -> Result<(), Status> {
159        let status = ffi::CompilerBuilder_add_library(self, library);
160        if status.is_ok() {
161            Ok(())
162        } else {
163            Err(status)
164        }
165    }
166
167    pub fn build(self: Pin<&mut Self>) -> Result<cxx::UniquePtr<Compiler<'a>>, Status> {
168        let mut result = cxx::UniquePtr::null();
169        let status = ffi::CompilerBuilder_build(self, &mut result);
170        if status.is_ok() {
171            Ok(result)
172        } else {
173            Err(status)
174        }
175    }
176}
177
178impl<'a> std::fmt::Debug for CompilerBuilder<'a> {
179    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180        write!(f, "CompilerBuilder {{ ptr: {:p} }}", self as *const Self)
181    }
182}
183
184// CompilerLibrary
185pub use ffi::CompilerLibrary;
186unsafe impl Send for CompilerLibrary {}
187unsafe impl Sync for CompilerLibrary {}
188
189impl CompilerLibrary {
190    pub fn new_standard() -> cxx::UniquePtr<Self> {
191        ffi::CompilerLibrary_new_standard()
192    }
193
194    pub fn new_optional() -> cxx::UniquePtr<Self> {
195        ffi::CompilerLibrary_new_optional()
196    }
197
198    pub fn from_checker_library(
199        checker_library: cxx::UniquePtr<CheckerLibrary>,
200    ) -> cxx::UniquePtr<Self> {
201        ffi::CompilerLibrary_from_checker_library(checker_library)
202    }
203}
204
205pub use ffi::CompilerOptions;
206unsafe impl Send for CompilerOptions {}
207unsafe impl Sync for CompilerOptions {}
208
209impl CompilerOptions {
210    pub fn new() -> cxx::UniquePtr<Self> {
211        let mut options = ffi::CompilerOptions_new();
212        *options
213            .pin_mut()
214            .parser_options_mut()
215            .enable_optional_syntax_mut() = true;
216        options
217    }
218
219    pub fn parser_options(&self) -> &ParserOptions {
220        ffi::CompilerOptions_parser_options(self)
221    }
222
223    pub fn parser_options_mut(self: Pin<&mut Self>) -> Pin<&mut ParserOptions> {
224        ffi::CompilerOptions_parser_options_mut(self)
225    }
226
227    pub fn checker_options(&self) -> &CheckerOptions {
228        ffi::CompilerOptions_checker_options(self)
229    }
230
231    pub fn checker_options_mut(self: Pin<&mut Self>) -> Pin<&mut CheckerOptions> {
232        ffi::CompilerOptions_checker_options_mut(self)
233    }
234}