1
#![forbid(unsafe_code)]
2

            
3
use std::collections::VecDeque;
4

            
5
use merc_collections::IndexedSet;
6

            
7
use crate::SymbolRef;
8
use crate::aterm::ATermRef;
9
use crate::storage::GcMutex;
10
use crate::storage::Marker;
11

            
12
/// This trait should be used on all objects and containers related to storing unprotected terms, or unprotected symbols.
13
///
14
/// The implementation should mark all contained [ATermRef] and [SymbolRef] values that must be
15
/// kept alive using the provided [Marker].
16
pub trait Markable {
17
    /// Marks all contained [ATermRef] values with the given [Marker] to prevent garbage collection.
18
    fn mark(&self, marker: &mut Marker);
19

            
20
    /// Should return true iff the given [ATermRef] is contained in the object. Used for runtime checks.
21
    fn contains_term(&self, term: &ATermRef<'_>) -> bool;
22

            
23
    /// Should return true iff the given [SymbolRef] is contained in the object. Used for runtime checks.
24
    fn contains_symbol(&self, symbol: &SymbolRef<'_>) -> bool;
25

            
26
    /// Returns the number of terms in the instance, used to delay garbage collection.
27
    fn len(&self) -> usize;
28

            
29
    /// Returns true iff the container is empty.
30
    fn is_empty(&self) -> bool {
31
        self.len() == 0
32
    }
33
}
34

            
35
impl<T: Markable> Markable for Vec<T> {
36
1305768
    fn mark(&self, marker: &mut Marker) {
37
3664017
        for value in self {
38
3663617
            value.mark(marker);
39
3663617
        }
40
1305768
    }
41

            
42
26592719
    fn contains_term(&self, term: &ATermRef<'_>) -> bool {
43
925246843
        self.iter().any(|v| v.contains_term(term))
44
26592719
    }
45

            
46
6266
    fn contains_symbol(&self, symbol: &SymbolRef<'_>) -> bool {
47
224321
        self.iter().any(|v| v.contains_symbol(symbol))
48
6266
    }
49

            
50
    fn len(&self) -> usize {
51
        self.len()
52
    }
53
}
54

            
55
impl<T: Markable> Markable for VecDeque<T> {
56
    fn mark(&self, marker: &mut Marker) {
57
        for value in self {
58
            value.mark(marker);
59
        }
60
    }
61

            
62
    fn contains_term(&self, term: &ATermRef<'_>) -> bool {
63
        self.iter().any(|v| v.contains_term(term))
64
    }
65

            
66
    fn contains_symbol(&self, symbol: &SymbolRef<'_>) -> bool {
67
        self.iter().any(|v| v.contains_symbol(symbol))
68
    }
69

            
70
    fn len(&self) -> usize {
71
        self.len()
72
    }
73
}
74

            
75
impl<T: Markable> Markable for GcMutex<T> {
76
1328539
    fn mark(&self, marker: &mut Marker) {
77
1328539
        self.lock().mark(marker);
78
1328539
    }
79

            
80
    fn contains_term(&self, term: &ATermRef<'_>) -> bool {
81
        self.lock().contains_term(term)
82
    }
83

            
84
    fn contains_symbol(&self, symbol: &SymbolRef<'_>) -> bool {
85
        self.lock().contains_symbol(symbol)
86
    }
87

            
88
    fn len(&self) -> usize {
89
        self.lock().len()
90
    }
91
}
92

            
93
impl<T: Markable> Markable for IndexedSet<T> {
94
22771
    fn mark(&self, marker: &mut Marker) {
95
291746
        for (_, value) in self.iter() {
96
291346
            value.mark(marker);
97
291346
        }
98
22771
    }
99

            
100
    fn contains_term(&self, term: &ATermRef<'_>) -> bool {
101
        self.iter().any(|(_, v)| v.contains_term(term))
102
    }
103

            
104
    fn contains_symbol(&self, symbol: &SymbolRef<'_>) -> bool {
105
        self.iter().any(|(_, v)| v.contains_symbol(symbol))
106
    }
107

            
108
    fn len(&self) -> usize {
109
        self.len()
110
    }
111
}
112

            
113
impl<T: Markable> Markable for Option<T> {
114
11989
    fn mark(&self, marker: &mut Marker) {
115
11989
        if let Some(value) = self {
116
7118
            value.mark(marker);
117
7118
        }
118
11989
    }
119

            
120
551076408
    fn contains_term(&self, term: &ATermRef<'_>) -> bool {
121
551076408
        if let Some(value) = self {
122
333966635
            value.contains_term(term)
123
        } else {
124
217109773
            false
125
        }
126
551076408
    }
127

            
128
    fn contains_symbol(&self, symbol: &SymbolRef<'_>) -> bool {
129
        if let Some(value) = self {
130
            value.contains_symbol(symbol)
131
        } else {
132
            false
133
        }
134
    }
135

            
136
    fn len(&self) -> usize {
137
        if let Some(value) = self { value.len() } else { 0 }
138
    }
139
}
140

            
141
// In Rust Its not yet possible to implement it for any tuples, so we implement it for some common sizes.
142
impl<T1: Markable, T2: Markable> Markable for (T1, T2) {
143
    fn mark(&self, marker: &mut Marker) {
144
        self.0.mark(marker);
145
        self.1.mark(marker);
146
    }
147

            
148
    fn contains_term(&self, term: &ATermRef<'_>) -> bool {
149
        self.0.contains_term(term) || self.1.contains_term(term)
150
    }
151

            
152
    fn contains_symbol(&self, symbol: &SymbolRef<'_>) -> bool {
153
        self.0.contains_symbol(symbol) || self.1.contains_symbol(symbol)
154
    }
155

            
156
    fn len(&self) -> usize {
157
        self.0.len() + self.1.len()
158
    }
159
}
160

            
161
impl Markable for bool {
162
    fn mark(&self, _marker: &mut Marker) {
163
        // Nothing to mark
164
    }
165

            
166
    fn contains_term(&self, _term: &ATermRef<'_>) -> bool {
167
        false
168
    }
169

            
170
    fn contains_symbol(&self, _symbol: &SymbolRef<'_>) -> bool {
171
        false
172
    }
173

            
174
    fn len(&self) -> usize {
175
        0
176
    }
177
}