| Crates.io | shmp |
| lib.rs | shmp |
| version | 0.1.0 |
| created_at | 2025-10-10 09:59:26.409214+00 |
| updated_at | 2025-10-10 09:59:26.409214+00 |
| description | A flexible and efficient MessagePack serialization implementation in Rust |
| homepage | |
| repository | https://github.com/shanpark/shmp |
| max_upload_size | |
| id | 1876744 |
| size | 349,121 |
A flexible and efficient MessagePack implementation in Rust, designed with serde integration in mind.
shmp offers two primary ways to work with MessagePack data:
Pack Enum: Work with a dynamic, serde_json::Value-like enum (shmp::Pack) to represent MessagePack data when the schema is unknown at compile time.serde allows for easy serialization and deserialization of custom types.Pack Type: A flexible enum for representing and manipulating any valid MessagePack data.pack! Macro: An intuitive, JSON-like macro for ergonomic creation of Pack values.&str and &[u8] from a byte slice without unnecessary allocations.EncodeExt and DecodeExt traits to easily support custom MessagePack extension types.chrono: Adds support for serializing/deserializing chrono::DateTime<Utc> and chrono::NaiveDateTime as MessagePack Timestamps.Add shmp to your Cargo.toml:
[dependencies]
shmp = "0.1.0"
To enable optional features like chrono:
[dependencies]
shmp = { version = "0.1.0", features = ["chrono"] }
This is the most common and idiomatic way to use shmp.
use serde::{Serialize, Deserialize};
use shmp::{to_vec, from_slice, to_writer, from_reader, to_pack, from_pack, Pack};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct User {
id: u32,
username: String,
is_active: bool,
}
fn main() -> Result<(), shmp::Error> {
let user = User {
id: 1024,
username: "shmp_user".to_string(),
is_active: true,
};
// 1. Direct serialization to/from bytes
let encoded: Vec<u8> = to_vec(&user)?;
let decoded: User = from_slice(&encoded)?;
assert_eq!(user, decoded);
println!("Successfully round-tripped via bytes: {:?}", decoded);
// 2. Serialization to/from an I/O stream (like a file or network socket)
let mut buffer: Vec<u8> = Vec::new();
to_writer(&mut buffer, &user)?;
let mut reader = std::io::Cursor::new(&buffer);
let decoded_from_reader: User = from_reader(&mut reader)?;
assert_eq!(user, decoded_from_reader);
println!("Successfully round-tripped via reader/writer: {:?}", decoded_from_reader);
// 3. Using the `Pack` enum as an intermediate representation
// Struct -> Pack -> Bytes
let encoded_pack: Pack = to_pack(&user)?; // Pass a reference, which also works.
let encoded_from_pack: Vec<u8> = to_vec(&encoded_pack)?;
// Bytes -> Pack -> Struct
let decoded_pack: Pack = from_slice(&encoded_from_pack)?;
let decoded_from_pack: User = from_pack(decoded_pack)?;
assert_eq!(user, decoded_from_pack);
println!("Successfully round-tripped via Pack enum: {:?}", decoded_from_pack);
return Ok(());
}
Pack EnumUseful when the structure is not known at compile time.
use shmp::{to_vec, from_slice, from_pack, pack, Pack};
use serde::Deserialize;
fn main() -> Result<(), shmp::Error> {
let manual_pack = Pack::Map(vec![
(Pack::String("id".into()), Pack::Uint(12345u64)),
(Pack::String("username".into()), Pack::String("shmp".into())),
(Pack::String("is_active".into()), Pack::Boolean(true)),
]);
// Manually creating a `Pack` value can be verbose.
// The `pack!` macro provides a much cleaner, JSON-like syntax for the same result.
let macro_pack = pack!({
"id": 12345u32,
"username": "shmp",
"is_active": true
});
assert_eq!(manual_pack, macro_pack);
println!("Successfully created Pack value with the pack! macro.");
// The macro-created value can be serialized and deserialized like any other `Pack`.
let encoded = to_vec(¯o_pack)?;
let decoded: Pack = from_slice(&encoded)?;
assert_eq!(macro_pack, decoded);
assert_eq!(manual_pack, macro_pack, "Both methods produce the same Pack value");
// It can also be deserialized directly into a struct.
#[derive(Deserialize, Debug, PartialEq)]
struct User {
id: u32,
username: String,
is_active: bool,
}
// It can also be deserialized directly into a struct.
let user = User {
id: 12345u32,
username: "shmp".to_string(),
is_active: true,
};
let macro_user: User = from_pack(macro_pack)?;
assert_eq!(user, macro_user);
println!("Successfully created and round-tripped User value with the pack! macro.");
Ok(())
}
This project is dual-licensed under either of
at your option.