1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use std::collections::BTreeMap;
use std::collections::btree_map;
use std::marker::{PhantomData, Sized};
pub trait MergeOverride: Clone + Sized {
fn merge_override(&self, ovr: &Self) -> Self {
ovr.to_owned()
}
}
macro_rules! assert_merge {
($ty:ty, $value1:expr, $value2:expr, $expected: expr) => {
assert_eq!(($value1 as $ty).merge_override(&($value2 as $ty)),
($expected as $ty));
}
}
impl MergeOverride for u16 {}
impl MergeOverride for u32 {}
impl MergeOverride for bool {}
impl MergeOverride for String {}
impl<T> MergeOverride for PhantomData<T> {}
#[test]
#[allow(trivial_numeric_casts)]
fn simple_types_are_replaced() {
assert_merge!(u16, 1, 2, 2);
assert_merge!(bool, false, true, true);
assert_merge!(String, "s1".to_owned(), "s2".to_owned(), "s2".to_owned());
}
impl<T: MergeOverride> MergeOverride for Option<T> {
fn merge_override(&self, ovr: &Self) -> Self {
match (self, ovr) {
(&Some(ref x), &Some(ref y)) => Some(x.merge_override(y)),
(&Some(ref x), &None) => Some(x.to_owned()),
(&None, &Some(ref y)) => Some(y.to_owned()),
(&None, &None) => None,
}
}
}
#[test]
fn option_uses_second_value_if_not_none() {
assert_merge!(Option<bool>, Some(false), Some(true), Some(true));
assert_merge!(Option<bool>, Some(false), None, Some(false));
assert_merge!(Option<bool>, None, Some(true), Some(true));
assert_merge!(Option<bool>, None, None, None);
assert_merge!(Option<Vec<bool>>,
Some(vec!(false)), Some(vec!(true)),
Some(vec!(false, true)));
}
impl<T: MergeOverride> MergeOverride for Vec<T> {
fn merge_override(&self, ovr: &Self) -> Self {
let mut result = self.clone();
result.extend_from_slice(ovr as &[T]);
result
}
}
#[test]
fn vec_appends_new_values() {
assert_merge!(Vec<bool>, vec!(false), vec!(true), vec!(false, true));
}
impl<K: Ord + Clone, T: MergeOverride> MergeOverride for BTreeMap<K, T> {
fn merge_override(&self, ovr: &Self) -> Self {
let mut result = self.clone();
for (ovr_key, ovr_val) in ovr {
match result.entry(ovr_key.to_owned()) {
btree_map::Entry::Vacant(vacant) => {
vacant.insert(ovr_val.clone());
}
btree_map::Entry::Occupied(mut occupied) => {
let merged = occupied.get().merge_override(ovr_val);
occupied.insert(merged);
}
}
}
result
}
}
#[test]
fn btree_map_merges_by_key() {
let mut map1 = BTreeMap::new();
map1.insert("a", vec!(false));
map1.insert("c", vec!(false));
let mut map2 = BTreeMap::new();
map2.insert("b", vec!(true));
map2.insert("c", vec!(true));
let mut expected = BTreeMap::new();
expected.insert("a", vec!(false));
expected.insert("b", vec!(true));
expected.insert("c", vec!(false, true));
assert_merge!(BTreeMap<&'static str, Vec<bool>>, map1, map2, expected);
}
macro_rules! derive_merge_override_for {
($ty:ident, { $( $field:ident ),+ }) => {
impl MergeOverride for $ty {
fn merge_override(&self, ovr: &Self) -> Self {
$ty {
$( $field: self.$field.merge_override(&ovr.$field) ),+
}
}
}
}
}