Skip to content

Commit d96c80f

Browse files
authored
Merge branch 'marshallpierce:master' into patch-1
2 parents e8e4a22 + 5d70ba7 commit d96c80f

File tree

13 files changed

+702
-815
lines changed

13 files changed

+702
-815
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ workflows:
2020
# get a nightly or stable toolchain via rustup instead of a mutable docker tag
2121
toolchain_override: [
2222
'__msrv__', # won't add any other toolchains, just uses what's in the docker image
23-
'1.65.0', # minimum needed to build dev-dependencies
23+
'1.70.0', # minimum needed to build dev-dependencies
2424
'stable',
2525
'beta',
2626
'nightly'

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "base64"
3-
version = "0.21.7"
3+
version = "0.22.0"
44
authors = ["Alice Maz <[email protected]>", "Marshall Pierce <[email protected]>"]
55
description = "encodes and decodes base64 as bytes or utf8"
66
repository = "https://github.com/marshallpierce/rust-base64"

RELEASE-NOTES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# 0.22.0
2+
3+
- `DecodeSliceError::OutputSliceTooSmall` is now conservative rather than precise. That is, the error will only occur if the decoded output _cannot_ fit, meaning that `Engine::decode_slice` can now be used with exactly-sized output slices. As part of this, `Engine::internal_decode` now returns `DecodeSliceError` instead of `DecodeError`, but that is not expected to affect any external callers.
4+
- `DecodeError::InvalidLength` now refers specifically to the _number of valid symbols_ being invalid (i.e. `len % 4 == 1`), rather than just the number of input bytes. This avoids confusing scenarios when based on interpretation you could make a case for either `InvalidLength` or `InvalidByte` being appropriate.
5+
- Decoding is somewhat faster (5-10%)
6+
17
# 0.21.7
28

39
- Support getting an alphabet's contents as a str via `Alphabet::as_str()`

benches/benchmarks.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,8 @@ fn do_encode_bench_slice(b: &mut Bencher, &size: &usize) {
102102
fn do_encode_bench_stream(b: &mut Bencher, &size: &usize) {
103103
let mut v: Vec<u8> = Vec::with_capacity(size);
104104
fill(&mut v);
105-
let mut buf = Vec::new();
105+
let mut buf = Vec::with_capacity(size * 2);
106106

107-
buf.reserve(size * 2);
108107
b.iter(|| {
109108
buf.clear();
110109
let mut stream_enc = write::EncoderWriter::new(&mut buf, &STANDARD);

src/decode.rs

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,20 @@ use std::error;
99
#[derive(Clone, Debug, PartialEq, Eq)]
1010
pub enum DecodeError {
1111
/// An invalid byte was found in the input. The offset and offending byte are provided.
12-
/// Padding characters (`=`) interspersed in the encoded form will be treated as invalid bytes.
12+
///
13+
/// Padding characters (`=`) interspersed in the encoded form are invalid, as they may only
14+
/// be present as the last 0-2 bytes of input.
15+
///
16+
/// This error may also indicate that extraneous trailing input bytes are present, causing
17+
/// otherwise valid padding to no longer be the last bytes of input.
1318
InvalidByte(usize, u8),
14-
/// The length of the input is invalid.
15-
/// A typical cause of this is stray trailing whitespace or other separator bytes.
16-
/// In the case where excess trailing bytes have produced an invalid length *and* the last byte
17-
/// is also an invalid base64 symbol (as would be the case for whitespace, etc), `InvalidByte`
18-
/// will be emitted instead of `InvalidLength` to make the issue easier to debug.
19-
InvalidLength,
19+
/// The length of the input, as measured in valid base64 symbols, is invalid.
20+
/// There must be 2-4 symbols in the last input quad.
21+
InvalidLength(usize),
2022
/// The last non-padding input symbol's encoded 6 bits have nonzero bits that will be discarded.
2123
/// This is indicative of corrupted or truncated Base64.
22-
/// Unlike `InvalidByte`, which reports symbols that aren't in the alphabet, this error is for
23-
/// symbols that are in the alphabet but represent nonsensical encodings.
24+
/// Unlike [DecodeError::InvalidByte], which reports symbols that aren't in the alphabet,
25+
/// this error is for symbols that are in the alphabet but represent nonsensical encodings.
2426
InvalidLastSymbol(usize, u8),
2527
/// The nature of the padding was not as configured: absent or incorrect when it must be
2628
/// canonical, or present when it must be absent, etc.
@@ -30,8 +32,10 @@ pub enum DecodeError {
3032
impl fmt::Display for DecodeError {
3133
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3234
match *self {
33-
Self::InvalidByte(index, byte) => write!(f, "Invalid byte {}, offset {}.", byte, index),
34-
Self::InvalidLength => write!(f, "Encoded text cannot have a 6-bit remainder."),
35+
Self::InvalidByte(index, byte) => {
36+
write!(f, "Invalid symbol {}, offset {}.", byte, index)
37+
}
38+
Self::InvalidLength(len) => write!(f, "Invalid input length: {}", len),
3539
Self::InvalidLastSymbol(index, byte) => {
3640
write!(f, "Invalid last symbol {}, offset {}.", byte, index)
3741
}
@@ -48,9 +52,7 @@ impl error::Error for DecodeError {}
4852
pub enum DecodeSliceError {
4953
/// A [DecodeError] occurred
5054
DecodeError(DecodeError),
51-
/// The provided slice _may_ be too small.
52-
///
53-
/// The check is conservative (assumes the last triplet of output bytes will all be needed).
55+
/// The provided slice is too small.
5456
OutputSliceTooSmall,
5557
}
5658

@@ -338,3 +340,47 @@ mod tests {
338340
}
339341
}
340342
}
343+
344+
#[allow(deprecated)]
345+
#[cfg(test)]
346+
mod coverage_gaming {
347+
use super::*;
348+
use std::error::Error;
349+
350+
#[test]
351+
fn decode_error() {
352+
let _ = format!("{:?}", DecodeError::InvalidPadding.clone());
353+
let _ = format!(
354+
"{} {} {} {}",
355+
DecodeError::InvalidByte(0, 0),
356+
DecodeError::InvalidLength(0),
357+
DecodeError::InvalidLastSymbol(0, 0),
358+
DecodeError::InvalidPadding,
359+
);
360+
}
361+
362+
#[test]
363+
fn decode_slice_error() {
364+
let _ = format!("{:?}", DecodeSliceError::OutputSliceTooSmall.clone());
365+
let _ = format!(
366+
"{} {}",
367+
DecodeSliceError::OutputSliceTooSmall,
368+
DecodeSliceError::DecodeError(DecodeError::InvalidPadding)
369+
);
370+
let _ = DecodeSliceError::OutputSliceTooSmall.source();
371+
let _ = DecodeSliceError::DecodeError(DecodeError::InvalidPadding).source();
372+
}
373+
374+
#[test]
375+
fn deprecated_fns() {
376+
let _ = decode("");
377+
let _ = decode_engine("", &crate::prelude::BASE64_STANDARD);
378+
let _ = decode_engine_vec("", &mut Vec::new(), &crate::prelude::BASE64_STANDARD);
379+
let _ = decode_engine_slice("", &mut [], &crate::prelude::BASE64_STANDARD);
380+
}
381+
382+
#[test]
383+
fn decoded_len_est() {
384+
assert_eq!(3, decoded_len_estimate(4));
385+
}
386+
}

0 commit comments

Comments
 (0)