/// B64-encode and pad (if configured). /// /// This helper exists to avoid recalculating encoded_size, which is relatively expensive on short /// inputs. /// /// `encoded_size` is the encoded size calculated for `input`. /// /// `output` must be of size `encoded_size`. /// /// All bytes in `output` will be written to since it is exactly the size of the output. pub(crate) fn encode_with_padding<E: Engine + ?Sized>(
input: &[u8],
output: &mut [u8],
engine: &E,
expected_encoded_size: usize,
) {
debug_assert_eq!(expected_encoded_size, output.len());
let b64_bytes_written = engine.internal_encode(input, output);
let padding_bytes = if engine.config().encode_padding() {
add_padding(b64_bytes_written, &mut output[b64_bytes_written..])
} else { 0
};
let encoded_bytes = b64_bytes_written
.checked_add(padding_bytes)
.expect("usize overflow when calculating b64 length");
/// Calculate the base64 encoded length for a given input length, optionally including any /// appropriate padding bytes. /// /// Returns `None` if the encoded length can't be represented in `usize`. This will happen for /// input lengths in approximately the top quarter of the range of `usize`. pubfn encoded_len(bytes_len: usize, padding: bool) -> Option<usize> { let rem = bytes_len % 3;
let complete_input_chunks = bytes_len / 3; let complete_chunk_output = complete_input_chunks.checked_mul(4);
if rem > 0 { if padding {
complete_chunk_output.and_then(|c| c.checked_add(4))
} else { let encoded_rem = match rem { 1 => 2, 2 => 3,
_ => unreachable!("Impossible remainder"),
};
complete_chunk_output.and_then(|c| c.checked_add(encoded_rem))
}
} else {
complete_chunk_output
}
}
/// Write padding characters. /// `unpadded_output_len` is the size of the unpadded but base64 encoded data. /// `output` is the slice where padding should be written, of length at least 2. /// /// Returns the number of padding bytes written. pub(crate) fn add_padding(unpadded_output_len: usize, output: &mut [u8]) -> usize { let pad_bytes = (4 - (unpadded_output_len % 4)) % 4; // for just a couple bytes, this has better performance than using // .fill(), or iterating over mutable refs, which call memset() #[allow(clippy::needless_range_loop)] for i in0..pad_bytes {
output[i] = PAD_BYTE;
}
pad_bytes
}
/// Errors that can occur while encoding into a slice. #[derive(Clone, Debug, PartialEq, Eq)] pubenum EncodeSliceError { /// The provided slice is too small.
OutputSliceTooSmall,
}
for _ in0..10_000 {
orig_data.clear();
prefix.clear();
encoded_data_no_prefix.clear();
encoded_data_with_prefix.clear();
decoded.clear();
let input_len = input_len_range.sample(&mut rng);
for _ in0..input_len {
orig_data.push(rng.gen());
}
let prefix_len = prefix_len_range.sample(&mut rng); for _ in0..prefix_len { // getting convenient random single-byte printable chars that aren't base64 is // annoying
prefix.push('#');
}
encoded_data_with_prefix.push_str(&prefix);
for _ in0..10_000 {
input.clear();
output.clear();
let input_len = input_len_range.sample(&mut rng);
for _ in0..input_len {
input.push(rng.gen());
}
let config = random_config(&mut rng); let engine = random_engine(&mut rng);
// fill up the output buffer with garbage let encoded_size = encoded_len(input_len, config.encode_padding()).unwrap(); for _ in0..encoded_size {
output.push(rng.gen());
}
let orig_output_buf = output.clone();
let bytes_written = engine.internal_encode(&input, &mut output);
// make sure the part beyond bytes_written is the same garbage it was before
assert_eq!(orig_output_buf[bytes_written..], output[bytes_written..]);
// make sure the encoded bytes are UTF-8 let _ = str::from_utf8(&output[0..bytes_written]).unwrap();
}
}
for _ in0..10_000 {
input.clear();
output.clear();
let input_len = input_len_range.sample(&mut rng);
for _ in0..input_len {
input.push(rng.gen());
}
let engine = random_engine(&mut rng);
// fill up the output buffer with garbage let encoded_size = encoded_len(input_len, engine.config().encode_padding()).unwrap(); for _ in0..encoded_size + 1000 {
output.push(rng.gen());
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.