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
72
73
74
75
76
77
78
use {
core::{
ops::RangeInclusive,
str::FromStr,
},
crate::{
ParseSemverError, Semver, SemverErrorKind, Range,
range::Kind,
},
};
const MARK_SIZE: usize = 1;
#[derive(Debug)]
enum Mark {
Inclusive,
Exclusive,
}
#[test]
fn test_mark() {
for c in &['[', ']', '(', ')'] {
assert_eq!(c.len_utf8(), MARK_SIZE);
}
}
impl FromStr for Range {
type Err = ParseSemverError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
const MAX_LEN: usize = 4096;
if s.len() > MAX_LEN {
return Err(ParseSemverError {
kind: SemverErrorKind::Other(alloc::format!("String is too long, max length supported: {} bytes", MAX_LEN)),
});
}
let err = || ParseSemverError {
kind: SemverErrorKind::Other(alloc::format!("Invalid range: {:?}", s)),
};
let open_mark = match s.chars().next() {
Some('[') => Mark::Inclusive,
Some('(') => Mark::Exclusive,
_ => return Err(err()),
};
let close_mark = if s.ends_with(']') {
Mark::Inclusive
} else if s.ends_with(')') {
Mark::Exclusive
} else {
return Err(err());
};
let mut parts = s[MARK_SIZE .. s.len() - MARK_SIZE].trim().split(',');
match (parts.next().map(|from| Semver::from_str(from)), parts.next().map(|to| Semver::from_str(to)), parts.next()) {
(Some(Ok(from)), Some(Ok(to)), None) => Ok(Self {
range: RangeInclusive::new(from, to),
kind: match (open_mark, close_mark) {
(Mark::Inclusive, Mark::Inclusive) => Kind::InclusiveInclusive,
(Mark::Inclusive, Mark::Exclusive) => Kind::InclusiveExclusive,
(Mark::Exclusive, Mark::Exclusive) => Kind::ExclusiveExclusive,
(Mark::Exclusive, Mark::Inclusive) => Kind::ExclusiveInclusive,
},
}),
_ => Err(err()),
}
}
}