11use std:: fmt:: { self , Display } ;
22use std:: str:: FromStr ;
33
4- use header:: { Header , HeaderFormat , RangeUnit } ;
4+ use header:: { Header , HeaderFormat } ;
55use header:: parsing:: { from_one_raw_str, from_one_comma_delimited} ;
66
77/// `Range` header, defined in [RFC7233](https://tools.ietf.org/html/rfc7233#section-3.1)
@@ -16,43 +16,58 @@ use header::parsing::{from_one_raw_str, from_one_comma_delimited};
1616/// Range = byte-ranges-specifier / other-ranges-specifier
1717/// other-ranges-specifier = other-range-unit "=" other-range-set
1818/// other-range-set = 1*VCHAR
19+ ///
20+ /// bytes-unit = "bytes"
21+ ///
22+ /// byte-ranges-specifier = bytes-unit "=" byte-range-set
23+ /// byte-range-set = 1#(byte-range-spec / suffix-byte-range-spec)
24+ /// byte-range-spec = first-byte-pos "-" [last-byte-pos]
25+ /// first-byte-pos = 1*DIGIT
26+ /// last-byte-pos = 1*DIGIT
1927/// ```
2028///
2129/// # Example values
2230/// * `bytes=1000-`
2331/// * `bytes=-2000`
2432/// * `bytes=0-1,30-40`
25- /// * `custom_unit=0-123,-200`
33+ /// * `bytes=0-10,20-90,-100`
34+ /// * `custom_unit=0-123`
35+ /// * `custom_unit=xxx-yyy`
2636///
2737/// # Examples
2838/// ```
29- /// use hyper::header::{Headers, Range, RangeSpec, RangeUnit };
39+ /// use hyper::header::{Headers, Range, ByteRangeSpec };
3040///
3141/// let mut headers = Headers::new();
42+ /// headers.set(Range::Bytes(
43+ /// vec![ByteRangeSpec::FromTo(1, 100), ByteRangeSpec::AllFrom(200)]
44+ /// ));
3245///
33- /// headers.set(Range {
34- /// unit: RangeUnit::Bytes,
35- /// ranges: vec![RangeSpec::FromTo(1, 100), RangeSpec::AllFrom(200)]
36- /// });
46+ /// headers.clear();
47+ /// headers.set(Range::Unregistered("letters".to_owned(), "a-f".to_owned()));
3748/// ```
3849/// ```
3950/// use hyper::header::{Headers, Range};
4051///
4152/// let mut headers = Headers::new();
4253/// headers.set(Range::bytes(1, 100));
54+ ///
55+ /// headers.clear();
56+ /// headers.set(Range::bytes_multi(vec![(1, 100), (200, 300)]));
4357/// ```
4458#[ derive( PartialEq , Clone , Debug ) ]
45- pub struct Range {
46- /// Unit of the Range i.e. bytes
47- pub unit : RangeUnit ,
48- /// Set of ranges as defined in the HTTP spec
49- pub ranges : Vec < RangeSpec > ,
59+ pub enum Range {
60+ /// Byte range
61+ Bytes ( Vec < ByteRangeSpec > ) ,
62+ /// Custom range, with unit not registered at IANA
63+ /// (`other-range-unit`: String , `other-range-set`: String)
64+ Unregistered ( String , String )
5065}
5166
52- /// Each ' Range' header can contain one or more RangeSpecs .
53- /// Each RangeSpec defines a range of units to fetch
67+ /// Each Range::Bytes header can contain one or more ByteRangeSpecs .
68+ /// Each ByteRangeSpec defines a range of bytes to fetch
5469#[ derive( PartialEq , Clone , Debug ) ]
55- pub enum RangeSpec {
70+ pub enum ByteRangeSpec {
5671 /// Get all bytes between x and y ("x-y")
5772 FromTo ( u64 , u64 ) ,
5873 /// Get all bytes starting from x ("x-")
@@ -64,36 +79,46 @@ pub enum RangeSpec {
6479impl Range {
6580 /// Get the most common byte range header ("bytes=from-to")
6681 pub fn bytes ( from : u64 , to : u64 ) -> Range {
67- Range {
68- unit : RangeUnit :: Bytes ,
69- ranges : vec ! [ RangeSpec :: FromTo ( from, to) ] ,
70- }
82+ Range :: Bytes ( vec ! [ ByteRangeSpec :: FromTo ( from, to) ] )
83+ }
84+
85+ /// Get byte range header with multiple subranges
86+ /// ("bytes=from1-to1,from2-to2,fromX-toX")
87+ pub fn bytes_multi ( ranges : Vec < ( u64 , u64 ) > ) -> Range {
88+ Range :: Bytes ( ranges. iter ( ) . map ( |r| ByteRangeSpec :: FromTo ( r. 0 , r. 1 ) ) . collect ( ) )
7189 }
7290}
7391
7492
75- impl fmt:: Display for RangeSpec {
93+ impl fmt:: Display for ByteRangeSpec {
7694 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
7795 match * self {
78- RangeSpec :: FromTo ( from, to) => write ! ( f, "{}-{}" , from, to) ,
79- RangeSpec :: Last ( pos) => write ! ( f, "-{}" , pos) ,
80- RangeSpec :: AllFrom ( pos) => write ! ( f, "{}-" , pos) ,
96+ ByteRangeSpec :: FromTo ( from, to) => write ! ( f, "{}-{}" , from, to) ,
97+ ByteRangeSpec :: Last ( pos) => write ! ( f, "-{}" , pos) ,
98+ ByteRangeSpec :: AllFrom ( pos) => write ! ( f, "{}-" , pos) ,
8199 }
82100 }
83101}
84102
85103
86104impl fmt:: Display for Range {
87105 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
88- try!( write ! ( f, "{}=" , self . unit) ) ;
89-
90- for ( i, range) in self . ranges . iter ( ) . enumerate ( ) {
91- if i != 0 {
92- try!( f. write_str ( "," ) ) ;
93- }
94- try!( Display :: fmt ( range, f) ) ;
106+ match * self {
107+ Range :: Bytes ( ref ranges) => {
108+ try!( write ! ( f, "bytes=" ) ) ;
109+
110+ for ( i, range) in ranges. iter ( ) . enumerate ( ) {
111+ if i != 0 {
112+ try!( f. write_str ( "," ) ) ;
113+ }
114+ try!( Display :: fmt ( range, f) ) ;
115+ }
116+ Ok ( ( ) )
117+ } ,
118+ Range :: Unregistered ( ref unit, ref range_str) => {
119+ write ! ( f, "{}={}" , unit, range_str)
120+ } ,
95121 }
96- Ok ( ( ) )
97122 }
98123}
99124
@@ -104,38 +129,42 @@ impl FromStr for Range {
104129 let mut iter = s. splitn ( 2 , "=" ) ;
105130
106131 match ( iter. next ( ) , iter. next ( ) ) {
107- ( Some ( unit ) , Some ( ranges) ) => {
108- match ( RangeUnit :: from_str ( unit ) , from_one_comma_delimited ( ranges. as_bytes ( ) ) ) {
109- ( Ok ( unit ) , Ok ( ranges) ) => {
132+ ( Some ( "bytes" ) , Some ( ranges) ) => {
133+ match from_one_comma_delimited ( ranges. as_bytes ( ) ) {
134+ Ok ( ranges) => {
110135 if ranges. is_empty ( ) {
111136 return Err ( :: Error :: Header ) ;
112137 }
113- Ok ( Range { unit : unit , ranges : ranges} )
138+ Ok ( Range :: Bytes ( ranges) )
114139 } ,
115- _ => Err ( :: Error :: Header )
140+ Err ( _ ) => Err ( :: Error :: Header )
116141 }
117142 }
143+ ( Some ( unit) , Some ( range_str) ) if unit != "" && range_str != "" => {
144+ Ok ( Range :: Unregistered ( unit. to_owned ( ) , range_str. to_owned ( ) ) )
145+
146+ } ,
118147 _ => Err ( :: Error :: Header )
119148 }
120149 }
121150}
122151
123- impl FromStr for RangeSpec {
152+ impl FromStr for ByteRangeSpec {
124153 type Err = :: Error ;
125154
126- fn from_str ( s : & str ) -> :: Result < RangeSpec > {
155+ fn from_str ( s : & str ) -> :: Result < ByteRangeSpec > {
127156 let mut parts = s. splitn ( 2 , "-" ) ;
128157
129158 match ( parts. next ( ) , parts. next ( ) ) {
130159 ( Some ( "" ) , Some ( end) ) => {
131- end. parse ( ) . or ( Err ( :: Error :: Header ) ) . map ( |end| RangeSpec :: Last ( end) )
160+ end. parse ( ) . or ( Err ( :: Error :: Header ) ) . map ( |end| ByteRangeSpec :: Last ( end) )
132161 } ,
133162 ( Some ( start) , Some ( "" ) ) => {
134- start. parse ( ) . or ( Err ( :: Error :: Header ) ) . map ( |start| RangeSpec :: AllFrom ( start) )
163+ start. parse ( ) . or ( Err ( :: Error :: Header ) ) . map ( |start| ByteRangeSpec :: AllFrom ( start) )
135164 } ,
136165 ( Some ( start) , Some ( end) ) => {
137166 match ( start. parse ( ) , end. parse ( ) ) {
138- ( Ok ( start) , Ok ( end) ) if start <= end => Ok ( RangeSpec :: FromTo ( start, end) ) ,
167+ ( Ok ( start) , Ok ( end) ) if start <= end => Ok ( ByteRangeSpec :: FromTo ( start, end) ) ,
139168 _ => Err ( :: Error :: Header )
140169 }
141170 } ,
@@ -164,7 +193,7 @@ impl HeaderFormat for Range {
164193}
165194
166195#[ test]
167- fn test_parse_valid ( ) {
196+ fn test_parse_bytes_range_valid ( ) {
168197 let r: Range = Header :: parse_header ( & [ b"bytes=1-100" . to_vec ( ) ] ) . unwrap ( ) ;
169198 let r2: Range = Header :: parse_header ( & [ b"bytes=1-100,-" . to_vec ( ) ] ) . unwrap ( ) ;
170199 let r3 = Range :: bytes ( 1 , 100 ) ;
@@ -173,21 +202,39 @@ fn test_parse_valid() {
173202
174203 let r: Range = Header :: parse_header ( & [ b"bytes=1-100,200-" . to_vec ( ) ] ) . unwrap ( ) ;
175204 let r2: Range = Header :: parse_header ( & [ b"bytes= 1-100 , 101-xxx, 200- " . to_vec ( ) ] ) . unwrap ( ) ;
176- let r3 = Range {
177- unit : RangeUnit :: Bytes ,
178- ranges : vec ! [ RangeSpec :: FromTo ( 1 , 100 ) , RangeSpec :: AllFrom ( 200 ) ]
179- } ;
205+ let r3 = Range :: Bytes (
206+ vec ! [ ByteRangeSpec :: FromTo ( 1 , 100 ) , ByteRangeSpec :: AllFrom ( 200 ) ]
207+ ) ;
180208 assert_eq ! ( r, r2) ;
181209 assert_eq ! ( r2, r3) ;
182210
183- let r: Range = Header :: parse_header ( & [ b"custom=1-100,-100" . to_vec ( ) ] ) . unwrap ( ) ;
184- let r2: Range = Header :: parse_header ( & [ b"custom=1-100, ,,-100" . to_vec ( ) ] ) . unwrap ( ) ;
185- let r3 = Range {
186- unit : RangeUnit :: Unregistered ( "custom" . to_owned ( ) ) ,
187- ranges : vec ! [ RangeSpec :: FromTo ( 1 , 100 ) , RangeSpec :: Last ( 100 ) ]
188- } ;
211+ let r: Range = Header :: parse_header ( & [ b"bytes=1-100,-100" . to_vec ( ) ] ) . unwrap ( ) ;
212+ let r2: Range = Header :: parse_header ( & [ b"bytes=1-100, ,,-100" . to_vec ( ) ] ) . unwrap ( ) ;
213+ let r3 = Range :: Bytes (
214+ vec ! [ ByteRangeSpec :: FromTo ( 1 , 100 ) , ByteRangeSpec :: Last ( 100 ) ]
215+ ) ;
189216 assert_eq ! ( r, r2) ;
190217 assert_eq ! ( r2, r3) ;
218+
219+ let r: Range = Header :: parse_header ( & [ b"custom=1-100,-100" . to_vec ( ) ] ) . unwrap ( ) ;
220+ let r2 = Range :: Unregistered ( "custom" . to_owned ( ) , "1-100,-100" . to_owned ( ) ) ;
221+ assert_eq ! ( r, r2) ;
222+
223+ }
224+
225+ #[ test]
226+ fn test_parse_unregistered_range_valid ( ) {
227+ let r: Range = Header :: parse_header ( & [ b"custom=1-100,-100" . to_vec ( ) ] ) . unwrap ( ) ;
228+ let r2 = Range :: Unregistered ( "custom" . to_owned ( ) , "1-100,-100" . to_owned ( ) ) ;
229+ assert_eq ! ( r, r2) ;
230+
231+ let r: Range = Header :: parse_header ( & [ b"custom=abcd" . to_vec ( ) ] ) . unwrap ( ) ;
232+ let r2 = Range :: Unregistered ( "custom" . to_owned ( ) , "abcd" . to_owned ( ) ) ;
233+ assert_eq ! ( r, r2) ;
234+
235+ let r: Range = Header :: parse_header ( & [ b"custom=xxx-yyy" . to_vec ( ) ] ) . unwrap ( ) ;
236+ let r2 = Range :: Unregistered ( "custom" . to_owned ( ) , "xxx-yyy" . to_owned ( ) ) ;
237+ assert_eq ! ( r, r2) ;
191238}
192239
193240#[ test]
@@ -206,26 +253,36 @@ fn test_parse_invalid() {
206253
207254 let r: :: Result < Range > = Header :: parse_header ( & [ b"bytes=" . to_vec ( ) ] ) ;
208255 assert_eq ! ( r. ok( ) , None ) ;
256+
257+ let r: :: Result < Range > = Header :: parse_header ( & [ b"custom=" . to_vec ( ) ] ) ;
258+ assert_eq ! ( r. ok( ) , None ) ;
259+
260+ let r: :: Result < Range > = Header :: parse_header ( & [ b"=1-100" . to_vec ( ) ] ) ;
261+ assert_eq ! ( r. ok( ) , None ) ;
209262}
210263
211264#[ test]
212265fn test_fmt ( ) {
213266 use header:: Headers ;
214267
215- let range_header = Range {
216- unit : RangeUnit :: Bytes ,
217- ranges : vec ! [ RangeSpec :: FromTo ( 0 , 1000 ) , RangeSpec :: AllFrom ( 2000 ) ] ,
218- } ;
219268 let mut headers = Headers :: new ( ) ;
220- headers. set ( range_header) ;
221269
270+ headers. set (
271+ Range :: Bytes (
272+ vec ! [ ByteRangeSpec :: FromTo ( 0 , 1000 ) , ByteRangeSpec :: AllFrom ( 2000 ) ]
273+ ) ) ;
222274 assert_eq ! ( & headers. to_string( ) , "Range: bytes=0-1000,2000-\r \n " ) ;
223275
224276 headers. clear ( ) ;
225- headers. set ( Range { unit : RangeUnit :: Bytes , ranges : vec ! [ ] } ) ;
277+ headers. set ( Range :: Bytes ( vec ! [ ] ) ) ;
226278
227279 assert_eq ! ( & headers. to_string( ) , "Range: bytes=\r \n " ) ;
280+
281+ headers. clear ( ) ;
282+ headers. set ( Range :: Unregistered ( "custom" . to_owned ( ) , "1-xxx" . to_owned ( ) ) ) ;
283+
284+ assert_eq ! ( & headers. to_string( ) , "Range: custom=1-xxx\r \n " ) ;
228285}
229286
230287bench_header ! ( bytes_multi, Range , { vec![ b"bytes=1-1001,2001-3001,10001-" . to_vec( ) ] } ) ;
231- bench_header ! ( custom_unit, Range , { vec![ b"custom_unit =0-100000" . to_vec( ) ] } ) ;
288+ bench_header ! ( custom_unit, Range , { vec![ b"other =0-100000" . to_vec( ) ] } ) ;
0 commit comments