Merge pull request #265 from zip-rs/explainer

Picking the low-hanging documentation fruit
This commit is contained in:
Alexander Zaitsev 2022-03-08 18:23:21 +03:00 committed by GitHub
commit 25a5b4e4ba
Signed by: DevComp
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 134 additions and 81 deletions

View file

@ -1,7 +1,26 @@
//! An ergonomic API for reading and writing ZIP files. //! A library for reading and writing ZIP archives.
//! ZIP is a format designed for cross-platform file "archiving".
//! That is, storing a collection of files in a single datastream
//! to make them easier to share between computers.
//! Additionally, ZIP is able to compress and encrypt files in its
//! archives.
//! //!
//! The current implementation is based on [PKWARE's APPNOTE.TXT v6.3.9](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT) //! The current implementation is based on [PKWARE's APPNOTE.TXT v6.3.9](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
// TODO(#184): Decide on the crate's bias: Do we prioritise permissiveness/correctness/speed/ergonomics? //!
//! ---
//!
//! [`zip`](`crate`) has support for the most common ZIP archives found in common use.
//! However, in special cases,
//! there are some zip archives that are difficult to read or write.
//!
//! This is a list of supported features:
//!
//! | | Reading | Writing |
//! | ------- | ------ | ------- |
//! | Deflate | ✅ [->](`crate::ZipArchive::by_name`) | ✅ [->](`crate::write::FileOptions::compression_method`) |
//!
//!
//!
#![warn(missing_docs)] #![warn(missing_docs)]

View file

@ -34,13 +34,15 @@ mod ffi {
pub const S_IFREG: u32 = 0o0100000; pub const S_IFREG: u32 = 0o0100000;
} }
// Put the struct declaration in a private module to convince rustdoc to display ZipArchive nicely
pub(crate) mod zip_archive {
/// Extract immutable data from `ZipArchive` to make it cheap to clone /// Extract immutable data from `ZipArchive` to make it cheap to clone
#[derive(Debug)] #[derive(Debug)]
struct Shared { pub struct Shared {
files: Vec<ZipFileData>, pub(super) files: Vec<super::ZipFileData>,
names_map: HashMap<String, usize>, pub(super) names_map: super::HashMap<String, usize>,
offset: u64, pub(super) offset: u64,
comment: Vec<u8>, pub(super) comment: Vec<u8>,
} }
/// ZIP archive reader /// ZIP archive reader
@ -65,10 +67,12 @@ struct Shared {
/// ``` /// ```
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ZipArchive<R> { pub struct ZipArchive<R> {
reader: R, pub(super) reader: R,
shared: Arc<Shared>, pub(super) shared: super::Arc<Shared>,
}
} }
pub use zip_archive::{Shared, ZipArchive};
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
enum CryptoReader<'a> { enum CryptoReader<'a> {
Plaintext(io::Take<&'a mut dyn Read>), Plaintext(io::Take<&'a mut dyn Read>),

View file

@ -1,4 +1,6 @@
//! Types that specify what is contained in a ZIP. //! Types that specify what is contained in a ZIP.
#[cfg(doc)]
use {crate::read::ZipFile, crate::write::FileOptions};
use std::sync::atomic; use std::sync::atomic;
@ -24,19 +26,23 @@ impl System {
} }
} }
/// A DateTime field to be used for storing timestamps in a zip file /// Representation of a moment in time.
/// ///
/// This structure does bounds checking to ensure the date is able to be stored in a zip file. /// Zip files use an old format from DOS to store timestamps,
/// with its own set of peculiarities.
/// For example, it has a resolution of 2 seconds!
/// ///
/// When constructed manually from a date and time, it will also check if the input is sensible /// A [`DateTime`] can be stored directly in a zipfile with [`FileOptions::last_modified_time`],
/// (e.g. months are from [1, 12]), but when read from a zip some parts may be out of their normal /// or read from one with [`ZipFile::last_modified`]
/// bounds (e.g. month 0, or hour 31).
/// ///
/// # Warning /// # Warning
/// ///
/// Some utilities use alternative timestamps to improve the accuracy of their /// Because there is no timezone associated with the [`DateTime`], they should ideally only
/// ZIPs, but we don't parse them yet. [We're working on this](https://github.com/zip-rs/zip/issues/156#issuecomment-652981904), /// be used for user-facing descriptions. This also means [`DateTime::to_time`] returns an
/// however this API shouldn't be considered complete. /// [`OffsetDateTime`] (which is the equivalent of chrono's `NaiveDateTime`).
///
/// Modern zip files store more precise timestamps, which are ignored by [`crate::read::ZipArchive`],
/// so keep in mind that these timestamps are unreliable. [We're working on this](https://github.com/zip-rs/zip/issues/156#issuecomment-652981904).
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct DateTime { pub struct DateTime {
year: u16, year: u16,
@ -168,26 +174,46 @@ impl DateTime {
} }
/// Get the month, where 1 = january and 12 = december /// Get the month, where 1 = january and 12 = december
///
/// # Warning
///
/// When read from a zip file, this may not be a reasonable value
pub fn month(&self) -> u8 { pub fn month(&self) -> u8 {
self.month self.month
} }
/// Get the day /// Get the day
///
/// # Warning
///
/// When read from a zip file, this may not be a reasonable value
pub fn day(&self) -> u8 { pub fn day(&self) -> u8 {
self.day self.day
} }
/// Get the hour /// Get the hour
///
/// # Warning
///
/// When read from a zip file, this may not be a reasonable value
pub fn hour(&self) -> u8 { pub fn hour(&self) -> u8 {
self.hour self.hour
} }
/// Get the minute /// Get the minute
///
/// # Warning
///
/// When read from a zip file, this may not be a reasonable value
pub fn minute(&self) -> u8 { pub fn minute(&self) -> u8 {
self.minute self.minute
} }
/// Get the second /// Get the second
///
/// # Warning
///
/// When read from a zip file, this may not be a reasonable value
pub fn second(&self) -> u8 { pub fn second(&self) -> u8 {
self.second self.second
} }

View file

@ -42,7 +42,9 @@ enum GenericZipWriter<W: Write + io::Seek> {
#[cfg(feature = "zstd")] #[cfg(feature = "zstd")]
Zstd(ZstdEncoder<'static, W>), Zstd(ZstdEncoder<'static, W>),
} }
// Put the struct declaration in a private module to convince rustdoc to display ZipWriter nicely
pub(crate) mod zip_writer {
use super::*;
/// ZIP archive generator /// ZIP archive generator
/// ///
/// Handles the bookkeeping involved in building an archive, and provides an /// Handles the bookkeeping involved in building an archive, and provides an
@ -72,15 +74,17 @@ enum GenericZipWriter<W: Write + io::Seek> {
/// # doit().unwrap(); /// # doit().unwrap();
/// ``` /// ```
pub struct ZipWriter<W: Write + io::Seek> { pub struct ZipWriter<W: Write + io::Seek> {
inner: GenericZipWriter<W>, pub(super) inner: GenericZipWriter<W>,
files: Vec<ZipFileData>, pub(super) files: Vec<ZipFileData>,
stats: ZipWriterStats, pub(super) stats: ZipWriterStats,
writing_to_file: bool, pub(super) writing_to_file: bool,
writing_to_extra_field: bool, pub(super) writing_to_extra_field: bool,
writing_to_central_extra_field_only: bool, pub(super) writing_to_central_extra_field_only: bool,
writing_raw: bool, pub(super) writing_raw: bool,
comment: Vec<u8>, pub(super) comment: Vec<u8>,
} }
}
pub use zip_writer::ZipWriter;
#[derive(Default)] #[derive(Default)]
struct ZipWriterStats { struct ZipWriterStats {