use crate::error::Error;
use crate::platform;
use crate::platform::ffi;
use std::marker::PhantomData;
use std::path::Path;
pub struct ReadStream {
handle: ffi::CzReadStream,
}
unsafe impl Send for ReadStream {}
impl ReadStream {
pub const BUFFER_SIZE: usize = 1024 * 1024;
pub fn new() -> Result<Self, Error> {
Self::opened(ffi::cz_read_stream_new(), "make an empty read stream".to_string())
}
pub fn with_url(url: &Path, buffer_size: usize) -> Result<Self, Error> {
Self::opened(
ffi::cz_read_stream_with_url(&url.display().to_string(), buffer_size),
format!("read {}", url.display()),
)
}
pub fn with_data(data: &[u8], buffer_size: usize) -> Result<Self, Error> {
Self::opened(
ffi::cz_read_stream_with_data(data.to_vec(), buffer_size),
"read bytes as a stream".to_string(),
)
}
fn opened(outcome: ffi::CzOutcome, action: String) -> Result<Self, Error> {
platform::outcome(outcome, action).map(|outcome| Self {
handle: outcome.read_stream(),
})
}
pub fn reset(&self) -> Result<(), Error> {
platform::outcome(self.handle.reset(), "reset a read stream").map(drop)
}
pub fn data_stream(&self) -> DataStream<'_> {
DataStream {
handle: self.handle.data_stream(),
stream: PhantomData,
}
}
}
pub struct DataStream<'a> {
handle: ffi::CzDataStream,
stream: PhantomData<&'a ReadStream>,
}
impl Iterator for DataStream<'_> {
type Item = Vec<u8>;
fn next(&mut self) -> Option<Vec<u8>> {
let outcome = self.handle.next();
outcome.is_some().then(|| outcome.bytes())
}
}