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