azure_core/request_options/
range.rs
1use crate::error::{Error, ErrorKind, ResultExt};
2use crate::headers::{self, AsHeaders, HeaderName, HeaderValue};
3use std::fmt;
4use std::ops::{Range as StdRange, RangeFrom};
5use std::str::FromStr;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum Range {
9 Range(StdRange<u64>),
10 RangeFrom(RangeFrom<u64>),
11}
12
13impl Range {
14 pub fn new(start: u64, end: u64) -> Range {
15 (start..end).into()
16 }
17
18 fn optional_len(&self) -> Option<u64> {
19 match self {
20 Range::Range(r) => Some(r.end - r.start),
21 Range::RangeFrom(_) => None,
22 }
23 }
24}
25
26impl From<StdRange<u64>> for Range {
27 fn from(r: StdRange<u64>) -> Self {
28 Self::Range(r)
29 }
30}
31
32impl From<RangeFrom<u64>> for Range {
33 fn from(r: RangeFrom<u64>) -> Self {
34 Self::RangeFrom(r)
35 }
36}
37
38impl From<StdRange<usize>> for Range {
39 fn from(r: StdRange<usize>) -> Self {
40 (r.start as u64..r.end as u64).into()
41 }
42}
43
44impl From<RangeFrom<usize>> for Range {
45 fn from(r: RangeFrom<usize>) -> Self {
46 (r.start as u64..).into()
47 }
48}
49
50impl AsHeaders for Range {
51 type Iter = std::vec::IntoIter<(HeaderName, HeaderValue)>;
52
53 fn as_headers(&self) -> Self::Iter {
54 let mut headers = vec![(headers::MS_RANGE, format!("{self}").into())];
55 if let Some(len) = self.optional_len() {
56 if len < 1024 * 1024 * 4 {
57 headers.push((
58 headers::RANGE_GET_CONTENT_CRC64,
59 HeaderValue::from_static("true"),
60 ));
61 }
62 }
63 headers.into_iter()
64 }
65}
66
67impl FromStr for Range {
68 type Err = Error;
69 fn from_str(s: &str) -> crate::Result<Range> {
70 let v = s.split('/').collect::<Vec<&str>>();
71 if v.len() != 2 {
72 return Err(Error::with_message(ErrorKind::Other, || {
73 format!(
74 "expected token \"{}\" not found when parsing Range from \"{}\"",
75 "/", s
76 )
77 }));
78 }
79
80 let cp_start = v[0].parse::<u64>().map_kind(ErrorKind::DataConversion)?;
81 let cp_end = v[1].parse::<u64>().map_kind(ErrorKind::DataConversion)? + 1;
82
83 Ok((cp_start..cp_end).into())
84 }
85}
86
87impl fmt::Display for Range {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 match self {
90 Range::Range(r) => write!(f, "bytes={}-{}", r.start, r.end - 1),
91 Range::RangeFrom(r) => write!(f, "bytes={}-", r.start),
92 }
93 }
94}
95
96#[cfg(test)]
97mod test {
98 use super::*;
99
100 #[test]
101 fn test_range_parse() {
102 let range = "1000/2000".parse::<Range>().unwrap();
103 assert_eq!(range, Range::new(1000, 2001));
104 }
105
106 #[test]
107 fn test_range_parse_panic_1() {
108 "abba/2000".parse::<Range>().unwrap_err();
109 }
110
111 #[test]
112 fn test_range_parse_panic_2() {
113 "1000-2000".parse::<Range>().unwrap_err();
114 }
115
116 #[test]
117 fn test_range_display() {
118 let range = Range::new(100, 501);
119 let txt = format!("{range}");
120 assert_eq!(txt, "bytes=100-500");
121 }
122}