azure-sdk-rust 0.1.2

**Under very heavy development** It will most likely break! Microsoft Azure SDK for Rust. Originally designed to stay as close as possible to aws-sdk-rust but design decision changed to make it Azure specific. An abstract library will be used to manage the differences between the two for those needing cross cloud access.
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");
    }
}