azure_sdk_core_rs/
range.rs

1use crate::ba512_range::BA512Range;
2use std::convert::From;
3use std::fmt;
4use std::num::ParseIntError;
5use std::str::FromStr;
6
7#[derive(Debug, Copy, Clone, PartialEq)]
8pub struct Range {
9    pub start: u64,
10    pub end: u64,
11}
12
13impl Range {
14    pub fn new(start: u64, end: u64) -> Range {
15        Range { start, end }
16    }
17
18    pub fn len(&self) -> u64 {
19        self.end - self.start
20    }
21
22    pub fn is_empty(&self) -> bool {
23        self.end == self.start
24    }
25}
26
27#[derive(Debug, Clone, PartialEq)]
28pub enum ParseError {
29    SplitNotFound,
30    ParseIntError(ParseIntError),
31}
32
33impl<'a> From<&'a BA512Range> for Range {
34    fn from(ba: &'a BA512Range) -> Range {
35        Range {
36            start: ba.start(),
37            end: ba.end(),
38        }
39    }
40}
41
42impl From<std::ops::Range<u64>> for Range {
43    fn from(r: std::ops::Range<u64>) -> Self {
44        Self {
45            start: r.start,
46            end: r.end,
47        }
48    }
49}
50
51impl From<std::ops::Range<i32>> for Range {
52    fn from(r: std::ops::Range<i32>) -> Self {
53        Self {
54            start: r.start as u64,
55            end: r.end as u64,
56        }
57    }
58}
59
60impl From<std::ops::Range<usize>> for Range {
61    fn from(r: std::ops::Range<usize>) -> Self {
62        Self {
63            start: r.start as u64,
64            end: r.end as u64,
65        }
66    }
67}
68
69impl From<ParseIntError> for ParseError {
70    fn from(pie: ParseIntError) -> ParseError {
71        ParseError::ParseIntError(pie)
72    }
73}
74
75impl FromStr for Range {
76    type Err = ParseError;
77    fn from_str(s: &str) -> Result<Range, ParseError> {
78        let v = s.split('/').collect::<Vec<&str>>();
79        if v.len() != 2 {
80            return Err(ParseError::SplitNotFound);
81        }
82
83        let cp_start = v[0].parse::<u64>()?;
84        let cp_end = v[1].parse::<u64>()? + 1;
85
86        Ok(Range {
87            start: cp_start,
88            end: cp_end,
89        })
90    }
91}
92
93impl fmt::Display for Range {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        write!(f, "bytes={}-{}", self.start, self.end - 1)
96    }
97}
98
99#[cfg(test)]
100mod test {
101    use super::*;
102
103    #[test]
104    fn test_range_parse() {
105        let range = "1000/2000".parse::<Range>().unwrap();
106
107        assert_eq!(range.start, 1000);
108        assert_eq!(range.end, 2001);
109    }
110
111    #[test]
112    #[should_panic(expected = "ParseIntError(ParseIntError { kind: InvalidDigit })")]
113    fn test_range_parse_panic_1() {
114        "abba/2000".parse::<Range>().unwrap();
115    }
116
117    #[test]
118    #[should_panic(expected = "SplitNotFound")]
119    fn test_range_parse_panic_2() {
120        "1000-2000".parse::<Range>().unwrap();
121    }
122
123    #[test]
124    fn test_range_display() {
125        let range = Range {
126            start: 100,
127            end: 501,
128        };
129
130        let txt = format!("{}", range);
131
132        assert_eq!(txt, "bytes=100-500");
133    }
134}