//! Base64 encoding and decoding.
use std::io::{self, Read, Write};
use base64::engine;
use base64::prelude::BASE64_STANDARD_NO_PAD;
use base64::{read::DecoderReader, write::EncoderWriter};
use crate::pipeline::traits::{self, Base64Decode, Base64Encode, Error};
// TODO: Implement dedicated `encode_key()`/`decode_key()` methods.
// As per the `GeneralPurpose` engine docs:
// It is not constant-time, though, so it is vulnerable to timing
// side-channel attacks. For loading cryptographic keys, etc, it is
// suggested to use the forthcoming constant-time implementation.
impl Base64Encode for &[u8] {
fn base64_encode(&self) -> String {
let mut reader = io::Cursor::new(self);
let mut encoded = Vec::new();
let mut base64_sink = Base64Sink::new(&mut encoded);
io::copy(&mut reader, &mut base64_sink).expect("this is all in memory");
std::mem::drop(base64_sink); // Explicit drop needed to reborrow `&mut encoded`.
String::from_utf8_lossy(&encoded).to_string()
}
}
impl<const N: usize> Base64Encode for &[u8; N] {
fn base64_encode(&self) -> String {
self.as_slice().base64_encode()
}
}
impl Base64Encode for Vec<u8> {
fn base64_encode(&self) -> String {
self.as_slice().base64_encode()
}
}
impl Base64Decode for &str {
fn base64_decode(&self) -> traits::Result<Vec<u8>> {
let mut reader = io::Cursor::new(self);
let mut decoded = Vec::new();
let mut base64_source = Base64Source::new(&mut reader);
io::copy(&mut base64_source, &mut decoded)
.map_err(|reason| Error::Base64Decode(reason.to_string()))?;
Ok(decoded)
}
}
impl Base64Decode for String {
fn base64_decode(&self) -> traits::Result<Vec<u8>> {
self.as_str().base64_decode()
}
}
/// When written to, it encodes the bytes as base64.
pub struct Base64Sink<'a, W: Write> {
encoder: EncoderWriter<'a, engine::GeneralPurpose, &'a mut W>,
}
impl<'a, W: Write> Base64Sink<'a, W> {
pub fn new(writer: &'a mut W) -> Self {
let encoder = EncoderWriter::new(writer, &BASE64_STANDARD_NO_PAD);
Self { encoder }
}
}
impl<W: Write> Write for Base64Sink<'_, W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.encoder.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.encoder.flush()
}
}
struct NewlineTrimmer<'a, R: Read> {
reader: &'a mut R,
is_trimmed: bool,
}
impl<'a, R: Read> NewlineTrimmer<'a, R> {
fn new(reader: &'a mut R) -> Self {
Self {
reader,
is_trimmed: false,
}
}
}
impl<T: Read> Read for NewlineTrimmer<'_, T> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut n = self.reader.read(buf)?;
if self.is_trimmed {
// Trimming is only allowed _once_ at the end.
//
// If we are here, it means we are reading _again_ after
// trimming. This is an error in the input, unless:
//
// - We read 0 bytes (EOF).
// - We read more `\n`s.
//
// Anything else is invalid.
if buf[..n].iter().any(|&c| c != b'\n') {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Unexpected data after final newline",
));
}
}
// Trim trailing `\n`s and remember it.
while n > 0 && buf[n - 1] == b'\n' {
n -= 1;
self.is_trimmed = true;
}
Ok(n)
}
}
/// When read from, it decodes base64 as bytes.
pub struct Base64Source<'a, R: Read> {
decoder: DecoderReader<'a, engine::GeneralPurpose, NewlineTrimmer<'a, R>>,
}
impl<'a, R: Read> Base64Source<'a, R> {
pub fn new(reader: &'a mut R) -> Self {
let newline_stripper = NewlineTrimmer::new(reader);
let decoder = DecoderReader::new(newline_stripper, &BASE64_STANDARD_NO_PAD);
Self { decoder }
}
}
impl<R: Read> Read for Base64Source<'_, R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.decoder.read(buf)
}
}
#[cfg(test)]
pub mod tests {
use super::*;
const HELLO_WORLD_1000: &str = "aGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIWhlbGxvLCB3b3JsZCFoZWxsbywgd29ybGQhaGVsbG8sIHdvcmxkIQ";
#[test]
fn base64_encode_bytes() {
let plaintext = b"hello, world!";
let base64 = plaintext.base64_encode();
assert_eq!(base64, "aGVsbG8sIHdvcmxkIQ");
}
#[test]
fn base64_decode_string() {
let base64 = "aGVsbG8sIHdvcmxkIQ";
let plaintext = base64.base64_decode().unwrap();
let plaintext = String::from_utf8_lossy(&plaintext).to_string();
assert_eq!(plaintext, "hello, world!");
}
#[test]
fn base64_encode_sink_short() {
let plaintext = b"hello, world!";
let mut writer = io::Cursor::new(plaintext);
let mut encoded = Vec::new();
let mut base64_sink = Base64Sink::new(&mut encoded);
io::copy(&mut writer, &mut base64_sink).unwrap();
std::mem::drop(base64_sink);
let base64 = String::from_utf8_lossy(&encoded);
assert_eq!(base64, "aGVsbG8sIHdvcmxkIQ");
}
#[test]
fn base64_encode_sink_long() {
let plaintext = b"hello, world!".repeat(1000);
let mut writer = io::Cursor::new(plaintext);
let mut encoded = Vec::new();
let mut base64_sink = Base64Sink::new(&mut encoded);
io::copy(&mut writer, &mut base64_sink).unwrap();
std::mem::drop(base64_sink);
let base64 = String::from_utf8_lossy(&encoded);
assert_eq!(base64, HELLO_WORLD_1000);
}
#[test]
fn base64_decode_source_short() {
let base64 = "aGVsbG8sIHdvcmxkIQ";
let mut reader = io::Cursor::new(base64);
let mut decoded = Vec::new();
let mut base64_source = Base64Source::new(&mut reader);
io::copy(&mut base64_source, &mut decoded).unwrap();
let plaintext = String::from_utf8_lossy(&decoded);
assert_eq!(plaintext, "hello, world!");
}
#[test]
fn base64_decode_source_long() {
let base64 = HELLO_WORLD_1000;
let mut reader = io::Cursor::new(base64);
let mut decoded = Vec::new();
let mut base64_source = Base64Source::new(&mut reader);
io::copy(&mut base64_source, &mut decoded).unwrap();
let plaintext = String::from_utf8_lossy(&decoded);
assert_eq!(plaintext, "hello, world!".repeat(1000));
}
}