A Rust library for handling buffer encoding and decoding with automatic file format detection and convenient type-safe states (Decoded/Encoded).
- Buffer states: work with
Buffer<state::Decoded>andBuffer<state::Encoded>safely - File format detection via
file-formatwhen constructing from bytes - Base64 Data URL encode/decode helpers
- Size and formatting helpers (byte_unit)
- Optional features:
hash-sha2: SHA-256 and SHA-512 hashing on decoded buffershash-md5: MD5 hashing on decoded buffersserde: Serialize/Deserialize support (serializes to a Data URL string; deserializes into Encoded)
Add this to your Cargo.toml:
[dependencies]
# If published
buffer = { version = "0.1", features = ["serde"] }
# Or, as a local/path dependency
# buffer = { path = "../buffer", features = ["serde"] }Enable only the features you need, for example:
[dependencies]
buffer = { version = "0.1", features = ["hash-sha2"] }Create a decoded buffer from bytes, inspect format, encode to a Data URL, and decode back:
use buffer::{Buffer, state};
use byte_unit::UnitType;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Start with some bytes (e.g., part of a JPEG)
let raw: Vec<u8> = vec![0xFF, 0xD8, 0xFF];
// Construct a decoded buffer; format is detected automatically
let buf: Buffer<state::Decoded> = Buffer::from(raw);
println!("media type: {}", buf.media_type());
println!("extension: .{}", buf.extension());
println!("size: {}", buf.size_as_str(UnitType::Decimal));
// Encode to Data URL (base64) — stays type-safe as Encoded
let encoded: Buffer<state::Encoded> = buf.encode();
println!("data URL prefix: {}", &encoded.buffer()[..16.min(encoded.buffer().len())]);
// Decode back to bytes
let decoded = encoded.decode()?;
assert_eq!(decoded.len(), 3);
Ok(())
}Create an encoded buffer from a Data URL string and decode it:
use buffer::{Buffer, state};
fn run() -> Result<(), buffer::BufferError> {
let encoded: Buffer<state::Encoded> = Buffer::from("data:text/plain;base64,SGVsbG8=");
let decoded = encoded.decode()?;
assert!(!decoded.is_empty());
Ok(())
}You can quickly validate a decoded buffer with a closure (return Ok(()) to pass):
use buffer::{Buffer, state, ValidatorResult};
fn is_small(b: &Buffer<state::Decoded>) -> ValidatorResult<&'static str> {
if b.len() <= 1024 { Ok(()) } else { Err("too large") }
}
fn main() {
let raw = vec![1, 2, 3];
let buf: Buffer<state::Decoded> = Buffer::from(raw);
assert!(buf.is_valid(is_small));
}- Serialize: both
Buffer<Decoded>andBuffer<Encoded>serialize to a Data URL string. - Deserialize:
Buffer<Encoded>can be deserialized from a string (Data URL). To obtain bytes, call.decode()afterwards.
#[cfg(feature = "serde")]
mod example {
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct Avatar {
// Store the image as an encoded Data URL in JSON
image: buffer::Buffer<buffer::state::Encoded>,
}
}use buffer::{Buffer, state};
fn main() {
let buf: Buffer<state::Decoded> = Buffer::from(vec![1,2,3]);
#[cfg(feature = "hash-md5")]
println!("md5: {}", buf.hash_md5());
#[cfg(feature = "hash-sha2")]
{
println!("sha256: {}", buf.hash_sha256());
println!("sha512: {}", buf.hash_sha512());
}
}Buffer<state::Encoded>::decode() returns Result<Buffer<state::Decoded>, BufferError>.
use buffer::{Buffer, state};
fn main() {
let encoded: Buffer<state::Encoded> = Buffer::from("not a data url");
match encoded.decode() {
Ok(_) => {}
Err(e) => match e {
buffer::BufferError::DataUrlError(msg) => eprintln!("data URL error: {}", msg),
buffer::BufferError::InvalidBase64 => eprintln!("invalid base64"),
}
}
}- File format detection happens when constructing a decoded buffer from bytes.
encode()returns a Data URL string with the detected media type and base64 payload.- This crate uses Rust 2024 edition.
MIT License — see LICENSE.