1use once_cell::sync::Lazy;
2use siphasher::sip128::SipHasher13;
3use std::borrow::Cow;
4
5pub const DEFAULT_MINIFY_KEY: bool = false;
7
8pub const DEFAULT_MINIFY_KEY_LEN: usize = 24;
10
11pub const DEFAULT_MINIFY_KEY_PREFIX: &str = "";
13
14pub const DEFAULT_MINIFY_KEY_THRESH: usize = 127;
16
17static TR_KEY_HASHER: Lazy<SipHasher13> = Lazy::new(SipHasher13::new);
19
20pub fn hash128<T: AsRef<[u8]> + ?Sized>(value: &T) -> u128 {
22 TR_KEY_HASHER.hash(value.as_ref()).as_u128()
23}
24
25pub fn minify_key<'r>(value: &'r str, len: usize, prefix: &str, threshold: usize) -> Cow<'r, str> {
40 if value.len() <= threshold {
41 return Cow::Borrowed(value);
42 }
43 let encoded = base62::encode(hash128(value));
44 let len = len.min(encoded.len());
45 format!("{}{}", prefix, &encoded[..len]).into()
46}
47
48pub trait MinifyKey<'a> {
50 fn minify_key(&'a self, len: usize, prefix: &str, threshold: usize) -> Cow<'a, str>;
52}
53
54impl<'a> MinifyKey<'a> for str {
55 #[inline]
56 fn minify_key(&'a self, len: usize, prefix: &str, threshold: usize) -> Cow<'a, str> {
57 minify_key(self, len, prefix, threshold)
58 }
59}
60
61impl<'a> MinifyKey<'a> for &str {
62 #[inline]
63 fn minify_key(&'a self, len: usize, prefix: &str, threshold: usize) -> Cow<'a, str> {
64 minify_key(self, len, prefix, threshold)
65 }
66}
67
68impl<'a> MinifyKey<'a> for String {
69 #[inline]
70 fn minify_key(&'a self, len: usize, prefix: &str, threshold: usize) -> Cow<'a, str> {
71 if self.len() <= threshold {
72 return Cow::Borrowed(self);
73 }
74 minify_key(self, len, prefix, threshold)
75 }
76}
77
78impl<'a> MinifyKey<'a> for &String {
79 #[inline]
80 fn minify_key(&'a self, len: usize, prefix: &str, threshold: usize) -> Cow<'a, str> {
81 if self.len() <= threshold {
82 return Cow::from(*self);
83 }
84 minify_key(self, len, prefix, threshold)
85 }
86}
87
88impl<'a> MinifyKey<'a> for Cow<'a, str> {
89 #[inline]
90 fn minify_key(&'a self, len: usize, prefix: &str, threshold: usize) -> Cow<'a, str> {
91 if self.len() <= threshold {
92 return Cow::Borrowed(self);
93 }
94 minify_key(self, len, prefix, threshold)
95 }
96}
97
98impl<'a> MinifyKey<'a> for &Cow<'a, str> {
99 #[inline]
100 fn minify_key(&'a self, len: usize, prefix: &str, threshold: usize) -> Cow<'a, str> {
101 if self.len() <= threshold {
102 return Cow::Borrowed(*self);
103 }
104 minify_key(self, len, prefix, threshold)
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_minify_key() {
114 let msg = "Hello, world!";
115 assert_eq!(
116 minify_key(msg, 24, DEFAULT_MINIFY_KEY_PREFIX, 0),
117 "1LokVzuiIrh1xByyZG4wjZ"
118 );
119 assert_eq!(
120 msg.minify_key(24, DEFAULT_MINIFY_KEY_PREFIX, 0),
121 "1LokVzuiIrh1xByyZG4wjZ"
122 );
123 let msg = "Hello, world!".to_string();
124 assert_eq!(
125 minify_key(&msg, 24, DEFAULT_MINIFY_KEY_PREFIX, 0),
126 "1LokVzuiIrh1xByyZG4wjZ"
127 );
128 assert_eq!(
129 msg.minify_key(24, DEFAULT_MINIFY_KEY_PREFIX, 0),
130 "1LokVzuiIrh1xByyZG4wjZ"
131 );
132 assert_eq!(
133 msg.minify_key(24, DEFAULT_MINIFY_KEY_PREFIX, 128),
134 "Hello, world!"
135 );
136 let msg = &msg;
137 assert_eq!(
138 msg.minify_key(24, DEFAULT_MINIFY_KEY_PREFIX, 0),
139 "1LokVzuiIrh1xByyZG4wjZ"
140 );
141 let msg = Cow::Owned("Hello, world!".to_owned());
142 assert_eq!(
143 minify_key(&msg, 24, DEFAULT_MINIFY_KEY_PREFIX, 0),
144 "1LokVzuiIrh1xByyZG4wjZ"
145 );
146 assert_eq!(
147 msg.minify_key(24, DEFAULT_MINIFY_KEY_PREFIX, 0),
148 "1LokVzuiIrh1xByyZG4wjZ"
149 );
150 assert_eq!(
151 msg.minify_key(24, DEFAULT_MINIFY_KEY_PREFIX, 128),
152 "Hello, world!"
153 );
154 assert_eq!("".minify_key(24, DEFAULT_MINIFY_KEY_PREFIX, 0), "");
155 assert_eq!(
156 "1".minify_key(24, DEFAULT_MINIFY_KEY_PREFIX, 0),
157 "knx7vOJBRfzgQvNfEkbEi"
158 );
159 assert_eq!("1".minify_key(24, "t_", 0), "t_knx7vOJBRfzgQvNfEkbEi");
160 }
161}