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
extern crate unidecode;
use unidecode::unidecode_char;
use std::ascii::AsciiExt;
pub fn slugify<S: AsRef<str>>(s: S) -> String {
let s = s.as_ref();
let mut string = String::with_capacity(s.len());
{
let output = unsafe { string.as_mut_vec() };
let mut dash = true;
let mut push_char = |c: char| {
match c {
'a'...'z'|'0'...'9'|'A'...'Z' => {
match c {
'a'...'z'|'0'...'9' => output.push(c as u8),
'A'...'Z' => output.push((c as u8)-('A' as u8)+('a' as u8)),
_ => unreachable!(),
}
dash = false;
},
_ => if dash {
match c {
'@' => output.extend(b"at-"),
'&' => output.extend(b"and-"),
_ => {}
}
} else {
match c {
'@' => output.extend(b"-at-"),
'&' => output.extend(b"-and-"),
_ => output.push(b'-'),
}
dash = true;
}
}
};
for c in s.chars() {
if c.is_ascii() {
(push_char)(c);
} else {
for c in unidecode_char(c).chars() {
(push_char)(c);
}
}
}
}
if string.ends_with('-') {
string.pop();
}
string.shrink_to_fit();
string
}