Skip to main content

helpers/
macros.rs

1//! Macros for this workspace.
2
3/// Allow merging two objects of the same type into one.
4pub trait Mergeable {
5    /// Merge `other` into `self`, with `other` taking precedence.
6    fn merge(&mut self, other: Self);
7
8    /// Merge `other` into `self`, with `self` taking precedence.
9    fn merge_weak(&mut self, other: Self);
10}
11
12impl<T> Mergeable for Option<T> {
13    fn merge(&mut self, other: Self) {
14        if other.is_some() {
15            *self = other;
16        }
17    }
18
19    fn merge_weak(&mut self, other: Self) {
20        if self.is_none() {
21            *self = other;
22        }
23    }
24}
25
26impl Mergeable for bool {
27    fn merge(&mut self, other: Self) {
28        *self |= other;
29    }
30
31    fn merge_weak(&mut self, other: Self) {
32        *self |= other;
33    }
34}
35
36impl<T> Mergeable for Vec<T> {
37    /// Append `other` to `self`, in this order.
38    ///
39    /// Ordering is influenced by the local desire to have prompts with higher precedence later.
40    fn merge(&mut self, mut other: Self) {
41        self.append(&mut other);
42    }
43
44    /// Append `self` to `other`, in this order, putting the result into `self`.
45    ///
46    /// Ordering is influenced by the local desire to have prompts with higher precedence later.
47    fn merge_weak(&mut self, mut other: Self) {
48        other.append(self);
49        *self = other;
50    }
51}
52
53/// Derive the `Mergeable` trait for structs composed entirely of `Mergeable` fields.
54#[macro_export]
55macro_rules! derive_merge {
56    (
57        $(#[$attr:meta])*
58        $vis:vis struct $struct_name:ident {
59            $(
60                $(#[$field_attr:meta])*
61                $field_id:ident: $field_type:ty,
62            )+
63        }
64    ) => {
65        $(#[$attr])*
66        $vis struct $struct_name {
67            $(
68                $(#[$field_attr])*
69                $field_id: $field_type,
70            )+
71        }
72
73        impl $crate::macros::Mergeable for $struct_name {
74            fn merge(&mut self, other: Self) {
75                $(self.$field_id.merge(other.$field_id);)+
76            }
77
78            fn merge_weak(&mut self, other: Self) {
79                $(self.$field_id.merge_weak(other.$field_id);)+
80            }
81        }
82    };
83}
84
85pub use derive_merge;