aoc_parse/parsers/
collections.rs

1//! Parsers that produce collections other than `Vec`s.
2
3use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
4use std::marker::PhantomData;
5
6use crate::parsers::map::{MapParser, Mapping};
7use crate::Parser;
8
9#[derive(Debug, Clone, Copy, Default)]
10pub struct Collect<C> {
11    phantom: PhantomData<fn() -> C>,
12}
13
14impl<V, C> Mapping<(V,)> for Collect<C>
15where
16    V: IntoIterator,
17    C: FromIterator<V::Item>,
18{
19    type RawOutput = (C,);
20
21    fn apply(&self, (value,): (V,)) -> (C,) {
22        (value.into_iter().collect(),)
23    }
24}
25
26/// Convert the output of `parser` from a `Vec<(K, V)>` or other collection of pairs
27/// into a `HashMap`.
28///
29/// For example, the parser `lines(alpha " = " u64)` produces a `Vec<(char, u64)>`.
30/// Wrapping that parser in `hash_map` makes it produce a `HashMap<char, u64>` instead:
31///
32/// ```
33/// # use aoc_parse::{parser, prelude::*};
34/// let p = parser!(hash_map(lines(alpha " = " u64)));
35///
36/// let h = p.parse("X = 33\nY = 75\n").unwrap();
37/// assert_eq!(h[&'X'], 33);
38/// assert_eq!(h[&'Y'], 75);
39/// ```
40pub fn hash_map<P, K, V>(parser: P) -> MapParser<P, Collect<HashMap<K, V>>>
41where
42    P: Parser,
43    P::Output: IntoIterator<Item = (K, V)>,
44{
45    MapParser {
46        inner: parser,
47        mapper: Collect::default(),
48    }
49}
50
51/// Convert the output of `parser` from a `Vec<V>` or other collection
52/// into a `HashSet`.
53///
54/// For example, the parser `alpha+` produces a `Vec<char>`,
55/// so `hash_set(alpha+)` produces a `HashSet<char>`:
56///
57/// ```
58/// # use aoc_parse::{parser, prelude::*};
59/// let p = parser!(hash_set(alpha+));
60///
61/// let set = p.parse("xZjZZd").unwrap();
62/// assert_eq!(set.len(), 4); // x Z j d
63/// assert!(set.contains(&'d'));
64/// assert!(!set.contains(&'r'));
65/// ```
66pub fn hash_set<P, V>(parser: P) -> MapParser<P, Collect<HashSet<V>>>
67where
68    P: Parser,
69    P::Output: IntoIterator<Item = V>,
70{
71    MapParser {
72        inner: parser,
73        mapper: Collect::default(),
74    }
75}
76
77/// Convert the output of `parser` from a `Vec<(K, V)>` or other collection of pairs
78/// into a `BTreeMap`.
79pub fn btree_map<P, K, V>(parser: P) -> MapParser<P, Collect<BTreeMap<K, V>>>
80where
81    P: Parser,
82    P::Output: IntoIterator<Item = (K, V)>,
83{
84    MapParser {
85        inner: parser,
86        mapper: Collect::default(),
87    }
88}
89
90/// Convert the output of `parser` from a `Vec<V>` or other collection
91/// into a `BTreeSet`.
92pub fn btree_set<P, V>(parser: P) -> MapParser<P, Collect<BTreeSet<V>>>
93where
94    P: Parser,
95    P::Output: IntoIterator<Item = V>,
96{
97    MapParser {
98        inner: parser,
99        mapper: Collect::default(),
100    }
101}
102
103/// Convert the output of `parser` from a `Vec<V>` or other collection
104/// into a `VecDeque`.
105pub fn vec_deque<P, V>(parser: P) -> MapParser<P, Collect<VecDeque<V>>>
106where
107    P: Parser,
108    P::Output: IntoIterator<Item = V>,
109{
110    // NOTE: A mapping that uses `Into` might be faster, but I'm not sure. The standard library has
111    // some specializations to do iterator-based colletion operations like this in-place.
112    MapParser {
113        inner: parser,
114        mapper: Collect::default(),
115    }
116}