diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ff3dcf1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,29 @@ +# Changelog + +All notable changes to this crate are documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this crate adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.0] - 2026-05-02 + +Initial release. + +- `encode(&[u8]) -> String` and `decode(&str) -> Result, DecodeError>`, + byte-for-byte compatible with the `base85` crate v2.0.0 on the success path. +- aarch64 NEON-accelerated encode (4 blocks/iter) and decode (4 blocks/iter, + ~10× the reference scalar throughput on Apple M-series). +- x86_64 AVX2-accelerated encode and decode (8 blocks/iter), with runtime + feature detection and scalar fallback for hosts lacking AVX2. +- Portable scalar implementation for other architectures. +- Strict overflow detection: 5-character blocks whose value exceeds `u32::MAX` + return `DecodeError::Overflow` rather than silently wrapping (release) or + panicking (debug) as the reference does. +- Diagnostic `DecodeError` enum with byte positions; marked `#[non_exhaustive]` + for forward-compatibility. +- MSRV: Rust 1.85. + +[Unreleased]: https://github.com/cipherstash/base85-simd/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/cipherstash/base85-simd/releases/tag/v0.1.0 diff --git a/Cargo.toml b/Cargo.toml index e09f537..9a52971 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,14 +3,24 @@ name = "base85-simd" version = "0.1.0" edition = "2024" rust-version = "1.85" -description = "Fast base85 (RFC 1924 / Z85-style) encoder and decoder, with a NEON SIMD encode path on aarch64." +authors = ["Dan Draper "] +description = "Fast base85 (RFC 1924 / Z85-style) encoder and decoder, with SIMD on aarch64 (NEON) and x86_64 (AVX2)." license = "MIT OR Apache-2.0" repository = "https://github.com/cipherstash/base85-simd" +homepage = "https://github.com/cipherstash/base85-simd" readme = "README.md" keywords = ["base85", "ascii85", "simd", "neon", "encoding"] categories = ["encoding"] exclude = ["*.xlsx", ".DS_Store", "mise.toml"] +[package.metadata.docs.rs] +# Build docs for both SIMD targets so the per-arch entry points +# (NeonEncoder / Avx2Encoder, etc.) all render. docs.rs's default +# x86_64-unknown-linux-gnu picks up the AVX2 path; we add aarch64 +# so the NEON path is also documented in the rendered output. +targets = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"] +rustdoc-args = ["--cfg", "docsrs"] + [dependencies] [dev-dependencies] diff --git a/src/lib.rs b/src/lib.rs index de6eab4..ef0ca09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,11 @@ use block::{decode_block, decode_tail, encode_block, encode_tail}; use std::fmt; /// Errors returned by [`decode`]. +/// +/// Marked `#[non_exhaustive]` — match arms must include `_ => …` so future +/// additions don't break downstream code. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub enum DecodeError { /// The input contained a byte that is not part of the base85 alphabet. InvalidChar {