1use std::borrow::Cow;
2
3use crate::Rep;
4
5#[cxx::bridge]
6mod ffi {
7 #[namespace = "absl"]
8 unsafe extern "C++" {
9 include!(<absl/time/time.h>);
10
11 type Duration = super::Duration;
12 fn Nanoseconds(n: i64) -> Duration;
13 fn ToInt64Nanoseconds(duration: Duration) -> i64;
14
15 type Time = super::Timestamp;
16 fn ToUnixNanos(time: Time) -> i64;
17 fn FromUnixNanos(nanos: i64) -> Time;
18
19 include!(<absl/status/status.h>);
20 type StatusCode = super::StatusCode;
21
22 type Status = super::Status;
23 #[rust_name = "is_ok"]
24 fn ok(self: &Status) -> bool;
25 fn code(self: &Status) -> StatusCode;
26 fn message<'a>(self: &'a Status) -> string_view<'a>;
27
28 fn OkStatus() -> Status;
29 fn IsAborted(status: &Status) -> bool;
30 fn IsAlreadyExists(status: &Status) -> bool;
31 fn IsCancelled(status: &Status) -> bool;
32 fn IsDataLoss(status: &Status) -> bool;
33 fn IsDeadlineExceeded(status: &Status) -> bool;
34 fn IsFailedPrecondition(status: &Status) -> bool;
35 fn IsInternal(status: &Status) -> bool;
36 fn IsInvalidArgument(status: &Status) -> bool;
37 fn IsNotFound(status: &Status) -> bool;
38 fn IsOutOfRange(status: &Status) -> bool;
39 fn IsPermissionDenied(status: &Status) -> bool;
40 fn IsResourceExhausted(status: &Status) -> bool;
41 fn IsUnauthenticated(status: &Status) -> bool;
42 fn IsUnavailable(status: &Status) -> bool;
43 fn IsUnimplemented(status: &Status) -> bool;
44 fn IsUnknown(status: &Status) -> bool;
45
46 fn AbortedError(msg: string_view) -> Status;
47 fn AlreadyExistsError(msg: string_view) -> Status;
48 fn CancelledError(msg: string_view) -> Status;
49 fn DataLossError(msg: string_view) -> Status;
50 fn DeadlineExceededError(msg: string_view) -> Status;
51 fn FailedPreconditionError(msg: string_view) -> Status;
52 fn InternalError(msg: string_view) -> Status;
53 fn InvalidArgumentError(msg: string_view) -> Status;
54 fn NotFoundError(msg: string_view) -> Status;
55 fn OutOfRangeError(msg: string_view) -> Status;
56 fn PermissionDeniedError(msg: string_view) -> Status;
57 fn ResourceExhaustedError(msg: string_view) -> Status;
58 fn UnauthenticatedError(msg: string_view) -> Status;
59 fn UnavailableError(msg: string_view) -> Status;
60 fn UnimplementedError(msg: string_view) -> Status;
61 fn UnknownError(msg: string_view) -> Status;
62
63 include!(<absl/strings/string_view.h>);
64 #[allow(unused, non_camel_case_types)]
65 type string_view<'a> = super::StringView<'a>;
66 #[rust_name = "len"]
67 fn size(self: &string_view) -> usize;
68 fn data(self: &string_view) -> *const c_char;
69 }
70
71 #[namespace = "absl"]
72 unsafe extern "C++" {
73 include!(<absl/log/log_entry.h>);
74
75 type LogSeverity = super::log::LogSeverity;
76 type LogSeverityAtLeast = super::log::LogSeverityAtLeast;
77
78 type LogEntry;
79 fn log_severity(self: &LogEntry) -> LogSeverity;
81 fn text_message<'a>(self: &'a LogEntry) -> string_view<'a>;
82 fn source_filename<'a>(self: &'a LogEntry) -> string_view<'a>;
83 fn source_line(self: &LogEntry) -> i32;
85
86 include!(<absl/log/globals.h>);
87 #[rust_name = "set_stderr_threshold"]
88 fn SetStderrThreshold(severity: LogSeverityAtLeast);
89 }
90
91 #[namespace = "rust::cel_cxx"]
92 unsafe extern "C++" {
93 include!(<cel-cxx-ffi/include/absl.h>);
94
95 fn Duration_new(seconds: i64, nanos: u32) -> Duration;
96 fn Duration_seconds(duration: Duration) -> i64;
97 fn Duration_nanos(duration: Duration) -> u32;
98
99 fn Timestamp_new(seconds: i64, nanos: u32) -> Time;
100 fn Timestamp_seconds(timestamp: Time) -> i64;
101 fn Timestamp_nanos(timestamp: Time) -> u32;
102
103 fn StringView_new<'a>(bytes: &'a [u8]) -> string_view<'a>;
104
105 fn StatusCode_to_string(code: StatusCode) -> String;
106
107 fn Status_new(code: StatusCode, msg: &str) -> Status;
108 fn Status_clone(status: &Status) -> Status;
109 fn Status_drop(status: &mut Status);
110 fn Status_to_string(status: &Status) -> String;
111
112 #[rust_name = "initialize_log"]
113 fn InitializeLog();
114
115 #[rust_name = "set_log_callback"]
116 fn SetLogCallback();
117 }
118
119 #[namespace = "rust::cel_cxx"]
120 extern "Rust" {
121 #[cxx_name = "LogCallback"]
122 fn log_callback(entry: &LogEntry);
123 }
124}
125
126use log::log_callback;
127pub mod log {
128 use super::ffi;
129 use std::sync::Once;
130
131 #[allow(dead_code)]
132 #[repr(i32)]
133 #[derive(Copy, Clone)]
134 pub(super) enum LogSeverity {
135 Info = 0,
136 Warning = 1,
137 Error = 2,
138 Fatal = 3,
139 }
140 unsafe impl cxx::ExternType for LogSeverity {
141 type Id = cxx::type_id!("absl::LogSeverity");
142 type Kind = cxx::kind::Trivial;
143 }
144
145 #[allow(dead_code)]
146 #[repr(i32)]
147 #[derive(Copy, Clone)]
148 pub(super) enum LogSeverityAtLeast {
149 Info = 0,
150 Warning = 1,
151 Error = 2,
152 Fatal = 3,
153 Infinity = 1000,
154 }
155 unsafe impl cxx::ExternType for LogSeverityAtLeast {
156 type Id = cxx::type_id!("absl::LogSeverityAtLeast");
157 type Kind = cxx::kind::Trivial;
158 }
159
160 static ONCE: Once = Once::new();
161
162 pub fn init() {
165 ONCE.call_once(|| {
166 ffi::initialize_log();
167
168 ffi::set_log_callback();
169
170 ffi::set_stderr_threshold(LogSeverityAtLeast::Infinity);
171 });
172 }
173
174 pub(super) fn log_callback(entry: &ffi::LogEntry) {
176 let level = match entry.log_severity() {
178 LogSeverity::Info => log::Level::Info,
179 LogSeverity::Warning => log::Level::Warn,
180 LogSeverity::Error => log::Level::Error,
181 LogSeverity::Fatal => log::Level::Error,
182 };
183
184 let message = entry.text_message().to_string_lossy();
186 let file = entry.source_filename().to_string_lossy();
187 let line = entry.source_line();
188
189 log::logger().log(
191 &log::Record::builder()
192 .args(format_args!("{message}"))
193 .level(level)
194 .file(Some(file.as_ref()))
195 .line(if line > 0 { Some(line as u32) } else { None })
196 .build()
197 );
198 }
199}
200
201#[repr(transparent)]
202#[derive(Copy, Clone)]
203pub struct Duration(Rep<'static, u32, 3>);
204
205unsafe impl cxx::ExternType for Duration {
206 type Id = cxx::type_id!("absl::Duration");
207 type Kind = cxx::kind::Trivial;
208}
209
210impl Duration {
211 pub fn new(seconds: i64, nanos: u32) -> Self {
212 ffi::Duration_new(seconds, nanos)
213 }
214
215 pub fn from_nanos(nanos: i64) -> Self {
216 ffi::Nanoseconds(nanos)
217 }
218
219 pub fn to_nanos(&self) -> i64 {
220 ffi::ToInt64Nanoseconds(*self)
221 }
222
223 pub fn seconds(&self) -> i64 {
224 ffi::Duration_seconds(*self)
225 }
226
227 pub fn nanos(&self) -> u32 {
228 ffi::Duration_nanos(*self)
229 }
230}
231
232impl From<chrono::Duration> for Duration {
233 fn from(value: chrono::Duration) -> Self {
234 Self::new(value.num_seconds(), value.subsec_nanos() as u32)
235 }
236}
237
238impl From<Duration> for chrono::Duration {
239 fn from(value: Duration) -> Self {
240 Self::new(value.seconds(), value.nanos()).unwrap_or_default()
241 }
242}
243
244#[repr(transparent)]
245#[derive(Copy, Clone)]
246pub struct Timestamp(Rep<'static, u32, 3>);
247
248unsafe impl cxx::ExternType for Timestamp {
249 type Id = cxx::type_id!("absl::Time");
250 type Kind = cxx::kind::Trivial;
251}
252
253impl Timestamp {
254 pub fn new(seconds: i64, nanos: u32) -> Self {
255 ffi::Timestamp_new(seconds, nanos)
256 }
257
258 pub fn from_unix_nanos(nanos: i64) -> Self {
259 ffi::FromUnixNanos(nanos)
260 }
261
262 pub fn unix_nanos(&self) -> i64 {
263 ffi::ToUnixNanos(*self)
264 }
265
266 pub fn seconds(&self) -> i64 {
267 ffi::Timestamp_seconds(*self)
268 }
269
270 pub fn nanos(&self) -> u32 {
271 ffi::Timestamp_nanos(*self)
272 }
273}
274
275impl From<chrono::DateTime<chrono::Utc>> for Timestamp {
276 fn from(value: chrono::DateTime<chrono::Utc>) -> Self {
277 Self::new(value.timestamp(), value.timestamp_subsec_nanos())
278 }
279}
280
281impl From<Timestamp> for chrono::DateTime<chrono::Utc> {
282 fn from(value: Timestamp) -> Self {
283 Self::from_timestamp(value.seconds(), value.nanos()).unwrap_or_default()
284 }
285}
286
287#[repr(i32)]
289#[derive(Copy, Clone)]
290pub enum StatusCode {
291 Ok = 0,
292 Cancelled = 1,
293 Unknown = 2,
294 InvalidArgument = 3,
295 DeadlineExceeded = 4,
296 NotFound = 5,
297 AlreadyExists = 6,
298 PermissionDenied = 7,
299 ResourceExhausted = 8,
300 FailedPrecondition = 9,
301 Aborted = 10,
302 OutOfRange = 11,
303 Unimplemented = 12,
304 Internal = 13,
305 Unavailable = 14,
306 DataLoss = 15,
307 Unauthenticated = 16,
308}
309
310unsafe impl cxx::ExternType for StatusCode {
311 type Id = cxx::type_id!("absl::StatusCode");
312 type Kind = cxx::kind::Trivial;
313}
314
315impl std::fmt::Display for StatusCode {
316 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
317 let string = ffi::StatusCode_to_string(*self);
318 write!(f, "{string}")
319 }
320}
321
322#[repr(transparent)]
324pub struct Status(Rep<'static, usize, 1>);
325
326unsafe impl cxx::ExternType for Status {
327 type Id = cxx::type_id!("absl::Status");
328 type Kind = cxx::kind::Trivial;
329}
330
331impl Clone for Status {
332 fn clone(&self) -> Self {
333 ffi::Status_clone(self)
334 }
335}
336
337impl Drop for Status {
338 fn drop(&mut self) {
339 ffi::Status_drop(self)
340 }
341}
342
343impl Default for Status {
344 fn default() -> Self {
345 ffi::OkStatus()
346 }
347}
348
349impl std::fmt::Display for Status {
350 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
351 let string = ffi::Status_to_string(self);
352 write!(f, "{string}")
353 }
354}
355
356impl std::fmt::Debug for Status {
357 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
358 let string = ffi::Status_to_string(self);
359 write!(f, "{string}")
360 }
361}
362
363impl std::error::Error for Status {}
364
365impl Status {
366 pub fn new(code: StatusCode, message: &str) -> Self {
367 ffi::Status_new(code, message)
368 }
369
370 pub fn ok() -> Self {
371 ffi::OkStatus()
372 }
373
374 pub fn is_aborted(&self) -> bool {
375 ffi::IsAborted(self)
376 }
377
378 pub fn is_already_exists(&self) -> bool {
379 ffi::IsAlreadyExists(self)
380 }
381
382 pub fn is_cancelled(&self) -> bool {
383 ffi::IsCancelled(self)
384 }
385
386 pub fn is_data_loss(&self) -> bool {
387 ffi::IsDataLoss(self)
388 }
389
390 pub fn is_deadline_exceeded(&self) -> bool {
391 ffi::IsDeadlineExceeded(self)
392 }
393
394 pub fn is_failed_precondition(&self) -> bool {
395 ffi::IsFailedPrecondition(self)
396 }
397
398 pub fn is_internal(&self) -> bool {
399 ffi::IsInternal(self)
400 }
401
402 pub fn is_invalid_argument(&self) -> bool {
403 ffi::IsInvalidArgument(self)
404 }
405
406 pub fn is_not_found(&self) -> bool {
407 ffi::IsNotFound(self)
408 }
409
410 pub fn is_out_of_range(&self) -> bool {
411 ffi::IsOutOfRange(self)
412 }
413
414 pub fn is_permission_denied(&self) -> bool {
415 ffi::IsPermissionDenied(self)
416 }
417
418 pub fn is_resource_exhausted(&self) -> bool {
419 ffi::IsResourceExhausted(self)
420 }
421
422 pub fn is_unauthenticated(&self) -> bool {
423 ffi::IsUnauthenticated(self)
424 }
425
426 pub fn is_unavailable(&self) -> bool {
427 ffi::IsUnavailable(self)
428 }
429
430 pub fn is_unimplemented(&self) -> bool {
431 ffi::IsUnimplemented(self)
432 }
433
434 pub fn is_unknown(&self) -> bool {
435 ffi::IsUnknown(self)
436 }
437
438 pub fn aborted(msg: &str) -> Self {
439 ffi::AbortedError(StringView::new_str(msg))
440 }
441
442 pub fn already_exists(msg: &str) -> Self {
443 ffi::AlreadyExistsError(StringView::new_str(msg))
444 }
445
446 pub fn cancelled(msg: &str) -> Self {
447 ffi::CancelledError(StringView::new_str(msg))
448 }
449
450 pub fn data_loss(msg: &str) -> Self {
451 ffi::DataLossError(StringView::new_str(msg))
452 }
453
454 pub fn deadline_exceeded(msg: &str) -> Self {
455 ffi::DeadlineExceededError(StringView::new_str(msg))
456 }
457
458 pub fn failed_precondition(msg: &str) -> Self {
459 ffi::FailedPreconditionError(StringView::new_str(msg))
460 }
461
462 pub fn internal(msg: &str) -> Self {
463 ffi::InternalError(StringView::new_str(msg))
464 }
465
466 pub fn invalid_argument(msg: &str) -> Self {
467 ffi::InvalidArgumentError(StringView::new_str(msg))
468 }
469
470 pub fn not_found(msg: &str) -> Self {
471 ffi::NotFoundError(StringView::new_str(msg))
472 }
473
474 pub fn out_of_range(msg: &str) -> Self {
475 ffi::OutOfRangeError(StringView::new_str(msg))
476 }
477
478 pub fn permission_denied(msg: &str) -> Self {
479 ffi::PermissionDeniedError(StringView::new_str(msg))
480 }
481
482 pub fn resource_exhausted(msg: &str) -> Self {
483 ffi::ResourceExhaustedError(StringView::new_str(msg))
484 }
485
486 pub fn unauthenticated(msg: &str) -> Self {
487 ffi::UnauthenticatedError(StringView::new_str(msg))
488 }
489
490 pub fn unavailable(msg: &str) -> Self {
491 ffi::UnavailableError(StringView::new_str(msg))
492 }
493
494 pub fn unimplemented(msg: &str) -> Self {
495 ffi::UnimplementedError(StringView::new_str(msg))
496 }
497
498 pub fn unknown(msg: &str) -> Self {
499 ffi::UnknownError(StringView::new_str(msg))
500 }
501}
502
503#[repr(C)]
505pub struct Span<'a, T: 'a + SpanElement> {
506 ptr: *const T,
507 len: usize,
508 _marker: std::marker::PhantomData<&'a T>,
509}
510
511impl<'a, T: 'a + SpanElement> Copy for Span<'a, T> {}
512impl<'a, T: 'a + SpanElement> Clone for Span<'a, T> {
513 fn clone(&self) -> Self {
514 *self
515 }
516}
517
518unsafe impl<'a, T: 'a + SpanElement> cxx::ExternType for Span<'a, T> {
519 type Id = T::TypeId;
520 type Kind = cxx::kind::Trivial;
521}
522
523impl<'a, T: 'a + SpanElement> Span<'a, T> {
524 pub fn len(&self) -> usize {
525 self.len
526 }
527
528 pub fn is_empty(&self) -> bool {
529 self.len == 0
530 }
531
532 pub fn get(&self, index: usize) -> Option<&'a T> {
533 if index < self.len() {
534 let offset = index * T::size_of();
535 unsafe { self.ptr.byte_add(offset).as_ref() }
536 } else {
537 None
538 }
539 }
540
541 pub fn iter(&self) -> SpanIter<'a, T> {
542 SpanIter {
543 span: *self,
544 index: 0,
545 }
546 }
547}
548
549impl<'a, T: 'a + SpanElement + cxx::ExternType<Kind = cxx::kind::Trivial>> Span<'a, T> {
550 pub fn from_slice(slice: &'a [T]) -> Self {
551 Self {
552 ptr: slice.as_ptr(),
553 len: slice.len(),
554 _marker: std::marker::PhantomData,
555 }
556 }
557
558 pub fn as_slice(&self) -> &'a [T] {
559 unsafe { std::slice::from_raw_parts(self.ptr, self.len) }
560 }
561}
562
563pub struct SpanIter<'a, T: 'a + SpanElement> {
564 span: Span<'a, T>,
565 index: usize,
566}
567
568impl<'a, T: 'a + SpanElement> std::iter::Iterator for SpanIter<'a, T> {
569 type Item = &'a T;
570
571 fn next(&mut self) -> Option<Self::Item> {
572 if let Some(item) = self.span.get(self.index) {
573 self.index += 1;
574 Some(item)
575 } else {
576 None
577 }
578 }
579
580 fn size_hint(&self) -> (usize, Option<usize>) {
581 (
582 self.span.len() - self.index,
583 Some(self.span.len() - self.index),
584 )
585 }
586}
587
588impl<'a, T: 'a + SpanElement> std::iter::FusedIterator for SpanIter<'a, T> {}
589
590impl<'a, T: 'a + SpanElement> std::iter::ExactSizeIterator for SpanIter<'a, T> {}
591
592impl<'a, T: 'a + SpanElement> std::iter::IntoIterator for Span<'a, T> {
593 type Item = &'a T;
594 type IntoIter = SpanIter<'a, T>;
595
596 fn into_iter(self) -> Self::IntoIter {
597 SpanIter {
598 span: self,
599 index: 0,
600 }
601 }
602}
603
604impl<'a, T: 'a + SpanElement + std::fmt::Debug> std::fmt::Debug for Span<'a, T> {
605 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
606 f.debug_list().entries(self.iter()).finish()
607 }
608}
609
610pub trait SpanElement: crate::SizedExternType {
611 type TypeId;
612}
613
614#[repr(C)]
616#[derive(Copy, Clone)]
617pub struct StringView<'a>(Rep<'a, usize, 2>);
618
619unsafe impl<'a> cxx::ExternType for StringView<'a> {
620 type Id = cxx::type_id!("absl::string_view");
621 type Kind = cxx::kind::Trivial;
622}
623
624impl<'a> crate::SizedExternType for StringView<'a> {}
625
626impl<'a> SpanElement for StringView<'a> {
627 type TypeId = cxx::type_id!("rust::cel_cxx::Span_StringView");
628}
629
630impl<'a> StringView<'a> {
631 pub fn new(bytes: &'a [u8]) -> Self {
632 ffi::StringView_new(bytes)
633 }
634
635 pub fn new_str(s: &'a str) -> Self {
636 Self::new(s.as_bytes())
637 }
638
639 pub fn is_empty(&self) -> bool {
640 self.len() == 0
641 }
642
643 pub fn as_bytes(&self) -> &'a [u8] {
644 unsafe { std::slice::from_raw_parts(self.as_ptr(), self.len()) }
645 }
646
647 pub fn to_str(&self) -> Result<&'a str, std::str::Utf8Error> {
648 std::str::from_utf8(self.as_bytes())
649 }
650
651 pub fn to_string_lossy(&self) -> Cow<'a, str> {
652 String::from_utf8_lossy(self.as_bytes())
653 }
654
655 pub fn as_ptr(&self) -> *const u8 {
656 self.data() as *const u8
657 }
658}