@@ -482,6 +482,46 @@ impl Body {
482482 pub fn set_mime ( & mut self , mime : impl Into < Mime > ) {
483483 self . mime = mime. into ( ) ;
484484 }
485+
486+ /// Create a Body by chaining another Body after this one, consuming both.
487+ ///
488+ /// If both Body instances have a length, and their sum does not overflow,
489+ /// the resulting Body will have a length.
490+ ///
491+ /// If both Body instances have the same fallback MIME type, the resulting
492+ /// Body will have the same fallback MIME type; otherwise, the resulting
493+ /// Body will have the fallback MIME type `application/octet-stream`.
494+ ///
495+ /// # Examples
496+ ///
497+ /// ```
498+ /// # fn main() -> http_types::Result<()> { async_std::task::block_on(async {
499+ /// use http_types::Body;
500+ /// use async_std::io::Cursor;
501+ ///
502+ /// let cursor = Cursor::new("Hello ");
503+ /// let body = Body::from_reader(cursor, None).chain(Body::from("Nori"));
504+ /// assert_eq!(&body.into_string().await.unwrap(), "Hello Nori");
505+ /// # Ok(()) }) }
506+ /// ```
507+ #[ cfg( feature = "async-std" ) ]
508+ pub fn chain ( self , other : Body ) -> Self {
509+ let mime = if self . mime == other. mime {
510+ self . mime . clone ( )
511+ } else {
512+ mime:: BYTE_STREAM
513+ } ;
514+ let length = match ( self . length , other. length ) {
515+ ( Some ( l1) , Some ( l2) ) => ( l1 - self . bytes_read ) . checked_add ( l2 - other. bytes_read ) ,
516+ _ => None ,
517+ } ;
518+ Self {
519+ mime,
520+ length,
521+ reader : Box :: new ( async_std:: io:: ReadExt :: chain ( self , other) ) ,
522+ bytes_read : 0 ,
523+ }
524+ }
485525}
486526
487527impl Debug for Body {
@@ -681,4 +721,148 @@ mod test {
681721
682722 Ok ( ( ) )
683723 }
724+
725+ #[ async_std:: test]
726+ async fn chain_strings ( ) -> crate :: Result < ( ) > {
727+ for buf_len in 1 ..13 {
728+ let mut body = Body :: from ( "hello " ) . chain ( Body :: from ( "world" ) ) ;
729+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
730+ assert_eq ! ( body. mime( ) , & mime:: PLAIN ) ;
731+ assert_eq ! (
732+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
733+ "hello world"
734+ ) ;
735+ assert_eq ! ( body. bytes_read, 11 ) ;
736+ }
737+
738+ Ok ( ( ) )
739+ }
740+
741+ #[ async_std:: test]
742+ async fn chain_mixed_bytes_string ( ) -> crate :: Result < ( ) > {
743+ for buf_len in 1 ..13 {
744+ let mut body = Body :: from ( & b"hello " [ ..] ) . chain ( Body :: from ( "world" ) ) ;
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_mixed_reader_string ( ) -> crate :: Result < ( ) > {
759+ for buf_len in 1 ..13 {
760+ let mut body =
761+ Body :: from_reader ( Cursor :: new ( "hello " ) , Some ( 6 ) ) . chain ( Body :: from ( "world" ) ) ;
762+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
763+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
764+ assert_eq ! (
765+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
766+ "hello world"
767+ ) ;
768+ assert_eq ! ( body. bytes_read, 11 ) ;
769+ }
770+
771+ Ok ( ( ) )
772+ }
773+
774+ #[ async_std:: test]
775+ async fn chain_mixed_nolen_len ( ) -> crate :: Result < ( ) > {
776+ for buf_len in 1 ..13 {
777+ let mut body =
778+ Body :: from_reader ( Cursor :: new ( "hello " ) , None ) . chain ( Body :: from ( "world" ) ) ;
779+ assert_eq ! ( body. len( ) , None ) ;
780+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
781+ assert_eq ! (
782+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
783+ "hello world"
784+ ) ;
785+ assert_eq ! ( body. bytes_read, 11 ) ;
786+ }
787+
788+ Ok ( ( ) )
789+ }
790+
791+ #[ async_std:: test]
792+ async fn chain_mixed_len_nolen ( ) -> crate :: Result < ( ) > {
793+ for buf_len in 1 ..13 {
794+ let mut body =
795+ Body :: from ( "hello " ) . chain ( Body :: from_reader ( Cursor :: new ( "world" ) , None ) ) ;
796+ assert_eq ! ( body. len( ) , None ) ;
797+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
798+ assert_eq ! (
799+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
800+ "hello world"
801+ ) ;
802+ assert_eq ! ( body. bytes_read, 11 ) ;
803+ }
804+
805+ Ok ( ( ) )
806+ }
807+
808+ #[ async_std:: test]
809+ async fn chain_short ( ) -> crate :: Result < ( ) > {
810+ for buf_len in 1 ..26 {
811+ let mut body = Body :: from_reader ( Cursor :: new ( "hello xyz" ) , Some ( 6 ) )
812+ . chain ( Body :: from_reader ( Cursor :: new ( "world abc" ) , Some ( 5 ) ) ) ;
813+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
814+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
815+ assert_eq ! (
816+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
817+ "hello world"
818+ ) ;
819+ assert_eq ! ( body. bytes_read, 11 ) ;
820+ }
821+
822+ Ok ( ( ) )
823+ }
824+
825+ #[ async_std:: test]
826+ async fn chain_many ( ) -> crate :: Result < ( ) > {
827+ for buf_len in 1 ..13 {
828+ let mut body = Body :: from ( "hello" )
829+ . chain ( Body :: from ( & b" " [ ..] ) )
830+ . chain ( Body :: from ( "world" ) ) ;
831+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
832+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
833+ assert_eq ! (
834+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
835+ "hello world"
836+ ) ;
837+ assert_eq ! ( body. bytes_read, 11 ) ;
838+ }
839+
840+ Ok ( ( ) )
841+ }
842+
843+ #[ async_std:: test]
844+ async fn chain_skip_start ( ) -> crate :: Result < ( ) > {
845+ for buf_len in 1 ..26 {
846+ let mut body1 = Body :: from_reader ( Cursor :: new ( "1234 hello xyz" ) , Some ( 11 ) ) ;
847+ let mut buf = vec ! [ 0 ; 5 ] ;
848+ body1. read ( & mut buf) . await ?;
849+ assert_eq ! ( buf, b"1234 " ) ;
850+
851+ let mut body2 = Body :: from_reader ( Cursor :: new ( "321 world abc" ) , Some ( 9 ) ) ;
852+ let mut buf = vec ! [ 0 ; 4 ] ;
853+ body2. read ( & mut buf) . await ?;
854+ assert_eq ! ( buf, b"321 " ) ;
855+
856+ let mut body = body1. chain ( body2) ;
857+ assert_eq ! ( body. len( ) , Some ( 11 ) ) ;
858+ assert_eq ! ( body. mime( ) , & mime:: BYTE_STREAM ) ;
859+ assert_eq ! (
860+ read_with_buffers_of_size( & mut body, buf_len) . await ?,
861+ "hello world"
862+ ) ;
863+ assert_eq ! ( body. bytes_read, 11 ) ;
864+ }
865+
866+ Ok ( ( ) )
867+ }
684868}
0 commit comments