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
use std::ops::Index;
pub struct Tags<'a> {
raw: &'a str,
}
impl<'a> Tags<'a> {
pub fn new(raw: &'a str) -> Tags<'a> {
Tags {
raw,
}
}
pub fn len(&self) -> usize {
self.raw.len()
}
pub fn iter(&self) -> impl Iterator<Item=(&'a str, &'a str)> {
self.raw.split(';')
.map(|kv| {
let mut split = kv.split('=');
(split.next().unwrap(), split.next().unwrap())
})
}
fn find(&self, key: &'a str) -> Option<(usize, usize)> {
self.raw.find(key)
.map(|start| {
start + key.len() + 1
})
.and_then(|start| {
self.raw[start..].find(';')
.or(self.raw[start..].find(' '))
.or(Some(self.raw.len() - start))
.map(|end| (start, start + end))
})
}
}
impl<'a> Index<&'a str> for Tags<'a> {
type Output = str;
fn index(&self, key: &'a str) -> &Self::Output {
let (start, end) = self.find(key).unwrap();
&self.raw[start..end]
}
}