semver_store/
lib.rs

1mod node;
2
3pub struct SemverStore<T> {
4    tree: node::Node<T>,
5}
6
7impl<T> SemverStore<T> {
8    pub fn new() -> Self {
9        SemverStore {
10            tree: node::Node::new(0),
11        }
12    }
13
14    pub fn insert(&mut self, version: &String, store: T) {
15        let semver: Vec<&str> = version.split('.').collect();
16        let mut current_node = &mut self.tree;
17        for v in semver {
18            let version_number = v.parse::<u32>().unwrap();
19            let node = node::Node::new(version_number);
20            current_node = current_node.add_child(node);
21        }
22        current_node.set_store(store);
23    }
24
25    pub fn get(&mut self, version: &String) -> Option<&T> {
26        let semver: Vec<&str> = version.split('.').collect();
27        let major = semver.get(0).unwrap();
28        let minor = semver.get(1).unwrap();
29        let patch = semver.get(2).unwrap_or(&"x");
30
31        if let &"x" = minor {
32            return self
33                .tree
34                .get_child(int(&major))
35                .and_then(|major| major.get_max_child())
36                .and_then(|minor| minor.get_max_child())
37                .and_then(|patch| patch.store.as_ref());
38        }
39
40        if let &"x" = patch {
41            return self
42                .tree
43                .get_child(int(&major))
44                .and_then(|major| major.get_child(int(&minor)))
45                .and_then(|minor| minor.get_max_child())
46                .and_then(|patch| patch.store.as_ref());
47        }
48
49        self.tree
50            .get_child(int(&major))
51            .and_then(|major| major.get_child(int(&minor)))
52            .and_then(|minor| minor.get_child(int(&patch)))
53            .and_then(|patch| patch.store.as_ref())
54    }
55
56    pub fn contains_key(&mut self, version: &String) -> bool {
57        match self.get(version) {
58            Some(_v) => true,
59            None => false,
60        }
61    }
62
63    pub fn remove(&mut self, version: &String) -> Option<T> {
64        if self.contains_key(&version) == false {
65            return None;
66        }
67
68        let semver: Vec<&str> = version.split('.').collect();
69        let major = semver.get(0).unwrap();
70        let minor = semver.get(1).unwrap();
71        let patch = semver.get(2).unwrap_or(&"x");
72
73        let major_node = self.tree.get_child(int(&major)).unwrap();
74
75        // eg: '1.x'
76        if let &"x" = minor {
77            let minor_prefix = major_node
78                .get_max_child()
79                .and_then(|minor| Some(minor.prefix))
80                .unwrap();
81
82            let patch_prefix = major_node
83                .get_child(minor_prefix)
84                .and_then(|minor| minor.get_max_child())
85                .and_then(|patch| Some(patch.prefix))
86                .unwrap();
87
88            let patch_node = major_node
89                .get_child(minor_prefix)
90                .and_then(|minor| minor.remove_child(patch_prefix));
91
92            self.tree.remove_child(int(&major));
93
94            return patch_node.and_then(|node| node.store);
95        }
96
97        let minor_node = major_node.get_child(int(&minor)).unwrap();
98
99        // eg: '1.2.x' (or 1.2, since no patch means 'x')
100        if let &"x" = patch {
101            let patch_prefix = minor_node
102                .get_max_child()
103                .and_then(|patch| Some(patch.prefix))
104                .unwrap();
105
106            let patch_node = minor_node.remove_child(patch_prefix);
107
108            major_node.remove_child(int(&minor));
109            if major_node.children.len() == 0 {
110                self.tree.remove_child(int(&major));
111            }
112
113            return patch_node.and_then(|node| node.store);
114        }
115
116        // eg: '1.2.3'
117        let patch_node = minor_node.remove_child(int(&patch));
118
119        // if we removed the last child, we should
120        // also remove the parent node
121        if minor_node.children.len() == 0 {
122            major_node.remove_child(int(&minor));
123        }
124        if major_node.children.len() == 0 {
125            self.tree.remove_child(int(&major));
126        }
127
128        return patch_node.and_then(|node| node.store);
129    }
130
131    pub fn empty(&mut self) {
132        self.tree = node::Node::new(0);
133    }
134}
135
136fn int(str: &str) -> u32 {
137    str.parse::<u32>().unwrap()
138}
139
140#[cfg(test)]
141mod semver_store_tests {
142    use super::SemverStore;
143
144    #[test]
145    fn create_a_store() {
146        let store = SemverStore::<i32>::new();
147        assert_eq!(store.tree.prefix, 0);
148    }
149
150    #[test]
151    fn store_a_string() {
152        let mut store = SemverStore::<String>::new();
153        store.insert(&"1.0.0".to_string(), "hello".to_string());
154        assert_eq!(store.get(&"1.0.0".to_string()).unwrap(), &"hello");
155    }
156
157    #[test]
158    fn not_found() {
159        let mut store = SemverStore::<i32>::new();
160        store.insert(&"1.0.0".to_string(), 1);
161        assert_eq!(store.get(&"1.2.0".to_string()), None);
162        assert_eq!(store.get(&"1.0.1".to_string()), None);
163        assert_eq!(store.get(&"1.1.x".to_string()), None);
164        assert_eq!(store.get(&"2.0.0".to_string()), None);
165        assert_eq!(store.get(&"2.1".to_string()), None);
166        assert_eq!(store.get(&"2.x".to_string()), None);
167    }
168
169    #[test]
170    fn store_multiple_values() {
171        let mut store = SemverStore::<i32>::new();
172        store.insert(&"1.0.0".to_string(), 1);
173        store.insert(&"1.1.0".to_string(), 2);
174        store.insert(&"1.2.0".to_string(), 3);
175        store.insert(&"1.3.0".to_string(), 4);
176
177        // the node with prefix `1` should have 4 children
178        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 4);
179        assert_eq!(store.get(&"1.0.0".to_string()).unwrap(), &1);
180        assert_eq!(store.get(&"1.1.0".to_string()).unwrap(), &2);
181        assert_eq!(store.get(&"1.2.0".to_string()).unwrap(), &3);
182        assert_eq!(store.get(&"1.3.0".to_string()).unwrap(), &4);
183    }
184
185    #[test]
186    fn store_has_key() {
187        let mut store = SemverStore::<i32>::new();
188        store.insert(&"1.0.0".to_string(), 1);
189        store.insert(&"1.1.0".to_string(), 2);
190        store.insert(&"1.2.0".to_string(), 3);
191        store.insert(&"1.3.0".to_string(), 4);
192
193        assert_eq!(store.contains_key(&"1.1.0".to_string()), true);
194        assert_eq!(store.contains_key(&"1.2.3".to_string()), false);
195    }
196
197    #[test]
198    fn store_multiple_values_and_multiple_prefixes() {
199        let mut store = SemverStore::<i32>::new();
200        store.insert(&"1.1.0".to_string(), 11);
201        store.insert(&"1.2.0".to_string(), 12);
202        store.insert(&"1.3.0".to_string(), 13);
203
204        store.insert(&"2.0.0".to_string(), 21);
205        store.insert(&"2.1.0".to_string(), 22);
206        store.insert(&"2.2.0".to_string(), 23);
207        store.insert(&"2.3.0".to_string(), 24);
208
209        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 3);
210        assert_eq!(store.tree.children.get(&2).unwrap().children.len(), 4);
211
212        assert_eq!(store.get(&"1.1.0".to_string()).unwrap(), &11);
213        assert_eq!(store.get(&"1.2.0".to_string()).unwrap(), &12);
214        assert_eq!(store.get(&"1.3.0".to_string()).unwrap(), &13);
215
216        assert_eq!(store.get(&"2.0.0".to_string()).unwrap(), &21);
217        assert_eq!(store.get(&"2.1.0".to_string()).unwrap(), &22);
218        assert_eq!(store.get(&"2.2.0".to_string()).unwrap(), &23);
219        assert_eq!(store.get(&"2.3.0".to_string()).unwrap(), &24);
220    }
221
222    #[test]
223    fn delete_stored_values() {
224        let mut store = SemverStore::<i32>::new();
225        store.insert(&"1.0.0".to_string(), 1);
226        store.insert(&"1.1.0".to_string(), 2);
227        store.insert(&"1.2.0".to_string(), 3);
228        store.insert(&"1.3.0".to_string(), 4);
229
230        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 4);
231        assert_eq!(store.remove(&"1.2.0".to_string()), Some(3));
232        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 3);
233        assert_eq!(store.remove(&"2.2.0".to_string()), None);
234        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 3);
235        assert_eq!(store.remove(&"1.4.2".to_string()), None);
236        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 3);
237    }
238
239    #[test]
240    fn delete_minor_wildcard_shortcut() {
241        let mut store = SemverStore::<i32>::new();
242        store.insert(&"1.0.0".to_string(), 1);
243        store.insert(&"1.1.0".to_string(), 2);
244        store.insert(&"1.1.1".to_string(), 3);
245        store.insert(&"1.1.2".to_string(), 4);
246        store.insert(&"1.2.0".to_string(), 5);
247        store.insert(&"1.2.1".to_string(), 6);
248        store.insert(&"1.2.2".to_string(), 7);
249
250        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 3);
251        assert_eq!(store.remove(&"1.1.x".to_string()), Some(4));
252        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 2);
253        assert_eq!(store.remove(&"1.2".to_string()), Some(7));
254        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 1);
255        assert_eq!(store.remove(&"1.3".to_string()), None);
256        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 1);
257        assert_eq!(store.remove(&"1.3.x".to_string()), None);
258        assert_eq!(store.tree.children.get(&1).unwrap().children.len(), 1);
259    }
260
261    #[test]
262    fn delete_major_wildcard_shortcut() {
263        let mut store = SemverStore::<i32>::new();
264        store.insert(&"1.0.0".to_string(), 1);
265        store.insert(&"1.1.0".to_string(), 2);
266        store.insert(&"2.0.0".to_string(), 3);
267        store.insert(&"2.1.0".to_string(), 4);
268        store.insert(&"3.0.0".to_string(), 5);
269        store.insert(&"3.1.0".to_string(), 6);
270
271        assert_eq!(store.tree.children.len(), 3);
272        assert_eq!(store.remove(&"1.x".to_string()), Some(2));
273        assert_eq!(store.tree.children.len(), 2);
274        assert_eq!(store.remove(&"2.x".to_string()), Some(4));
275        assert_eq!(store.tree.children.len(), 1);
276        assert_eq!(store.remove(&"4.x".to_string()), None);
277        assert_eq!(store.tree.children.len(), 1);
278    }
279
280    #[test]
281    fn get_patch_wildcard_shortcut() {
282        let mut store = SemverStore::<i32>::new();
283        store.insert(&"1.0.1".to_string(), 1);
284        store.insert(&"1.0.2".to_string(), 2);
285        store.insert(&"1.0.3".to_string(), 3);
286        store.insert(&"2.0.0".to_string(), 4);
287
288        assert_eq!(store.get(&"1.0.x".to_string()).unwrap(), &3);
289        assert_eq!(store.get(&"1.0".to_string()).unwrap(), &3);
290    }
291
292    #[test]
293    fn get_minor_wildcard() {
294        let mut store = SemverStore::<i32>::new();
295        store.insert(&"1.0.1".to_string(), 1);
296        store.insert(&"1.1.2".to_string(), 2);
297        store.insert(&"1.2.3".to_string(), 3);
298        store.insert(&"2.0.0".to_string(), 4);
299
300        assert_eq!(store.get(&"1.1".to_string()).unwrap(), &2);
301        assert_eq!(store.get(&"1.x".to_string()).unwrap(), &3);
302    }
303
304    #[test]
305    fn empty_store() {
306        let mut store = SemverStore::<String>::new();
307        store.insert(&"1.0.0".to_string(), "hello".to_string());
308        assert_eq!(store.get(&"1.0.0".to_string()).unwrap(), &"hello");
309        store.empty();
310        assert_eq!(store.get(&"1.0.0".to_string()), None);
311    }
312}