Skip to content

Commit d00b4db

Browse files
Move decode functions to Engine methods
1 parent d0d2c14 commit d00b4db

File tree

17 files changed

+240
-199
lines changed

17 files changed

+240
-199
lines changed

RELEASE-NOTES.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
### Breaking changes
44

55
- `FastPortable` was only meant to be an interim name, and shouldn't have shipped in 0.20. It is now `GeneralPurpose` to
6-
make its intended usage more
7-
clear.
6+
make its intended usage more clear.
87
- `GeneralPurpose` and its config are now `pub use`'d in the `engine` module for convenience.
9-
- Change a few `from()` functions to be `new()`. `from()` causes confusing compiler errors because of confusion with `From::from`, and is a little bit misleading because some of those invocations are not very cheap as one would usually expect from a `from` call.
8+
- Change a few `from()` functions to be `new()`. `from()` causes confusing compiler errors because of confusion with `From::from`, and is a little misleading because some of those invocations are not very cheap as one would usually expect from a `from` call.
109
- `encode*` and `decode*` top level functions are now methods on `Engine`.
1110

1211
# 0.20.0

benches/benchmarks.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
extern crate criterion;
33

44
use base64::{
5-
decode, decode_engine_slice, decode_engine_vec, display,
5+
display,
66
engine::{Engine, DEFAULT_ENGINE},
77
write,
88
};
@@ -16,7 +16,7 @@ fn do_decode_bench(b: &mut Bencher, &size: &usize) {
1616
let encoded = DEFAULT_ENGINE.encode(&v);
1717

1818
b.iter(|| {
19-
let orig = decode(&encoded);
19+
let orig = DEFAULT_ENGINE.decode(&encoded);
2020
black_box(&orig);
2121
});
2222
}
@@ -28,7 +28,7 @@ fn do_decode_bench_reuse_buf(b: &mut Bencher, &size: &usize) {
2828

2929
let mut buf = Vec::new();
3030
b.iter(|| {
31-
decode_engine_vec(&encoded, &mut buf, &DEFAULT_ENGINE).unwrap();
31+
DEFAULT_ENGINE.decode_vec(&encoded, &mut buf).unwrap();
3232
black_box(&buf);
3333
buf.clear();
3434
});
@@ -42,7 +42,7 @@ fn do_decode_bench_slice(b: &mut Bencher, &size: &usize) {
4242
let mut buf = Vec::new();
4343
buf.resize(size, 0);
4444
b.iter(|| {
45-
decode_engine_slice(&encoded, &mut buf, &DEFAULT_ENGINE).unwrap();
45+
DEFAULT_ENGINE.decode_slice(&encoded, &mut buf).unwrap();
4646
black_box(&buf);
4747
});
4848
}

fuzz/fuzzers/decode_random.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ fuzz_target!(|data: &[u8]| {
1111

1212
// The data probably isn't valid base64 input, but as long as it returns an error instead
1313
// of crashing, that's correct behavior.
14-
let _ = decode_engine(data, &engine);
14+
let _ = engine.decode(data);
1515
});

fuzz/fuzzers/roundtrip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ use base64::{Engine as _, engine::DEFAULT_ENGINE};
66

77
fuzz_target!(|data: &[u8]| {
88
let encoded = DEFAULT_ENGINE.encode(data);
9-
let decoded = base64::decode_engine(&encoded, &DEFAULT_ENGINE).unwrap();
9+
let decoded = DEFAULT_ENGINE.decode(&encoded).unwrap();
1010
assert_eq!(data, decoded.as_slice());
1111
});

fuzz/fuzzers/roundtrip_no_pad.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ fuzz_target!(|data: &[u8]| {
1212
let engine = general_purpose::GeneralPurpose::new(&base64::alphabet::STANDARD, config);
1313

1414
let encoded = engine.encode(data);
15-
let decoded = base64::decode_engine(&encoded, &engine).unwrap();
15+
let decoded = engine.decode(&encoded).unwrap();
1616
assert_eq!(data, decoded.as_slice());
1717
});

fuzz/fuzzers/roundtrip_random_config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ fuzz_target!(|data: &[u8]| {
1010
let engine = utils::random_engine(data);
1111

1212
let encoded = engine.encode(data);
13-
let decoded = decode_engine(&encoded, &engine).unwrap();
13+
let decoded = engine.decode(&encoded).unwrap();
1414
assert_eq!(data, decoded.as_slice());
1515
});

src/decode.rs

Lines changed: 27 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#[cfg(any(feature = "alloc", feature = "std", test))]
2-
use crate::engine::DecodeEstimate;
31
use crate::engine::Engine;
42
#[cfg(any(feature = "alloc", feature = "std", test))]
53
use crate::engine::DEFAULT_ENGINE;
@@ -61,138 +59,50 @@ impl error::Error for DecodeError {
6159
}
6260

6361
///Decode base64 using the [default engine](DEFAULT_ENGINE).
64-
///Returns a `Result` containing a `Vec<u8>`.
65-
///
66-
///# Example
6762
///
68-
///```rust
69-
/// let bytes = base64::decode("aGVsbG8gd29ybGQ=").unwrap();
70-
/// println!("{:?}", bytes);
71-
///```
63+
/// See [Engine::decode].
64+
#[deprecated(since = "0.21.0", note = "Use Engine::decode")]
7265
#[cfg(any(feature = "alloc", feature = "std", test))]
7366
pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<Vec<u8>, DecodeError> {
74-
decode_engine(input, &DEFAULT_ENGINE)
67+
DEFAULT_ENGINE.decode(input)
7568
}
7669

7770
///Decode from string reference as octets using the specified [Engine].
78-
///Returns a `Result` containing a `Vec<u8>`.
79-
///
80-
///# Example
81-
///
82-
///```rust
83-
/// let bytes = base64::decode_engine(
84-
/// "aGVsbG8gd29ybGR+Cg==",
85-
/// &base64::engine::DEFAULT_ENGINE,
86-
/// ).unwrap();
87-
/// println!("{:?}", bytes);
8871
///
89-
/// // custom engine setup
90-
/// let bytes_url = base64::decode_engine(
91-
/// "aGVsbG8gaW50ZXJuZXR-Cg",
92-
/// &base64::engine::GeneralPurpose::new(
93-
/// &base64::alphabet::URL_SAFE,
94-
/// base64::engine::general_purpose::NO_PAD),
95-
///
96-
/// ).unwrap();
97-
/// println!("{:?}", bytes_url);
98-
///```
72+
/// See [Engine::decode].
73+
///Returns a `Result` containing a `Vec<u8>`.
74+
#[deprecated(since = "0.21.0", note = "Use Engine::decode")]
9975
#[cfg(any(feature = "alloc", feature = "std", test))]
10076
pub fn decode_engine<E: Engine, T: AsRef<[u8]>>(
10177
input: T,
10278
engine: &E,
10379
) -> Result<Vec<u8>, DecodeError> {
104-
let decoded_length_estimate = (input
105-
.as_ref()
106-
.len()
107-
.checked_add(3)
108-
.expect("decoded length calculation overflow"))
109-
/ 4
110-
* 3;
111-
let mut buffer = Vec::<u8>::with_capacity(decoded_length_estimate);
112-
decode_engine_vec(input, &mut buffer, engine).map(|_| buffer)
80+
engine.decode(input)
11381
}
11482

115-
///Decode from string reference as octets.
116-
///Writes into the supplied `Vec`, which may allocate if its internal buffer isn't big enough.
117-
///Returns a `Result` containing an empty tuple, aka `()`.
118-
///
119-
///# Example
120-
///
121-
///```rust
122-
///const URL_SAFE_ENGINE: base64::engine::GeneralPurpose =
123-
/// base64::engine::GeneralPurpose::new(
124-
/// &base64::alphabet::URL_SAFE,
125-
/// base64::engine::general_purpose::PAD);
126-
///
127-
///fn main() {
128-
/// let mut buffer = Vec::<u8>::new();
129-
/// // with the default engine
130-
/// base64::decode_engine_vec(
131-
/// "aGVsbG8gd29ybGR+Cg==",
132-
/// &mut buffer,
133-
/// &base64::engine::DEFAULT_ENGINE
134-
/// ).unwrap();
135-
/// println!("{:?}", buffer);
83+
/// Decode from string reference as octets.
13684
///
137-
/// buffer.clear();
138-
///
139-
/// // with a custom engine
140-
/// base64::decode_engine_vec(
141-
/// "aGVsbG8gaW50ZXJuZXR-Cg==",
142-
/// &mut buffer,
143-
/// &URL_SAFE_ENGINE
144-
/// ).unwrap();
145-
/// println!("{:?}", buffer);
146-
///}
147-
///```
85+
/// See [Engine::decode_vec].
14886
#[cfg(any(feature = "alloc", feature = "std", test))]
87+
#[deprecated(since = "0.21.0", note = "Use Engine::decode_vec")]
14988
pub fn decode_engine_vec<E: Engine, T: AsRef<[u8]>>(
15089
input: T,
15190
buffer: &mut Vec<u8>,
15291
engine: &E,
15392
) -> Result<(), DecodeError> {
154-
let input_bytes = input.as_ref();
155-
156-
let starting_output_len = buffer.len();
157-
158-
let estimate = engine.decoded_length_estimate(input_bytes.len());
159-
let total_len_estimate = estimate
160-
.decoded_length_estimate()
161-
.checked_add(starting_output_len)
162-
.expect("Overflow when calculating output buffer length");
163-
buffer.resize(total_len_estimate, 0);
164-
165-
let buffer_slice = &mut buffer.as_mut_slice()[starting_output_len..];
166-
let bytes_written = engine.decode(input_bytes, buffer_slice, estimate)?;
167-
168-
buffer.truncate(starting_output_len + bytes_written);
169-
170-
Ok(())
93+
engine.decode_vec(input, buffer)
17194
}
17295

17396
/// Decode the input into the provided output slice.
17497
///
175-
/// This will not write any bytes past exactly what is decoded (no stray garbage bytes at the end).
176-
///
177-
/// If you don't know ahead of time what the decoded length should be, size your buffer with a
178-
/// conservative estimate for the decoded length of an input: 3 bytes of output for every 4 bytes of
179-
/// input, rounded up, or in other words `(input_len + 3) / 4 * 3`.
180-
///
181-
/// # Panics
182-
///
183-
/// If the slice is not large enough, this will panic.
98+
/// See [Engine::decode_slice].
99+
#[deprecated(since = "0.21.0", note = "Use Engine::decode_slice")]
184100
pub fn decode_engine_slice<E: Engine, T: AsRef<[u8]>>(
185101
input: T,
186102
output: &mut [u8],
187103
engine: &E,
188104
) -> Result<usize, DecodeError> {
189-
let input_bytes = input.as_ref();
190-
191-
engine.decode(
192-
input_bytes,
193-
output,
194-
engine.decoded_length_estimate(input_bytes.len()),
195-
)
105+
engine.decode_slice(input, output)
196106
}
197107

198108
#[cfg(test)]
@@ -249,9 +159,13 @@ mod tests {
249159
decoded_with_prefix.copy_from_slice(&prefix);
250160

251161
// decode into the non-empty buf
252-
decode_engine_vec(&encoded_data, &mut decoded_with_prefix, &engine).unwrap();
162+
engine
163+
.decode_vec(&encoded_data, &mut decoded_with_prefix)
164+
.unwrap();
253165
// also decode into the empty buf
254-
decode_engine_vec(&encoded_data, &mut decoded_without_prefix, &engine).unwrap();
166+
engine
167+
.decode_vec(&encoded_data, &mut decoded_without_prefix)
168+
.unwrap();
255169

256170
assert_eq!(
257171
prefix_len + decoded_without_prefix.len(),
@@ -304,8 +218,9 @@ mod tests {
304218
let offset = 1000;
305219

306220
// decode into the non-empty buf
307-
let decode_bytes_written =
308-
decode_engine_slice(&encoded_data, &mut decode_buf[offset..], &engine).unwrap();
221+
let decode_bytes_written = engine
222+
.decode_slice(&encoded_data, &mut decode_buf[offset..])
223+
.unwrap();
309224

310225
assert_eq!(orig_data.len(), decode_bytes_written);
311226
assert_eq!(
@@ -347,8 +262,9 @@ mod tests {
347262
decode_buf.resize(input_len, 0);
348263

349264
// decode into the non-empty buf
350-
let decode_bytes_written =
351-
decode_engine_slice(&encoded_data, &mut decode_buf[..], &engine).unwrap();
265+
let decode_bytes_written = engine
266+
.decode_slice(&encoded_data, &mut decode_buf[..])
267+
.unwrap();
352268

353269
assert_eq!(orig_data.len(), decode_bytes_written);
354270
assert_eq!(orig_data, decode_buf);
@@ -363,7 +279,7 @@ mod tests {
363279
let mut prefix = "AAAA".repeat(num_prefix_quads);
364280
prefix.push_str(suffix);
365281
// make sure no overflow (and thus a panic) occurs
366-
let res = decode_engine(prefix, &engine);
282+
let res = engine.decode(prefix);
367283
assert!(res.is_ok());
368284
}
369285
}

src/encode.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ mod tests {
134134

135135
use crate::{
136136
alphabet::{IMAP_MUTF7, STANDARD, URL_SAFE},
137-
decode::decode_engine_vec,
138137
engine::{
139138
general_purpose::{GeneralPurpose, NO_PAD},
140139
DEFAULT_ENGINE,
@@ -262,7 +261,9 @@ mod tests {
262261

263262
assert_eq!(prefix, encoded_data_with_prefix);
264263

265-
decode_engine_vec(&encoded_data_no_prefix, &mut decoded, &engine).unwrap();
264+
engine
265+
.decode_vec(&encoded_data_no_prefix, &mut decoded)
266+
.unwrap();
266267
assert_eq!(orig_data, decoded);
267268
}
268269
}
@@ -317,7 +318,9 @@ mod tests {
317318
&encoded_data_original_state[encoded_size..]
318319
);
319320

320-
decode_engine_vec(&encoded_data[0..encoded_size], &mut decoded, &engine).unwrap();
321+
engine
322+
.decode_vec(&encoded_data[0..encoded_size], &mut decoded)
323+
.unwrap();
321324
assert_eq!(orig_data, decoded);
322325
}
323326
}
@@ -360,7 +363,9 @@ mod tests {
360363
input_len,
361364
);
362365

363-
decode_engine_vec(&encoded_data[0..encoded_size], &mut decoded, &engine).unwrap();
366+
engine
367+
.decode_vec(&encoded_data[0..encoded_size], &mut decoded)
368+
.unwrap();
364369
assert_eq!(orig_data, decoded);
365370
}
366371
}

src/engine/general_purpose/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl super::Engine for GeneralPurpose {
164164
GeneralPurposeEstimate::new(input_len)
165165
}
166166

167-
fn decode(
167+
fn inner_decode(
168168
&self,
169169
input: &[u8],
170170
output: &mut [u8],

0 commit comments

Comments
 (0)