1use crate::seq::Shift;
2use patterns_macros::because;
3use std::collections::BTreeMap;
4
5pub fn looked<K: Ord, V: Clone>(map: &BTreeMap<K, V>, key: &K) -> Option<V> {
6 map.get(key).cloned()
7}
8because!(looked, "one entry of a keyed table by its key, cloned, so a reducer reads a row the way found reads a list and never indexes");
9
10pub fn placed_in<K: Ord, V>(map: BTreeMap<K, V>, key: K, value: V) -> BTreeMap<K, V> {
11 let mut out = map;
12 out.insert(key, value);
13 out
14}
15because!(placed_in, "a keyed table with one entry set, taking the table by value and handing it back, so a reducer that owns its state updates a row without a copy of every other row");
16
17pub fn shifted_in<M, K: Ord, V: Shift<M> + Clone>(map: BTreeMap<K, V>, key: K, fresh: V, by: V::By) -> BTreeMap<K, V> {
18 let mut out = map;
19 let current = out.remove(&key).unwrap_or(fresh);
20 out.insert(key, current.shifted(by));
21 out
22}
23because!(shifted_in, "one row of a keyed table moved by a step, starting from a fresh row when the key is new, which is how an event touches one account among thousands without the table being rebuilt");
24
25pub fn entries<K: Clone, V: Clone>(map: &BTreeMap<K, V>) -> Vec<(K, V)> {
26 map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
27}
28because!(entries, "a keyed table as a list of pairs in key order, the form a store writes and a test compares");
29
30pub fn rows<K, V: Clone>(map: &BTreeMap<K, V>) -> Vec<V> {
31 map.values().cloned().collect()
32}
33because!(rows, "the values of a keyed table in key order without their keys, for a caller that wants the rows and already knows how they were keyed");
34
35pub fn latest<K: Ord + Copy, V: Clone>(map: &BTreeMap<K, V>) -> Option<(K, V)> {
36 map.iter().next_back().map(|(k, v)| (*k, v.clone()))
37}
38because!(latest, "the highest keyed entry of a table, which for a table keyed by day is the newest day it holds");
39
40pub fn earliest<K: Ord + Copy, V: Clone>(map: &BTreeMap<K, V>) -> Option<(K, V)> {
41 map.iter().next().map(|(k, v)| (*k, v.clone()))
42}
43because!(earliest, "the lowest keyed entry of a table, the oldest day of a series, which a lookup before the series began falls back to");
44
45pub fn at_or_before<K: Ord + Copy, V: Clone>(map: &BTreeMap<K, V>, key: K) -> Option<V> {
46 map.range(..=key).next_back().map(|(_, v)| v.clone())
47}
48because!(at_or_before, "the newest entry at or before a key, which is how a value known only on some days is carried forward onto the days between, in one ordered lookup rather than a scan");
49
50pub fn from_key<K: Ord + Copy, V: Clone>(map: &BTreeMap<K, V>, key: K) -> Vec<(K, V)> {
51 map.range(key..).map(|(k, v)| (*k, v.clone())).collect()
52}
53because!(from_key, "every entry of a table from a key onward in order, the tail of a series a reader asked for from a day");
54
55pub fn removed<K: Ord, V>(map: BTreeMap<K, V>, key: &K) -> BTreeMap<K, V> {
56 let mut out = map;
57 out.remove(key);
58 out
59}
60because!(removed, "a keyed table with one entry taken out, by value like placed_in, for the row an event retires");
61
62pub fn merged<K: Ord, V>(into: BTreeMap<K, V>, from: BTreeMap<K, V>) -> BTreeMap<K, V> {
63 let mut out = into;
64 out.extend(from);
65 out
66}
67because!(merged, "two keyed tables as one, the second winning on a shared key, which is how rows fetched for a batch are laid over the rows already held");
68
69pub fn keys<K: Clone, V>(map: &BTreeMap<K, V>) -> Vec<K> {
70 map.keys().cloned().collect()
71}
72because!(keys, "the keys of a table in order, for a caller that needs to know which days or which accounts a batch touched");
73
74pub fn tabled<K: Ord, V>(pairs: Vec<(K, V)>) -> BTreeMap<K, V> {
75 pairs.into_iter().collect()
76}
77because!(tabled, "a list of pairs as a keyed table, the reverse of entries, so a store's rows become the state a reducer works on");
78
79pub fn count_in<K, V>(map: &BTreeMap<K, V>) -> usize {
80 map.len()
81}
82because!(count_in, "how many entries a keyed table holds, the size of a table as size is the size of a list");
83
84pub fn latest_value<K: Ord, V: Clone>(map: &BTreeMap<K, V>) -> Option<V> {
85 map.values().next_back().cloned()
86}
87because!(latest_value, "the value under the highest key, or nothing when the table is empty, the newest reading a tile shows or leaves blank");
88
89pub fn latest_value_or<K: Ord, V: Clone>(map: &BTreeMap<K, V>, fallback: V) -> V {
90 map.values().next_back().cloned().unwrap_or(fallback)
91}
92because!(latest_value_or, "the value under the highest key or a fallback when the table is empty, today's price or zero");
93
94pub fn union_keys<K: Ord + Copy, V>(maps: &[&BTreeMap<K, V>]) -> Vec<K> {
95 let mut keys = std::collections::BTreeSet::new();
96 for map in maps {
97 keys.extend(map.keys().copied());
98 }
99 keys.into_iter().collect()
100}
101because!(union_keys, "every key any of several tables holds, once each and in order, the axis a chart over more than one series walks");
102
103pub fn latest_key_or<K: Ord + Copy, V>(map: &BTreeMap<K, V>, fallback: K) -> K {
104 map.keys().next_back().copied().unwrap_or(fallback)
105}
106because!(latest_key_or, "the highest key of a table or a fallback when it is empty, which is where a fetch of a day series resumes from: the newest day held, or today when nothing is held yet");
107
108pub fn empty_table<K: Ord, V>() -> BTreeMap<K, V> {
109 BTreeMap::new()
110}
111because!(empty_table, "a keyed table with nothing in it, the counterpart of an empty list, since a reducer's initial state may only call the library and a constructor is not a pattern");
112
113pub fn empty_set<K: Ord>() -> std::collections::BTreeSet<K> {
114 std::collections::BTreeSet::new()
115}
116because!(empty_set, "a set with nothing in it, the counterpart of empty_table for a reducer that only needs to know whether a pair has been seen");