diff --git a/lib/src/archive/read.rs b/lib/src/archive/read.rs index b95c9e24..00a0c05a 100644 --- a/lib/src/archive/read.rs +++ b/lib/src/archive/read.rs @@ -9,6 +9,7 @@ use crate::{ use futures_io::AsyncRead; #[cfg(feature = "unstable-async")] use futures_util::AsyncReadExt; +pub(crate) use slice::read_header_from_slice; use std::{ collections::VecDeque, io::{self, Read, Seek, SeekFrom}, diff --git a/lib/src/archive/read/slice.rs b/lib/src/archive/read/slice.rs index f7ecc753..5c6a5af6 100644 --- a/lib/src/archive/read/slice.rs +++ b/lib/src/archive/read/slice.rs @@ -5,7 +5,7 @@ use crate::{ use std::borrow::Cow; use std::io; -fn read_header_from_slice(bytes: &[u8]) -> io::Result<&[u8]> { +pub(crate) fn read_header_from_slice(bytes: &[u8]) -> io::Result<&[u8]> { // TODO: use split_at_checked instead let (header, body) = bytes.split_at(PNA_HEADER.len()); if header != PNA_HEADER { diff --git a/lib/src/chunk.rs b/lib/src/chunk.rs index b7ebf9b2..e923e6fa 100644 --- a/lib/src/chunk.rs +++ b/lib/src/chunk.rs @@ -337,6 +337,52 @@ pub fn read_as_chunks( }) } +/// Read chunks from archive slice +/// +/// # Example +/// +/// ``` +/// # use std::{io, fs}; +/// use libpna::{prelude::*, read_chunks_from_slice}; +/// # fn main() -> io::Result<()> { +/// let bytes = include_bytes!("../../resources/test/zstd.pna"); +/// for chunk in read_chunks_from_slice(bytes)? { +/// let chunk = chunk?; +/// println!("chunk type: {}, chunk data size: {}", chunk.ty(), chunk.length()); +/// } +/// # Ok(()) +/// # } +/// ``` +#[inline] +pub fn read_chunks_from_slice<'s>( + archive: &'s [u8], +) -> io::Result>> { + struct Chunks<'a> { + reader: &'a [u8], + eoa: bool, + } + impl<'a> Iterator for Chunks<'a> { + type Item = io::Result>; + #[inline] + fn next(&mut self) -> Option { + if self.eoa { + return None; + } + Some(read_chunk_from_slice(self.reader).map(|(chunk, bytes)| { + self.eoa = chunk.ty() == ChunkType::AEND; + self.reader = bytes; + chunk + })) + } + } + let archive = crate::archive::read_header_from_slice(archive)?; + + Ok(Chunks { + reader: archive, + eoa: false, + }) +} + #[cfg(test)] mod tests { use super::*;