Skip to content

Commit

Permalink
Added unty dependency and added type checks
Browse files Browse the repository at this point in the history
  • Loading branch information
VictorKoenders committed Sep 23, 2023
1 parent 2969a24 commit 0574e6a
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 146 deletions.
139 changes: 70 additions & 69 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,69 +1,70 @@
[workspace]
members = ["derive", "compatibility"]

[package]
name = "bincode"
version = "2.0.0-rc.3" # remember to update html_root_url and bincode_derive
authors = [
"Ty Overby <[email protected]>",
"Zoey Riordan <[email protected]>",
"Victor Koenders <[email protected]>",
]
exclude = ["logo.svg", "examples/*", ".gitignore", ".github/"]

publish = true

repository = "https://github.com/bincode-org/bincode"
documentation = "https://docs.rs/bincode"
readme = "./readme.md"
categories = ["encoding", "network-programming"]
keywords = ["binary", "encode", "decode", "serialize", "deserialize"]

license = "MIT"
description = "A binary serialization / deserialization strategy for transforming structs into bytes and vice versa!"

edition = "2021"

[features]
default = ["std", "derive"]
std = ["alloc", "serde?/std"]
alloc = ["serde?/alloc"]
derive = ["bincode_derive"]

[dependencies]
bincode_derive = { path = "derive", version = "2.0.0-rc.3", optional = true }
serde = { version = "1.0", default-features = false, optional = true }

# Used for tests
[dev-dependencies]
serde_derive = "1.0"
serde_json = { version = "1.0", default-features = false }
tempfile = "3.2"
criterion = "0.5"
rand = "0.8"
uuid = { version = "1.1", features = ["serde"] }
chrono = { version = "0.4", features = ["serde"] }
glam = { version = "0.24", features = ["serde"] }
bincode_1 = { version = "1.3", package = "bincode" }
serde = { version = "1.0", features = ["derive"] }

[[bench]]
name = "varint"
harness = false

[[bench]]
name = "inline"
harness = false

[[bench]]
name = "string"
harness = false

[profile.bench]
codegen-units = 1
debug = 1
lto = true

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[workspace]
members = ["derive", "compatibility"]

[package]
name = "bincode"
version = "2.0.0-rc.3" # remember to update html_root_url and bincode_derive
authors = [
"Ty Overby <[email protected]>",
"Zoey Riordan <[email protected]>",
"Victor Koenders <[email protected]>",
]
exclude = ["logo.svg", "examples/*", ".gitignore", ".github/"]

publish = true

repository = "https://github.com/bincode-org/bincode"
documentation = "https://docs.rs/bincode"
readme = "./readme.md"
categories = ["encoding", "network-programming"]
keywords = ["binary", "encode", "decode", "serialize", "deserialize"]

license = "MIT"
description = "A binary serialization / deserialization strategy for transforming structs into bytes and vice versa!"

edition = "2021"

[features]
default = ["std", "derive"]
std = ["alloc", "serde?/std"]
alloc = ["serde?/alloc"]
derive = ["bincode_derive"]

[dependencies]
bincode_derive = { path = "derive", version = "2.0.0-rc.3", optional = true }
serde = { version = "1.0", default-features = false, optional = true }
unty = "0.0.1"

# Used for tests
[dev-dependencies]
serde_derive = "1.0"
serde_json = { version = "1.0", default-features = false }
tempfile = "3.2"
criterion = "0.5"
rand = "0.8"
uuid = { version = "1.1", features = ["serde"] }
chrono = { version = "0.4", features = ["serde"] }
glam = { version = "0.24", features = ["serde"] }
bincode_1 = { version = "1.3", package = "bincode" }
serde = { version = "1.0", features = ["derive"] }

[[bench]]
name = "varint"
harness = false

[[bench]]
name = "inline"
harness = false

[[bench]]
name = "string"
harness = false

[profile.bench]
codegen-units = 1
debug = 1
lto = true

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
84 changes: 40 additions & 44 deletions src/de/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,28 +446,26 @@ where
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?;

// TODO: we can't limit `T: 'static` because that would break other things
// but we want to have this optimization
// This will be another contendor for specialization implementation
// if TypeId::of::<u8>() == TypeId::of::<T>() {
// let mut buf = [0u8; N];
// decoder.reader().read(&mut buf)?;
// let ptr = &mut buf as *mut _ as *mut [T; N];

// // Safety: we know that T is a u8, so it is perfectly safe to
// // translate an array of u8 into an array of T
// let res = unsafe { ptr.read() };
// Ok(res)
// }
let result = super::impl_core::collect_into_array(&mut (0..N).map(|_| {
// See the documentation on `unclaim_bytes_read` as to why we're doing this here
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
T::decode(decoder)
}));

// result is only None if N does not match the values of `(0..N)`, which it always should
// So this unwrap should never occur
result.unwrap()
if unty::type_equal::<T, u8>() {
let mut buf = [0u8; N];
decoder.reader().read(&mut buf)?;
let ptr = &mut buf as *mut _ as *mut [T; N];

// Safety: we know that T is a u8, so it is perfectly safe to
// translate an array of u8 into an array of T
let res = unsafe { ptr.read() };
Ok(res)
} else {
let result = super::impl_core::collect_into_array(&mut (0..N).map(|_| {
// See the documentation on `unclaim_bytes_read` as to why we're doing this here
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
T::decode(decoder)
}));

// result is only None if N does not match the values of `(0..N)`, which it always should
// So this unwrap should never occur
result.unwrap()
}
}
}

Expand All @@ -478,28 +476,26 @@ where
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?;

// TODO: we can't limit `T: 'static` because that would break other things
// but we want to have this optimization
// This will be another contendor for specialization implementation
// if TypeId::of::<u8>() == TypeId::of::<T>() {
// let mut buf = [0u8; N];
// decoder.reader().read(&mut buf)?;
// let ptr = &mut buf as *mut _ as *mut [T; N];

// // Safety: we know that T is a u8, so it is perfectly safe to
// // translate an array of u8 into an array of T
// let res = unsafe { ptr.read() };
// Ok(res)
// }
let result = super::impl_core::collect_into_array(&mut (0..N).map(|_| {
// See the documentation on `unclaim_bytes_read` as to why we're doing this here
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
T::borrow_decode(decoder)
}));

// result is only None if N does not match the values of `(0..N)`, which it always should
// So this unwrap should never occur
result.unwrap()
if unty::type_equal::<T, u8>() {
let mut buf = [0u8; N];
decoder.reader().read(&mut buf)?;
let ptr = &mut buf as *mut _ as *mut [T; N];

// Safety: we know that T is a u8, so it is perfectly safe to
// translate an array of u8 into an array of T
let res = unsafe { ptr.read() };
Ok(res)
} else {
let result = super::impl_core::collect_into_array(&mut (0..N).map(|_| {
// See the documentation on `unclaim_bytes_read` as to why we're doing this here
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
T::borrow_decode(decoder)
}));

// result is only None if N does not match the values of `(0..N)`, which it always should
// So this unwrap should never occur
result.unwrap()
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/enc/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,13 @@ impl Encode for char {

impl<T> Encode for [T]
where
T: Encode + 'static,
T: Encode,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
super::encode_slice_len(encoder, self.len())?;

if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
if unty::type_equal::<T, u8>() {
// Safety: T = u8
let t: &[u8] = unsafe { core::mem::transmute(self) };
encoder.writer().write(t)?;
return Ok(());
Expand Down
63 changes: 32 additions & 31 deletions src/features/impl_alloc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
de::{BorrowDecoder, Decode, Decoder},
de::{read::Reader, BorrowDecoder, Decode, Decoder},
enc::{
self,
write::{SizeWriter, Writer},
Expand All @@ -8,8 +8,6 @@ use crate::{
error::{DecodeError, EncodeError},
impl_borrow_decode, BorrowDecode, Config,
};
#[cfg(target_has_atomic = "ptr")]
use alloc::sync::Arc;
use alloc::{
borrow::{Cow, ToOwned},
boxed::Box,
Expand All @@ -19,6 +17,9 @@ use alloc::{
vec::Vec,
};

#[cfg(target_has_atomic = "ptr")]
use alloc::sync::Arc;

#[derive(Default)]
pub(crate) struct VecWriter {
inner: Vec<u8>,
Expand Down Expand Up @@ -283,28 +284,26 @@ where
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = crate::de::decode_slice_len(decoder)?;

// TODO: we can't limit `T: 'static` because that would break other things
// but we want to have this optimization
// This will be another contendor for specialization implementation
// if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
// decoder.claim_container_read::<T>(len)?;
// // optimize for reading u8 vecs
// let mut vec = Vec::new();
// vec.resize(len, 0u8);
// decoder.reader().read(&mut vec)?;
// // Safety: Vec<T> is Vec<u8>
// return Ok(unsafe { core::mem::transmute(vec) });
// }
decoder.claim_container_read::<T>(len)?;

let mut vec = Vec::with_capacity(len);
for _ in 0..len {
// See the documentation on `unclaim_bytes_read` as to why we're doing this here
decoder.unclaim_bytes_read(core::mem::size_of::<T>());

vec.push(T::decode(decoder)?);
if unty::type_equal::<T, u8>() {
decoder.claim_container_read::<T>(len)?;
// optimize for reading u8 vecs
let mut vec = Vec::new();
vec.resize(len, 0u8);
decoder.reader().read(&mut vec)?;
// Safety: Vec<T> is Vec<u8>
Ok(unsafe { core::mem::transmute(vec) })
} else {
decoder.claim_container_read::<T>(len)?;

let mut vec = Vec::with_capacity(len);
for _ in 0..len {
// See the documentation on `unclaim_bytes_read` as to why we're doing this here
decoder.unclaim_bytes_read(core::mem::size_of::<T>());

vec.push(T::decode(decoder)?);
}
Ok(vec)
}
Ok(vec)
}
}

Expand All @@ -329,19 +328,21 @@ where

impl<T> Encode for Vec<T>
where
T: Encode + 'static,
T: Encode,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
crate::enc::encode_slice_len(encoder, self.len())?;
if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
if unty::type_equal::<T, u8>() {
// Safety: T == u8
let slice: &[u8] = unsafe { core::mem::transmute(self.as_slice()) };
encoder.writer().write(slice)?;
return Ok(());
Ok(())
} else {
for item in self.iter() {
item.encode(encoder)?;
}
Ok(())
}
for item in self.iter() {
item.encode(encoder)?;
}
Ok(())
}
}

Expand Down

0 comments on commit 0574e6a

Please sign in to comment.