pingora_cache/
variance.rs1use std::{borrow::Cow, collections::BTreeMap};
2
3use blake2::Digest;
4
5use crate::key::{Blake2b128, HashBinary};
6
7pub struct VarianceBuilder<'a> {
11 values: BTreeMap<Cow<'a, str>, Cow<'a, [u8]>>,
12}
13
14impl<'a> VarianceBuilder<'a> {
15 pub fn new() -> Self {
18 VarianceBuilder {
19 values: BTreeMap::new(),
20 }
21 }
22
23 pub fn add_value(&mut self, name: &'a str, value: &'a (impl AsRef<[u8]> + ?Sized)) {
26 self.values
27 .insert(name.into(), Cow::Borrowed(value.as_ref()));
28 }
29
30 pub fn add_owned_value(&mut self, name: &'a str, value: Vec<u8>) {
35 self.values.insert(name.into(), Cow::Owned(value));
36 }
37
38 pub fn add_owned_name_value(&mut self, name: String, value: Vec<u8>) {
41 self.values.insert(Cow::Owned(name), Cow::Owned(value));
42 }
43
44 pub fn has_variance(&self) -> bool {
46 !self.values.is_empty()
47 }
48
49 pub fn finalize(self) -> Option<HashBinary> {
51 const SALT: &[u8; 1] = &[0u8; 1];
52 if self.has_variance() {
53 let mut hash = Blake2b128::new();
54 for (name, value) in self.values.iter() {
55 hash.update(name.as_bytes());
56 hash.update(SALT);
57 hash.update(value);
58 hash.update(SALT);
59 }
60 Some(hash.finalize().into())
61 } else {
62 None
63 }
64 }
65}
66
67#[cfg(test)]
68mod test {
69 use super::*;
70
71 #[test]
72 fn test_basic() {
73 let key_empty = VarianceBuilder::new().finalize();
74 assert_eq!(None, key_empty);
75
76 let mut key_value = VarianceBuilder::new();
77 key_value.add_value("a", "a");
78 let key_value = key_value.finalize();
79
80 let mut key_owned_value = VarianceBuilder::new();
81 key_owned_value.add_owned_value("a", "a".as_bytes().to_vec());
82 let key_owned_value = key_owned_value.finalize();
83
84 assert_ne!(key_empty, key_value);
85 assert_ne!(key_empty, key_owned_value);
86 assert_eq!(key_value, key_owned_value);
87 }
88
89 #[test]
90 fn test_value_ordering() {
91 let mut key_abc = VarianceBuilder::new();
92 key_abc.add_value("a", "a");
93 key_abc.add_value("b", "b");
94 key_abc.add_value("c", "c");
95 let key_abc = key_abc.finalize().unwrap();
96
97 let mut key_bac = VarianceBuilder::new();
98 key_bac.add_value("b", "b");
99 key_bac.add_value("a", "a");
100 key_bac.add_value("c", "c");
101 let key_bac = key_bac.finalize().unwrap();
102
103 let mut key_cba = VarianceBuilder::new();
104 key_cba.add_value("c", "c");
105 key_cba.add_value("b", "b");
106 key_cba.add_value("a", "a");
107 let key_cba = key_cba.finalize().unwrap();
108
109 assert_eq!(key_abc, key_bac);
110 assert_eq!(key_abc, key_cba);
111 }
112
113 #[test]
114 fn test_value_overriding() {
115 let mut key_a = VarianceBuilder::new();
116 key_a.add_value("a", "a");
117 let key_a = key_a.finalize().unwrap();
118
119 let mut key_b = VarianceBuilder::new();
120 key_b.add_value("a", "b");
121 key_b.add_value("a", "a");
122 let key_b = key_b.finalize().unwrap();
123
124 assert_eq!(key_a, key_b);
125 }
126}