Skip to main content

azul_css/
macros.rs

1//! Macros for generating C-ABI-compatible collection types (`Vec`, `Option`, `Result`)
2//! used throughout the codebase for FFI interop.
3//!
4//! Each macro produces `#[repr(C)]` types
5//! with a destructor model: `DefaultRust` (library-owned), `NoDestructor` (`&'static`),
6//! `External` (caller-provided destructor fn), and `AlreadyDestroyed` (post-drop guard).
7
8#[macro_export]
9macro_rules! impl_vec {
10    ($struct_type:ident, $struct_name:ident, $destructor_name:ident, $destructor_type_name:ident, $slice_name:ident, $option_type:ident) => {
11        pub type $destructor_type_name = extern "C" fn(*mut $struct_name);
12
13        /// C-compatible slice type for `$struct_name`.
14        /// This is a non-owning view into a Vec's data.
15        #[repr(C)]
16        #[derive(Debug, Copy, Clone)]
17        pub struct $slice_name {
18            pub ptr: *const $struct_type,
19            pub len: usize,
20        }
21
22        impl $slice_name {
23            /// Creates an empty slice.
24            #[inline]
25            #[must_use] pub const fn empty() -> Self {
26                Self {
27                    ptr: core::ptr::null(),
28                    len: 0,
29                }
30            }
31
32            /// Returns the number of elements in the slice.
33            #[inline]
34            #[must_use] pub const fn len(&self) -> usize {
35                self.len
36            }
37
38            /// Returns true if the slice is empty.
39            #[inline]
40            #[must_use] pub const fn is_empty(&self) -> bool {
41                self.len == 0
42            }
43
44            /// Returns a pointer to the slice's data.
45            #[inline]
46            #[must_use] pub const fn as_ptr(&self) -> *const $struct_type {
47                self.ptr
48            }
49
50            /// Converts the C-slice to a Rust slice.
51            #[inline]
52            #[must_use] pub const fn as_slice(&self) -> &[$struct_type] {
53                if self.ptr.is_null() || self.len == 0 {
54                    &[]
55                } else {
56                    unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
57                }
58            }
59
60            /// Returns a reference to the element at the given index, or None if out of bounds.
61            #[inline]
62            #[must_use] pub fn get(&self, index: usize) -> Option<&$struct_type> {
63                self.as_slice().get(index)
64            }
65
66            /// Returns an iterator over the elements.
67            #[inline]
68            pub fn iter(&self) -> core::slice::Iter<'_, $struct_type> {
69                self.as_slice().iter()
70            }
71        }
72
73        unsafe impl Send for $slice_name {}
74        unsafe impl Sync for $slice_name {}
75
76        impl<'a> IntoIterator for &'a $slice_name {
77            type Item = &'a $struct_type;
78            type IntoIter = core::slice::Iter<'a, $struct_type>;
79            #[inline]
80            fn into_iter(self) -> Self::IntoIter {
81                self.iter()
82            }
83        }
84
85        impl<'a> IntoIterator for &'a $struct_name {
86            type Item = &'a $struct_type;
87            type IntoIter = core::slice::Iter<'a, $struct_type>;
88            #[inline]
89            fn into_iter(self) -> Self::IntoIter {
90                self.iter()
91            }
92        }
93
94        #[repr(C)]
95        pub struct $struct_name {
96            ptr: *const $struct_type,
97            len: usize,
98            cap: usize,
99            destructor: $destructor_name,
100        }
101
102        #[derive(Debug, Copy, Clone)]
103        #[repr(C, u8)]
104        pub enum $destructor_name {
105            DefaultRust,
106            NoDestructor,
107            External($destructor_type_name),
108            /// Destructor was already run — prevents double-free.
109            /// Set by Drop impl after destruction.
110            AlreadyDestroyed,
111        }
112
113        unsafe impl Send for $struct_name {}
114        unsafe impl Sync for $struct_name {}
115
116        impl $struct_name {
117            #[inline]
118            #[must_use] pub const fn new() -> $struct_name {
119                // lets hope the optimizer catches this
120                Self::from_vec(alloc::vec::Vec::new())
121            }
122
123            #[inline]
124            #[must_use] pub fn with_capacity(cap: usize) -> Self {
125                Self::from_vec(alloc::vec::Vec::<$struct_type>::with_capacity(cap))
126            }
127
128            #[inline]
129            #[must_use] pub const fn from_const_slice(input: &'static [$struct_type]) -> Self {
130                Self {
131                    ptr: input.as_ptr(),
132                    len: input.len(),
133                    cap: input.len(),
134                    destructor: $destructor_name::NoDestructor, // because of &'static
135                }
136            }
137
138            #[inline]
139            #[must_use] pub const fn from_vec(input: alloc::vec::Vec<$struct_type>) -> Self {
140                let ptr = input.as_ptr();
141                let len = input.len();
142                let cap = input.capacity();
143
144                let _ = ::core::mem::ManuallyDrop::new(input);
145
146                Self {
147                    ptr,
148                    len,
149                    cap,
150                    destructor: $destructor_name::DefaultRust,
151                }
152            }
153
154            #[inline]
155            pub fn iter(&self) -> core::slice::Iter<'_, $struct_type> {
156                self.as_ref().iter()
157            }
158
159            #[inline]
160            #[must_use] pub const fn len(&self) -> usize {
161                self.len
162            }
163
164            #[inline]
165            #[must_use] pub const fn capacity(&self) -> usize {
166                self.cap
167            }
168
169            #[inline]
170            #[must_use] pub const fn is_empty(&self) -> bool {
171                self.len == 0
172            }
173
174            /// Returns a reference to the element at the given index (Rust-only, inline).
175            #[inline]
176            #[must_use] pub fn get(&self, index: usize) -> Option<&$struct_type> {
177                self.as_ref().get(index)
178            }
179
180            /// C-API compatible get function. Returns a copy of the element at the given index.
181            /// Returns None if the index is out of bounds.
182            #[inline]
183            #[must_use] pub fn c_get(&self, index: usize) -> $option_type
184            where
185                $struct_type: Clone,
186            {
187                self.get(index).cloned().into()
188            }
189
190            #[allow(dead_code)]
191            #[inline]
192            unsafe fn get_unchecked(&self, index: usize) -> &$struct_type { unsafe {
193                self.as_ref().get_unchecked(index)
194            }}
195
196            /// Returns the vec as a Rust slice (Rust-only, not C-API compatible).
197            #[inline]
198            #[must_use] pub fn as_slice(&self) -> &[$struct_type] {
199                self.as_ref()
200            }
201
202            /// Returns a C-compatible slice of the entire Vec.
203            #[inline]
204            #[must_use] pub const fn as_c_slice(&self) -> $slice_name {
205                $slice_name {
206                    ptr: self.ptr,
207                    len: self.len,
208                }
209            }
210
211            /// Returns a C-compatible slice of a range within the Vec.
212            /// If the range is out of bounds, it is clamped to the valid range.
213            #[inline]
214            #[must_use] pub fn as_c_slice_range(&self, start: usize, end: usize) -> $slice_name {
215                let start = start.min(self.len);
216                let end = end.min(self.len).max(start);
217                let len = end - start;
218                if len == 0 || self.ptr.is_null() {
219                    $slice_name::empty()
220                } else {
221                    $slice_name {
222                        ptr: unsafe { self.ptr.add(start) },
223                        len,
224                    }
225                }
226            }
227
228            /// Returns a pointer to the Vec's data.
229            /// Use `len()` to get the number of elements.
230            #[inline]
231            #[must_use] pub const fn as_ptr(&self) -> *const $struct_type {
232                self.ptr
233            }
234        }
235
236        impl AsRef<[$struct_type]> for $struct_name {
237            fn as_ref(&self) -> &[$struct_type] {
238                if self.ptr.is_null() || self.len == 0 {
239                    &[]
240                } else {
241                    unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
242                }
243            }
244        }
245
246        impl Default for $struct_name {
247            fn default() -> Self {
248                Self::from_vec(alloc::vec::Vec::new())
249            }
250        }
251
252        impl core::iter::FromIterator<$struct_type> for $struct_name {
253            fn from_iter<T>(iter: T) -> Self
254            where
255                T: IntoIterator<Item = $struct_type>,
256            {
257                Self::from_vec(alloc::vec::Vec::from_iter(iter))
258            }
259        }
260
261        impl From<alloc::vec::Vec<$struct_type>> for $struct_name {
262            fn from(input: alloc::vec::Vec<$struct_type>) -> $struct_name {
263                $struct_name::from_vec(input)
264            }
265        }
266
267        impl From<&'static [$struct_type]> for $struct_name {
268            fn from(input: &'static [$struct_type]) -> $struct_name {
269                Self::from_const_slice(input)
270            }
271        }
272
273        impl Drop for $struct_name {
274            fn drop(&mut self) {
275                match self.destructor {
276                    $destructor_name::DefaultRust => {
277                        // Defensive: a library-owned Vec only owns an allocation
278                        // when `ptr` is non-null and `cap != 0`. A zeroed / moved-
279                        // from FFI husk (e.g. a struct field a C++ wrapper move-
280                        // cleared, leaving destructor == DefaultRust [tag 0] with a
281                        // null ptr but a stale len) would otherwise hit
282                        // `Vec::from_raw_parts(null, len, _)` and deref 0x0 on drop.
283                        // Skip when there is nothing to free. (Empty Vecs have
284                        // cap == 0; valid non-empty Vecs are unaffected.)
285                        if !self.ptr.is_null() && self.cap != 0 {
286                            drop(unsafe {
287                                alloc::vec::Vec::from_raw_parts(
288                                    self.ptr.cast_mut(),
289                                    self.len,
290                                    self.cap,
291                                )
292                            });
293                        }
294                        self.destructor = $destructor_name::AlreadyDestroyed;
295                    }
296                    $destructor_name::External(f) => {
297                        f(self);
298                        self.destructor = $destructor_name::AlreadyDestroyed;
299                    }
300                    $destructor_name::NoDestructor | $destructor_name::AlreadyDestroyed => {}
301                }
302            }
303        }
304    };
305}
306
307/// Implement the `From` trait for any type.
308/// Example usage:
309/// ```no_run,ignore
310/// enum MyError<'a> {
311///     Bar(BarError<'a>),
312///     Foo(FooError<'a>)
313/// }
314///
315/// impl_from!(BarError<'a>, MyError::Bar);
316/// impl_from!(FooError<'a>, MyError::Foo);
317/// ```
318macro_rules! impl_from {
319    // From a type with a lifetime to a type which also has a lifetime
320    ($a:ident < $c:lifetime > , $b:ident:: $enum_type:ident) => {
321        impl<$c> From<$a<$c>> for $b<$c> {
322            fn from(e: $a<$c>) -> Self {
323                $b::$enum_type(e)
324            }
325        }
326    };
327
328    // (No "non-lifetime → lifetime-bearing target" arm: it can only generate
329    // `impl<'a> From<A> for B<'a>` where 'a is single-use, which trips
330    // single_use_lifetimes. Write those impls out by hand with `B<'_>` instead.)
331
332    // From a type without a lifetime to a type which also does not have a lifetime
333    ($a:ident, $b:ident:: $enum_type:ident) => {
334        impl From<$a> for $b {
335            fn from(e: $a) -> Self {
336                $b::$enum_type(e)
337            }
338        }
339    };
340}
341
342/// Implement `Display` for an enum.
343///
344/// Example usage:
345/// ```no_run,ignore
346/// enum Foo<'a> {
347///     Bar(&'a str),
348///     Baz(i32)
349/// }
350///
351/// impl_display!{ Foo<'a>, {
352///     Bar(s) => s,
353///     Baz(i) => format!("{}", i)
354/// }}
355/// ```
356#[macro_export]
357macro_rules! impl_display {
358    // For a type with a lifetime
359    ($enum:ident<$lt:lifetime>, {$($variant:pat => $fmt_string:expr),+$(,)* }) => {
360
361        impl ::core::fmt::Display for $enum<'_> {
362            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
363                use self::$enum::*;
364                match &self {
365                    $(
366                        $variant => write!(f, "{}", $fmt_string),
367                    )+
368                }
369            }
370        }
371
372    };
373
374    // For a type without a lifetime
375    ($enum:ident, {$($variant:pat => $fmt_string:expr),+$(,)* }) => {
376
377        impl ::core::fmt::Display for $enum {
378            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
379                use self::$enum::*;
380                match &self {
381                    $(
382                        $variant => write!(f, "{}", $fmt_string),
383                    )+
384                }
385            }
386        }
387
388    };
389}
390
391/// Implements `Debug` to use `Display` instead - assumes the that the type has implemented
392/// `Display`
393#[macro_export]
394macro_rules! impl_debug_as_display {
395    // For a type with a lifetime
396    ($enum:ident < $lt:lifetime >) => {
397        impl ::core::fmt::Debug for $enum<'_> {
398            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
399                write!(f, "{}", self)
400            }
401        }
402    };
403
404    // For a type without a lifetime
405    ($enum:ident) => {
406        impl ::core::fmt::Debug for $enum {
407            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
408                write!(f, "{}", self)
409            }
410        }
411    };
412}
413
414#[macro_export]
415macro_rules! impl_vec_as_hashmap {
416    ($struct_type:ident, $struct_name:ident) => {
417        impl $struct_name {
418            pub fn insert_hm_item(&mut self, item: $struct_type) {
419                if !self.contains_hm_item(&item) {
420                    self.push(item);
421                }
422            }
423
424            pub fn remove_hm_item(&mut self, remove_key: &$struct_type) {
425                *self = Self::from_vec(
426                    self.as_ref()
427                        .iter()
428                        .filter_map(|r| if *r == *remove_key { None } else { Some(*r) })
429                        .collect::<Vec<_>>(),
430                );
431            }
432
433            pub fn contains_hm_item(&self, searched: &$struct_type) -> bool {
434                self.as_ref().iter().any(|i| i == searched)
435            }
436        }
437    };
438}
439
440/// NOTE: `impl_vec_mut` can only exist for vectors that are known to be library-allocated!
441#[macro_export]
442macro_rules! impl_vec_mut {
443    ($struct_type:ident, $struct_name:ident) => {
444        impl<'a> IntoIterator for &'a mut $struct_name {
445            type Item = &'a mut $struct_type;
446            type IntoIter = core::slice::IterMut<'a, $struct_type>;
447            #[inline]
448            fn into_iter(self) -> Self::IntoIter {
449                self.iter_mut()
450            }
451        }
452
453        impl AsMut<[$struct_type]> for $struct_name {
454            fn as_mut(&mut self) -> &mut [$struct_type] {
455                unsafe { core::slice::from_raw_parts_mut(self.ptr.cast_mut(), self.len) }
456            }
457        }
458
459        impl From<$struct_name> for alloc::vec::Vec<$struct_type> {
460            #[allow(unused_mut)]
461            fn from(mut input: $struct_name) -> alloc::vec::Vec<$struct_type> {
462                input.into_library_owned_vec()
463            }
464        }
465
466        impl core::iter::Extend<$struct_type> for $struct_name {
467            fn extend<T: core::iter::IntoIterator<Item = $struct_type>>(&mut self, iter: T) {
468                for elem in iter {
469                    self.push(elem);
470                }
471            }
472        }
473
474        impl $struct_name {
475            #[inline]
476            pub const fn as_mut_ptr(&mut self) -> *mut $struct_type {
477                self.ptr.cast_mut()
478            }
479
480            #[inline]
481            pub fn sort_by<F: FnMut(&$struct_type, &$struct_type) -> core::cmp::Ordering>(
482                &mut self,
483                compare: F,
484            ) {
485                self.as_mut().sort_by(compare);
486            }
487
488            #[inline]
489            pub fn push(&mut self, value: $struct_type) {
490                // code is copied from the rust stdlib, since it's not possible to
491                // create a temporary Vec here. Doing that would create two
492                if self.len == self.capacity() {
493                    self.buf_reserve(self.len, 1);
494                }
495                unsafe {
496                    let end = self.as_mut_ptr().add(self.len);
497                    core::ptr::write(end, value);
498                    self.len += 1;
499                }
500            }
501
502            pub fn insert(&mut self, index: usize, element: $struct_type) {
503                let len = self.len();
504                if index > len {
505                    return;
506                }
507
508                // space for the new element
509                if len == self.capacity() {
510                    self.reserve(1);
511                }
512
513                unsafe {
514                    // infallible
515                    // The spot to put the new value
516                    {
517                        let p = self.as_mut_ptr().add(index);
518                        // Shift everything over to make space. (Duplicating the
519                        // `index`th element into two consecutive places.)
520                        core::ptr::copy(p, p.offset(1), len - index);
521                        // Write it in, overwriting the first copy of the `index`th
522                        // element.
523                        core::ptr::write(p, element);
524                    }
525                    self.set_len(len + 1);
526                }
527            }
528
529            pub fn remove(&mut self, index: usize) {
530                let len = self.len();
531                if index >= len {
532                    return;
533                }
534
535                unsafe {
536                    // infallible
537                    let ret;
538                    {
539                        // the place we are taking from.
540                        let ptr = self.as_mut_ptr().add(index);
541                        // copy it out, unsafely having a copy of the value on
542                        // the stack and in the vector at the same time.
543                        ret = core::ptr::read(ptr);
544
545                        // Shift everything down to fill in that spot.
546                        core::ptr::copy(ptr.offset(1), ptr, len - index - 1);
547                    }
548                    self.set_len(len - 1);
549                    // Named binding (not `let _ =` / `drop()`): this macro is
550                    // generic over the element type, so a bare drop trips
551                    // dropping_copy_types for Copy elements while `let _ =` trips
552                    // let_underscore_drop for ones with a destructor. A named
553                    // unused binding drops at scope end and satisfies both.
554                    let _ret = ret;
555                }
556            }
557
558            #[inline]
559            pub const fn pop(&mut self) -> Option<$struct_type> {
560                if self.len == 0 {
561                    None
562                } else {
563                    unsafe {
564                        self.len -= 1;
565                        Some(core::ptr::read(self.ptr.add(self.len())))
566                    }
567                }
568            }
569
570            #[inline]
571            pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, $struct_type> {
572                self.as_mut().iter_mut()
573            }
574
575            #[inline]
576            #[must_use] pub fn into_iter(self) -> alloc::vec::IntoIter<$struct_type> {
577                let v1: alloc::vec::Vec<$struct_type> = self.into();
578                v1.into_iter()
579            }
580
581            #[inline]
582            fn amortized_new_size(
583                &self,
584                used_cap: usize,
585                needed_extra_cap: usize,
586            ) -> Result<usize, bool> {
587                // Nothing we can really do about these checks :(
588                let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(true)?;
589                // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
590                let double_cap = self.cap * 2;
591                // `double_cap` guarantees exponential growth.
592                Ok(core::cmp::max(double_cap, required_cap))
593            }
594
595            #[inline]
596            const fn current_layout(&self) -> Option<core::alloc::Layout> {
597                if self.cap == 0 {
598                    None
599                } else {
600                    // We have an allocated chunk of memory, so we can bypass runtime
601                    // checks to get our current layout.
602                    unsafe {
603                        let align = core::mem::align_of::<$struct_type>();
604                        let size = core::mem::size_of::<$struct_type>() * self.cap;
605                        Some(core::alloc::Layout::from_size_align_unchecked(size, align))
606                    }
607                }
608            }
609
610            #[inline]
611            const fn alloc_guard(alloc_size: usize) -> Result<(), bool> {
612                if core::mem::size_of::<usize>() < 8 && alloc_size > ::core::isize::MAX as usize {
613                    Err(true)
614                } else {
615                    Ok(())
616                }
617            }
618
619            #[inline]
620            // the reallocated pointer comes from the global allocator with a Layout
621            // computed for `$struct_type`, so it is correctly aligned for the cast.
622            #[allow(clippy::cast_ptr_alignment)]
623            fn try_reserve(
624                &mut self,
625                used_cap: usize,
626                needed_extra_cap: usize,
627            ) -> Result<(), bool> {
628                // NOTE: we don't early branch on ZSTs here because we want this
629                // to actually catch "asking for more than usize::MAX" in that case.
630                // If we make it past the first branch then we are guaranteed to
631                // panic.
632
633                // Don't actually need any more capacity.
634                // Wrapping in case they give a bad `used_cap`
635                if self.capacity().wrapping_sub(used_cap) >= needed_extra_cap {
636                    return Ok(());
637                }
638
639                let new_cap = self.amortized_new_size(used_cap, needed_extra_cap)?;
640                let new_layout =
641                    alloc::alloc::Layout::array::<$struct_type>(new_cap).map_err(|_| true)?;
642
643                $struct_name::alloc_guard(new_layout.size())?;
644
645                let res = unsafe {
646                    match self.current_layout() {
647                        Some(layout) => {
648                            alloc::alloc::realloc(self.ptr.cast::<u8>().cast_mut(), layout, new_layout.size())
649                        }
650                        None => alloc::alloc::alloc(new_layout),
651                    }
652                };
653
654                if res.is_null() {
655                    return Err(false);
656                }
657
658                self.ptr = res as *mut $struct_type;
659                self.cap = new_cap;
660
661                Ok(())
662            }
663
664            fn buf_reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
665                match self.try_reserve(used_cap, needed_extra_cap) {
666                    Err(true /* Overflow */) => {
667                        panic!("memory allocation failed: overflow");
668                    }
669                    Err(false /* AllocError(_) */) => {
670                        panic!("memory allocation failed: error allocating new memory");
671                    }
672                    Ok(()) => { /* yay */ }
673                }
674            }
675
676            pub fn append(&mut self, other: &mut Self) {
677                unsafe {
678                    self.append_elements(core::ptr::from_ref(other.as_slice()));
679                    other.set_len(0);
680                }
681            }
682
683            unsafe fn set_len(&mut self, new_len: usize) {
684                debug_assert!(new_len <= self.capacity());
685                self.len = new_len;
686            }
687
688            pub fn reserve(&mut self, additional: usize) {
689                self.buf_reserve(self.len, additional);
690            }
691
692            /// Appends elements to `Self` from other buffer.
693            #[inline]
694            unsafe fn append_elements(&mut self, other: *const [$struct_type]) { unsafe {
695                let count = (&(*other)).len();
696                self.reserve(count);
697                let len = self.len();
698                core::ptr::copy_nonoverlapping(
699                    other as *const $struct_type,
700                    self.as_mut_ptr().add(len),
701                    count,
702                );
703                self.len += count;
704            }}
705
706            pub fn truncate(&mut self, len: usize) {
707                // This is safe because:
708                //
709                // * the slice passed to `drop_in_place` is valid; the `len > self.len` case avoids
710                //   creating an invalid slice, and
711                // * the `len` of the vector is shrunk before calling `drop_in_place`, such that no
712                //   value will be dropped twice in case `drop_in_place` were to panic once (if it
713                //   panics twice, the program aborts).
714                unsafe {
715                    if len > self.len {
716                        return;
717                    }
718                    let remaining_len = self.len - len;
719                    let s = core::ptr::slice_from_raw_parts_mut(
720                        self.as_mut_ptr().add(len),
721                        remaining_len,
722                    );
723                    self.len = len;
724                    core::ptr::drop_in_place(s);
725                }
726            }
727
728            pub fn retain<F>(&mut self, mut f: F)
729            where
730                F: FnMut(&$struct_type) -> bool,
731            {
732                let len = self.len();
733                let mut del = 0;
734
735                {
736                    for i in 0..len {
737                        if unsafe { !f(self.get_unchecked(i)) } {
738                            del += 1;
739                        } else if del > 0 {
740                            self.as_mut().swap(i - del, i);
741                        }
742                    }
743                }
744
745                if del > 0 {
746                    self.truncate(len - del);
747                }
748            }
749        }
750    };
751}
752
753#[macro_export]
754macro_rules! impl_vec_debug {
755    ($struct_type:ident, $struct_name:ident) => {
756        impl core::fmt::Debug for $struct_name {
757            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
758                self.as_ref().fmt(f)
759            }
760        }
761    };
762}
763
764#[macro_export]
765macro_rules! impl_vec_partialord {
766    ($struct_type:ident, $struct_name:ident) => {
767        impl PartialOrd for $struct_name {
768            fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
769                self.as_ref().partial_cmp(rhs.as_ref())
770            }
771        }
772    };
773}
774
775#[macro_export]
776macro_rules! impl_vec_ord {
777    ($struct_type:ident, $struct_name:ident) => {
778        impl Ord for $struct_name {
779            fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
780                self.as_ref().cmp(rhs.as_ref())
781            }
782        }
783    };
784}
785
786#[macro_export]
787macro_rules! impl_vec_clone {
788    ($struct_type:ident, $struct_name:ident, $destructor_name:ident) => {
789        impl $struct_name {
790            // Creates a `Vec` from a `Cow<'static, [T]>` - useful to avoid allocating in the case
791            // of &'static memory
792            #[inline]
793            #[must_use] pub fn from_copy_on_write(
794                input: alloc::borrow::Cow<'static, [$struct_type]>,
795            ) -> $struct_name {
796                match input {
797                    alloc::borrow::Cow::Borrowed(static_array) => {
798                        Self::from_const_slice(static_array)
799                    }
800                    alloc::borrow::Cow::Owned(owned_vec) => Self::from_vec(owned_vec),
801                }
802            }
803
804            /// Creates a Vec containing a single element
805            #[inline]
806            #[must_use] pub fn from_item(item: $struct_type) -> Self {
807                Self::from_vec(alloc::vec![item])
808            }
809
810            /// Copies elements from a C array pointer into a new Vec.
811            /// 
812            /// # Safety
813            /// - `ptr` must be valid for reading `len` elements
814            /// - The memory must be properly aligned for `$struct_type`
815            /// - The elements are cloned, so `$struct_type` must implement `Clone`
816            #[inline]
817            #[must_use] pub unsafe fn copy_from_ptr(ptr: *const $struct_type, len: usize) -> Self { unsafe {
818                if ptr.is_null() || len == 0 {
819                    return Self::new();
820                }
821                let slice = core::slice::from_raw_parts(ptr, len);
822                Self::from_vec(slice.to_vec())
823            }}
824
825            /// NOTE: CLONES the memory if the memory is external or &'static
826            /// Moves the memory out if the memory is library-allocated
827            #[inline]
828            #[must_use] pub fn clone_self(&self) -> Self {
829                match self.destructor {
830                    $destructor_name::NoDestructor | $destructor_name::AlreadyDestroyed => Self {
831                        ptr: self.ptr,
832                        len: self.len,
833                        cap: self.cap,
834                        destructor: $destructor_name::NoDestructor,
835                    },
836                    $destructor_name::External(_) | $destructor_name::DefaultRust => {
837                        Self::from_vec(self.as_ref().to_vec())
838                    }
839                }
840            }
841
842            /// NOTE: CLONES the memory if the memory is external or &'static
843            /// Moves the memory out if the memory is library-allocated
844            #[inline]
845            #[must_use] pub fn into_library_owned_vec(self) -> alloc::vec::Vec<$struct_type> {
846                match self.destructor {
847                    $destructor_name::NoDestructor | $destructor_name::External(_) | $destructor_name::AlreadyDestroyed => {
848                        self.as_ref().to_vec()
849                    }
850                    $destructor_name::DefaultRust => {
851                        let v = unsafe {
852                            alloc::vec::Vec::from_raw_parts(
853                                self.ptr.cast_mut(),
854                                self.len,
855                                self.cap,
856                            )
857                        };
858                        core::mem::forget(self);
859                        v
860                    }
861                }
862            }
863        }
864        impl Clone for $struct_name {
865            fn clone(&self) -> Self {
866                self.clone_self()
867            }
868        }
869    };
870}
871
872#[macro_export]
873macro_rules! impl_vec_partialeq {
874    ($struct_type:ident, $struct_name:ident) => {
875        impl PartialEq for $struct_name {
876            fn eq(&self, rhs: &Self) -> bool {
877                self.as_ref().eq(rhs.as_ref())
878            }
879        }
880    };
881}
882
883#[macro_export]
884macro_rules! impl_vec_eq {
885    ($struct_type:ident, $struct_name:ident) => {
886        impl Eq for $struct_name {}
887    };
888}
889
890#[macro_export]
891macro_rules! impl_vec_hash {
892    ($struct_type:ident, $struct_name:ident) => {
893        impl core::hash::Hash for $struct_name {
894            fn hash<H>(&self, state: &mut H)
895            where
896                H: core::hash::Hasher,
897            {
898                self.as_ref().hash(state);
899            }
900        }
901    };
902}
903
904#[macro_export]
905macro_rules! impl_option_inner {
906    ($struct_type:ident, $struct_name:ident) => {
907        impl From<$struct_name> for Option<$struct_type> {
908            fn from(o: $struct_name) -> Option<$struct_type> {
909                match o {
910                    $struct_name::None => None,
911                    $struct_name::Some(t) => Some(t),
912                }
913            }
914        }
915
916        impl From<Option<$struct_type>> for $struct_name {
917            fn from(o: Option<$struct_type>) -> $struct_name {
918                match o {
919                    None => $struct_name::None,
920                    Some(t) => $struct_name::Some(t),
921                }
922            }
923        }
924
925        impl Default for $struct_name {
926            fn default() -> $struct_name {
927                $struct_name::None
928            }
929        }
930
931        impl $struct_name {
932            #[must_use] pub const fn as_option(&self) -> Option<&$struct_type> {
933                match self {
934                    $struct_name::None => None,
935                    $struct_name::Some(t) => Some(t),
936                }
937            }
938            // Returns the PREVIOUS value (mem::replace semantics); callers may discard it,
939            // so #[must_use] would be wrong here.
940            #[allow(clippy::return_self_not_must_use)]
941            pub const fn replace(&mut self, value: $struct_type) -> $struct_name {
942                ::core::mem::replace(self, $struct_name::Some(value))
943            }
944            #[must_use] pub const fn is_some(&self) -> bool {
945                match self {
946                    $struct_name::None => false,
947                    $struct_name::Some(_) => true,
948                }
949            }
950            #[must_use] pub const fn is_none(&self) -> bool {
951                !self.is_some()
952            }
953            #[must_use] pub const fn as_ref(&self) -> Option<&$struct_type> {
954                match *self {
955                    $struct_name::Some(ref x) => Some(x),
956                    $struct_name::None => None,
957                }
958            }
959            pub const fn as_mut(&mut self) -> Option<&mut $struct_type> {
960                match self {
961                    $struct_name::Some(x) => Some(x),
962                    $struct_name::None => None,
963                }
964            }
965            pub fn map<U, F: FnOnce($struct_type) -> U>(self, f: F) -> Option<U> {
966                match self {
967                    $struct_name::Some(x) => Some(f(x)),
968                    $struct_name::None => None,
969                }
970            }
971            pub fn and_then<U, F>(self, f: F) -> Option<U>
972            where
973                F: FnOnce($struct_type) -> Option<U>,
974            {
975                match self {
976                    $struct_name::None => None,
977                    $struct_name::Some(x) => f(x),
978                }
979            }
980        }
981    };
982}
983
984#[macro_export]
985macro_rules! impl_option {
986    ($struct_type:ident, $struct_name:ident, copy = false, clone = false, [$($derive:meta),* ]) => (
987        $(#[derive($derive)])*
988        #[repr(C, u8)]
989        pub enum $struct_name {
990            None,
991            Some($struct_type)
992        }
993
994        impl $struct_name {
995            pub fn into_option(self) -> Option<$struct_type> {
996                match self {
997                    $struct_name::None => None,
998                    $struct_name::Some(t) => Some(t),
999                }
1000            }
1001        }
1002
1003        impl_option_inner!($struct_type, $struct_name);
1004    );
1005    ($struct_type:ident, $struct_name:ident, copy = false, [$($derive:meta),* ]) => (
1006        $(#[derive($derive)])*
1007        #[repr(C, u8)]
1008        // This arm (copy = false) deliberately does NOT derive Copy so the
1009        // wrapper can hold non-Copy payloads; missing_copy_implementations is a
1010        // false positive for the Copy-payload instantiations routed through here.
1011        #[allow(missing_copy_implementations, variant_size_differences)]
1012        pub enum $struct_name {
1013            None,
1014            Some($struct_type)
1015        }
1016
1017        impl $struct_name {
1018            #[must_use] pub fn into_option(&self) -> Option<$struct_type> {
1019                match self {
1020                    $struct_name::None => None,
1021                    $struct_name::Some(t) => Some(t.clone()),
1022                }
1023            }
1024        }
1025
1026        impl_option_inner!($struct_type, $struct_name);
1027    );
1028    ($struct_type:ident, $struct_name:ident, [$($derive:meta),* ]) => (
1029        $(#[derive($derive)])*
1030        #[repr(C, u8)]
1031        // This (default) arm does NOT derive Copy so the wrapper can hold
1032        // non-Copy payloads; missing_copy_implementations is a false positive
1033        // for the Copy-payload instantiations routed through here.
1034        #[allow(missing_copy_implementations, variant_size_differences)]
1035        pub enum $struct_name {
1036            None,
1037            Some($struct_type)
1038        }
1039
1040        impl $struct_name {
1041            #[must_use] pub fn into_option(&self) -> Option<$struct_type> {
1042                match self {
1043                    $struct_name::None => None,
1044                    $struct_name::Some(t) => Some(t.clone()),
1045                }
1046            }
1047        }
1048
1049        impl_option_inner!($struct_type, $struct_name);
1050    );
1051}
1052
1053#[macro_export]
1054macro_rules! impl_result_inner {
1055    ($ok_struct_type:ident, $err_struct_type:ident, $struct_name:ident) => {
1056        impl From<$struct_name> for Result<$ok_struct_type, $err_struct_type> {
1057            fn from(o: $struct_name) -> Result<$ok_struct_type, $err_struct_type> {
1058                match o {
1059                    $struct_name::Ok(o) => Ok(o),
1060                    $struct_name::Err(e) => Err(e),
1061                }
1062            }
1063        }
1064
1065        impl From<Result<$ok_struct_type, $err_struct_type>> for $struct_name {
1066            fn from(o: Result<$ok_struct_type, $err_struct_type>) -> $struct_name {
1067                match o {
1068                    Ok(o) => $struct_name::Ok(o),
1069                    Err(e) => $struct_name::Err(e),
1070                }
1071            }
1072        }
1073
1074        impl $struct_name {
1075            pub fn as_result(&self) -> Result<&$ok_struct_type, &$err_struct_type> {
1076                match self {
1077                    $struct_name::Ok(o) => Ok(o),
1078                    $struct_name::Err(e) => Err(e),
1079                }
1080            }
1081            pub fn is_ok(&self) -> bool {
1082                match self {
1083                    $struct_name::Ok(_) => true,
1084                    $struct_name::Err(_) => false,
1085                }
1086            }
1087            pub fn is_err(&self) -> bool {
1088                !self.is_ok()
1089            }
1090        }
1091    };
1092}
1093
1094#[macro_export]
1095macro_rules! impl_result {
1096    ($ok_struct_type:ident, $err_struct_type:ident, $struct_name:ident, copy = false, clone = false, [$($derive:meta),* ]) => (
1097        $(#[derive($derive)])*
1098        #[repr(C, u8)]
1099        pub enum $struct_name {
1100            Ok($ok_struct_type),
1101            Err($err_struct_type)
1102        }
1103
1104        impl $struct_name {
1105            pub fn into_result(self) -> Result<$ok_struct_type, $err_struct_type> {
1106                match self {
1107                    $struct_name::Ok(o) => Ok(o),
1108                    $struct_name::Err(e) => Err(e),
1109                }
1110            }
1111        }
1112
1113        impl_result_inner!($ok_struct_type, $err_struct_type, $struct_name);
1114    );
1115    ($ok_struct_type:ident, $err_struct_type:ident, $struct_name:ident, copy = false, [$($derive:meta),* ]) => (
1116        $(#[derive($derive)])*
1117        #[repr(C, u8)]
1118        pub enum $struct_name {
1119            Ok($ok_struct_type),
1120            Err($err_struct_type)
1121        }
1122        impl $struct_name {
1123            pub fn into_result(&self) -> Result<$ok_struct_type, $err_struct_type> {
1124                match self {
1125                    $struct_name::Ok(o) => Ok(o.clone()),
1126                    $struct_name::Err(e) => Err(e.clone()),
1127                }
1128            }
1129        }
1130
1131        impl_result_inner!($ok_struct_type, $err_struct_type, $struct_name);
1132    );
1133    ($ok_struct_type:ident, $err_struct_type:ident,  $struct_name:ident, [$($derive:meta),* ]) => (
1134        $(#[derive($derive)])*
1135        #[repr(C, u8)]
1136        pub enum $struct_name {
1137            Ok($ok_struct_type),
1138            Err($err_struct_type)
1139        }
1140
1141        impl $struct_name {
1142            pub fn into_result(&self) -> Result<$ok_struct_type, $err_struct_type> {
1143                match self {
1144                    $struct_name::Ok(o) => Ok(*o),
1145                    $struct_name::Err(e) => Err(*e),
1146                }
1147            }
1148        }
1149
1150        impl_result_inner!($ok_struct_type, $err_struct_type, $struct_name);
1151    );
1152}
1153
1154macro_rules! impl_color_value_fmt {
1155    ($struct_name:ty) => {
1156        impl FormatAsRustCode for $struct_name {
1157            fn format_as_rust_code(&self, _tabs: usize) -> String {
1158                format!(
1159                    "{} {{ inner: {} }}",
1160                    stringify!($struct_name),
1161                    format_color_value(&self.inner)
1162                )
1163            }
1164        }
1165    };
1166}
1167
1168macro_rules! impl_enum_fmt {($enum_name:ident, $($enum_type:ident),+) => (
1169    impl crate::codegen::format::FormatAsRustCode for $enum_name {
1170        fn format_as_rust_code(&self, _tabs: usize) -> String {
1171            match self {
1172                $(
1173                    $enum_name::$enum_type => {
1174                        String::from(
1175                            concat!(stringify!($enum_name), "::", stringify!($enum_type))
1176                        )
1177                    },
1178                )+
1179            }
1180        }
1181    }
1182)}