serial_traits

Crates.ioserial_traits
lib.rsserial_traits
version1.1.1
created_at2025-06-27 11:17:16.154224+00
updated_at2025-07-07 21:43:18.788101+00
descriptionA trait that allows you to serialize to and parse from Vec buffers. Comes with implementations for primitive types, String and generic collection types (if the item type implements the trait too.)
homepage
repositoryhttps://codeberg.org/Taureon/serial_traits
max_upload_size
id1728513
size39,635
Taureon (Taureon)

documentation

README

serial_traits

A trait that allows you to serialize to and parse from Vec<u8> buffers.

This is great for sending them across for example tcp or ws sockets.

Comes with implementations for primitive types, String and generic collection types, so long the item type implements the trait too.

The buffer is no more larger than what you serialized, if you serialize a struct with two f32s, the final buffer will be 8 bytes large.

(PS: Variable-sized collections use an usize to keep track of their size, and _sizes use LEB128.)

Using types that implement the trait:

// this is the trait
use serial_traits::Serializable;

// serializing a type that implements it
let mut buffer: Vec<u8> = 6754_u16.serialize();

// deserializing a type that implements it
match u16::parse(&mut buffer) {
	Some(value) => println!("got {value}!"),
	None => panic!("could not get a valid u16 value!");
}

// the parse function consumes the buffer
assert_eq(buffer.len(), 0);

Implementing the trait for your own structs:

struct ChatMessage {
	author_id: u32,
	content: String,
}

impl Serializable for ChatMessage {
	fn serialize(&self) -> Vec<u8> {
		let mut result = self.author_id.serialize();
		result.append(self.content.serialize());
		result
	}
	fn parse(data: &mut Vec<u8>) -> Option<Self> {
		let author_id = match u32::parse(data) {
			Some(value) => value,
			None => return None,
		};

		match String::parse(data) {
			Some(content) => Some(Self {
				author_id,
				content
			}),
			None => None,
		}
	}
}

fn main() {
	let msg = ChatMessage {
		author_id: 7832,
		content: "Hello World!".to_string(),
	};

	let buffer = msg.serialize();
	// 00 00 1e 98 0c 48 65 6c 6c 6f 20 57 6f 72 6c 64 21
	// [    7832 ] 12 "H  e  l  l o     W  o  r  l  d  !"
}

Types with Serializable implemented:

  • f32, f64
  • u8, u16, u32, u64, u128
  • i8, i16, i32, i64, i128
  • usize, isize
  • char, bool
  • [T; N]
  • String
  • Vec<T>, VecDeque<T>, LinkedList<T>
  • HashMap<K, V>, BTreeMap<K, V>
  • HashSet<T>, BTreeSet<T>
  • BinaryHeap<T>
  • and any tuples (T₁, T₂, …, Tₙ) up to length 12

T, K, and V must additionally implement Serializable.

The trait implementations for usize and isize directly call the two LEB128 functions that come with this crate.

If wanted, you can also use the leb128 module of this crate for your own needs:

use serial_traits::leb128::{parse, serialize};

// a small number stored in a larger integer data type
let value = 8_i128;

let mut buffer = serialize(value);

// buffer is 1 byte long despite `value` being an i128
println!("buffer length: {}", buffer.len());

let parsed = parse::<i128>(&mut buffer);

assert_eq(parsed.unwrap(), value);

Both LEB128 functions work with all primitive integer types.

Can't forget, big thanks to GDenisC for helping a lot with design!

Commit count: 0

cargo fmt