subset_map/lib.rs
1//! # subset-map
2//!
3//! ## Summary
4//!
5//! `subset-map` is a map like data structure where the keys are combinations
6//! of elements the `SubsetMap` has been initialized with.
7//!
8//! The order of the elements is defined by the position of an element
9//! within the elements the `SubsetMap` has been initialized with.
10//!
11//! `SubsetMap` clones the elements into the subsets. So you should
12//! consider to only use element types where you would feel good to assign
13//! them the `Copy` trait.
14//!
15//! Lookup is done linearly. Therefore `SubsetMap` should only be used
16//! with not too big sets of elements.
17//!
18//! ### Example
19//!
20//! ```
21//! use subset_map::*;
22//! // Initialize the map where the payloads are basically the keys
23//! let subset_map = SubsetMap::fill(&[1, 2, 3], |x| x.iter().cloned().collect::<Vec<_>>());
24//!
25//! assert_eq!(subset_map.get(&[1]), Some(&vec![1]));
26//! assert_eq!(subset_map.get(&[2]), Some(&vec![2]));
27//! assert_eq!(subset_map.get(&[3]), Some(&vec![3]));
28//! assert_eq!(subset_map.get(&[1, 2]), Some(&vec![1, 2]));
29//! assert_eq!(subset_map.get(&[2, 3]), Some(&vec![2, 3]));
30//! assert_eq!(subset_map.get(&[1, 3]), Some(&vec![1, 3]));
31//! assert_eq!(subset_map.get(&[1, 2, 3]), Some(&vec![1, 2, 3]));
32//!
33//! // No internal ordering is performed:
34//! // The position in the original set is crucial:
35//! assert_eq!(subset_map.get(&[2,1]), None);
36//! ```
37//!
38//! ## Features
39//!
40//! The `serde` feature allows serialization and deserialization with `serde`.
41//!
42//! ## Recent Changes
43//!
44//! * 0.3.2
45//! * Added more methods to iterate/walk
46//! * 0.3.1
47//! * Added methods to work with payloads
48//! * 0.3.0
49//! * [BREAKING CHANGES]: Changed API to be more consistent
50//! * 0.2.2
51//! * fixed `size` function
52//! * 0.2.1
53//! * Optimized `find` and `lookup` a bit
54//! * Added `size` finction to return the number of combinations
55//! * 0.2.0
56//! * Renamed MatchQuality to `LookupResult`
57//! * `LookupResult` also contains the no match case
58//! * improved documentation
59//!
60//! ## License
61//!
62//! `subset-map` is distributed under the terms of both the MIT license and the Apache License (Version
63//! 2.0).
64//!
65//! Copyright(2018) Christian Douven
66//!
67//! See LICENSE-APACHE and LICENSE-MIT for details.
68#[cfg(feature = "serde")]
69#[macro_use]
70extern crate serde;
71
72type Nodes<I, P> = Vec<SubsetMapNode<I, P>>;
73
74/// A map like data structure where the keys are subsets made of
75/// combinations of the original sets.
76#[derive(Debug, Clone, PartialEq, Eq)]
77#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
78pub struct SubsetMap<E, P> {
79 nodes: Nodes<E, P>,
80}
81
82impl<E, P> SubsetMap<E, P>
83where
84 E: Clone,
85{
86 /// Creates a new instance where the payloads are
87 /// initialized with a closure that is passed the
88 /// current subset of elements.
89 ///
90 /// This function assigns values to those combinations where
91 /// the given closure `init` returns `Some`.
92 ///
93 /// # Example
94 ///
95 /// ```
96 /// use subset_map::*;
97 ///
98 /// let subset_map = SubsetMap::new(&[1, 2], |x| {
99 /// let sum = x.iter().sum::<i32>();
100 /// if sum == 1 {
101 /// None
102 /// } else {
103 /// Some(sum)
104 /// }
105 /// });
106 ///
107 /// assert_eq!(subset_map.get(&[1]), None);
108 /// assert_eq!(subset_map.get(&[2]), Some(&2));
109 /// assert_eq!(subset_map.get(&[1, 2]), Some(&3));
110 /// assert_eq!(subset_map.get(&[]), None);
111 /// assert_eq!(subset_map.get(&[2, 1]), None);
112 /// assert_eq!(subset_map.get(&[0]), None);
113 /// assert_eq!(subset_map.get(&[0, 1]), None);
114 /// ```
115 pub fn new<F>(elements: &[E], mut init: F) -> SubsetMap<E, P>
116 where
117 F: FnMut(&[E]) -> Option<P>,
118 {
119 init_root::<_, _, _, ()>(elements, &mut |elements| Ok(init(elements))).unwrap()
120 }
121
122 /// Creates a new instance where the payloads are
123 /// initialized with a closure that is passed the
124 /// current subset of elements.
125 ///
126 /// This fuction will assign an element to each subset.
127 ///
128 /// # Example
129 ///
130 /// ```
131 /// use subset_map::*;
132 ///
133 /// let subset_map = SubsetMap::fill(&[1, 2], |x| x.iter().sum::<i32>());
134 /// assert_eq!(subset_map.get(&[1]), Some(&1));
135 /// assert_eq!(subset_map.get(&[2]), Some(&2));
136 /// assert_eq!(subset_map.get(&[1, 2]), Some(&3));
137 /// assert_eq!(subset_map.get(&[]), None);
138 /// assert_eq!(subset_map.get(&[2, 1]), None);
139 /// assert_eq!(subset_map.get(&[0]), None);
140 /// assert_eq!(subset_map.get(&[0, 1]), None);
141 /// ```
142 pub fn fill<F>(elements: &[E], mut init: F) -> SubsetMap<E, P>
143 where
144 F: FnMut(&[E]) -> P,
145 {
146 init_root::<_, _, _, ()>(elements, &mut |elements| Ok(Some(init(elements)))).unwrap()
147 }
148
149 /// Initializes the `SubsetMap` with a closure that can fail.
150 /// This function initializes all those subsets with the returned payloads
151 /// where the `init` closure returned an `Result::Ok(Option::Some)`
152 /// given that all calls on the closure returned `Result::Ok`.
153 ///
154 /// Failure of the `init` closure will result in a failure
155 /// of the whole initialization process.
156 ///
157 /// # Example
158 ///
159 /// The whole initialization process fails.
160 ///
161 /// ```
162 /// use subset_map::*;
163 ///
164 /// let subset_map = SubsetMap::init(&[1, 2], |x| {
165 /// let sum = x.iter().sum::<i32>();
166 /// if sum == 1 {
167 /// Ok(Some(sum))
168 /// } else if sum == 2 {
169 /// Ok(None)
170 /// } else {
171 /// Err("bang!")
172 /// }
173 /// });
174 ///
175 /// assert_eq!(subset_map, Err("bang!"));
176 /// ```
177 pub fn init<F, X>(elements: &[E], mut init: F) -> Result<SubsetMap<E, P>, X>
178 where
179 F: FnMut(&[E]) -> Result<Option<P>, X>,
180 {
181 init_root(elements, &mut init)
182 }
183
184 /// Initializes the `SubsetMap` with a closure that can fail.
185 /// This function initializes all subsets with the returned payloads
186 /// given that all calls on the closure returned `Result::Ok`.
187 ///
188 /// Failure of the `init` closure will result in a failure
189 /// of the whole initialization process.
190 ///
191 /// # Example
192 ///
193 /// ```
194 /// use subset_map::*;
195 ///
196 /// let subset_map = SubsetMap::init_filled(&[1, 2], |x| {
197 /// let sum = x.iter().sum::<i32>();
198 /// if sum != 3 {
199 /// Ok(sum)
200 /// } else {
201 /// Err("bang!")
202 /// }
203 /// });
204 ///
205 /// assert_eq!(subset_map, Err("bang!"));
206 /// ```
207 pub fn init_filled<F, X>(elements: &[E], mut init: F) -> Result<SubsetMap<E, P>, X>
208 where
209 F: FnMut(&[E]) -> Result<P, X>,
210 {
211 init_root::<_, _, _, X>(elements, &mut |elements| init(elements).map(Some))
212 }
213
214 /// Creates a new instance where the payloads are all initialized
215 /// with the same value.
216 ///
217 /// # Example
218 ///
219 /// ```
220 /// use subset_map::*;
221 ///
222 /// let subset_map = SubsetMap::with_value(&[1, 2], || 42);
223 /// assert_eq!(subset_map.get(&[1]), Some(&42));
224 /// assert_eq!(subset_map.get(&[2]), Some(&42));
225 /// assert_eq!(subset_map.get(&[1, 2]), Some(&42));
226 /// assert_eq!(subset_map.get(&[]), None);
227 /// assert_eq!(subset_map.get(&[2, 1]), None);
228 /// assert_eq!(subset_map.get(&[0]), None);
229 /// assert_eq!(subset_map.get(&[0, 1]), None);
230 /// ```
231 pub fn with_value<F>(elements: &[E], mut init: F) -> SubsetMap<E, P>
232 where
233 F: FnMut() -> P,
234 {
235 init_root::<_, _, _, ()>(elements, &mut |_| Ok(Some(init()))).unwrap()
236 }
237
238 /// Creates a new instance where the payloads are all initialized
239 /// with the `Default::default()` value of the payload type.
240 /// Creates a new instance where the payloads are all initialized
241 /// with the same value.
242 ///
243 /// # Example
244 ///
245 /// ```
246 /// use subset_map::*;
247 ///
248 /// let subset_map = SubsetMap::with_default(&[1, 2]);
249 /// assert_eq!(subset_map.get(&[1]), Some(&0));
250 /// assert_eq!(subset_map.get(&[2]), Some(&0));
251 /// assert_eq!(subset_map.get(&[1, 2]), Some(&0));
252 /// assert_eq!(subset_map.get(&[]), None);
253 /// assert_eq!(subset_map.get(&[2, 1]), None);
254 /// assert_eq!(subset_map.get(&[0]), None);
255 /// assert_eq!(subset_map.get(&[0, 1]), None);
256 /// ```
257 pub fn with_default(elements: &[E]) -> SubsetMap<E, P>
258 where
259 P: Default,
260 {
261 init_root::<_, _, _, ()>(elements, &mut |_| Ok(Some(P::default()))).unwrap()
262 }
263
264 /// Gets a payload by the given subset.
265 ///
266 /// Only "perfect" matches on `subset` are returned.
267 ///
268 /// The function returns `None` regardless of whether
269 /// `subset` was part of the map or there was no payload
270 /// assigned to the given subset.
271 ///
272 /// ```
273 /// use subset_map::*;
274 ///
275 /// let subset_map = SubsetMap::new(&[1, 2, 3], |x| {
276 /// let payload = x.iter().cloned().collect::<Vec<_>>();
277 /// if payload.len() == 1 {
278 /// None
279 /// } else {
280 /// Some(payload)
281 /// }
282 /// });
283 /// assert_eq!(subset_map.get(&[1]), None);
284 /// assert_eq!(subset_map.get(&[2]), None);
285 /// assert_eq!(subset_map.get(&[3]), None);
286 /// assert_eq!(subset_map.get(&[1, 2]), Some(&vec![1, 2]));
287 /// assert_eq!(subset_map.get(&[2, 3]), Some(&vec![2, 3]));
288 /// assert_eq!(subset_map.get(&[1, 3]), Some(&vec![1, 3]));
289 /// assert_eq!(subset_map.get(&[1, 2, 3]), Some(&vec![1, 2, 3]));
290 ///
291 /// assert_eq!(subset_map.get(&[]), None);
292 /// assert_eq!(subset_map.get(&[7]), None);
293 /// assert_eq!(subset_map.get(&[3, 2, 1]), None);
294 /// assert_eq!(subset_map.get(&[1, 3, 2]), None);
295 /// assert_eq!(subset_map.get(&[3, 2, 1]), None);
296 /// assert_eq!(subset_map.get(&[2, 1]), None);
297 /// ```
298 pub fn get<'a>(&'a self, subset: &[E]) -> Option<&'a P>
299 where
300 E: Eq,
301 {
302 get(subset, &self.nodes)
303 }
304
305 /// Looks up a payload by the given subset and returns the
306 /// corresponding owned value.
307 ///
308 /// The function returns `None` regardless of wether
309 /// `subset` was part of the map or there was no payload
310 /// assigned to the given subset.
311 ///
312 /// Only perfect matches on `subset` are returned. See `get`.
313 pub fn get_owned(&self, subset: &[E]) -> Option<P::Owned>
314 where
315 E: Eq,
316 P: ToOwned,
317 {
318 get(subset, &self.nodes).map(|p| p.to_owned())
319 }
320
321 /// Looks up a subset and maybe returns the assigned payload.
322 ///
323 /// Elements in `subset` that are not part of the initial set are
324 /// skipped.
325 ///
326 /// The returned `LookupResult` may still contain an optional
327 /// payload. None indicates that the subset was matched but
328 /// there was no payload for the given subset.
329 ///
330 /// Use this method if you are interested whether there was
331 /// a matching subset and then process the maybe present payload.
332 /// Otherwise use `find` or `lookup`.
333 ///
334 /// # Example
335 ///
336 /// ```
337 /// use subset_map::*;
338 ///
339 /// let subset_map = SubsetMap::new(&[1u32, 2, 3], |x| {
340 /// if x == &[2] {
341 /// None
342 /// } else {
343 /// let payload = x.iter().cloned().collect::<Vec<_>>();
344 /// Some(payload)
345 /// }
346 /// });
347 ///
348 /// let empty: &[u32] = &[];
349 ///
350 /// // A perfect match with a payload:
351 /// let match_result = subset_map.lookup(&[1]);
352 /// assert_eq!(match_result.payload(), Some(&vec![1]));
353 /// assert_eq!(match_result.excluded_elements(), empty);
354 /// assert_eq!(match_result.is_match(), true);
355 /// assert_eq!(match_result.is_perfect(), true);
356 /// assert_eq!(match_result.is_excluded(), false);
357 ///
358 /// // A perfect match that has no payload:
359 /// let match_result = subset_map.lookup(&[2]);
360 /// assert_eq!(match_result.payload(), None);
361 /// assert_eq!(match_result.excluded_elements(), empty);
362 /// assert_eq!(match_result.is_match(), true);
363 /// assert_eq!(match_result.is_perfect(), true);
364 /// assert_eq!(match_result.is_excluded(), false);
365 ///
366 /// // There is no answer at all:
367 /// let match_result = subset_map.lookup(&[42]);
368 /// assert_eq!(match_result.is_no_match(), true);
369 /// assert_eq!(match_result.is_perfect(), false);
370 /// assert_eq!(match_result.is_excluded(), false);
371 /// assert_eq!(match_result.excluded_elements(), empty);
372 ///
373 /// // A nearby match but that has a payload:
374 /// let match_result = subset_map.lookup(&[3,1]);
375 /// assert_eq!(match_result.payload(), Some(&vec![3]));
376 /// assert_eq!(match_result.excluded_elements(), &[1]);
377 /// assert_eq!(match_result.is_perfect(), false);
378 /// assert_eq!(match_result.is_excluded(), true);
379 /// assert_eq!(match_result.is_match(), true);
380 ///
381 /// ```
382 pub fn lookup<'a>(&'a self, subset: &[E]) -> LookupResult<'a, E, P>
383 where
384 E: Eq,
385 {
386 lookup(subset, &self.nodes)
387 }
388
389 /// Finds a payload by the given subset.
390 ///
391 /// Elements in `subset` that are not part of the initial set are
392 /// skipped.
393 ///
394 /// If there was no match or no payload for the given subset
395 /// `FindResult::NotFound` is returned.
396 ///
397 /// Use this function if you are mostly interested in
398 /// payloads and how they were matched. Otherwise
399 /// use `lookup` or `get`
400 ///
401 /// # Example
402 ///
403 /// ```
404 /// use subset_map::*;
405 ///
406 /// let subset_map = SubsetMap::new(&[1u32, 2, 3], |x| {
407 /// if x == &[2] {
408 /// None
409 /// } else {
410 /// let payload = x.iter().cloned().collect::<Vec<_>>();
411 /// Some(payload)
412 /// }
413 /// });
414 ///
415 /// let empty: &[u32] = &[];
416 ///
417 /// // A perfect match with a payload:
418 /// let match_result = subset_map.find(&[1]);
419 ///
420 /// assert_eq!(match_result.payload(), Some(&vec![1]));
421 /// assert_eq!(match_result.is_found(), true);
422 /// assert_eq!(match_result.is_found_and_perfect(), true);
423 /// assert_eq!(match_result.is_found_and_excluded(), false);
424 /// assert_eq!(match_result.excluded_elements(), empty);
425 ///
426 /// // A perfect match that has no payload:
427 /// let match_result = subset_map.find(&[2]);
428 ///
429 /// assert_eq!(match_result.payload(), None);
430 /// assert_eq!(match_result.is_found(), false);
431 /// assert_eq!(match_result.is_found_and_perfect(), false);
432 /// assert_eq!(match_result.is_found_and_excluded(), false);
433 /// assert_eq!(match_result.excluded_elements(), empty);
434 ///
435 /// // There is no answer at all:
436 /// let match_result = subset_map.find(&[42]);
437 ///
438 /// assert_eq!(match_result.payload(), None);
439 /// assert_eq!(match_result.is_not_found(), true);
440 /// assert_eq!(match_result.is_found_and_perfect(), false);
441 /// assert_eq!(match_result.is_found_and_excluded(), false);
442 /// assert_eq!(match_result.excluded_elements(), empty);
443 ///
444 /// // A nearby match but that has a payload:
445 /// let match_result = subset_map.find(&[3,1]);
446 ///
447 /// assert_eq!(match_result.is_found_and_perfect(), false);
448 /// assert_eq!(match_result.is_found_and_excluded(), true);
449 /// assert_eq!(match_result.is_found(), true);
450 /// assert_eq!(match_result.payload(), Some(&vec![3]));
451 /// assert_eq!(match_result.excluded_elements(), &[1]);
452 /// ```
453 pub fn find<'a>(&'a self, subset: &[E]) -> FindResult<'a, E, P>
454 where
455 E: Eq,
456 {
457 match self.lookup(subset) {
458 LookupResult::Perfect(Some(p)) => FindResult::Perfect(p),
459 LookupResult::Perfect(None) => FindResult::NotFound,
460 LookupResult::Excluded(Some(p), e) => FindResult::Excluded(p, e),
461 LookupResult::Excluded(None, _) => FindResult::NotFound,
462 LookupResult::NoMatch => FindResult::NotFound,
463 }
464 }
465
466 /// Sets the payload of all subsets to `None`
467 /// where the given payload does not fulfill the `predicate`
468 pub fn filter_values<F>(&mut self, mut predicate: F)
469 where
470 F: FnMut(&P) -> bool,
471 {
472 self.nodes
473 .iter_mut()
474 .for_each(|n| n.filter_values(&mut predicate))
475 }
476
477 /// Executes the given mutable closure `f`
478 /// on the value of each node.
479 pub fn walk_values<F>(&self, mut f: F)
480 where
481 F: FnMut(&P),
482 {
483 self.nodes.iter().for_each(|n| n.walk_values(&mut f))
484 }
485
486 /// Executes the given mutable closure `f`
487 /// on the value of each node until the
488 /// first closure returns false.
489 pub fn walk_values_until<F>(&self, mut f: F)
490 where
491 F: FnMut(&P) -> bool,
492 {
493 for node in &self.nodes {
494 if !node.walk_values_until(&mut f) {
495 return;
496 }
497 }
498 }
499
500 /// Executes the given mutable closure `f`
501 /// on the payload of each node
502 pub fn walk_payloads<F>(&self, mut f: F)
503 where
504 F: FnMut(Option<&P>),
505 {
506 self.nodes.iter().for_each(|n| n.walk_payloads(&mut f))
507 }
508
509 /// Executes the given mutable closure `f`
510 /// on the payload of each node until the
511 /// first closure returns false.
512 pub fn walk_payloads_until<F>(&self, mut f: F)
513 where
514 F: FnMut(Option<&P>) -> bool,
515 {
516 for node in &self.nodes {
517 if !node.walk_payloads_until(&mut f) {
518 return;
519 }
520 }
521 }
522
523 /// Walk all elements with their payloads
524 pub fn walk<F>(&self, mut f: F)
525 where
526 F: FnMut(&[&E], Option<&P>),
527 {
528 self.nodes.iter().for_each(|n| n.walk(&mut f))
529 }
530
531 /// Executes the given mutable closure `f`
532 /// on the payload of each node
533 pub fn for_each_value<F>(&self, mut f: F)
534 where
535 F: FnMut(&P),
536 {
537 self.walk_values_until(|p| {
538 f(p);
539 true
540 })
541 }
542
543 /// Executes the given mutable closure `f`
544 /// on the payload of each node
545 pub fn for_each_payload<F>(&self, mut f: F)
546 where
547 F: FnMut(Option<&P>),
548 {
549 self.walk_payloads_until(|p| {
550 f(p);
551 true
552 })
553 }
554
555 /// Returns true if there are nodes and all
556 /// of these have a payload set.
557 pub fn all_subsets_have_values(&self) -> bool {
558 if self.is_empty() {
559 return false;
560 }
561
562 let mut all_set = true;
563
564 self.walk_payloads_until(|p| {
565 if p.is_none() {
566 all_set = false;
567 false
568 } else {
569 true
570 }
571 });
572
573 all_set
574 }
575
576 /// Returns true if there are no subsets or all
577 /// of these have no payload set.
578 ///
579 /// # Example
580 ///
581 /// An empty map has no values:
582 ///
583 /// ```
584 /// use subset_map::*;
585 ///
586 /// let subset_map = SubsetMap::<u8, u8>::with_default(&[]);
587 ///
588 /// assert_eq!(subset_map.no_subset_with_value(), true);
589 /// ```
590 ///
591 /// An map with a set entry has values:
592 ///
593 /// ```
594 /// use subset_map::*;
595 ///
596 /// let subset_map = SubsetMap::<u8, u8>::with_default(&[1]);
597 ///
598 /// assert_eq!(subset_map.no_subset_with_value(), false);
599 /// ```
600 ///
601 /// An non empty map where at least one subset has a value:
602 ///
603 /// ```
604 /// use subset_map::*;
605 ///
606 /// let mut subset_map = SubsetMap::fill(&[1, 2], |c| c.len());
607 ///
608 /// subset_map.filter_values(|p| *p == 2);
609 ///
610 /// assert_eq!(subset_map.no_subset_with_value(), false);
611 /// ```
612 ///
613 /// An non empty map where no subset has a value:
614 ///
615 /// ```
616 /// use subset_map::*;
617 ///
618 /// let mut subset_map = SubsetMap::<u8, u8>::with_default(&[1, 2]);
619 ///
620 /// // Set all payloads to `None`
621 /// subset_map.filter_values(|p| false);
622 ///
623 /// assert_eq!(subset_map.no_subset_with_value(), true);
624 /// ```
625 pub fn no_subset_with_value(&self) -> bool {
626 if self.is_empty() {
627 return true;
628 }
629
630 let mut no_value_set = true;
631
632 self.walk_payloads_until(|p| {
633 if p.is_some() {
634 no_value_set = false;
635 false
636 } else {
637 true
638 }
639 });
640
641 no_value_set
642 }
643
644 /// Returns true if the map is empty and contains no subsets.
645 pub fn is_empty(&self) -> bool {
646 self.nodes.is_empty()
647 }
648
649 /// The number of subsets in this map
650 pub fn size(&self) -> usize {
651 2usize.pow(self.nodes.len() as u32) - 1
652 }
653}
654
655impl<E, P> Default for SubsetMap<E, P> {
656 fn default() -> Self {
657 SubsetMap {
658 nodes: Default::default(),
659 }
660 }
661}
662
663#[derive(Debug, Clone, PartialEq, Eq)]
664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
665struct SubsetMapNode<E, P> {
666 pub element: E,
667 pub payload: Option<P>,
668 pub nodes: Nodes<E, P>,
669}
670
671impl<E, P> SubsetMapNode<E, P> {
672 pub fn filter_values<F>(&mut self, predicate: &mut F)
673 where
674 F: FnMut(&P) -> bool,
675 {
676 let keep = self.payload.as_ref().map(|p| predicate(p)).unwrap_or(true);
677 if !keep {
678 self.payload = None;
679 }
680 self.nodes
681 .iter_mut()
682 .for_each(|n| n.filter_values(predicate))
683 }
684
685 pub fn walk_values<F>(&self, f: &mut F)
686 where
687 F: FnMut(&P),
688 {
689 if let Some(ref payload) = self.payload {
690 f(payload);
691 }
692 self.nodes.iter().for_each(|n| n.walk_values(f))
693 }
694
695 pub fn walk_payloads<F>(&self, f: &mut F)
696 where
697 F: FnMut(Option<&P>),
698 {
699 f(self.payload.as_ref());
700 self.nodes.iter().for_each(|n| n.walk_payloads(f))
701 }
702
703 pub fn walk_values_until<F>(&self, f: &mut F) -> bool
704 where
705 F: FnMut(&P) -> bool,
706 {
707 let go_on = if let Some(ref payload) = self.payload {
708 f(payload)
709 } else {
710 true
711 };
712
713 if go_on {
714 for node in &self.nodes {
715 if !node.walk_values_until(f) {
716 return false;
717 }
718 }
719 }
720
721 true
722 }
723
724 pub fn walk_payloads_until<F>(&self, f: &mut F) -> bool
725 where
726 F: FnMut(Option<&P>) -> bool,
727 {
728 if f(self.payload.as_ref()) {
729 for node in &self.nodes {
730 if !node.walk_payloads_until(f) {
731 return false;
732 }
733 }
734 true
735 } else {
736 false
737 }
738 }
739
740 pub fn walk<F>(&self, mut f: F)
741 where
742 F: FnMut(&[&E], Option<&P>),
743 {
744 let mut elements = Vec::new();
745 self.walk_internal(&mut elements, &mut f)
746 }
747
748 fn walk_internal<'a, F>(&'a self, elements: &mut Vec<&'a E>, f: &mut F)
749 where
750 F: FnMut(&[&E], Option<&P>),
751 {
752 elements.push(&self.element);
753 f(elements.as_slice(), self.payload.as_ref());
754 self.nodes.iter().for_each(|n| n.walk_internal(elements, f));
755 elements.pop();
756 }
757}
758
759/// The result of `SubsetMap::lookup`.
760///
761/// It can either be a perfect match on the subset
762/// or a match where some elements of the input set
763/// had to be excluded.
764///
765/// A value of `None` for the payload indicates
766/// that there was a match for a given subset but
767/// nevertheless there was no payload stored for
768/// that subset.
769#[derive(Debug)]
770pub enum LookupResult<'a, E, P: 'a> {
771 /// The input set exactly matched a combination
772 /// of the original set.
773 Perfect(Option<&'a P>),
774 /// There were some elements in the input set that had
775 /// to be excluded to match a subset of the original set
776 ///
777 /// The excluded elements are returned.
778 Excluded(Option<&'a P>, Vec<E>),
779 /// There was no match at all for the given subset
780 NoMatch,
781}
782
783impl<'a, E, P> LookupResult<'a, E, P> {
784 pub fn payload(&self) -> Option<&P> {
785 match *self {
786 LookupResult::Perfect(p) => p,
787 LookupResult::Excluded(p, _) => p,
788 LookupResult::NoMatch => None,
789 }
790 }
791
792 /// Returns the excluded elements if there was
793 /// a match at all.
794 ///
795 /// If there was no match the returned slice
796 /// is also empty.
797 pub fn excluded_elements(&self) -> &[E] {
798 match *self {
799 LookupResult::Perfect(_) => &[],
800 LookupResult::Excluded(_, ref skipped) => &*skipped,
801 LookupResult::NoMatch => &[],
802 }
803 }
804
805 /// Returns `true` if there was a perfect match
806 pub fn is_perfect(&self) -> bool {
807 match *self {
808 LookupResult::Perfect(_) => true,
809 _ => false,
810 }
811 }
812
813 /// Returns `true` if there was a match
814 /// but some elements had to be excluded
815 pub fn is_excluded(&self) -> bool {
816 match *self {
817 LookupResult::Excluded(_, _) => true,
818 _ => false,
819 }
820 }
821
822 /// Returns `true` if there was no match at all
823 pub fn is_no_match(&self) -> bool {
824 !self.is_match()
825 }
826
827 /// Returns `true` if there was a match even
828 /// though some elements had to be excluded
829 pub fn is_match(&self) -> bool {
830 match *self {
831 LookupResult::NoMatch => false,
832 _ => true,
833 }
834 }
835}
836
837/// The result of `SubsetMap::find`.
838///
839/// It can either be a perfect match on the subset
840/// or a match where some elements of the input set
841/// had to be excluded.
842///
843/// For `FindResult::NotFound` no tracking of
844/// excluded elements is done.
845#[derive(Debug)]
846pub enum FindResult<'a, E, P: 'a> {
847 /// The input set exactly matched a combination
848 /// of the original set and there was a payload.
849 Perfect(&'a P),
850 /// There were some elements in the input set that had
851 /// to be excluded to match a subset of the original set.
852 ///
853 /// Still there was a payload at the given position.
854 ///
855 /// The excluded elements are returned.
856 Excluded(&'a P, Vec<E>),
857 /// There was no match at all or the payload
858 /// for the matched subset was `None`
859 NotFound,
860}
861
862impl<'a, E, P> FindResult<'a, E, P> {
863 pub fn payload(&self) -> Option<&P> {
864 match *self {
865 FindResult::Perfect(p) => Some(p),
866 FindResult::Excluded(p, _) => Some(p),
867 FindResult::NotFound => None,
868 }
869 }
870
871 /// Returns the excluded elements if there was
872 /// a match at all.
873 ///
874 /// If there was no match the returned slice
875 /// is also empty.
876 pub fn excluded_elements(&self) -> &[E] {
877 match *self {
878 FindResult::Perfect(_) => &[],
879 FindResult::Excluded(_, ref skipped) => &*skipped,
880 FindResult::NotFound => &[],
881 }
882 }
883
884 /// Returns `true` if there was a perfect match
885 pub fn is_found_and_perfect(&self) -> bool {
886 match *self {
887 FindResult::Perfect(_) => true,
888 _ => false,
889 }
890 }
891
892 /// Returns `true` if there was a match
893 /// but some elements had to be excluded
894 pub fn is_found_and_excluded(&self) -> bool {
895 match *self {
896 FindResult::Excluded(_, _) => true,
897 _ => false,
898 }
899 }
900
901 /// Returns `true` if there was no match
902 /// or if the payload for the matched subset was
903 /// `None`
904 pub fn is_not_found(&self) -> bool {
905 !self.is_found()
906 }
907
908 /// Returns `true` if there was a match even
909 /// though some elements had to be excluded
910 /// and if there was a payload for the matched
911 /// subset.
912 pub fn is_found(&self) -> bool {
913 match *self {
914 FindResult::NotFound => false,
915 _ => true,
916 }
917 }
918}
919
920fn init_root<E, P, F, X>(elements: &[E], init_with: &mut F) -> Result<SubsetMap<E, P>, X>
921where
922 E: Clone,
923 F: FnMut(&[E]) -> Result<Option<P>, X>,
924{
925 let mut stack = Vec::new();
926 let mut nodes = Vec::new();
927
928 for fixed in 0..elements.len() {
929 let element = elements[fixed].clone();
930 let payload = init_with(&elements[fixed..=fixed])?;
931 let mut node = SubsetMapNode {
932 element,
933 payload,
934 nodes: Vec::new(),
935 };
936 stack.clear();
937 stack.push(elements[fixed].clone());
938 init_node(elements, &mut stack, fixed, &mut node, init_with)?;
939 nodes.push(node)
940 }
941 Ok(SubsetMap { nodes })
942}
943
944fn init_node<E, P, F, X>(
945 elements: &[E],
946 stack: &mut Vec<E>,
947 fixed: usize,
948 into: &mut SubsetMapNode<E, P>,
949 init_with: &mut F,
950) -> Result<(), X>
951where
952 E: Clone,
953 F: FnMut(&[E]) -> Result<Option<P>, X>,
954{
955 for fixed in fixed + 1..elements.len() {
956 stack.push(elements[fixed].clone());
957 let mut node = SubsetMapNode {
958 element: elements[fixed].clone(),
959 payload: init_with(&stack)?,
960 nodes: Vec::new(),
961 };
962 let _ = init_node(elements, stack, fixed, &mut node, init_with);
963 stack.pop();
964 into.nodes.push(node);
965 }
966 Ok(())
967}
968
969fn get<'a, 'b, E, P>(subset: &'b [E], nodes: &'a [SubsetMapNode<E, P>]) -> Option<&'a P>
970where
971 E: Eq,
972{
973 let mut nodes = nodes;
974 let mut result = None;
975 for element in subset {
976 if let Some(node) = nodes.iter().find(|n| n.element == *element) {
977 result = node.payload.as_ref();
978 nodes = &node.nodes;
979 } else {
980 return None;
981 }
982 }
983
984 result
985}
986
987fn lookup<'a, 'b, E, P>(subset: &'b [E], nodes: &'a [SubsetMapNode<E, P>]) -> LookupResult<'a, E, P>
988where
989 E: Eq + Clone,
990{
991 let mut excluded = Vec::new();
992 let mut nodes = nodes;
993 let mut result_node = None;
994
995 for element in subset {
996 if let Some(node) = nodes.iter().find(|n| n.element == *element) {
997 result_node = Some(node);
998 nodes = &node.nodes;
999 } else {
1000 excluded.push(element.clone())
1001 }
1002 }
1003
1004 if let Some(result_node) = result_node {
1005 if excluded.is_empty() {
1006 LookupResult::Perfect(result_node.payload.as_ref())
1007 } else {
1008 LookupResult::Excluded(result_node.payload.as_ref(), excluded)
1009 }
1010 } else {
1011 LookupResult::NoMatch
1012 }
1013}
1014
1015#[cfg(test)]
1016mod tests {
1017 use super::*;
1018 #[test]
1019 fn create_empty() {
1020 let sample = SubsetMap::<u32, ()>::default();
1021
1022 assert!(sample.is_empty());
1023 }
1024
1025 #[test]
1026 fn one_element() {
1027 let sample = SubsetMap::fill(&[1], |_| 1);
1028
1029 assert_eq!(sample.get(&[1]), Some(&1));
1030 assert_eq!(sample.get(&[]), None);
1031 assert_eq!(sample.get(&[2]), None);
1032 }
1033
1034 #[test]
1035 fn two_elements() {
1036 let sample = SubsetMap::fill(&[1, 2], |x| x.iter().sum::<i32>());
1037
1038 assert_eq!(sample.get(&[1]), Some(&1));
1039 assert_eq!(sample.get(&[2]), Some(&2));
1040 assert_eq!(sample.get(&[1, 2]), Some(&3));
1041 assert_eq!(sample.get(&[]), None);
1042 assert_eq!(sample.get(&[2, 1]), None);
1043 assert_eq!(sample.get(&[0]), None);
1044 assert_eq!(sample.get(&[0, 1]), None);
1045 }
1046
1047 #[test]
1048 fn three_elements() {
1049 let sample = SubsetMap::fill(&[1, 2, 3], |x| x.iter().sum::<i32>());
1050
1051 assert_eq!(sample.get(&[1]), Some(&1));
1052 assert_eq!(sample.get(&[2]), Some(&2));
1053 assert_eq!(sample.get(&[3]), Some(&3));
1054 assert_eq!(sample.get(&[1, 2]), Some(&3));
1055 assert_eq!(sample.get(&[2, 3]), Some(&5));
1056 assert_eq!(sample.get(&[1, 3]), Some(&4));
1057 assert_eq!(sample.get(&[1, 2, 3]), Some(&6));
1058 assert_eq!(sample.get(&[]), None);
1059 assert_eq!(sample.get(&[2, 1]), None);
1060 assert_eq!(sample.get(&[0]), None);
1061 assert_eq!(sample.get(&[0, 1]), None);
1062 }
1063
1064 #[test]
1065 fn three_elements_identity_vec() {
1066 let sample = SubsetMap::fill(&[1, 2, 3], |x| x.to_vec());
1067
1068 assert_eq!(sample.get(&[1]), Some(&vec![1]));
1069 assert_eq!(sample.get(&[2]), Some(&vec![2]));
1070 assert_eq!(sample.get(&[3]), Some(&vec![3]));
1071 assert_eq!(sample.get(&[1, 2]), Some(&vec![1, 2]));
1072 assert_eq!(sample.get(&[2, 3]), Some(&vec![2, 3]));
1073 assert_eq!(sample.get(&[1, 3]), Some(&vec![1, 3]));
1074 assert_eq!(sample.get(&[1, 2, 3]), Some(&vec![1, 2, 3]));
1075 }
1076
1077 #[test]
1078 fn walk_5_elems_keeps_order() {
1079 let elements: Vec<_> = (0..5).collect();
1080
1081 let mut n = 0;
1082 let map = SubsetMap::fill(&elements, |_x| {
1083 n += 1;
1084 n
1085 });
1086
1087 let mut n = 0;
1088 map.walk(|_elements, payload| {
1089 n += 1;
1090 assert_eq!(payload, Some(&n));
1091 })
1092 }
1093
1094 #[test]
1095 fn test_lookup_result() {
1096 let subset_map = SubsetMap::new(&[1u32, 2, 3, 4], |x| {
1097 if x == &[2, 3] {
1098 None
1099 } else {
1100 let payload = x.iter().cloned().collect::<Vec<_>>();
1101 Some(payload)
1102 }
1103 });
1104
1105 let empty: &[u32] = &[];
1106
1107 let match_result = subset_map.lookup(&[]);
1108 assert_eq!(match_result.payload(), None);
1109 assert_eq!(match_result.excluded_elements(), empty);
1110 assert_eq!(match_result.is_match(), false);
1111 assert_eq!(match_result.is_perfect(), false);
1112 assert_eq!(match_result.is_excluded(), false);
1113
1114 let match_result = subset_map.lookup(&[1]);
1115 assert_eq!(match_result.payload(), Some(&vec![1]));
1116 assert_eq!(match_result.excluded_elements(), empty);
1117 assert_eq!(match_result.is_match(), true);
1118 assert_eq!(match_result.is_perfect(), true);
1119 assert_eq!(match_result.is_excluded(), false);
1120
1121 let match_result = subset_map.lookup(&[2, 3]);
1122 assert_eq!(match_result.payload(), None);
1123 assert_eq!(match_result.excluded_elements(), empty);
1124 assert_eq!(match_result.is_match(), true);
1125 assert_eq!(match_result.is_perfect(), true);
1126 assert_eq!(match_result.is_excluded(), false);
1127
1128 let match_result = subset_map.lookup(&[42]);
1129 assert_eq!(match_result.is_no_match(), true);
1130 assert_eq!(match_result.is_perfect(), false);
1131 assert_eq!(match_result.is_excluded(), false);
1132 assert_eq!(match_result.excluded_elements(), empty);
1133
1134 let match_result = subset_map.lookup(&[42, 3]);
1135 assert_eq!(match_result.payload(), Some(&vec![3]));
1136 assert_eq!(match_result.excluded_elements(), &[42]);
1137 assert_eq!(match_result.is_perfect(), false);
1138 assert_eq!(match_result.is_excluded(), true);
1139 assert_eq!(match_result.is_match(), true);
1140
1141 let match_result = subset_map.lookup(&[3, 1]);
1142 assert_eq!(match_result.payload(), Some(&vec![3]));
1143 assert_eq!(match_result.excluded_elements(), &[1]);
1144 assert_eq!(match_result.is_perfect(), false);
1145 assert_eq!(match_result.is_excluded(), true);
1146 assert_eq!(match_result.is_match(), true);
1147
1148 let match_result = subset_map.lookup(&[3, 1, 4, 2]);
1149 assert_eq!(match_result.payload(), Some(&vec![3, 4]));
1150 assert_eq!(match_result.excluded_elements(), &[1, 2]);
1151 assert_eq!(match_result.is_perfect(), false);
1152 assert_eq!(match_result.is_excluded(), true);
1153 assert_eq!(match_result.is_match(), true);
1154
1155 let match_result = subset_map.lookup(&[4, 3, 2, 1]);
1156 assert_eq!(match_result.payload(), Some(&vec![4]));
1157 assert_eq!(match_result.excluded_elements(), &[3, 2, 1]);
1158 assert_eq!(match_result.is_perfect(), false);
1159 assert_eq!(match_result.is_excluded(), true);
1160 assert_eq!(match_result.is_match(), true);
1161
1162 let match_result = subset_map.lookup(&[99, 2, 1, 77, 78, 3, 4, 2, 1, 2]);
1163 assert_eq!(match_result.payload(), Some(&vec![2, 3, 4]));
1164 assert_eq!(match_result.excluded_elements(), &[99, 1, 77, 78, 2, 1, 2]);
1165 assert_eq!(match_result.is_perfect(), false);
1166 assert_eq!(match_result.is_excluded(), true);
1167 assert_eq!(match_result.is_match(), true);
1168 }
1169}