@@ -34,14 +34,61 @@ impl PartialHttpRequest {
3434 headers : Vec < Range < usize > > ,
3535 body : Option < Range < usize > > ,
3636 ) -> Self {
37- Self {
37+ let partial = Self {
3838 message : message. to_string ( ) ,
3939 method,
4040 uri,
4141 http_version,
4242 headers,
4343 body,
44+ } ;
45+
46+ partial. verify_spans ( ) ;
47+
48+ partial
49+ }
50+
51+ /// Verify all the spans in the struct are valid
52+ ///
53+ /// - Aren't out of bounds of the message
54+ /// - Parts aren't overlapping or out of order
55+ fn verify_spans ( & self ) {
56+ self . method . as_ref ( ) . inspect ( |span| {
57+ assert ! ( span. start < span. end) ;
58+ assert_text_span ( self . message ( ) , span) ;
59+ } ) ;
60+
61+ self . uri . as_ref ( ) . inspect ( |span| {
62+ assert ! ( span. start < span. end) ;
63+ assert_text_span ( self . message ( ) , span) ;
64+
65+ if let Some ( method) = self . method_span ( ) {
66+ if !( method. start < span. start && method. end < span. start ) {
67+ panic ! ( "uri {span:?} and method {method:?} spans conflict" ) ;
68+ }
69+ }
70+ } ) ;
71+
72+ self . http_version . as_ref ( ) . inspect ( |span| {
73+ assert ! ( span. start < span. end) ;
74+ assert_text_span ( self . message ( ) , span) ;
75+
76+ if let Some ( uri) = self . uri_span ( ) {
77+ if !( uri. start < span. start && uri. end < span. start ) {
78+ panic ! ( "http version {span:?} and uri {uri:?} spans conflict" ) ;
79+ }
80+ }
81+ } ) ;
82+
83+ for span in self . header_spans ( ) . iter ( ) {
84+ assert ! ( span. start < span. end) ;
85+ assert_text_span ( self . message ( ) , span) ;
4486 }
87+
88+ self . body . as_ref ( ) . inspect ( |span| {
89+ assert ! ( span. start < span. end) ;
90+ assert_text_span ( self . message ( ) , span) ;
91+ } ) ;
4592 }
4693
4794 /// Get the original HTTP request message text
@@ -117,6 +164,11 @@ impl PartialHttpRequest {
117164 }
118165}
119166
167+ fn assert_text_span ( text : & str , span : & Range < usize > ) {
168+ text. get ( span. clone ( ) )
169+ . expect ( & format ! ( "span {:?} is outside of text bounds" , span) ) ;
170+ }
171+
120172impl Default for PartialHttpRequest {
121173 fn default ( ) -> Self {
122174 Self :: from_str ( "GET https://example.com HTTP/1.1" ) . unwrap ( )
@@ -245,6 +297,79 @@ mod tests {
245297 models:: { request:: HttpRequest , uri:: Uri } ,
246298 } ;
247299
300+ #[ test]
301+ #[ should_panic]
302+ fn verifies_out_of_bounds_method_span ( ) {
303+ PartialHttpRequest :: new ( "" , Some ( 1 ..2 ) , None , None , vec ! [ ] , None ) ;
304+ }
305+
306+ #[ test]
307+ #[ should_panic]
308+ fn verifies_inverted_method_span ( ) {
309+ PartialHttpRequest :: new ( "" , Some ( 2 ..1 ) , None , None , vec ! [ ] , None ) ;
310+ }
311+
312+ #[ test]
313+ #[ should_panic]
314+ fn verifies_out_of_bounds_uri_span ( ) {
315+ PartialHttpRequest :: new ( "" , None , Some ( 1 ..2 ) , None , vec ! [ ] , None ) ;
316+ }
317+
318+ #[ test]
319+ #[ should_panic]
320+ fn verifies_inverted_uri_span ( ) {
321+ PartialHttpRequest :: new ( "" , None , Some ( 2 ..1 ) , None , vec ! [ ] , None ) ;
322+ }
323+
324+ #[ test]
325+ #[ should_panic]
326+ fn verifies_method_span_overlaps_uri_span ( ) {
327+ PartialHttpRequest :: new (
328+ "GET https://example.com" ,
329+ Some ( 0 ..3 ) ,
330+ Some ( 2 ..10 ) ,
331+ None ,
332+ vec ! [ ] ,
333+ None ,
334+ ) ;
335+ }
336+
337+ #[ test]
338+ #[ should_panic]
339+ fn verifies_out_of_bounds_http_version_span ( ) {
340+ PartialHttpRequest :: new ( "" , None , None , Some ( 1 ..2 ) , vec ! [ ] , None ) ;
341+ }
342+
343+ #[ test]
344+ #[ should_panic]
345+ fn verifies_inverted_http_version_span ( ) {
346+ PartialHttpRequest :: new ( "" , None , None , Some ( 2 ..1 ) , vec ! [ ] , None ) ;
347+ }
348+
349+ #[ test]
350+ #[ should_panic]
351+ fn verifies_out_of_bounds_header_span ( ) {
352+ PartialHttpRequest :: new ( "" , None , None , None , vec ! [ 1 ..2 ] , None ) ;
353+ }
354+
355+ #[ test]
356+ #[ should_panic]
357+ fn verifies_inverted_header_span ( ) {
358+ PartialHttpRequest :: new ( "" , None , None , None , vec ! [ 2 ..1 ] , None ) ;
359+ }
360+
361+ #[ test]
362+ #[ should_panic]
363+ fn verifies_out_of_bounds_body_span ( ) {
364+ PartialHttpRequest :: new ( "" , None , None , None , vec ! [ ] , Some ( 1 ..2 ) ) ;
365+ }
366+
367+ #[ test]
368+ #[ should_panic]
369+ fn verifies_inverted_body_span ( ) {
370+ PartialHttpRequest :: new ( "" , None , None , None , vec ! [ ] , Some ( 2 ..1 ) ) ;
371+ }
372+
248373 #[ test]
249374 fn implements_default ( ) {
250375 let partial = PartialHttpRequest :: default ( ) ;
0 commit comments