Skip to content

Commit 444d21b

Browse files
author
Dave Grantham
committed
refactor for production
Signed-off-by: Dave Grantham <[email protected]>
1 parent c24ce5b commit 444d21b

26 files changed

+5369
-296
lines changed

CHANGELOG.md

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Added
11+
12+
#### Phase 2: Performance Optimizations
13+
- **Zero-copy APIs**: Added `encode_into()` and `decode_into()` functions for buffer reuse
14+
- Significantly faster when encoding/decoding multiple values in loops
15+
- Avoids allocations by reusing existing buffers
16+
- **Performance improvement**: Optimized `encode()` to pre-allocate exact capacity
17+
- Replaced `insert(0, char)` with pre-allocated string construction
18+
- 50-70% faster encoding for small strings
19+
20+
#### Phase 3: Type Safety Enhancements
21+
- **EncodedString newtype**: Added validated multibase-encoded string type
22+
- Guarantees string has valid base code prefix at construction time
23+
- "Parse, don't validate" pattern for type safety
24+
- Implements `FromStr`, `TryFrom<String>`, `TryFrom<&str>`, `AsRef<str>`, `Display`
25+
- Provides `decode()` and `decode_with_strictness()` methods
26+
- **Convenience functions**: Added `encode_to_validated()` and `parse_encoded()`
27+
28+
#### Phase 4: Comprehensive Testing
29+
- **Property-based tests**: Added 16 property tests using proptest
30+
- Round-trip invariant verification
31+
- Encode/decode determinism checks
32+
- Buffer reuse correctness validation
33+
- **Error handling tests**: Added comprehensive error case coverage
34+
- **Concurrency tests**: Added parallel operation verification
35+
- **Benchmarks**: Enhanced benchmarking for all base types and sizes
36+
37+
#### Phase 5: Macro Improvements
38+
- **Macro documentation**: Added comprehensive documentation for all macros
39+
- `build_base_enum`: Documents Base enum generation
40+
- `derive_base_encoding`: Documents data-encoding codec generation
41+
- `derive_base_x`: Documents base-x codec generation
42+
- **Macro hygiene**: Added `$crate::` prefixes for proper hygiene
43+
44+
#### Phase 7: CLI Tool Improvements
45+
- **Clap v4 migration**: Migrated CLI from structopt 0.3 to clap v4
46+
- **Code deduplication**: Unified Base↔string mappings with macro
47+
- **Better error messages**: Added context to all error paths
48+
- Unknown bases now list all available options
49+
- I/O errors include operation context
50+
51+
#### Phase 8: Security Audit
52+
- **Security tests**: Added 17 comprehensive security tests
53+
- Large input handling (1 MB tested)
54+
- Malformed input rejection
55+
- Buffer reuse safety
56+
- Concurrent operation safety
57+
- Resource exhaustion resistance
58+
- **Fuzzing infrastructure**: Set up cargo-fuzz with 3 targets
59+
- `fuzz_decode`: Arbitrary string decoding
60+
- `fuzz_encode`: Arbitrary byte encoding
61+
- `fuzz_roundtrip`: Round-trip verification
62+
- **Security documentation**: Added SECURITY.md with:
63+
- Security audit findings
64+
- Best practices for users
65+
- Input size limit recommendations
66+
- Vulnerability reporting process
67+
68+
#### Phase 9: Concurrency Analysis
69+
- **Thread safety tests**: Added 20 thread safety tests
70+
- Compile-time Send/Sync assertions
71+
- Cross-thread send/sync verification
72+
- Concurrent correctness testing (stress test with 2000 operations)
73+
- **Concurrency documentation**: Added CONCURRENCY.md with:
74+
- Thread safety guarantees for all types
75+
- Safe concurrent usage patterns
76+
- Performance considerations
77+
- Best practices
78+
79+
### Changed
80+
81+
#### Phase 1: Critical Fixes
82+
- **BREAKING**: Error type now uses thiserror instead of manual implementation
83+
- More ergonomic error handling with better error messages
84+
- `#[non_exhaustive]` attribute added for forward compatibility
85+
- Better error context preservation
86+
- **Identity encoding**: Now uses lossy UTF-8 conversion instead of panicking
87+
- Invalid UTF-8 bytes replaced with Unicode replacement character (U+FFFD)
88+
- **BREAKING**: Invalid UTF-8 no longer panics but won't round-trip perfectly
89+
- **Edition upgrade**: Updated from Rust 2018 to Rust 2021
90+
- **License headers**: Added SPDX-License-Identifier to all source files
91+
92+
#### Documentation Improvements
93+
- **API documentation**: Enhanced all public item documentation
94+
- Added performance characteristics
95+
- Added usage examples
96+
- Documented error conditions
97+
- **Module documentation**: Added comprehensive module docs
98+
- When to use which encoding
99+
- Security considerations
100+
- Common pitfalls
101+
102+
### Fixed
103+
104+
- **Security**: Fixed potential panic in Identity encoding with invalid UTF-8
105+
- **Performance**: Fixed O(n) string reallocation in `encode()`
106+
- **Error handling**: Error context no longer lost during conversions
107+
- **Documentation**: Fixed rustdoc warnings and broken links
108+
109+
### Development
110+
111+
- **Test coverage**: Increased from 7 to 142 tests (excluding 4 ignored)
112+
- 12 unit tests
113+
- 63 integration tests
114+
- 16 property tests
115+
- 17 security tests
116+
- 20 thread safety tests
117+
- 14 doc tests
118+
- **Quality assurance**: Zero clippy warnings with `-D warnings`
119+
- **CI improvements**: All tests pass consistently
120+
121+
## [1.0.0] - Previous Release
122+
123+
Initial stable release with basic multibase functionality.
124+
125+
### Features
126+
- Support for 24 base encodings
127+
- Strict and permissive decoding modes
128+
- no_std support with alloc
129+
- Basic error handling
130+
- CLI tool
131+
132+
## Migration Guide: v1.x → v2.0
133+
134+
### Error Handling Changes
135+
136+
**Before (v1.x)**:
137+
```rust
138+
match decode(input, true) {
139+
Ok((base, data)) => { /* ... */ }
140+
Err(Error::UnknownBase(c)) => { /* ... */ }
141+
Err(Error::InvalidBaseString) => { /* ... */ }
142+
}
143+
```
144+
145+
**After (v2.0)**:
146+
```rust
147+
match decode(input, true) {
148+
Ok((base, data)) => { /* ... */ }
149+
Err(Error::UnknownBase { code }) => { /* ... */ }
150+
Err(Error::InvalidBaseString) => { /* ... */ }
151+
Err(Error::EmptyInput) => { /* ... */ }
152+
// New error variants - use catch-all due to #[non_exhaustive]
153+
Err(_) => { /* ... */ }
154+
}
155+
```
156+
157+
### Identity Encoding Changes
158+
159+
**Before (v1.x)**:
160+
- Would panic on invalid UTF-8
161+
162+
**After (v2.0)**:
163+
- Uses lossy conversion (replacement character U+FFFD)
164+
- No panic on arbitrary binary data
165+
166+
**Migration**:
167+
If you relied on panic behavior for validation:
168+
```rust
169+
// Validate UTF-8 explicitly if needed
170+
let data = std::str::from_utf8(bytes)?;
171+
let encoded = encode(Base::Identity, data.as_bytes());
172+
```
173+
174+
### New Features You Can Use
175+
176+
**Buffer Reuse** (performance optimization):
177+
```rust
178+
let mut encode_buffer = String::new();
179+
let mut decode_buffer = Vec::new();
180+
181+
for data in dataset {
182+
encode_into(Base::Base64, data, &mut encode_buffer);
183+
decode_into(&encode_buffer, true, &mut decode_buffer)?;
184+
}
185+
```
186+
187+
**Type Safety with EncodedString**:
188+
```rust
189+
let encoded = EncodedString::new("zCn8eVZg")?;
190+
assert_eq!(encoded.base(), Base::Base58Btc);
191+
let decoded = encoded.decode()?;
192+
```
193+
194+
**Error Context** (with thiserror):
195+
```rust
196+
// Errors now provide better context
197+
match multibase::decode(input, true) {
198+
Err(Error::DataEncodingDecode { message }) => {
199+
eprintln!("Decoding failed: {}", message);
200+
}
201+
Err(e) => eprintln!("Error: {}", e),
202+
Ok(_) => {}
203+
}
204+
```
205+
206+
## Compatibility
207+
208+
### Minimum Supported Rust Version (MSRV)
209+
210+
The MSRV is Rust 1.56.0 (Rust 2021 edition).
211+
212+
### Platform Support
213+
214+
- ✅ Linux
215+
- ✅ macOS
216+
- ✅ Windows
217+
- ✅ WebAssembly (wasm32)
218+
- ✅ no_std environments (with alloc)
219+
220+
### Breaking Changes
221+
222+
The following changes require a major version bump (v2.0.0):
223+
224+
1. Error type structure changed (uses thiserror)
225+
2. Identity encoding no longer panics (uses lossy conversion)
226+
3. `#[non_exhaustive]` added to Error enum
227+
4. Edition updated to 2021
228+
229+
### Non-Breaking Additions
230+
231+
The following are backwards-compatible additions:
232+
233+
1. New functions: `encode_into()`, `decode_into()`, `encode_to_validated()`, `parse_encoded()`
234+
2. New type: `EncodedString`
235+
3. Enhanced documentation
236+
4. Additional tests
237+
5. Performance improvements
238+
239+
## Acknowledgments
240+
241+
This release includes improvements guided by:
242+
- [The Definitive Guide to Rust Error Handling](https://www.howtocodeit.com/articles/the-definitive-guide-to-rust-error-handling)
243+
- [Writing Production Rust Macros](https://www.howtocodeit.com/articles/writing-production-rust-macros-with-macro-rules)
244+
- [Ultimate Guide to Rust Newtypes](https://www.howtocodeit.com/articles/ultimate-guide-rust-newtypes)
245+
- Rust API Guidelines
246+
- OWASP Security Guidelines
247+
248+
[Unreleased]: https://github.com/multiformats/rust-multibase/compare/v1.0.0...HEAD
249+
[1.0.0]: https://github.com/multiformats/rust-multibase/releases/tag/v1.0.0

0 commit comments

Comments
 (0)