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}