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