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
pub(crate) fn sanitize<T: AsRef<str>>(raw: T) -> String {
let mut escaped = raw
.as_ref()
.chars()
.map(|c| if c.is_ascii_alphanumeric() { c } else { '_' })
.peekable();
let prefix = if escaped.peek().map_or(false, |c| c.is_ascii_digit()) {
"key_"
} else if escaped.peek().map_or(false, |&c| c == '_') {
"key"
} else {
""
};
prefix.chars().chain(escaped).take(100).collect()
}
#[cfg(test)]
mod tests {
use super::*;
use std::borrow::Cow;
fn key_data() -> Vec<(&'static str, Cow<'static, str>, Cow<'static, str>)> {
vec![
(
"replace character",
"test/key-1".into(),
"test_key_1".into(),
),
(
"add prefix if starting with digit",
"0123456789".into(),
"key_0123456789".into(),
),
(
"add prefix if starting with _",
"_0123456789".into(),
"key_0123456789".into(),
),
(
"starts with _ after sanitization",
"/0123456789".into(),
"key_0123456789".into(),
),
(
"limits to 100",
"a".repeat(101).into(),
"a".repeat(100).into(),
),
(
"valid input",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789".into(),
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789".into(),
),
]
}
#[test]
fn sanitize_key_names() {
for (name, raw, sanitized) in key_data() {
assert_eq!(sanitize(raw), sanitized, "{} doesn't match", name)
}
}
}