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