diff --git a/src/lib.rs b/src/lib.rs index 20bd18c..264fc2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,14 +43,15 @@ impl Eszip { reader: R, ) -> Result<(Eszip, EszipParserFuture), ParseError> { let mut reader = futures::io::BufReader::new(reader); - reader.fill_buf().await?; - let buffer = reader.buffer(); - if EszipV2::has_magic(buffer) { - let (eszip, fut) = EszipV2::parse(reader).await?; + let mut magic = [0; 8]; + reader.read_exact(&mut magic).await?; + if EszipV2::has_magic(&magic) { + let (eszip, fut) = EszipV2::parse_with_magic(&magic, reader).await?; Ok((Eszip::V2(eszip), Box::pin(fut))) } else { let mut buffer = Vec::new(); - reader.read_to_end(&mut buffer).await?; + let mut reader_w_magic = magic.chain(&mut reader); + reader_w_magic.read_to_end(&mut buffer).await?; let eszip = EszipV1::parse(&buffer)?; let fut = async move { Ok::<_, ParseError>(reader) }; Ok((Eszip::V1(eszip), Box::pin(fut))) @@ -215,6 +216,9 @@ pub enum ModuleKind { mod tests { use super::*; use futures::io::AllowStdIo; + use futures::stream; + use futures::StreamExt; + use futures::TryStreamExt; #[tokio::test] async fn parse_v1() { @@ -351,4 +355,20 @@ mod tests { ); } } + + #[tokio::test] + async fn parse_small_chunks_reader() { + let bytes = std::fs::read("./src/testdata/redirect.eszip2") + .unwrap() + .chunks(2) + .map(|chunk| chunk.to_vec()) + .collect::>(); + let reader = stream::iter(bytes) + .map(std::io::Result::Ok) + .into_async_read(); + + let (eszip, fut) = Eszip::parse(reader).await.unwrap(); + fut.await.unwrap(); + assert!(matches!(eszip, Eszip::V2(_))); + } } diff --git a/src/v2.rs b/src/v2.rs index 4e04cee..ec893f7 100644 --- a/src/v2.rs +++ b/src/v2.rs @@ -235,6 +235,19 @@ impl EszipV2 { return Err(ParseError::InvalidV2); } + Self::parse_with_magic(&magic, reader).await + } + + pub(super) async fn parse_with_magic( + magic: &[u8], + mut reader: futures::io::BufReader, + ) -> Result< + ( + EszipV2, + impl Future, ParseError>>, + ), + ParseError, + > { let is_v3 = magic == *ESZIP_V2_1_MAGIC; let header = HashedSection::read(&mut reader).await?; if !header.hash_valid() {