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
use crate::attributes::{Attribute, AttributeModifier, CompositeAttribute, FieldAttribute};
#[derive(Clone, Default)]
pub(crate) struct UnpackContext {
inherited: Vec<Attribute>,
}
impl UnpackContext {
pub fn modify_composite(&mut self, attributes: Vec<CompositeAttribute>) -> Vec<Attribute> {
let mut freeze = self.inherited.clone();
let current = attributes
.into_iter()
.filter_map(|ca| {
// handle standard attribute
let Some(modifier) = &ca.modifier else {
let a: Attribute = ca.into();
if freeze.contains(&a) {
panic!("already in the stack");
//todo: improve this error message
// already defined so do something
}
return Some(a);
};
// handle attribute with modifier
match modifier {
AttributeModifier::Star(_) => {
let a: Attribute = ca.into();
// already defined so lets error
if freeze.contains(&a) {
panic!("already in the stack (*)")
// todo: improve error msg
}
// add attribute to the downstream stack
self.inherited.push(a.clone());
// return the attribute
Some(a)
}
AttributeModifier::Slash(_) => {
let a: Attribute = ca.into();
// already defined so lets error
if !freeze.contains(&a) {
panic!("not in the stack, dont need to remove (/)");
}
// remove from the future
self.inherited.retain(|attr| attr != &a);
// remove from freeze
freeze.retain(|attr| attr != &a);
// remove it from the current
None
}
AttributeModifier::Minus(_) => {
let a: Attribute = ca.into();
// not in the stack so cant remove, lets error
if !freeze.contains(&a) {
panic!("not in the stack, dont need to remove (-)");
}
// don't remove it from the future
// remove from freeze
freeze.retain(|attr| attr != &a);
// remove it from the current
None
}
}
})
.collect();
[freeze, current].concat()
}
pub(crate) fn filter_field_nested(field_attributes: Vec<FieldAttribute>) -> (Vec<Attribute>, Vec<CompositeAttribute>) {
let mut field_applied_now = vec![];
let mut composite = vec![];
field_attributes.into_iter().for_each(|attr| {
match attr {
FieldAttribute::Field(fa) => field_applied_now.push(fa),
FieldAttribute::Nested(na) => composite.push(na.into())
}
});
(field_applied_now, composite)
}
}