@@ -419,6 +419,46 @@ impl Body {
419
419
pub fn set_mime ( & mut self , mime : impl Into < Mime > ) {
420
420
self . mime = mime. into ( ) ;
421
421
}
422
+
423
+ /// Create a Body by chaining another Body after this one, consuming both.
424
+ ///
425
+ /// If both Body instances have a length, and their sum does not overflow,
426
+ /// the resulting Body will have a length.
427
+ ///
428
+ /// If both Body instances have the same fallback MIME type, the resulting
429
+ /// Body will have the same fallback MIME type; otherwise, the resulting
430
+ /// Body will have the fallback MIME type `application/octet-stream`.
431
+ ///
432
+ /// # Examples
433
+ ///
434
+ /// ```
435
+ /// # fn main() -> http_types::Result<()> { async_std::task::block_on(async {
436
+ /// use http_types::Body;
437
+ /// use async_std::io::Cursor;
438
+ ///
439
+ /// let cursor = Cursor::new("Hello ");
440
+ /// let body = Body::from_reader(cursor, None).chain(Body::from("Nori"));
441
+ /// assert_eq!(&body.into_string().await.unwrap(), "Hello Nori");
442
+ /// # Ok(()) }) }
443
+ /// ```
444
+ #[ cfg( feature = "async-std" ) ]
445
+ pub fn chain ( self , other : Body ) -> Self {
446
+ let mime = if self . mime == other. mime {
447
+ self . mime . clone ( )
448
+ } else {
449
+ mime:: BYTE_STREAM
450
+ } ;
451
+ let length = match ( self . length , other. length ) {
452
+ ( Some ( l1) , Some ( l2) ) => ( l1 - self . bytes_read ) . checked_add ( l2 - other. bytes_read ) ,
453
+ _ => None ,
454
+ } ;
455
+ Self {
456
+ mime,
457
+ length,
458
+ reader : Box :: new ( async_std:: io:: ReadExt :: chain ( self , other) ) ,
459
+ bytes_read : 0 ,
460
+ }
461
+ }
422
462
}
423
463
424
464
impl Debug for Body {
@@ -613,4 +653,122 @@ mod test {
613
653
614
654
Ok ( ( ) )
615
655
}
656
+
657
+ #[ async_std:: test]
658
+ async fn chain_strings ( ) -> crate :: Result < ( ) > {
659
+ for buf_len in 1 ..13 {
660
+ let mut body = Body :: from ( "hello " ) . chain ( Body :: from ( "world" ) ) ;
661
+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
662
+ assert_eq ! ( body. mime( ) , & mime:: PLAIN ) ;
663
+ assert_eq ! (
664
+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
665
+ "hello world"
666
+ ) ;
667
+ assert_eq ! ( body. bytes_read, 11 ) ;
668
+ }
669
+
670
+ Ok ( ( ) )
671
+ }
672
+
673
+ #[ async_std:: test]
674
+ async fn chain_mixed_bytes_string ( ) -> crate :: Result < ( ) > {
675
+ for buf_len in 1 ..13 {
676
+ let mut body = Body :: from ( & b"hello " [ ..] ) . chain ( Body :: from ( "world" ) ) ;
677
+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
678
+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
679
+ assert_eq ! (
680
+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
681
+ "hello world"
682
+ ) ;
683
+ assert_eq ! ( body. bytes_read, 11 ) ;
684
+ }
685
+
686
+ Ok ( ( ) )
687
+ }
688
+
689
+ #[ async_std:: test]
690
+ async fn chain_mixed_reader_string ( ) -> crate :: Result < ( ) > {
691
+ for buf_len in 1 ..13 {
692
+ let mut body =
693
+ Body :: from_reader ( Cursor :: new ( "hello " ) , Some ( 6 ) ) . chain ( Body :: from ( "world" ) ) ;
694
+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
695
+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
696
+ assert_eq ! (
697
+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
698
+ "hello world"
699
+ ) ;
700
+ assert_eq ! ( body. bytes_read, 11 ) ;
701
+ }
702
+
703
+ Ok ( ( ) )
704
+ }
705
+
706
+ #[ async_std:: test]
707
+ async fn chain_mixed_nolen_len ( ) -> crate :: Result < ( ) > {
708
+ for buf_len in 1 ..13 {
709
+ let mut body =
710
+ Body :: from_reader ( Cursor :: new ( "hello " ) , None ) . chain ( Body :: from ( "world" ) ) ;
711
+ assert_eq ! ( body. len( ) , None ) ;
712
+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
713
+ assert_eq ! (
714
+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
715
+ "hello world"
716
+ ) ;
717
+ assert_eq ! ( body. bytes_read, 11 ) ;
718
+ }
719
+
720
+ Ok ( ( ) )
721
+ }
722
+
723
+ #[ async_std:: test]
724
+ async fn chain_mixed_len_nolen ( ) -> crate :: Result < ( ) > {
725
+ for buf_len in 1 ..13 {
726
+ let mut body =
727
+ Body :: from ( "hello " ) . chain ( Body :: from_reader ( Cursor :: new ( "world" ) , None ) ) ;
728
+ assert_eq ! ( body. len( ) , None ) ;
729
+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
730
+ assert_eq ! (
731
+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
732
+ "hello world"
733
+ ) ;
734
+ assert_eq ! ( body. bytes_read, 11 ) ;
735
+ }
736
+
737
+ Ok ( ( ) )
738
+ }
739
+
740
+ #[ async_std:: test]
741
+ async fn chain_short ( ) -> crate :: Result < ( ) > {
742
+ for buf_len in 1 ..26 {
743
+ let mut body = Body :: from_reader ( Cursor :: new ( "hello xyz" ) , Some ( 6 ) )
744
+ . chain ( Body :: from_reader ( Cursor :: new ( "world abc" ) , Some ( 5 ) ) ) ;
745
+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
746
+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
747
+ assert_eq ! (
748
+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
749
+ "hello world"
750
+ ) ;
751
+ assert_eq ! ( body. bytes_read, 11 ) ;
752
+ }
753
+
754
+ Ok ( ( ) )
755
+ }
756
+
757
+ #[ async_std:: test]
758
+ async fn chain_many ( ) -> crate :: Result < ( ) > {
759
+ for buf_len in 1 ..13 {
760
+ let mut body = Body :: from ( "hello" )
761
+ . chain ( Body :: from ( & b" " [ ..] ) )
762
+ . chain ( Body :: from ( "world" ) ) ;
763
+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
764
+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
765
+ assert_eq ! (
766
+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
767
+ "hello world"
768
+ ) ;
769
+ assert_eq ! ( body. bytes_read, 11 ) ;
770
+ }
771
+
772
+ Ok ( ( ) )
773
+ }
616
774
}
0 commit comments