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 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        // Compiler
57        fn Compiler_compile(
58            compiler: &Compiler,
59            source: &[u8],
60            description: &str,
61            result: &mut UniquePtr<ValidationResult>,
62        ) -> Status;
63
64        // CompilerBuilder
65        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        // CompilerLibrary
82        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
169// CompilerLibrary
170pub 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}