Skip to content

Commit bcde50c

Browse files
joshtriplettFishrock123
authored andcommitted
Add Body::chain to create a Body from a series of two Body instances
This method helps when prepending or appending some data to a Body.
1 parent 02cfa96 commit bcde50c

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

src/body.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,46 @@ impl Body {
419419
pub fn set_mime(&mut self, mime: impl Into<Mime>) {
420420
self.mime = mime.into();
421421
}
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+
}
422462
}
423463

424464
impl Debug for Body {
@@ -613,4 +653,122 @@ mod test {
613653

614654
Ok(())
615655
}
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+
}
616774
}

0 commit comments

Comments
 (0)