Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion derse/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "derse"
version = "0.1.32"
version = "0.1.33"
authors.workspace = true
edition.workspace = true
homepage.workspace = true
Expand Down
6 changes: 6 additions & 0 deletions derse/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ pub enum Error {
InvalidBool(u8),
#[error("invalid string: {0:?}")]
InvalidString(Vec<u8>),
#[error("invalid cstr: {0}")]
InvalidCStr(String),
#[error("varint is short")]
VarintIsShort,
#[error("invalid type: {0}")]
InvalidType(String),
#[error("invalid value: {0}")]
InvalidValue(String),
#[error("invalid char: {0}")]
InvalidChar(u32),
#[error("invalid length: {0}, error: {1}")]
InvalidLength(usize, String),
}

impl Default for Error {
Expand Down
96 changes: 96 additions & 0 deletions derse/src/impls/array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use crate::*;

impl<T: Serialize, const N: usize> Serialize for [T; N] {
fn serialize_to<S: Serializer>(&self, serializer: &mut S) -> Result<()> {
for item in self.iter().rev() {
item.serialize_to(serializer)?;
}
Ok(())
}
}

macro_rules! array_impls {
($($len:expr => ($($n:tt)+))+) => {
$(
impl<'a, T: Deserialize<'a>> Deserialize<'a> for [T; $len] {
fn deserialize_from<D: Deserializer<'a>>(buf: &mut D) -> Result<Self>
where
Self: Sized,
{
Ok([$(

Check warning on line 20 in derse/src/impls/array.rs

View check run for this annotation

Codecov / codecov/patch

derse/src/impls/array.rs#L20

Added line #L20 was not covered by tests
match T::deserialize_from(buf) {
Ok(val) => val,
Err(e) => return Err(Error::InvalidLength($n, e.to_string())),
}
),+])
}
}
)+
}
}

array_impls! {
1 => (0)
2 => (0 1)
3 => (0 1 2)
4 => (0 1 2 3)
5 => (0 1 2 3 4)
6 => (0 1 2 3 4 5)
7 => (0 1 2 3 4 5 6)
8 => (0 1 2 3 4 5 6 7)
9 => (0 1 2 3 4 5 6 7 8)
10 => (0 1 2 3 4 5 6 7 8 9)
11 => (0 1 2 3 4 5 6 7 8 9 10)
12 => (0 1 2 3 4 5 6 7 8 9 10 11)
13 => (0 1 2 3 4 5 6 7 8 9 10 11 12)
14 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13)
15 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14)
16 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
17 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16)
18 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17)
19 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)
20 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
21 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)
22 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21)
23 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22)
24 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
25 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24)
26 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25)
27 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26)
28 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27)
29 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28)
30 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29)
31 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30)
32 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_array() {
{
let ser: [i32; 3] = [1, 2, 3];
let bytes: DownwardBytes = ser.serialize().unwrap();
let der = <[i32; 3]>::deserialize(&bytes[..]).unwrap();
assert_eq!(ser, der);

<[bool; 3]>::deserialize([].as_slice()).unwrap_err();
<[bool; 3]>::deserialize([1].as_slice()).unwrap_err();
<[bool; 3]>::deserialize([2].as_slice()).unwrap_err();
<[bool; 3]>::deserialize([1, 1].as_slice()).unwrap_err();
<[bool; 3]>::deserialize([1, 2].as_slice()).unwrap_err();
<[bool; 3]>::deserialize([1, 1, 1].as_slice()).unwrap();
<[bool; 3]>::deserialize([1, 1, 2].as_slice()).unwrap_err();
}

{
let ser = 233u32;
let bytes = ser.serialize::<DownwardBytes>().unwrap();
let array = <[u8; 4]>::deserialize(&bytes[..]).unwrap();
let der = u32::from_le_bytes(array);
assert_eq!(ser, der);
}
}
}
227 changes: 227 additions & 0 deletions derse/src/impls/collections.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
use crate::*;
use std::cmp::Eq;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
use std::hash::Hash;

macro_rules! seq_se_rev_impl {
(
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)*>
) => {
impl<T> Serialize for $ty<T>
where
T: Serialize,
{
#[inline]
fn serialize_to<S: Serializer>(&self, serializer: &mut S) -> Result<()> {
for item in self.iter().rev() {
item.serialize_to(serializer)?;
}
VarInt64(self.len() as u64).serialize_to(serializer)
}
}
};
}

seq_se_rev_impl! {
Vec<T>
}

seq_se_rev_impl! {
VecDeque<T>
}

seq_se_rev_impl! {
LinkedList<T>
}

seq_se_rev_impl! {
BinaryHeap<T: Ord>
}

macro_rules! seq_se_for_impl {
(
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)*>
) => {
impl<T> Serialize for $ty<T>
where
T: Serialize,
{
#[inline]
fn serialize_to<S: Serializer>(&self, serializer: &mut S) -> Result<()> {
for item in self.iter() {
item.serialize_to(serializer)?;
}
VarInt64(self.len() as u64).serialize_to(serializer)
}
}
};
}

seq_se_for_impl! {
BTreeSet<T: Ord>
}

seq_se_for_impl! {
HashSet<T: Eq + Hash>
}

macro_rules! seq_de_impl {
(
$ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)*>
) => {
impl<'a, T> Deserialize<'a> for $ty<T>
where
T: Deserialize<'a> $(+ $tbound1 $(+ $tbound2)*)*,
{
fn deserialize_from<D: Deserializer<'a>>(buf: &mut D) -> Result<Self>
where
Self: Sized,
{
let len = VarInt64::deserialize_from(buf)?.0 as usize;
(0..len).map(|_| T::deserialize_from(buf)).collect::<Result<Self>>()
}
}
};
}

seq_de_impl! {
Vec<T>
}

seq_de_impl! {
VecDeque<T>
}

seq_de_impl! {
LinkedList<T>
}

seq_de_impl! {
BinaryHeap<T: Ord>
}

seq_de_impl! {
BTreeSet<T: Ord>
}

seq_de_impl! {
HashSet<T: Eq + Hash>
}

macro_rules! map_impl {
(
$ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V>
) => {
impl<K, V> Serialize for $ty<K, V>
where
K: Serialize,
V: Serialize,
{
#[inline]
fn serialize_to<S: Serializer>(&self, serializer: &mut S) -> Result<()> {
for item in self.iter() {
item.serialize_to(serializer)?;
}
VarInt64(self.len() as u64).serialize_to(serializer)
}
}

impl<'a, K, V> Deserialize<'a> for $ty<K, V>
where
Self: Sized,
K: Deserialize<'a> $(+ $kbound1 $(+ $kbound2)*)*,
V: Deserialize<'a>,
{
#[inline]
fn deserialize_from<D: Deserializer<'a>>(buf: &mut D) -> Result<Self>
where
Self: Sized,
{
let len = VarInt64::deserialize_from(buf)?.0 as usize;
(0..len).map(|_| <(K, V)>::deserialize_from(buf)).collect::<Result<Self>>()
}
}
}
}

map_impl! {
BTreeMap<K: Ord, V>
}

map_impl! {
HashMap<K: Eq + Hash, V>
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_collections() {
{
let ser = vec!["hello", "world", "!"];
let bytes: DownwardBytes = ser.serialize().unwrap();
let der = Vec::<String>::deserialize(&bytes[..]).unwrap();
assert_eq!(ser, der);

assert!(Vec::<u8>::deserialize([128].as_ref()).is_err());
assert!(Vec::<u8>::deserialize([1].as_ref()).is_err());
assert!(Vec::<u8>::deserialize([0].as_ref()).unwrap().is_empty());
}

{
let ser: LinkedList<_> = (0..10).collect();
let bytes: DownwardBytes = ser.serialize().unwrap();
let der = LinkedList::<i32>::deserialize(&bytes[..]).unwrap();
assert_eq!(ser, der);
}

{
let ser = Some("hello".to_string());
let bytes: DownwardBytes = ser.serialize().unwrap();
assert_eq!(bytes.len(), 1 + 1 + 5);
let der = Option::<String>::deserialize(&bytes[..]).unwrap();
assert_eq!(ser, der);
let der = Vec::<String>::deserialize(&bytes[..]).unwrap();
assert_eq!(ser.as_ref(), der.first());

let ser = None;
let bytes: DownwardBytes = ser.serialize().unwrap();
assert_eq!(bytes.len(), 1);
let der = Option::<String>::deserialize(&bytes[..]).unwrap();
assert_eq!(ser, der);
let der = Vec::<String>::deserialize(&bytes[..]).unwrap();
assert_eq!(ser.as_ref(), der.first());

assert!(Option::<String>::deserialize([128].as_ref()).is_err());
assert!(Option::<String>::deserialize([1].as_ref()).is_err());
assert!(Option::<String>::deserialize([0].as_ref())
.unwrap()
.is_none());
}

{
let ser: HashSet<String> = "hello world !".split(' ').map(|s| s.to_owned()).collect();
let bytes: DownwardBytes = ser.serialize().unwrap();
let der = HashSet::<String>::deserialize(&bytes[..]).unwrap();
assert_eq!(ser, der);

assert!(HashSet::<u8>::deserialize([128].as_ref()).is_err());
assert!(HashSet::<u8>::deserialize([1].as_ref()).is_err());
assert!(HashSet::<u8>::deserialize([0].as_ref()).unwrap().is_empty());
}

{
let ser: HashMap<String, u32> = (0..10).map(|i| (i.to_string(), i)).collect();
let bytes: DownwardBytes = ser.serialize().unwrap();
let der = HashMap::<String, u32>::deserialize(&bytes[..]).unwrap();
assert_eq!(ser, der);

let mut der = Vec::<(String, u32)>::deserialize(&bytes[..]).unwrap();
assert_eq!(der.len(), 10);
der.sort();
assert_eq!(der[0].0, "0");
assert_eq!(der[9].0, "9");
}
}
}
File renamed without changes.
Loading
Loading