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 symmbols.
13
///
14
/// The implementation should mark all contained aterms and symbols that must be kept alive using the provided `Marker`.
15
pub trait Markable {
16
    /// Marks all the ATermRefs to prevent them from being garbage collected.
17
    fn mark(&self, marker: &mut Marker);
18

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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