cel_cxx_ffi/
absl.rs

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