Loading page…
Rust walkthroughs
Loading page…
The base64 crate provides Base64 encoding and decoding for Rust. Base64 is a binary-to-text encoding scheme that represents binary data as ASCII characters. It's commonly used for encoding binary data in JSON, URLs, email attachments, and other text-based protocols. The crate supports multiple Base64 variants (standard, URL-safe, etc.) and configurable character sets.
Key concepts:
+ and / with = padding- and _ instead of + and /Base64 encodes 3 bytes into 4 characters, expanding data by ~33%.
# Cargo.toml
[dependencies]
base64 = "0.22"use base64::{Engine as _, engine::general_purpose};
fn main() {
// Simple encoding and decoding
let data = b"Hello, World!";
let encoded = general_purpose::STANDARD.encode(data);
println!("Encoded: {}", encoded);
let decoded = general_purpose::STANDARD.decode(&encoded).unwrap();
println!("Decoded: {}", String::from_utf8_lossy(&decoded));
}use base64::{Engine as _, engine::general_purpose};
fn main() {
// Standard Base64 encoding
let original = "Hello, Rust!";
let encoded = general_purpose::STANDARD.encode(original.as_bytes());
println!("Original: {}", original);
println!("Encoded: {}", encoded);
// Standard Base64 decoding
let decoded = general_purpose::STANDARD.decode(&encoded).unwrap();
let decoded_str = String::from_utf8(decoded).unwrap();
println!("Decoded: {}", decoded_str);
// Encoding binary data
let binary_data: Vec<u8> = vec![0, 1, 2, 255, 254, 253];
let encoded = general_purpose::STANDARD.encode(&binary_data);
println!("\nBinary encoded: {}", encoded);
let decoded = general_purpose::STANDARD.decode(&encoded).unwrap();
println!("Binary decoded: {:?}", decoded);
}use base64::{Engine as _, engine::general_purpose};
fn main() {
let data = b"Data with + and / characters";
// Standard encoding (uses + and /)
let standard = general_purpose::STANDARD.encode(data);
println!("Standard: {}", standard);
// URL-safe encoding (uses - and _ instead)
let url_safe = general_purpose::URL_SAFE.encode(data);
println!("URL-safe: {}", url_safe);
// URL-safe without padding
let url_safe_no_pad = general_purpose::URL_SAFE_NO_PAD.encode(data);
println!("URL-safe no pad: {}", url_safe_no_pad);
// Decode URL-safe
let decoded = general_purpose::URL_SAFE.decode(&url_safe).unwrap();
println!("Decoded: {:?}", String::from_utf8_lossy(&decoded));
// The difference in characters
let test_data = b"\xff\xff"; // Encodes to //+ in standard
println!("\nStandard: {}", general_purpose::STANDARD.encode(test_data));
println!("URL-safe: {}", general_purpose::URL_SAFE.encode(test_data));
}use base64::{Engine as _, engine::general_purpose};
use std::fs;
use std::path::Path;
fn main() {
// Encode a string
let text = "This is some text to encode";
let encoded = general_purpose::STANDARD.encode(text.as_bytes());
println!("Encoded text: {}", encoded);
// Decode back to string
let decoded_bytes = general_purpose::STANDARD.decode(&encoded).unwrap();
let decoded_text = String::from_utf8(decoded_bytes).unwrap();
println!("Decoded text: {}", decoded_text);
// Encode JSON-like data
let json_data = r#"{"user":"alice","id":42}"#;
let encoded = general_purpose::STANDARD.encode(json_data.as_bytes());
println!("\nEncoded JSON: {}", encoded);
// Simulate file encoding
let file_content = b"\x89PNG\r\n\x1a\n"; // PNG header
let encoded = general_purpose::STANDARD.encode(file_content);
println!("\nEncoded PNG header: {}", encoded);
// Decode and verify
let decoded = general_purpose::STANDARD.decode(&encoded).unwrap();
assert_eq!(file_content.to_vec(), decoded);
println!("Round-trip successful!");
}use base64::{Engine as _, engine::general_purpose};
fn main() {
// Encode numbers (as bytes)
let number: u32 = 12345678;
let bytes = number.to_be_bytes();
let encoded = general_purpose::STANDARD.encode(bytes);
println!("Encoded number: {}", encoded);
let decoded_bytes = general_purpose::STANDARD.decode(&encoded).unwrap();
let decoded_number = u32::from_be_bytes(
decoded_bytes.try_into().unwrap()
);
println!("Decoded number: {}", decoded_number);
// Encode a struct
#[derive(Debug)]
struct Point {
x: f64,
y: f64,
}
let point = Point { x: 10.5, y: 20.3 };
let bytes: [u8; 16] = unsafe {
// In real code, prefer bytemuck or zerocopy crates
std::mem::transmute([point.x.to_be_bytes(), point.y.to_be_bytes()])
};
let encoded = general_purpose::STANDARD.encode(bytes);
println!("\nEncoded point: {}", encoded);
// Encode a vector of bytes
let data = vec![0x00, 0xFF, 0xAB, 0xCD, 0xEF];
let encoded = general_purpose::STANDARD.encode(&data);
println!("\nEncoded vec: {}", encoded);
// Encode empty data
let empty: &[u8] = &[];
let encoded = general_purpose::STANDARD.encode(empty);
println!("Empty encoded: '{}'", encoded);
}use base64::{Engine as _, engine::general_purpose::{self, GeneralPurpose}};
use base64::engine::{GeneralPurposeConfig, PaddingDirection};
fn main() {
// Using pre-defined configurations
let data = b"Hello";
// Standard with padding (default)
println!("STANDARD: {}", general_purpose::STANDARD.encode(data));
// Standard without padding
println!("STANDARD_NO_PAD: {}", general_purpose::STANDARD_NO_PAD.encode(data));
// URL-safe with padding
println!("URL_SAFE: {}", general_purpose::URL_SAFE.encode(data));
// URL-safe without padding
println!("URL_SAFE_NO_PAD: {}", general_purpose::URL_SAFE_NO_PAD.encode(data));
// Custom configuration
let custom_config = GeneralPurposeConfig::new()
.with_encode_padding(true)
.with_decode_padding_mode(base64::engine::DecodePaddingMode::Indifferent);
let custom_engine = GeneralPurpose::new(
&base64::alphabet::STANDARD,
custom_config,
);
let encoded = custom_engine.encode(data);
println!("\nCustom config: {}", encoded);
}use base64::{Engine as _, engine::general_purpose};
use base64::DecodeError;
fn decode_safely(encoded: &str) -> Result<Vec<u8>, String> {
general_purpose::STANDARD.decode(encoded)
.map_err(|e| format!("Decode error: {}", e))
}
fn main() {
// Valid encoding
match decode_safely("SGVsbG8gV29ybGQ=") {
Ok(data) => println!("Decoded: {:?}", String::from_utf8_lossy(&data)),
Err(e) => println!("Error: {}", e),
}
// Invalid Base64 characters
match decode_safely("Invalid!@#$") {
Ok(data) => println!("Decoded: {:?}", data),
Err(e) => println!("Error: {}", e),
}
// Invalid padding
match decode_safely("SGVsbG8") {
Ok(data) => println!("Decoded: {:?}", String::from_utf8_lossy(&data)),
Err(e) => println!("Error: {}", e),
}
// Wrong padding length
match decode_safely("SGVsbG8=") {
Ok(data) => println!("Decoded: {:?}", String::from_utf8_lossy(&data)),
Err(e) => println!("Error: {}", e),
}
// Empty string
match decode_safely("") {
Ok(data) => println!("Empty decoded: {:?}", data),
Err(e) => println!("Error: {}", e),
}
}use base64::{Engine as _, engine::general_purpose};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct Image {
filename: String,
#[serde(
serialize_with = "serialize_base64",
deserialize_with = "deserialize_base64"
)]
data: Vec<u8>,
}
fn serialize_base64<S>(data: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let encoded = general_purpose::STANDARD.encode(data);
serializer.serialize_str(&encoded)
}
fn deserialize_base64<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
D: serde::Deserializer<'de>,
{
let encoded = String::deserialize(deserializer)?;
general_purpose::STANDARD.decode(&encoded)
.map_err(serde::de::Error::custom)
}
fn main() {
// Create an image struct
let image = Image {
filename: "photo.png".to_string(),
data: vec![0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A], // PNG header
};
// Serialize to JSON
let json = serde_json::to_string(&image).unwrap();
println!("JSON: {}", json);
// Deserialize from JSON
let decoded: Image = serde_json::from_str(&json).unwrap();
println!("Decoded: {:?}", decoded);
}use base64::{Engine as _, engine::general_purpose};
fn create_data_uri(mime_type: &str, data: &[u8]) -> String {
let encoded = general_purpose::STANDARD.encode(data);
format!("data:{};base64,{}", mime_type, encoded)
}
fn main() {
// Create a data URI for a small image
let png_data = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR"; // PNG header
let data_uri = create_data_uri("image/png", png_data);
println!("Data URI: {}", data_uri);
// Create a data URI for text
let text = b"Hello, World!";
let data_uri = create_data_uri("text/plain", text);
println!("Text URI: {}", data_uri);
// Create a data URI for CSS
let css = b"body { color: red; }";
let data_uri = create_data_uri("text/css", css);
println!("CSS URI: {}", data_uri);
// Create inline HTML with embedded image
let html = format!(
r#"<img src="{}" alt="Embedded image">"#,
create_data_uri("image/gif", b"GIF89a")
);
println!("HTML: {}", html);
}use base64::{Engine as _, engine::general_purpose};
fn encode_chunked(data: &[u8], chunk_size: usize) -> String {
data.chunks(chunk_size)
.map(|chunk| general_purpose::STANDARD.encode(chunk))
.collect::<Vec<_>>()
.join("\n")
}
fn main() {
// Simulate a large file
let large_data: Vec<u8> = (0..=255).cycle().take(1000).collect();
// Encode in chunks (for display purposes)
let encoded = encode_chunked(&large_data, 300);
println!("Encoded in chunks:");
for (i, line) in encoded.lines().enumerate() {
println!(" Chunk {}: {}... ({} chars)", i + 1, &line[..40.min(line.len())], line.len());
}
// Encode the whole thing at once
let full_encoded = general_purpose::STANDARD.encode(&large_data);
println!("\nFull encoded length: {} chars", full_encoded.len());
// Decode and verify
let decoded = general_purpose::STANDARD.decode(&full_encoded).unwrap();
assert_eq!(large_data, decoded);
println!("Round-trip verified!");
}use base64::{Engine as _, engine::general_purpose};
fn create_basic_auth(username: &str, password: &str) -> String {
let credentials = format!("{}:{}", username, password);
let encoded = general_purpose::STANDARD.encode(credentials.as_bytes());
format!("Basic {}", encoded)
}
fn parse_basic_auth(header: &str) -> Option<(String, String)> {
let prefix = "Basic ";
if !header.starts_with(prefix) {
return None;
}
let encoded = &header[prefix.len()..];
let decoded = general_purpose::STANDARD.decode(encoded).ok()?;
let credentials = String::from_utf8(decoded).ok()?;
let mut parts = credentials.splitn(2, ':');
let username = parts.next()?.to_string();
let password = parts.next()?.to_string();
Some((username, password))
}
fn main() {
// Create Basic Auth header
let auth_header = create_basic_auth("alice", "secret123");
println!("Authorization: {}", auth_header);
// Parse Basic Auth header
match parse_basic_auth(&auth_header) {
Some((user, pass)) => println!("Decoded: user={}, password={}", user, pass),
None => println!("Failed to parse"),
}
// Encode API token
let api_token = "sk-1234567890abcdef";
let encoded_token = general_purpose::URL_SAFE_NO_PAD.encode(api_token.as_bytes());
println!("\nEncoded token: {}", encoded_token);
let decoded_token = general_purpose::URL_SAFE_NO_PAD.decode(&encoded_token).unwrap();
println!("Decoded token: {}", String::from_utf8_lossy(&decoded_token));
}use base64::{Engine as _, engine::general_purpose};
fn main() {
let test_cases: Vec<&[u8]> = vec![
b"",
b"a",
b"ab",
b"abc",
b"abcd",
b"Hello, World!",
b"\x00\xff\xab\xcd",
];
println!("Comparing Base64 variants:\n");
println!("{:-12} | {:-24} | {:-24} | {::-24}",
"Input", "STANDARD", "STANDARD_NO_PAD", "URL_SAFE_NO_PAD");
println!("{}", "-".repeat(90));
for data in test_cases {
let preview = if data.is_empty() {
"(empty)".to_string()
} else if data.len() > 8 {
format!("{:02x?}...", &data[..8])
} else {
format!("{:02x?}", data)
};
let standard = general_purpose::STANDARD.encode(data);
let no_pad = general_purpose::STANDARD_NO_PAD.encode(data);
let url_safe = general_purpose::URL_SAFE_NO_PAD.encode(data);
println!("{:12} | {:24} | {:24} | {:24}",
preview, standard, no_pad, url_safe);
}
}use base64::{Engine as _, engine::general_purpose};
use std::io::{self, Read, Write};
struct Base64Encoder {
buffer: Vec<u8>,
}
impl Base64Encoder {
fn new() -> Self {
Base64Encoder { buffer: Vec::new() }
}
fn write(&mut self, data: &[u8]) {
self.buffer.extend_from_slice(data);
}
fn finish(self) -> String {
general_purpose::STANDARD.encode(&self.buffer)
}
}
struct Base64Decoder {
buffer: String,
}
impl Base64Decoder {
fn new() -> Self {
Base64Decoder { buffer: String::new() }
}
fn write(&mut self, data: &str) {
self.buffer.push_str(data);
}
fn finish(self) -> Result<Vec<u8>, String> {
general_purpose::STANDARD.decode(&self.buffer)
.map_err(|e| format!("Decode error: {}", e))
}
}
fn main() {
// Simulated streaming encode
let mut encoder = Base64Encoder::new();
encoder.write(b"Hello, ");
encoder.write(b"World!");
let encoded = encoder.finish();
println!("Encoded: {}", encoded);
// Simulated streaming decode
let mut decoder = Base64Decoder::new();
decoder.write(&encoded);
let decoded = decoder.finish().unwrap();
println!("Decoded: {}", String::from_utf8_lossy(&decoded));
}base64 crate for Base64 encoding/decodinggeneral_purpose::STANDARD.encode(data) for standard Base64 with paddinggeneral_purpose::STANDARD_NO_PAD.encode(data) without paddinggeneral_purpose::URL_SAFE.encode(data) for URL-safe Base64 (uses - and _)general_purpose::URL_SAFE_NO_PAD.encode(data) for URL-safe without paddingengine.decode(encoded) returns Result<Vec<u8>, DecodeError>+ and /, URL-safe uses - and _= is added to make length a multiple of 4decode().map_err()Engine trait allows custom configurations and character sets