use std::io;
use std::path::Path;
use std::fs::File;
use zip::result::ZipError;
use crate::read::NpyFile;
use crate::serialize::Serialize;
use crate::write::{WriterBuilder, write_options};
pub struct NpzArchive<R: io::Read + io::Seek> {
zip: zip::ZipArchive<R>,
}
impl NpzArchive<io::BufReader<File>> {
pub fn open(path: impl AsRef<Path>) -> io::Result<Self> {
Ok(Self::new(io::BufReader::new(File::open(path)?))?)
}
}
impl<R: io::Read + io::Seek> NpzArchive<R> {
pub fn new(reader: R) -> io::Result<Self> {
Ok(NpzArchive { zip: zip::ZipArchive::new(reader).map_err(invalid_data)? })
}
pub fn array_names(&self) -> impl Iterator<Item = &str> {
self.zip.file_names().filter_map(crate::npz::array_name_from_file_name)
}
pub fn by_name<'a>(&'a mut self, name: &str) -> io::Result<Option<NpyFile<zip::read::ZipFile<'a>>>> {
match self.zip.by_name(&crate::npz::file_name_from_array_name(name)) {
Ok(file) => Ok(Some(NpyFile::new(file)?)),
Err(ZipError::FileNotFound) => Ok(None),
Err(ZipError::Io(e)) => Err(e),
Err(ZipError::InvalidArchive(s)) => Err(invalid_data(s)),
Err(ZipError::UnsupportedArchive(s)) => Err(invalid_data(s)),
}
}
pub fn zip_archive(&mut self) -> &mut zip::ZipArchive<R> {
&mut self.zip
}
}
fn invalid_data<S: ToString>(s: S) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, s.to_string())
}
pub struct NpzWriter<W: io::Write + io::Seek> {
zip: zip::ZipWriter<W>,
}
impl NpzWriter<io::BufWriter<File>> {
pub fn create(path: impl AsRef<Path>) -> io::Result<Self> {
Ok(Self::new(io::BufWriter::new(File::create(path)?)))
}
}
impl<W: io::Write + io::Seek> NpzWriter<W> {
pub fn new(writer: W) -> Self {
NpzWriter { zip: zip::ZipWriter::new(writer) }
}
pub fn array<T: Serialize + ?Sized>(&mut self, name: &str, options: zip::write::FileOptions) -> io::Result<NpzWriterBuilder<'_, T, W>> {
self.zip.start_file(crate::npz::file_name_from_array_name(name), options)?;
Ok(write_options::WriteOptions::new().writer(&mut self.zip))
}
pub fn zip_writer(&mut self) -> &mut zip::ZipWriter<W> {
&mut self.zip
}
}
pub type NpzWriterBuilder<'w, T, W> = write_options::WithWriter<&'w mut zip::ZipWriter<W>, write_options::WriteOptions<T>>;