Crates.io | resend |
lib.rs | resend |
version | 0.1.4 |
source | src |
created_at | 2022-12-19 21:28:16.714027 |
updated_at | 2024-10-04 18:10:11.811116 |
description | resend is a easy to use, performant, customizable and extendable Rust library for little-endian/big-endian serializing and deserializing. |
homepage | |
repository | https://github.com/WalterYongtaoWang/resend |
max_upload_size | |
id | 741660 |
size | 77,969 |
Resend is a easy to use, performant, customizable and extendable Rust library for little-endian/big-endian serializing and deserializing.
Two functions only:
snd() for any Write implementors (File, TcpStream etc)
rcv() for any Read implementors (File, TcpStream etc)
Cargo.toml:
[dependencies]
#with little-endian feature
resend = {version = "0.1", features = ["little"]}
Code:
use resend::{Snd, Rcv};
let mut vec = Vec::new();
vec.snd(-8_i8)?;
vec.snd(22_u16)?;
vec.snd(0xFFABCDEF as u32)?;
vec.snd("Test")?;
let mut buf = &vec[..];
let v: i8 = buf.rcv()?;
let v: u16 = buf.rcv()?;
let v: u32 = buf.rcv()?;
let v: String = buf.rcv()?;
[dependencies]
resend = {version = "0.1", features = ["little"]}
resend_derive = "0.1"
use resend::{Snd, Rcv, endian::{Ascii, UTF16}};
use resend_derive::{Snd, Rcv};
#[repr(u32)]
#[derive(Snd, Rcv)]
pub enum DeviceType {
PrinterType(IoPrinter) = 4,
ScardType = 0x20,
}
#[derive(Snd, Rcv)]
struct Device{
device_id: u32,
#[len(8)]
dos_name: Ascii,
}
#[derive(Snd, Rcv)]
pub struct IoPrinter{
device: Device,
length: u32,
flags: u32,
code_page: u32,
pnp_name_len: u32,
driver_name_len: u32,
#[len(pnp_name_len)]
pnp_name: UTF16,
#[len(driver_name_len)]
driver_name: UTF16,
}
...
let dt: DeviceType = stream.rcv()?;
stream.snd(&dt)?;
Write/Read trait based, no intermediate variables.
#[derive(Snd, Rcv)]
#[repr(u16)]
enum Color {
Red,
Blue = 32,
Green =4,
}
Color::Red is serialized as 0_u16. Color::Blue is serialized as 32_u16.
#[repr(u32)]
#[derive(Snd, Rcv)]
pub enum DeviceType {
PrinterType(IoPrinter) = 4,
ScardType = 0x20,
}
DeviceType::PrinterType(printer) is serialized as 4_u32 + IoPrinter data. DeviceType::ScardType is serialized as 0x20_u32.
Please be aware: discriminants on non-unit variants are stable since Rust 1.66), you have to use Rust nightly for previous versions.
stream.snd(BE(100_u32))?;
No serialization with #[skip] attribute.
The length of String, Vector etc. can be from another field or constant with #[len(field_name_or_const)] attribute:
#[len(pnp_name_len)]
#[len(8)]
#[when(code_page > 0)]
#[when((flags & 2) != 0)]
resend = {version = "0.1", features = ["little", "len_16"]}
resend = {version = "0.1", features = ["big", "len_vlq"]}
resend = {version = "0.1", features = ["little", "len_16", "MAX_LEN_100M"]}
For example, you want a string with variable-length quantity
pub struct VarLenString (pub String);
impl Sendable for VarLenString {
fn snd_to<S>(&self, writer: &mut S) -> io::Result<()>
where
S: resend::Sender {
writer.snd(resend::endian::VLQ(self.0.len()))?;
writer.snd_all(self.0.as_bytes())
}
}
impl Receivable for VarLenString {
fn rcv_from<R>(reader: &mut R) -> io::Result<Self>
where
R: resend::Receiver {
let len: VLQ = reader.rcv()?;
let b = reader.rcv_bytes(*len)?;
let s = std::str::from_utf8(&b)?;
Ok(Self(s.to_string()))
}
}
Resend includes the following types for your convenience:
use resend::endian::{Ascii, UTF16, UTF16Char, VLQ};
Implements resend::FromReader and resend::IntoWriter if you need the "len(field_name)" attribute working on your type. For example:
impl FromReader for Vec<u8> {
#[inline]
fn from_reader<R: Receiver>(reader: &mut R, len: usize) -> crate::Result<Self> {
reader.rcv_bytes(len)
}
}
impl IntoWriter for Vec<u8> {
#[inline]
fn into_writer<S: Sender>(&self, writer: &mut S, len: usize) -> crate::Result<()> {
let len_s = self.len();
let (l, left) = if len > len_s {
(len_s, len - len_s)
} else {
(len, 0)
};
let b = &self[..l];
writer.snd_all(b)?;
if left > 0 {
writer.snd_all(&vec![0; left])?;
}
Ok(())
}
}
String, Ascii and UTF16 with #[len(field_name_or_const)] attribute: if the specified length is bigger then the actual length: extra '\0' will be appended when it's serialized, and extra '\0' will be removed after it's deserialized; if the specified length is smaller, the string will be truncated to that length. This is useful if you need null terminated, fixed length string.
Convert int to Enum
//Conver little-endian u16 to Blue ("little" feature)
//[u8] doesn't implement Read, convert it to &[u8] with as_ref()
let c: Color = [32_u8, 0].as_ref().rcv()?;
//type value (enum tag value) after the parent class
struct YourObject {
parent: ParentClass,
child: EnumOfChildClass,
}
//type value (enum tag value) before the parent class
struct Child {
parent: ParentClass,
child_field,
...
}
enum {
child1,
child2,
}
MIT OR Apache-2.0
This library is developed for Remote Spark Corp's RDP (Remote Desktop Protocol) Project.