1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::Counter;
use num_traits::Zero;
use std::borrow::Borrow;
use std::hash::{BuildHasher, Hash};
use std::ops::{Index, IndexMut};
impl<T, Q, N, S> Index<&'_ Q> for Counter<T, N, S>
where
T: Hash + Eq + Borrow<Q>,
Q: Hash + Eq,
N: Zero,
S: BuildHasher,
{
type Output = N;
/// Index in immutable contexts.
///
/// Returns a reference to a [`zero`] value for missing keys.
///
/// [`zero`]:
/// https://docs.rs/num-traits/latest/num_traits/identities/trait.Zero.html#tymethod.zero
///
/// ```
/// # use counter::Counter;
/// let counter = "aabbcc".chars().collect::<Counter<_>>();
/// assert_eq!(counter[&'a'], 2);
/// assert_eq!(counter[&'b'], 2);
/// assert_eq!(counter[&'c'], 2);
/// assert_eq!(counter[&'d'], 0);
/// ```
///
/// Note that the [`zero`] is a struct field but not one of the values of the inner
/// [`HashMap`]. This method does not modify any existing value.
///
/// [`zero`]:
/// https://docs.rs/num-traits/latest/num_traits/identities/trait.Zero.html#tymethod.zero
/// [`HashMap`]: https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html
///
/// ```
/// # use counter::Counter;
/// let counter = "".chars().collect::<Counter<_>>();
/// assert_eq!(counter[&'a'], 0);
/// assert_eq!(counter.get(&'a'), None); // as `Deref<Target = HashMap<_, _>>`
/// ```
fn index(&self, key: &'_ Q) -> &N {
self.map.get(key).unwrap_or(&self.zero)
}
}
impl<T, Q, N, S> IndexMut<&'_ Q> for Counter<T, N, S>
where
T: Hash + Eq + Borrow<Q>,
Q: Hash + Eq + ToOwned<Owned = T>,
N: Zero,
S: BuildHasher,
{
/// Index in mutable contexts.
///
/// If the given key is not present, creates a new entry and initializes it with a [`zero`]
/// value.
///
/// [`zero`]:
/// https://docs.rs/num-traits/latest/num_traits/identities/trait.Zero.html#tymethod.zero
///
/// ```
/// # use counter::Counter;
/// let mut counter = "aabbcc".chars().collect::<Counter<_>>();
/// counter[&'c'] += 1;
/// counter[&'d'] += 1;
/// assert_eq!(counter[&'c'], 3);
/// assert_eq!(counter[&'d'], 1);
/// ```
///
/// Unlike `Index::index`, the returned mutable reference to the [`zero`] is actually one of the
/// values of the inner [`HashMap`].
///
/// [`zero`]:
/// https://docs.rs/num-traits/latest/num_traits/identities/trait.Zero.html#tymethod.zero
/// [`HashMap`]: https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html
///
/// ```
/// # use counter::Counter;
/// let mut counter = "".chars().collect::<Counter<_>>();
/// assert_eq!(counter.get(&'a'), None); // as `Deref<Target = HashMap<_, _>>`
/// let _ = &mut counter[&'a'];
/// assert_eq!(counter.get(&'a'), Some(&0));
/// ```
fn index_mut(&mut self, key: &'_ Q) -> &mut N {
self.map.entry(key.to_owned()).or_insert_with(N::zero)
}
}