This is an educational, simple, dependency-free implementation of Base64 encoding, written as a learning exercise. This project focuses on a clear and understandable implementation of the Base64 algorithm (RFC 4648) from scratch.
This library was written to practice Rust. It has not been audited for security or optimized for all edge cases. It is not recommended for production use.
For a battle-tested, production-ready library, please use the official base64 crate.
- Base64 Encoding: Provides functions to encode byte slices (
&[u8]) into aStringor write them into a mutable byte slice (&mut [u8]). - Zero Dependencies: Written from scratch in pure, stable Rust.
The API is straightforward. It exposes three functions: encode, encode_bytes
and calc_out_capacity.
encode takes an input byte slice and returns an owned String.
fn main() {
let input = "Hello world! ☀️";
let encoded = not_base64::encode(input.as_bytes());
assert_eq!(encoded, "SGVsbG8gd29ybGQhIOKYgO+4jw==");
}encode_bytes, takes an input and a mutable output byte slices, filling the
output with the Base64 encoded bytes. It expects a pre-allocated buffer and
panics if output has not enough capacity. calc_out_capacity can be used to
compute the exact capacity needed to encode the input slice.
fn main() {
let input = "Hello world! ☀️".as_bytes();
let capacity = not_base64::calc_out_capacity(input);
let mut output = vec![0u8; capacity];
not_base64::encode_bytes(input, &mut output);
assert_eq!(output, b"SGVsbG8gd29ybGQhIOKYgO+4jw==");
}Base64 encoding works by taking 3 bytes of input and reorganizing the contained 24-bits into 4 groups of 6-bits. Each of the 4 bytes are zero-prefixed.
This implementation processes the input in chunks of 3 bytes, so the encoder can face three possible scenarios, the numeric values are meant to illustrate how the bits are re-distributed in the encoding process:
input -> 1111 2222 | 3333 4444 | 5555 6666
output -> 0011 1122 | 0022 3333 | 0044 4455 | 0055 6666In case the input length is not multiple of 3, the remaining bytes are handled
separately and the output will be padded with = character.
input -> 1111 2222 | 3333 4444 | 0000 0000
output -> 0011 1122 | 0022 3333 | 0044 4400 | 0000 0000
(pad '=')input -> 1111 2222 | 0000 0000 | 0000 0000
output -> 0011 1122 | 0022 0000 | 0000 0000 | 0000 0000
(pad '=') (pad '=')The encoder uses bitwise masks and shifts to extract the 6-bits values from the original 8-bit values.
For example, on the first input byte, we first apply the mask to isolate the first 6-bits, which will be grouped into the first output byte.
input b"i" 0x69 -> 0110 1001 &
mask 0xfc -> 1111 1100
0110 1000We then shift the resulting word by two bits to the right, to place the bits in position.
masked 6-bits -> 0110 1000 >>
shift positions -> 2
0001 1010
zero-prefix ^^A corresponding decode function is a potential future addition. The initial
implementation focused solely on the encoding functionality required for another
project.
not-base64 is released under MIT license. See LICENSE in this source
distribution for more information.