Skip to content

Commit f766bc6

Browse files
Merge pull request #223 from marshallpierce/mp/add_padding_len
Switch add_padding() to use encoded len
2 parents 29ed4d0 + 9687b03 commit f766bc6

File tree

3 files changed

+24
-20
lines changed

3 files changed

+24
-20
lines changed

src/chunked_encoder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ impl<'e, E: Engine + ?Sized> ChunkedEncoder<'e, E> {
4949
if self.engine.config().encode_padding() && !more_input_left {
5050
// no more input, add padding if needed. Buffer will have room because
5151
// max_input_length leaves room for it.
52-
b64_bytes_written += add_padding(bytes.len(), &mut encode_buf[b64_bytes_written..]);
52+
b64_bytes_written +=
53+
add_padding(b64_bytes_written, &mut encode_buf[b64_bytes_written..]);
5354
}
5455

5556
sink.write_encoded_bytes(&encode_buf[0..b64_bytes_written])?;

src/encode.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub(crate) fn encode_with_padding<E: Engine + ?Sized>(
7777
let b64_bytes_written = engine.internal_encode(input, output);
7878

7979
let padding_bytes = if engine.config().encode_padding() {
80-
add_padding(input.len(), &mut output[b64_bytes_written..])
80+
add_padding(b64_bytes_written, &mut output[b64_bytes_written..])
8181
} else {
8282
0
8383
};
@@ -117,20 +117,20 @@ pub fn encoded_len(bytes_len: usize, padding: bool) -> Option<usize> {
117117
}
118118

119119
/// Write padding characters.
120-
/// `input_len` is the size of the original, not encoded, input.
120+
/// `unpadded_output_len` is the size of the unpadded but base64 encoded data.
121121
/// `output` is the slice where padding should be written, of length at least 2.
122122
///
123123
/// Returns the number of padding bytes written.
124-
pub(crate) fn add_padding(input_len: usize, output: &mut [u8]) -> usize {
125-
// TODO base on encoded len to use cheaper mod by 4 (aka & 7)
126-
let rem = input_len % 3;
127-
let mut bytes_written = 0;
128-
for _ in 0..((3 - rem) % 3) {
129-
output[bytes_written] = PAD_BYTE;
130-
bytes_written += 1;
124+
pub(crate) fn add_padding(unpadded_output_len: usize, output: &mut [u8]) -> usize {
125+
let pad_bytes = (4 - (unpadded_output_len % 4)) % 4;
126+
// for just a couple bytes, this has better performance than using
127+
// .fill(), or iterating over mutable refs, which call memset()
128+
#[allow(clippy::needless_range_loop)]
129+
for i in 0..pad_bytes {
130+
output[i] = PAD_BYTE;
131131
}
132132

133-
bytes_written
133+
pad_bytes
134134
}
135135

136136
/// Errors that can occur while encoding into a slice.
@@ -434,18 +434,18 @@ mod tests {
434434

435435
let mut rng = rand::rngs::SmallRng::from_entropy();
436436

437-
// cover our bases for length % 3
438-
for input_len in 0..10 {
437+
// cover our bases for length % 4
438+
for unpadded_output_len in 0..20 {
439439
output.clear();
440440

441441
// fill output with random
442-
for _ in 0..10 {
442+
for _ in 0..100 {
443443
output.push(rng.gen());
444444
}
445445

446446
let orig_output_buf = output.clone();
447447

448-
let bytes_written = add_padding(input_len, &mut output);
448+
let bytes_written = add_padding(unpadded_output_len, &mut output);
449449

450450
// make sure the part beyond bytes_written is the same garbage it was before
451451
assert_eq!(orig_output_buf[bytes_written..], output[bytes_written..]);

src/engine/tests.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ fn rfc_test_vectors_std_alphabet<E: EngineWrapper>(engine_wrapper: E) {
8686
&encoded_without_padding,
8787
&std::str::from_utf8(&encode_buf[0..encode_len]).unwrap()
8888
);
89-
let pad_len = add_padding(orig.len(), &mut encode_buf[encode_len..]);
89+
let pad_len = add_padding(encode_len, &mut encode_buf[encode_len..]);
9090
assert_eq!(encoded.as_bytes(), &encode_buf[..encode_len + pad_len]);
9191

9292
let decode_len = engine
@@ -195,7 +195,10 @@ fn encode_doesnt_write_extra_bytes<E: EngineWrapper>(engine_wrapper: E) {
195195

196196
// pad so we can decode it in case our random engine requires padding
197197
let pad_len = if padded {
198-
add_padding(orig_len, &mut encode_buf[prefix_len + encoded_len_no_pad..])
198+
add_padding(
199+
encoded_len_no_pad,
200+
&mut encode_buf[prefix_len + encoded_len_no_pad..],
201+
)
199202
} else {
200203
0
201204
};
@@ -382,7 +385,7 @@ fn decode_detect_invalid_last_symbol_every_possible_two_symbols<E: EngineWrapper
382385
for b in 0_u8..=255 {
383386
let mut b64 = vec![0_u8; 4];
384387
assert_eq!(2, engine.internal_encode(&[b], &mut b64[..]));
385-
let _ = add_padding(1, &mut b64[2..]);
388+
let _ = add_padding(2, &mut b64[2..]);
386389

387390
assert!(base64_to_bytes.insert(b64, vec![b]).is_none());
388391
}
@@ -442,7 +445,7 @@ fn decode_detect_invalid_last_symbol_every_possible_three_symbols<E: EngineWrapp
442445
bytes[1] = b2;
443446
let mut b64 = vec![0_u8; 4];
444447
assert_eq!(3, engine.internal_encode(&bytes, &mut b64[..]));
445-
let _ = add_padding(2, &mut b64[3..]);
448+
let _ = add_padding(3, &mut b64[3..]);
446449

447450
let mut v = Vec::with_capacity(2);
448451
v.extend_from_slice(&bytes[..]);
@@ -1245,7 +1248,7 @@ fn generate_random_encoded_data<E: Engine, R: rand::Rng, D: distributions::Distr
12451248
let base_encoded_len = engine.internal_encode(&orig_data[..], &mut encode_buf[..]);
12461249

12471250
let enc_len_with_padding = if padding {
1248-
base_encoded_len + add_padding(orig_len, &mut encode_buf[base_encoded_len..])
1251+
base_encoded_len + add_padding(base_encoded_len, &mut encode_buf[base_encoded_len..])
12491252
} else {
12501253
base_encoded_len
12511254
};

0 commit comments

Comments
 (0)