Skip to content

Commit 206b53e

Browse files
authored
Merge pull request http-rs#342 from joshtriplett/body-chain
Add Body::chain to create a Body from a series of two Body instances
2 parents 419817d + d93c6fd commit 206b53e

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

src/body.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

487527
impl 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

Comments
 (0)