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 ParserBuilder = super::ParserBuilder;
27 type CheckerLibrary = super::CheckerLibrary;
28 type TypeChecker = super::TypeChecker;
29 type Parser = super::Parser;
30 type TypeCheckerBuilder<'a> = super::TypeCheckerBuilder<'a>;
31 type ValidationResult = super::ValidationResult;
32
33 type Compiler<'a>;
34 #[rust_name = "type_checker"]
35 fn GetTypeChecker<'a>(self: &Compiler<'a>) -> &TypeChecker;
36 #[rust_name = "parser"]
37 fn GetParser<'a>(self: &Compiler<'a>) -> &Parser;
38
39 type CompilerBuilder<'a>;
40 #[rust_name = "checker_builder"]
41 fn GetCheckerBuilder<'a>(
42 self: Pin<&mut CompilerBuilder<'a>>,
43 ) -> Pin<&mut TypeCheckerBuilder<'a>>;
44 #[rust_name = "parser_builder"]
45 fn GetParserBuilder<'a>(self: Pin<&mut CompilerBuilder<'a>>) -> Pin<&mut ParserBuilder>;
46
47 type CompilerLibrary;
48 type CompilerOptions = super::CompilerOptions;
49 }
50
51 #[namespace = "rust::cel_cxx"]
52 unsafe extern "C++" {
53 include!("cel-cxx-ffi/include/absl.h");
54 include!("cel-cxx-ffi/include/compiler.h");
55
56 fn Compiler_compile(
58 compiler: &Compiler,
59 source: &[u8],
60 description: &str,
61 result: &mut UniquePtr<ValidationResult>,
62 ) -> Status;
63
64 fn CompilerBuilder_new<'a>(
66 descriptor_pool: SharedPtr<DescriptorPool>,
67 options: &CompilerOptions,
68 result: &mut UniquePtr<CompilerBuilder<'a>>,
69 ) -> Status;
70
71 fn CompilerBuilder_add_library<'a>(
72 compiler_builder: Pin<&mut CompilerBuilder<'a>>,
73 library: UniquePtr<CompilerLibrary>,
74 ) -> Status;
75
76 fn CompilerBuilder_build<'a>(
77 compiler_builder: Pin<&mut CompilerBuilder<'a>>,
78 result: &mut UniquePtr<Compiler<'a>>,
79 ) -> Status;
80
81 fn CompilerLibrary_new_standard() -> UniquePtr<CompilerLibrary>;
83 fn CompilerLibrary_new_optional() -> UniquePtr<CompilerLibrary>;
84 fn CompilerLibrary_from_checker_library(
85 checker_library: UniquePtr<CheckerLibrary>,
86 ) -> UniquePtr<CompilerLibrary>;
87 }
88}
89
90pub use ffi::Compiler;
91unsafe impl<'a> Send for Compiler<'a> {}
92unsafe impl<'a> Sync for Compiler<'a> {}
93
94impl<'a> Compiler<'a> {
95 pub fn compile(
96 &self,
97 source: &[u8],
98 description: Option<&str>,
99 ) -> Result<cxx::UniquePtr<ValidationResult>, Status> {
100 let description = description.unwrap_or("<input>");
101 let mut result = cxx::UniquePtr::null();
102 let status = ffi::Compiler_compile(self, source, description, &mut result);
103 if status.is_ok() {
104 Ok(result)
105 } else {
106 Err(status)
107 }
108 }
109}
110
111impl<'a> std::fmt::Debug for Compiler<'a> {
112 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113 write!(
114 f,
115 "Compiler {{ type_checker: {:?}, parser: {:?} }}",
116 self.type_checker(),
117 self.parser(),
118 )
119 }
120}
121
122pub use ffi::CompilerBuilder;
123unsafe impl<'a> Send for CompilerBuilder<'a> {}
124unsafe impl<'a> Sync for CompilerBuilder<'a> {}
125
126impl<'a> CompilerBuilder<'a> {
127 pub fn new(
128 descriptor_pool: cxx::SharedPtr<DescriptorPool>,
129 options: &CompilerOptions,
130 ) -> Result<cxx::UniquePtr<Self>, Status> {
131 let mut result = cxx::UniquePtr::null();
132 let status = ffi::CompilerBuilder_new(descriptor_pool, options, &mut result);
133 if status.is_ok() {
134 Ok(result)
135 } else {
136 Err(status)
137 }
138 }
139
140 pub fn add_library(
141 self: Pin<&mut Self>,
142 library: cxx::UniquePtr<CompilerLibrary>,
143 ) -> Result<(), Status> {
144 let status = ffi::CompilerBuilder_add_library(self, library);
145 if status.is_ok() {
146 Ok(())
147 } else {
148 Err(status)
149 }
150 }
151
152 pub fn build(self: Pin<&mut Self>) -> Result<cxx::UniquePtr<Compiler<'a>>, Status> {
153 let mut result = cxx::UniquePtr::null();
154 let status = ffi::CompilerBuilder_build(self, &mut result);
155 if status.is_ok() {
156 Ok(result)
157 } else {
158 Err(status)
159 }
160 }
161}
162
163impl<'a> std::fmt::Debug for CompilerBuilder<'a> {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 write!(f, "CompilerBuilder {{ ptr: {:p} }}", self as *const Self)
166 }
167}
168
169pub use ffi::CompilerLibrary;
171unsafe impl Send for CompilerLibrary {}
172unsafe impl Sync for CompilerLibrary {}
173
174impl CompilerLibrary {
175 pub fn new_standard() -> cxx::UniquePtr<Self> {
176 ffi::CompilerLibrary_new_standard()
177 }
178
179 pub fn new_optional() -> cxx::UniquePtr<Self> {
180 ffi::CompilerLibrary_new_optional()
181 }
182
183 pub fn from_checker_library(
184 checker_library: cxx::UniquePtr<CheckerLibrary>,
185 ) -> cxx::UniquePtr<Self> {
186 ffi::CompilerLibrary_from_checker_library(checker_library)
187 }
188}
189
190#[repr(C)]
191#[derive(Debug, Clone, Copy, Default)]
192pub struct CompilerOptions {
193 pub parser_options: ParserOptions,
194 pub checker_options: CheckerOptions,
195}
196
197unsafe impl cxx::ExternType for CompilerOptions {
198 type Id = cxx::type_id!("cel::CompilerOptions");
199 type Kind = cxx::kind::Trivial;
200}