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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
use std::str::FromStr; use std::fmt; use std::num::ParseIntError; use std::convert::From; use azure::core::ba512_range::BA512Range; #[derive(Debug, Copy, Clone, PartialEq)] pub struct Range { pub start: u64, pub end: u64, } #[derive(Debug, Clone, PartialEq)] pub enum ParseError { SplitNotFound, ParseIntError(ParseIntError), } impl<'a> From<&'a BA512Range> for Range { fn from(ba: &'a BA512Range) -> Range { Range { start: ba.start(), end: ba.end(), } } } impl From<ParseIntError> for ParseError { fn from(pie: ParseIntError) -> ParseError { ParseError::ParseIntError(pie) } } impl FromStr for Range { type Err = ParseError; fn from_str(s: &str) -> Result<Range, ParseError> { let v = s.split("/").collect::<Vec<&str>>(); if v.len() != 2 { return Err(ParseError::SplitNotFound); } let cp_start = try!(v[0].parse::<u64>()); let cp_end = try!(v[1].parse::<u64>()); Ok(Range { start: cp_start, end: cp_end, }) } } impl fmt::Display for Range { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "bytes={}-{}", self.start, self.end) } } #[cfg(test)] mod test { use super::*; #[test] fn test_range_parse() { let range = "1000/2000".parse::<Range>().unwrap(); assert_eq!(range.start, 1000); assert_eq!(range.end, 2000); } #[test] #[should_panic(expected = "ParseIntError(ParseIntError { kind: InvalidDigit })")] fn test_range_parse_panic_1() { "abba/2000".parse::<Range>().unwrap(); } #[test] #[should_panic(expected = "SplitNotFound")] fn test_range_parse_panic_2() { "1000-2000".parse::<Range>().unwrap(); } #[test] fn test_range_display() { let range = Range { start: 100, end: 500, }; let txt = format!("{}", range); assert_eq!(txt, "bytes=100-500"); } }