Rewrite: seperated Decode and BorrowDecode (#526)

* Rewrite: seperated Decode and BorrowDecode

* Fixed cargo.toml issues

* Fixed clippy warning

* Removed the `impl_tuples` macro call with manually exported code

* Replaced the generated code in `impl_tuples` with the macro instead

* Implemented BorrowDecode for Box<[T]>

* Added a test to see if zoxide can be ported to bincode 2

* Added a test for Arc<str>

* Made several `Encode` implementations require `T: ?Sized`

* Implemented Decode for Arc<str>

* Added BlockedTODO links to commented out code

* Fixed clippy and lint issues

* Updated virtue dependency in fuzz lockfile
This commit is contained in:
Trangar 2022-06-04 15:23:55 +02:00 committed by GitHub
parent f979383adb
commit 86e03aeda7
26 changed files with 934 additions and 311 deletions

View File

@ -16,4 +16,4 @@ description = "Implementation of #[derive(Encode, Decode)] for bincode"
proc-macro = true
[dependencies]
virtue = "0.0.7"
virtue = "0.0.8"

View File

@ -3,12 +3,20 @@ use virtue::utils::{parse_tagged_attribute, ParsedAttribute};
pub struct ContainerAttributes {
pub crate_name: String,
pub bounds: Option<(String, Literal)>,
pub decode_bounds: Option<(String, Literal)>,
pub borrow_decode_bounds: Option<(String, Literal)>,
pub encode_bounds: Option<(String, Literal)>,
}
impl Default for ContainerAttributes {
fn default() -> Self {
Self {
crate_name: "::bincode".to_string(),
bounds: None,
decode_bounds: None,
encode_bounds: None,
borrow_decode_bounds: None,
}
}
}
@ -30,6 +38,44 @@ impl FromAttribute for ContainerAttributes {
return Err(Error::custom_at("Should be a literal str", val.span()));
}
}
ParsedAttribute::Property(key, val) if key.to_string() == "bounds" => {
let val_string = val.to_string();
if val_string.starts_with('"') && val_string.ends_with('"') {
result.bounds =
Some((val_string[1..val_string.len() - 1].to_string(), val));
} else {
return Err(Error::custom_at("Should be a literal str", val.span()));
}
}
ParsedAttribute::Property(key, val) if key.to_string() == "decode_bounds" => {
let val_string = val.to_string();
if val_string.starts_with('"') && val_string.ends_with('"') {
result.decode_bounds =
Some((val_string[1..val_string.len() - 1].to_string(), val));
} else {
return Err(Error::custom_at("Should be a literal str", val.span()));
}
}
ParsedAttribute::Property(key, val) if key.to_string() == "encode_bounds" => {
let val_string = val.to_string();
if val_string.starts_with('"') && val_string.ends_with('"') {
result.encode_bounds =
Some((val_string[1..val_string.len() - 1].to_string(), val));
} else {
return Err(Error::custom_at("Should be a literal str", val.span()));
}
}
ParsedAttribute::Property(key, val)
if key.to_string() == "borrow_decode_bounds" =>
{
let val_string = val.to_string();
if val_string.starts_with('"') && val_string.ends_with('"') {
result.borrow_decode_bounds =
Some((val_string[1..val_string.len() - 1].to_string(), val));
} else {
return Err(Error::custom_at("Should be a literal str", val.span()));
}
}
ParsedAttribute::Tag(i) => {
return Err(Error::custom_at("Unknown field attribute", i.span()))
}

View File

@ -22,12 +22,22 @@ impl DeriveEnum {
generator
.impl_for(format!("{}::Encode", crate_name))
.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) =
(self.attributes.encode_bounds.as_ref()).or(self.attributes.bounds.as_ref())
{
where_constraints.clear();
where_constraints
.push_parsed_constraint(bounds)
.map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints
.push_constraint(g, format!("{}::Encode", crate_name))
.unwrap();
}
})
}
Ok(())
})?
.generate_fn("encode")
.with_generic_deps("E", [format!("{}::enc::Encoder", crate_name)])
.with_self_arg(FnSelfArg::RefSelf)
@ -206,7 +216,7 @@ impl DeriveEnum {
Ok(())
}
pub fn generate_decode(&self, generator: &mut Generator) -> Result<()> {
pub fn generate_decode(self, generator: &mut Generator) -> Result<()> {
let crate_name = self.attributes.crate_name.as_str();
// Remember to keep this mostly in sync with generate_borrow_decode
@ -216,10 +226,16 @@ impl DeriveEnum {
generator
.impl_for(format!("{}::Decode", crate_name))
.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
where_constraints.clear();
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, format!("{}::Decode", crate_name)).unwrap();
}
})
}
Ok(())
})?
.generate_fn("decode")
.with_generic_deps("D", [format!("{}::de::Decoder", crate_name)])
.with_arg("decoder", "&mut D")
@ -293,6 +309,7 @@ impl DeriveEnum {
}
Ok(())
})?;
self.generate_borrow_decode(generator)?;
Ok(())
}
@ -304,10 +321,16 @@ impl DeriveEnum {
generator.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"])
.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
where_constraints.clear();
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, format!("{}::enc::BorrowDecode", crate_name)).unwrap();
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de>", crate_name)).unwrap();
}
})
}
Ok(())
})?
.generate_fn("borrow_decode")
.with_generic_deps("D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)])
.with_arg("decoder", "&mut D")

View File

@ -10,18 +10,26 @@ pub(crate) struct DeriveStruct {
impl DeriveStruct {
pub fn generate_encode(self, generator: &mut Generator) -> Result<()> {
let DeriveStruct { fields, attributes } = self;
let crate_name = attributes.crate_name;
let crate_name = &self.attributes.crate_name;
generator
.impl_for(&format!("{}::Encode", crate_name))
.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) =
(self.attributes.encode_bounds.as_ref()).or(self.attributes.bounds.as_ref())
{
where_constraints.clear();
where_constraints
.push_parsed_constraint(bounds)
.map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints
.push_constraint(g, format!("{}::Encode", crate_name))
.unwrap();
}
})
}
Ok(())
})?
.generate_fn("encode")
.with_generic_deps("E", [format!("{}::enc::Encoder", crate_name)])
.with_self_arg(virtue::generate::FnSelfArg::RefSelf)
@ -31,7 +39,7 @@ impl DeriveStruct {
crate_name
))
.body(|fn_body| {
for field in fields.names() {
for field in self.fields.names() {
let attributes = field
.attributes()
.get_attribute::<FieldAttributes>()?
@ -56,16 +64,21 @@ impl DeriveStruct {
pub fn generate_decode(self, generator: &mut Generator) -> Result<()> {
// Remember to keep this mostly in sync with generate_borrow_decode
let DeriveStruct { fields, attributes } = self;
let crate_name = attributes.crate_name;
let crate_name = &self.attributes.crate_name;
generator
.impl_for(format!("{}::Decode", crate_name))
.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
where_constraints.clear();
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, format!("{}::Decode", crate_name)).unwrap();
}
})
}
Ok(())
})?
.generate_fn("decode")
.with_generic_deps("D", [format!("{}::de::Decoder", crate_name)])
.with_arg("decoder", "&mut D")
@ -82,7 +95,7 @@ impl DeriveStruct {
// b: bincode::Decode::decode(decoder)?,
// ...
// }
for field in fields.names() {
for field in &self.fields.names() {
let attributes = field.attributes().get_attribute::<FieldAttributes>()?.unwrap_or_default();
if attributes.with_serde {
struct_body
@ -106,21 +119,27 @@ impl DeriveStruct {
})?;
Ok(())
})?;
self.generate_borrow_decode(generator)?;
Ok(())
}
pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> {
// Remember to keep this mostly in sync with generate_decode
let DeriveStruct { fields, attributes } = self;
let crate_name = attributes.crate_name;
let crate_name = self.attributes.crate_name;
generator
.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"])
.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
where_constraints.clear();
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, format!("{}::BorrowDecode", crate_name)).unwrap();
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de>", crate_name)).unwrap();
}
})
}
Ok(())
})?
.generate_fn("borrow_decode")
.with_generic_deps("D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)])
.with_arg("decoder", "&mut D")
@ -131,7 +150,7 @@ impl DeriveStruct {
fn_body.group(Delimiter::Parenthesis, |ok_group| {
ok_group.ident_str("Self");
ok_group.group(Delimiter::Brace, |struct_body| {
for field in fields.names() {
for field in self.fields.names() {
let attributes = field.attributes().get_attribute::<FieldAttributes>()?.unwrap_or_default();
if attributes.with_serde {
struct_body

5
fuzz/Cargo.lock generated
View File

@ -22,6 +22,7 @@ name = "bincode"
version = "2.0.0-rc.1"
dependencies = [
"bincode_derive",
"serde",
]
[[package]]
@ -121,6 +122,6 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "virtue"
version = "0.0.7"
version = "0.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "757cfbfe0d17ee6f22fe97e536d463047d451b47cf9d11e2b7d1398b0ef274dd"
checksum = "7b60dcd6a64dd45abf9bd426970c9843726da7fc08f44cd6fcebf68c21220a63"

View File

@ -8,7 +8,17 @@ use std::num::{NonZeroI128, NonZeroI32, NonZeroU128, NonZeroU32};
use std::path::PathBuf;
use std::time::{Duration, SystemTime};
#[derive(bincode::Decode, bincode::Encode, PartialEq, Debug, serde::Serialize, serde::Deserialize, Eq, PartialOrd, Ord)]
#[derive(
bincode::Decode,
bincode::Encode,
PartialEq,
Debug,
serde::Serialize,
serde::Deserialize,
Eq,
PartialOrd,
Ord,
)]
enum AllTypes {
BTreeMap(BTreeMap<u8, AllTypes>),
BTreeSet(BTreeSet<AllTypes>),
@ -47,14 +57,14 @@ fuzz_target!(|data: &[u8]| {
let bincode_v2: Result<(AllTypes, _), _> = bincode::decode_from_slice(data, config);
match (&bincode_v1, &bincode_v2) {
(Err(e), _) if e.to_string() == "the size limit has been reached" => {},
(_, Err(bincode::error::DecodeError::LimitExceeded)) => {},
(Err(e), _) if e.to_string() == "the size limit has been reached" => {}
(_, Err(bincode::error::DecodeError::LimitExceeded)) => {}
(Ok(bincode_v1), Ok((bincode_v2, _))) if bincode_v1 != bincode_v2 => {
println!("Bytes: {:?}", data);
println!("Bincode V1: {:?}", bincode_v1);
println!("Bincode V2: {:?}", bincode_v2);
panic!("failed equality check");
},
}
(Ok(_), Err(_)) | (Err(_), Ok(_)) => {
println!("Bytes: {:?}", data);
println!("Bincode V1: {:?}", bincode_v1);

View File

@ -1,4 +1,4 @@
use crate::{de::Decode, enc::Encode};
use crate::{de::Decode, enc::Encode, impl_borrow_decode};
use core::sync::atomic::Ordering;
#[cfg(target_has_atomic = "ptr")]
@ -32,6 +32,8 @@ impl Decode for AtomicBool {
Ok(AtomicBool::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "8")]
impl_borrow_decode!(AtomicBool);
#[cfg(target_has_atomic = "8")]
impl Encode for AtomicU8 {
@ -49,6 +51,8 @@ impl Decode for AtomicU8 {
Ok(AtomicU8::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "8")]
impl_borrow_decode!(AtomicU8);
#[cfg(target_has_atomic = "16")]
impl Encode for AtomicU16 {
@ -66,6 +70,8 @@ impl Decode for AtomicU16 {
Ok(AtomicU16::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "16")]
impl_borrow_decode!(AtomicU16);
#[cfg(target_has_atomic = "32")]
impl Encode for AtomicU32 {
@ -83,6 +89,8 @@ impl Decode for AtomicU32 {
Ok(AtomicU32::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "32")]
impl_borrow_decode!(AtomicU32);
#[cfg(target_has_atomic = "64")]
impl Encode for AtomicU64 {
@ -100,6 +108,8 @@ impl Decode for AtomicU64 {
Ok(AtomicU64::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "64")]
impl_borrow_decode!(AtomicU64);
#[cfg(target_has_atomic = "ptr")]
impl Encode for AtomicUsize {
@ -117,6 +127,8 @@ impl Decode for AtomicUsize {
Ok(AtomicUsize::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "ptr")]
impl_borrow_decode!(AtomicUsize);
#[cfg(target_has_atomic = "8")]
impl Encode for AtomicI8 {
@ -134,6 +146,8 @@ impl Decode for AtomicI8 {
Ok(AtomicI8::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "8")]
impl_borrow_decode!(AtomicI8);
#[cfg(target_has_atomic = "16")]
impl Encode for AtomicI16 {
@ -151,6 +165,8 @@ impl Decode for AtomicI16 {
Ok(AtomicI16::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "16")]
impl_borrow_decode!(AtomicI16);
#[cfg(target_has_atomic = "32")]
impl Encode for AtomicI32 {
@ -168,6 +184,8 @@ impl Decode for AtomicI32 {
Ok(AtomicI32::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "32")]
impl_borrow_decode!(AtomicI32);
#[cfg(target_has_atomic = "64")]
impl Encode for AtomicI64 {
@ -185,6 +203,8 @@ impl Decode for AtomicI64 {
Ok(AtomicI64::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "64")]
impl_borrow_decode!(AtomicI64);
#[cfg(target_has_atomic = "ptr")]
impl Encode for AtomicIsize {
@ -202,3 +222,5 @@ impl Decode for AtomicIsize {
Ok(AtomicIsize::new(Decode::decode(decoder)?))
}
}
#[cfg(target_has_atomic = "ptr")]
impl_borrow_decode!(AtomicIsize);

View File

@ -1,141 +1,54 @@
use super::{Decode, Decoder};
use super::{BorrowDecode, BorrowDecoder, Decode, Decoder};
use crate::error::DecodeError;
impl<A> Decode for (A,)
macro_rules! impl_tuple {
() => {};
($first:ident $(, $extra:ident)*) => {
impl<'de, $first $(, $extra)*> BorrowDecode<'de> for ($first, $($extra, )*)
where
A: Decode,
$first: BorrowDecode<'de>,
$(
$extra : BorrowDecode<'de>,
)*
{
fn decode<_D: Decoder>(mut decoder: &mut _D) -> Result<Self, DecodeError> {
Ok((A::decode(&mut decoder)?,))
}
}
impl<A, B> Decode for (A, B)
where
A: Decode,
B: Decode,
{
fn decode<_D: Decoder>(mut decoder: &mut _D) -> Result<Self, DecodeError> {
Ok((A::decode(&mut decoder)?, B::decode(&mut decoder)?))
}
}
impl<A, B, C> Decode for (A, B, C)
where
A: Decode,
B: Decode,
C: Decode,
{
fn decode<_D: Decoder>(mut decoder: &mut _D) -> Result<Self, DecodeError> {
fn borrow_decode<BD: BorrowDecoder<'de>>(decoder: &mut BD) -> Result<Self, DecodeError> {
Ok((
A::decode(&mut decoder)?,
B::decode(&mut decoder)?,
C::decode(&mut decoder)?,
$first::borrow_decode(decoder)?,
$($extra :: borrow_decode(decoder)?, )*
))
}
}
impl<A, B, C, D> Decode for (A, B, C, D)
impl<$first $(, $extra)*> Decode for ($first, $($extra, )*)
where
A: Decode,
B: Decode,
C: Decode,
D: Decode,
$first: Decode,
$(
$extra : Decode,
)*
{
fn decode<_D: Decoder>(mut decoder: &mut _D) -> Result<Self, DecodeError> {
fn decode<DE: Decoder>(decoder: &mut DE) -> Result<Self, DecodeError> {
Ok((
A::decode(&mut decoder)?,
B::decode(&mut decoder)?,
C::decode(&mut decoder)?,
D::decode(&mut decoder)?,
$first::decode(decoder)?,
$($extra :: decode(decoder)?, )*
))
}
}
}
}
impl<A, B, C, D, E> Decode for (A, B, C, D, E)
where
A: Decode,
B: Decode,
C: Decode,
D: Decode,
E: Decode,
{
fn decode<_D: Decoder>(mut decoder: &mut _D) -> Result<Self, DecodeError> {
Ok((
A::decode(&mut decoder)?,
B::decode(&mut decoder)?,
C::decode(&mut decoder)?,
D::decode(&mut decoder)?,
E::decode(&mut decoder)?,
))
}
}
impl<A, B, C, D, E, F> Decode for (A, B, C, D, E, F)
where
A: Decode,
B: Decode,
C: Decode,
D: Decode,
E: Decode,
F: Decode,
{
fn decode<_D: Decoder>(mut decoder: &mut _D) -> Result<Self, DecodeError> {
Ok((
A::decode(&mut decoder)?,
B::decode(&mut decoder)?,
C::decode(&mut decoder)?,
D::decode(&mut decoder)?,
E::decode(&mut decoder)?,
F::decode(&mut decoder)?,
))
}
}
impl<A, B, C, D, E, F, G> Decode for (A, B, C, D, E, F, G)
where
A: Decode,
B: Decode,
C: Decode,
D: Decode,
E: Decode,
F: Decode,
G: Decode,
{
fn decode<_D: Decoder>(mut decoder: &mut _D) -> Result<Self, DecodeError> {
Ok((
A::decode(&mut decoder)?,
B::decode(&mut decoder)?,
C::decode(&mut decoder)?,
D::decode(&mut decoder)?,
E::decode(&mut decoder)?,
F::decode(&mut decoder)?,
G::decode(&mut decoder)?,
))
}
}
impl<A, B, C, D, E, F, G, H> Decode for (A, B, C, D, E, F, G, H)
where
A: Decode,
B: Decode,
C: Decode,
D: Decode,
E: Decode,
F: Decode,
G: Decode,
H: Decode,
{
fn decode<_D: Decoder>(mut decoder: &mut _D) -> Result<Self, DecodeError> {
Ok((
A::decode(&mut decoder)?,
B::decode(&mut decoder)?,
C::decode(&mut decoder)?,
D::decode(&mut decoder)?,
E::decode(&mut decoder)?,
F::decode(&mut decoder)?,
G::decode(&mut decoder)?,
H::decode(&mut decoder)?,
))
}
}
impl_tuple!(A);
impl_tuple!(A, B);
impl_tuple!(A, B, C);
impl_tuple!(A, B, C, D);
impl_tuple!(A, B, C, D, E);
impl_tuple!(A, B, C, D, E, F);
impl_tuple!(A, B, C, D, E, F, G);
impl_tuple!(A, B, C, D, E, F, G, H);
impl_tuple!(A, B, C, D, E, F, G, H, I);
impl_tuple!(A, B, C, D, E, F, G, H, I, J);
impl_tuple!(A, B, C, D, E, F, G, H, I, J, K);
impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);

View File

@ -8,6 +8,7 @@ use crate::{
InternalIntEncodingConfig,
},
error::{DecodeError, IntegerType},
impl_borrow_decode,
};
use core::{
any::TypeId,
@ -29,6 +30,7 @@ impl Decode for bool {
}
}
}
impl_borrow_decode!(bool);
impl Decode for u8 {
#[inline]
@ -45,6 +47,7 @@ impl Decode for u8 {
}
}
}
impl_borrow_decode!(u8);
impl Decode for NonZeroU8 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -53,6 +56,7 @@ impl Decode for NonZeroU8 {
})
}
}
impl_borrow_decode!(NonZeroU8);
impl Decode for u16 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -72,6 +76,7 @@ impl Decode for u16 {
}
}
}
impl_borrow_decode!(u16);
impl Decode for NonZeroU16 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -80,6 +85,7 @@ impl Decode for NonZeroU16 {
})
}
}
impl_borrow_decode!(NonZeroU16);
impl Decode for u32 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -99,6 +105,7 @@ impl Decode for u32 {
}
}
}
impl_borrow_decode!(u32);
impl Decode for NonZeroU32 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -107,6 +114,7 @@ impl Decode for NonZeroU32 {
})
}
}
impl_borrow_decode!(NonZeroU32);
impl Decode for u64 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -126,6 +134,7 @@ impl Decode for u64 {
}
}
}
impl_borrow_decode!(u64);
impl Decode for NonZeroU64 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -134,6 +143,7 @@ impl Decode for NonZeroU64 {
})
}
}
impl_borrow_decode!(NonZeroU64);
impl Decode for u128 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -153,6 +163,7 @@ impl Decode for u128 {
}
}
}
impl_borrow_decode!(u128);
impl Decode for NonZeroU128 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -161,6 +172,7 @@ impl Decode for NonZeroU128 {
})
}
}
impl_borrow_decode!(NonZeroU128);
impl Decode for usize {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -185,6 +197,7 @@ impl Decode for usize {
}
}
}
impl_borrow_decode!(usize);
impl Decode for NonZeroUsize {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -193,6 +206,7 @@ impl Decode for NonZeroUsize {
})
}
}
impl_borrow_decode!(NonZeroUsize);
impl Decode for i8 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -202,6 +216,7 @@ impl Decode for i8 {
Ok(bytes[0] as i8)
}
}
impl_borrow_decode!(i8);
impl Decode for NonZeroI8 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -210,6 +225,7 @@ impl Decode for NonZeroI8 {
})
}
}
impl_borrow_decode!(NonZeroI8);
impl Decode for i16 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -229,6 +245,7 @@ impl Decode for i16 {
}
}
}
impl_borrow_decode!(i16);
impl Decode for NonZeroI16 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -237,6 +254,7 @@ impl Decode for NonZeroI16 {
})
}
}
impl_borrow_decode!(NonZeroI16);
impl Decode for i32 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -256,6 +274,7 @@ impl Decode for i32 {
}
}
}
impl_borrow_decode!(i32);
impl Decode for NonZeroI32 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -264,6 +283,7 @@ impl Decode for NonZeroI32 {
})
}
}
impl_borrow_decode!(NonZeroI32);
impl Decode for i64 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -283,6 +303,7 @@ impl Decode for i64 {
}
}
}
impl_borrow_decode!(i64);
impl Decode for NonZeroI64 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -291,6 +312,7 @@ impl Decode for NonZeroI64 {
})
}
}
impl_borrow_decode!(NonZeroI64);
impl Decode for i128 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -310,6 +332,7 @@ impl Decode for i128 {
}
}
}
impl_borrow_decode!(i128);
impl Decode for NonZeroI128 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -318,6 +341,7 @@ impl Decode for NonZeroI128 {
})
}
}
impl_borrow_decode!(NonZeroI128);
impl Decode for isize {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -337,6 +361,7 @@ impl Decode for isize {
}
}
}
impl_borrow_decode!(isize);
impl Decode for NonZeroIsize {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -345,6 +370,7 @@ impl Decode for NonZeroIsize {
})
}
}
impl_borrow_decode!(NonZeroIsize);
impl Decode for f32 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -357,6 +383,7 @@ impl Decode for f32 {
})
}
}
impl_borrow_decode!(f32);
impl Decode for f64 {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -369,6 +396,7 @@ impl Decode for f64 {
})
}
}
impl_borrow_decode!(f64);
impl Decode for char {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -398,6 +426,7 @@ impl Decode for char {
Ok(res)
}
}
impl_borrow_decode!(char);
impl<'a, 'de: 'a> BorrowDecode<'de> for &'a [u8] {
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
@ -407,18 +436,6 @@ impl<'a, 'de: 'a> BorrowDecode<'de> for &'a [u8] {
}
}
impl<'a, 'de: 'a> BorrowDecode<'de> for Option<&'a [u8]> {
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
match super::decode_option_variant(decoder, core::any::type_name::<Option<&[u8]>>())? {
Some(_) => {
let val = BorrowDecode::borrow_decode(decoder)?;
Ok(Some(val))
}
None => Ok(None),
}
}
}
impl<'a, 'de: 'a> BorrowDecode<'de> for &'a str {
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let slice = <&[u8]>::borrow_decode(decoder)?;
@ -426,18 +443,6 @@ impl<'a, 'de: 'a> BorrowDecode<'de> for &'a str {
}
}
impl<'a, 'de: 'a> BorrowDecode<'de> for Option<&'a str> {
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
match super::decode_option_variant(decoder, core::any::type_name::<Option<&str>>())? {
Some(_) => {
let val = BorrowDecode::borrow_decode(decoder)?;
Ok(Some(val))
}
None => Ok(None),
}
}
}
impl<T, const N: usize> Decode for [T; N]
where
T: Decode + Sized + 'static,
@ -479,17 +484,64 @@ where
}
}
impl<'de, T, const N: usize> BorrowDecode<'de> for [T; N]
where
T: BorrowDecode<'de> + Sized + 'static,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
if !D::C::SKIP_FIXED_ARRAY_LENGTH {
let length = super::decode_slice_len(decoder)?;
if length != N {
return Err(DecodeError::ArrayLengthMismatch {
found: length,
required: N,
});
}
}
decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?;
// Optimize for `[u8; N]`
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)
} 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()
}
}
}
impl Decode for () {
fn decode<D: Decoder>(_: &mut D) -> Result<Self, DecodeError> {
Ok(())
}
}
impl_borrow_decode!(());
impl<T> Decode for core::marker::PhantomData<T> {
fn decode<D: Decoder>(_: &mut D) -> Result<Self, DecodeError> {
Ok(core::marker::PhantomData)
}
}
impl<'de, T> BorrowDecode<'de> for core::marker::PhantomData<T> {
fn borrow_decode<D: BorrowDecoder<'de>>(_: &mut D) -> Result<Self, DecodeError> {
Ok(core::marker::PhantomData)
}
}
impl<T> Decode for Option<T>
where
@ -506,6 +558,37 @@ where
}
}
impl<'de, T> BorrowDecode<'de> for Option<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
match super::decode_option_variant(decoder, core::any::type_name::<Option<T>>())? {
Some(_) => {
let val = T::borrow_decode(decoder)?;
Ok(Some(val))
}
None => Ok(None),
}
}
}
// BlockedTODO: https://github.com/rust-lang/rust/issues/37653
//
// We'll want to implement BorrowDecode for both Option<&[u8]> and Option<&[T: Encode]>,
// but those implementations overlap because &'a [u8] also implements BorrowDecode
// impl<'a, 'de: 'a> BorrowDecode<'de> for Option<&'a [u8]> {
// fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
// match super::decode_option_variant(decoder, core::any::type_name::<Option<&[u8]>>())? {
// Some(_) => {
// let val = BorrowDecode::borrow_decode(decoder)?;
// Ok(Some(val))
// }
// None => Ok(None),
// }
// }
// }
impl<T, U> Decode for Result<T, U>
where
T: Decode,
@ -531,6 +614,31 @@ where
}
}
impl<'de, T, U> BorrowDecode<'de> for Result<T, U>
where
T: BorrowDecode<'de>,
U: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let is_ok = u32::decode(decoder)?;
match is_ok {
0 => {
let t = T::borrow_decode(decoder)?;
Ok(Ok(t))
}
1 => {
let u = U::borrow_decode(decoder)?;
Ok(Err(u))
}
x => Err(DecodeError::UnexpectedVariant {
found: x as u32,
allowed: crate::error::AllowedEnumVariants::Range { max: 1, min: 0 },
type_name: core::any::type_name::<Result<T, U>>(),
}),
}
}
}
impl<T> Decode for Cell<T>
where
T: Decode,
@ -541,6 +649,16 @@ where
}
}
impl<'de, T> BorrowDecode<'de> for Cell<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let t = T::borrow_decode(decoder)?;
Ok(Cell::new(t))
}
}
impl<T> Decode for RefCell<T>
where
T: Decode,
@ -551,6 +669,16 @@ where
}
}
impl<'de, T> BorrowDecode<'de> for RefCell<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let t = T::borrow_decode(decoder)?;
Ok(RefCell::new(t))
}
}
impl Decode for Duration {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
const NANOS_PER_SEC: u64 = 1_000_000_000;
@ -562,6 +690,7 @@ impl Decode for Duration {
Ok(Duration::new(secs, nanos))
}
}
impl_borrow_decode!(Duration);
impl<T> Decode for Range<T>
where
@ -573,6 +702,16 @@ where
Ok(min..max)
}
}
impl<'de, T> BorrowDecode<'de> for Range<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let min = T::borrow_decode(decoder)?;
let max = T::borrow_decode(decoder)?;
Ok(min..max)
}
}
impl<T> Decode for RangeInclusive<T>
where
@ -585,6 +724,17 @@ where
}
}
impl<'de, T> BorrowDecode<'de> for RangeInclusive<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let min = T::borrow_decode(decoder)?;
let max = T::borrow_decode(decoder)?;
Ok(RangeInclusive::new(min, max))
}
}
impl<T> Decode for Bound<T>
where
T: Decode,
@ -603,6 +753,24 @@ where
}
}
impl<'de, T> BorrowDecode<'de> for Bound<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
match u32::decode(decoder)? {
0 => Ok(Bound::Unbounded),
1 => Ok(Bound::Included(T::borrow_decode(decoder)?)),
2 => Ok(Bound::Excluded(T::borrow_decode(decoder)?)),
x => Err(DecodeError::UnexpectedVariant {
allowed: crate::error::AllowedEnumVariants::Range { max: 2, min: 0 },
found: x,
type_name: core::any::type_name::<Bound<T>>(),
}),
}
}
}
const UTF8_CHAR_WIDTH: [u8; 256] = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, // 0x1F

View File

@ -54,6 +54,16 @@ pub use self::decoder::DecoderImpl;
/// })
/// }
/// }
/// impl<'de> bincode::BorrowDecode<'de> for Entity {
/// fn borrow_decode<D: bincode::de::BorrowDecoder<'de>>(
/// decoder: &mut D,
/// ) -> core::result::Result<Self, bincode::error::DecodeError> {
/// Ok(Self {
/// x: bincode::BorrowDecode::borrow_decode(decoder)?,
/// y: bincode::BorrowDecode::borrow_decode(decoder)?,
/// })
/// }
/// }
/// ```
///
/// From here you can add/remove fields, or add custom logic.
@ -70,8 +80,9 @@ pub use self::decoder::DecoderImpl;
/// # Ok(Foo)
/// # }
/// # }
/// # bincode::impl_borrow_decode!(Foo);
/// ```
pub trait Decode: for<'de> BorrowDecode<'de> {
pub trait Decode: Sized {
/// Attempt to decode this type with the given [Decode].
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError>;
}
@ -86,11 +97,19 @@ pub trait BorrowDecode<'de>: Sized {
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError>;
}
impl<'de, T: Decode> BorrowDecode<'de> for T {
fn borrow_decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
Decode::decode(decoder)
/// Helper macro to implement `BorrowDecode` for any type that implements `Decode`.
#[macro_export]
macro_rules! impl_borrow_decode {
($ty:ty) => {
impl<'de> $crate::BorrowDecode<'de> for $ty {
fn borrow_decode<D: $crate::de::BorrowDecoder<'de>>(
decoder: &mut D,
) -> core::result::Result<Self, $crate::error::DecodeError> {
$crate::Decode::decode(decoder)
}
}
};
}
/// Any source that can decode basic types. This type is most notably implemented for [Decoder].
pub trait Decoder: Sealed {
@ -163,6 +182,24 @@ pub trait Decoder: Sealed {
/// Ok(result)
/// }
/// }
/// impl<'de, T: bincode::BorrowDecode<'de>> bincode::BorrowDecode<'de> for Container<T> {
/// fn borrow_decode<D: bincode::de::BorrowDecoder<'de>>(
/// decoder: &mut D,
/// ) -> core::result::Result<Self, bincode::error::DecodeError> {
/// let len = u64::borrow_decode(decoder)?;
/// let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?;
/// // Make sure we don't allocate too much memory
/// decoder.claim_bytes_read(len * core::mem::size_of::<T>());
///
/// let mut result = Container::with_capacity(len);
/// for _ in 0..len {
/// // un-claim the memory
/// decoder.unclaim_bytes_read(core::mem::size_of::<T>());
/// result.push(T::borrow_decode(decoder)?)
/// }
/// Ok(result)
/// }
/// }
/// ```
fn unclaim_bytes_read(&mut self, n: usize);
}

View File

@ -283,12 +283,12 @@ impl Encode for char {
}
}
impl Encode for &'_ [u8] {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
super::encode_slice_len(encoder, self.len())?;
encoder.writer().write(self)
}
}
// impl Encode for &'_ [u8] {
// fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
// super::encode_slice_len(encoder, self.len())?;
// encoder.writer().write(self)
// }
// }
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
@ -327,25 +327,24 @@ fn encode_utf8(writer: &mut impl Writer, c: char) -> Result<(), EncodeError> {
// BlockedTODO: https://github.com/rust-lang/rust/issues/37653
//
// We'll want to implement encoding for both &[u8] and &[T: Encode],
// but those implementations overlap because u8 also implements Encodeabl
//
// default impl Encode for &'_ [u8] {
// fn encode<E: Encode>(&self, encoder: &mut E) -> Result<(), EncodeError> {
// encoder.encode_slice(*self)
// }
// }
//
// impl<T: Encode> Encode for &'_ [T] {
// fn encode<E: Encode>(&self, encoder: &mut E) -> Result<(), EncodeError> {
// self.len().encode(encoder)?;
// for item in self.iter() {
// item.encode(encoder)?;
// }
// Ok(())
// but those implementations overlap because u8 also implements Encode
// impl Encode for &'_ [u8] {
// fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
// encoder.writer().write(*self)
// }
// }
impl Encode for &'_ str {
impl<T: Encode> Encode for &'_ [T] {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
self.len().encode(encoder)?;
for item in self.iter() {
item.encode(encoder)?;
}
Ok(())
}
}
impl Encode for str {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
self.as_bytes().encode(encoder)
}
@ -409,7 +408,7 @@ where
impl<T> Encode for RefCell<T>
where
T: Encode,
T: Encode + ?Sized,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
let borrow_guard = self
@ -476,7 +475,7 @@ where
impl<'a, T> Encode for &'a T
where
T: Encode,
T: Encode + ?Sized,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
T::encode(self, encoder)

View File

@ -1,10 +1,10 @@
use crate::{
de::{Decode, Decoder},
de::{BorrowDecoder, Decode, Decoder},
enc::{self, Encode, Encoder},
error::{DecodeError, EncodeError},
Config,
impl_borrow_decode, BorrowDecode, Config,
};
#[cfg(feature = "atomic")]
#[cfg(target_has_atomic = "ptr")]
use alloc::sync::Arc;
use alloc::{
borrow::{Cow, ToOwned},
@ -65,6 +65,25 @@ where
Ok(map)
}
}
impl<'de, T> BorrowDecode<'de> for BinaryHeap<T>
where
T: BorrowDecode<'de> + Ord,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = crate::de::decode_slice_len(decoder)?;
decoder.claim_container_read::<T>(len)?;
let mut map = BinaryHeap::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>());
let key = T::borrow_decode(decoder)?;
map.push(key);
}
Ok(map)
}
}
impl<T> Encode for BinaryHeap<T>
where
@ -100,6 +119,27 @@ where
Ok(map)
}
}
impl<'de, K, V> BorrowDecode<'de> for BTreeMap<K, V>
where
K: BorrowDecode<'de> + Ord,
V: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = crate::de::decode_slice_len(decoder)?;
decoder.claim_container_read::<(K, V)>(len)?;
let mut map = BTreeMap::new();
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::<(K, V)>());
let key = K::borrow_decode(decoder)?;
let value = V::borrow_decode(decoder)?;
map.insert(key, value);
}
Ok(map)
}
}
impl<K, V> Encode for BTreeMap<K, V>
where
@ -135,6 +175,25 @@ where
Ok(map)
}
}
impl<'de, T> BorrowDecode<'de> for BTreeSet<T>
where
T: BorrowDecode<'de> + Ord,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = crate::de::decode_slice_len(decoder)?;
decoder.claim_container_read::<T>(len)?;
let mut map = BTreeSet::new();
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>());
let key = T::borrow_decode(decoder)?;
map.insert(key);
}
Ok(map)
}
}
impl<T> Encode for BTreeSet<T>
where
@ -168,6 +227,25 @@ where
Ok(map)
}
}
impl<'de, T> BorrowDecode<'de> for VecDeque<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = crate::de::decode_slice_len(decoder)?;
decoder.claim_container_read::<T>(len)?;
let mut map = VecDeque::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>());
let key = T::borrow_decode(decoder)?;
map.push_back(key);
}
Ok(map)
}
}
impl<T> Encode for VecDeque<T>
where
@ -201,6 +279,25 @@ where
}
}
impl<'de, T> BorrowDecode<'de> for Vec<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = crate::de::decode_slice_len(decoder)?;
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::borrow_decode(decoder)?);
}
Ok(vec)
}
}
impl<T> Encode for Vec<T>
where
T: Encode,
@ -222,6 +319,7 @@ impl Decode for String {
})
}
}
impl_borrow_decode!(String);
impl Encode for String {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
@ -238,10 +336,19 @@ where
Ok(Box::new(t))
}
}
impl<'de, T> BorrowDecode<'de> for Box<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let t = T::borrow_decode(decoder)?;
Ok(Box::new(t))
}
}
impl<T> Encode for Box<T>
where
T: Encode,
T: Encode + ?Sized,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
T::encode(self, encoder)
@ -258,6 +365,16 @@ where
}
}
impl<'de, T> BorrowDecode<'de> for Box<[T]>
where
T: BorrowDecode<'de> + 'de,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let vec = Vec::borrow_decode(decoder)?;
Ok(vec.into_boxed_slice())
}
}
impl<T> Encode for Box<[T]>
where
T: Encode,
@ -271,20 +388,6 @@ where
}
}
// BlockedTODO: https://github.com/rust-lang/rust/issues/31844
// Cow should be able to decode a borrowed value
// Currently this conflicts with the owned `Decode` implementation below
// impl<'cow, T> BorrowDecode<'cow> for Cow<'cow, T>
// where
// T: BorrowDecode<'cow>,
// {
// fn borrow_decode<D: crate::de::BorrowDecoder<'cow>>(decoder: &mut D) -> Result<Self, DecodeError> {
// let t = T::borrow_decode(decoder)?;
// Ok(Cow::Borrowed(t))
// }
// }
impl<'cow, T> Decode for Cow<'cow, T>
where
T: ToOwned + ?Sized,
@ -295,6 +398,16 @@ where
Ok(Cow::Owned(t))
}
}
impl<'cow, T> BorrowDecode<'cow> for Cow<'cow, T>
where
T: ToOwned + ?Sized,
&'cow T: BorrowDecode<'cow>,
{
fn borrow_decode<D: BorrowDecoder<'cow>>(decoder: &mut D) -> Result<Self, DecodeError> {
let t = <&T>::borrow_decode(decoder)?;
Ok(Cow::Borrowed(t))
}
}
impl<'cow, T> Encode for Cow<'cow, T>
where
@ -316,16 +429,26 @@ where
}
}
impl<'de, T> BorrowDecode<'de> for Rc<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let t = T::borrow_decode(decoder)?;
Ok(Rc::new(t))
}
}
impl<T> Encode for Rc<T>
where
T: Encode,
T: Encode + ?Sized,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
T::encode(self, encoder)
}
}
#[cfg(feature = "atomic")]
#[cfg(target_has_atomic = "ptr")]
impl<T> Decode for Arc<T>
where
T: Decode,
@ -336,10 +459,37 @@ where
}
}
#[cfg(feature = "atomic")]
#[cfg(target_has_atomic = "ptr")]
impl Decode for Arc<str> {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
let decoded = String::decode(decoder)?;
Ok(decoded.into())
}
}
#[cfg(target_has_atomic = "ptr")]
impl<'de, T> BorrowDecode<'de> for Arc<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let t = T::borrow_decode(decoder)?;
Ok(Arc::new(t))
}
}
#[cfg(target_has_atomic = "ptr")]
impl<'de> BorrowDecode<'de> for Arc<str> {
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let decoded = String::decode(decoder)?;
Ok(decoded.into())
}
}
#[cfg(target_has_atomic = "ptr")]
impl<T> Encode for Arc<T>
where
T: Encode,
T: Encode + ?Sized,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
T::encode(self, encoder)

View File

@ -3,6 +3,7 @@ use crate::{
de::{read::Reader, BorrowDecode, BorrowDecoder, Decode, Decoder, DecoderImpl},
enc::{write::Writer, Encode, Encoder, EncoderImpl},
error::{DecodeError, EncodeError},
impl_borrow_decode,
};
use core::time::Duration;
use std::{
@ -146,6 +147,7 @@ impl Decode for CString {
CString::new(vec).map_err(|inner| DecodeError::CStringNulError { inner })
}
}
impl_borrow_decode!(CString);
impl<T> Encode for Mutex<T>
where
@ -168,6 +170,15 @@ where
Ok(Mutex::new(t))
}
}
impl<'de, T> BorrowDecode<'de> for Mutex<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let t = T::borrow_decode(decoder)?;
Ok(Mutex::new(t))
}
}
impl<T> Encode for RwLock<T>
where
@ -190,6 +201,15 @@ where
Ok(RwLock::new(t))
}
}
impl<'de, T> BorrowDecode<'de> for RwLock<T>
where
T: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let t = T::borrow_decode(decoder)?;
Ok(RwLock::new(t))
}
}
impl Encode for SystemTime {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
@ -212,6 +232,7 @@ impl Decode for SystemTime {
}
}
}
impl_borrow_decode!(SystemTime);
impl Encode for &'_ Path {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
@ -241,6 +262,7 @@ impl Decode for PathBuf {
Ok(string.into())
}
}
impl_borrow_decode!(PathBuf);
impl Encode for IpAddr {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
@ -270,6 +292,7 @@ impl Decode for IpAddr {
}
}
}
impl_borrow_decode!(IpAddr);
impl Encode for Ipv4Addr {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
@ -284,6 +307,7 @@ impl Decode for Ipv4Addr {
Ok(Self::from(buff))
}
}
impl_borrow_decode!(Ipv4Addr);
impl Encode for Ipv6Addr {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
@ -298,6 +322,7 @@ impl Decode for Ipv6Addr {
Ok(Self::from(buff))
}
}
impl_borrow_decode!(Ipv6Addr);
impl Encode for SocketAddr {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
@ -327,6 +352,7 @@ impl Decode for SocketAddr {
}
}
}
impl_borrow_decode!(SocketAddr);
impl Encode for SocketAddrV4 {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
@ -342,6 +368,7 @@ impl Decode for SocketAddrV4 {
Ok(Self::new(ip, port))
}
}
impl_borrow_decode!(SocketAddrV4);
impl Encode for SocketAddrV6 {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
@ -357,6 +384,7 @@ impl Decode for SocketAddrV6 {
Ok(Self::new(ip, port, 0, 0))
}
}
impl_borrow_decode!(SocketAddrV6);
impl std::error::Error for EncodeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
@ -416,6 +444,27 @@ where
Ok(map)
}
}
impl<'de, K, V> BorrowDecode<'de> for HashMap<K, V>
where
K: BorrowDecode<'de> + Eq + std::hash::Hash,
V: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = crate::de::decode_slice_len(decoder)?;
decoder.claim_container_read::<(K, V)>(len)?;
let mut map = HashMap::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::<(K, V)>());
let k = K::borrow_decode(decoder)?;
let v = V::borrow_decode(decoder)?;
map.insert(k, v);
}
Ok(map)
}
}
impl<T, S> Decode for HashSet<T, S>
where
@ -439,6 +488,27 @@ where
}
}
impl<'de, T, S> BorrowDecode<'de> for HashSet<T, S>
where
T: BorrowDecode<'de> + Eq + Hash,
S: std::hash::BuildHasher + Default,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = crate::de::decode_slice_len(decoder)?;
decoder.claim_container_read::<T>(len)?;
let mut map = HashSet::with_capacity_and_hasher(len, S::default());
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>());
let key = T::borrow_decode(decoder)?;
map.insert(key);
}
Ok(map)
}
}
impl<T, S> Encode for HashSet<T, S>
where
T: Encode,

View File

@ -193,6 +193,17 @@ where
T::deserialize(serde_decoder).map(Compat)
}
}
impl<'de, T> crate::BorrowDecode<'de> for Compat<T>
where
T: serde::de::DeserializeOwned,
{
fn borrow_decode<D: crate::de::BorrowDecoder<'de>>(
decoder: &mut D,
) -> Result<Self, crate::error::DecodeError> {
let serde_decoder = de_owned::SerdeDecoder { de: decoder };
T::deserialize(serde_decoder).map(Compat)
}
}
impl<T> crate::Encode for Compat<T>
where

View File

@ -90,6 +90,7 @@ use enc::write::Writer;
pub use features::*;
pub mod config;
#[macro_use]
pub mod de;
pub mod enc;
pub mod error;
@ -136,7 +137,23 @@ pub fn encode_into_writer<E: enc::Encode, W: Writer, C: Config>(
/// See the [config] module for more information on configurations.
///
/// [config]: config/index.html
pub fn decode_from_slice<'a, D: de::BorrowDecode<'a>, C: Config>(
pub fn decode_from_slice<D: de::Decode, C: Config>(
src: &[u8],
config: C,
) -> Result<(D, usize), error::DecodeError> {
let reader = de::read::SliceReader::new(src);
let mut decoder = de::DecoderImpl::<_, C>::new(reader, config);
let result = D::decode(&mut decoder)?;
let bytes_read = src.len() - decoder.reader().slice.len();
Ok((result, bytes_read))
}
/// Attempt to decode a given type `D` from the given slice.
///
/// See the [config] module for more information on configurations.
///
/// [config]: config/index.html
pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a>, C: Config>(
src: &'a [u8],
config: C,
) -> Result<(D, usize), error::DecodeError> {

View File

@ -496,7 +496,7 @@ fn test_decode_u64() {
(&[U32_BYTE, 0, 0, 0, 10], 167_772_160, 10),
(
&[U64_BYTE, 0, 0, 0, 0, 0, 0, 0, 10],
72_057_594_037_9279_360,
720_575_940_379_279_360,
10,
),
];
@ -574,7 +574,7 @@ fn test_decode_u128() {
(&[U32_BYTE, 0, 0, 0, 10], 167_772_160, 10),
(
&[U64_BYTE, 0, 0, 0, 0, 0, 0, 0, 10],
72_057_594_037_9279_360,
720_575_940_379_279_360,
10,
),
(

View File

@ -275,7 +275,7 @@ fn test_encode_u64() {
// these values should encode in 9 bytes (leading byte + 8 bytes)
// Values chosen at random, add new cases as needed
for i in [u32::MAX as u64 + 1, 500_0000_000, u64::MAX] {
for i in [u32::MAX as u64 + 1, 5_000_000_000, u64::MAX] {
let mut writer = SliceWriter::new(&mut buffer);
varint_encode_u64(&mut writer, Endian::Big, i).unwrap();
assert_eq!(writer.bytes_written(), 9);
@ -351,7 +351,7 @@ fn test_encode_u128() {
// these values should encode in 9 bytes (leading byte + 8 bytes)
// Values chosen at random, add new cases as needed
for i in [u32::MAX as u128 + 1, 500_0000_000, u64::MAX as u128] {
for i in [u32::MAX as u128 + 1, 5_000_000_000, u64::MAX as u128] {
let mut writer = SliceWriter::new(&mut buffer);
varint_encode_u128(&mut writer, Endian::Big, i).unwrap();
assert_eq!(writer.bytes_written(), 9);

View File

@ -1,3 +1,4 @@
#![allow(clippy::blacklisted_name)]
#![cfg(feature = "alloc")]
extern crate alloc;
@ -8,7 +9,7 @@ use alloc::borrow::Cow;
use alloc::collections::*;
#[cfg(not(feature = "serde"))]
use alloc::rc::Rc;
#[cfg(all(feature = "atomic", not(feature = "serde")))]
#[cfg(all(target_has_atomic = "ptr", not(feature = "serde")))]
use alloc::sync::Arc;
use utils::{the_same, the_same_with_comparer};
@ -38,6 +39,7 @@ impl bincode::Decode for Foo {
})
}
}
bincode::impl_borrow_decode!(Foo);
#[test]
fn test_vec() {
@ -49,6 +51,30 @@ fn test_vec() {
assert_eq!(foo.a, 5);
assert_eq!(foo.b, 10);
assert_eq!(len, 2);
let vec: Vec<u8> = bincode::decode_from_slice(
&[4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4],
bincode::config::legacy(),
)
.unwrap()
.0;
assert_eq!(vec, &[1, 2, 3, 4]);
let vec: Vec<Cow<'static, u8>> = bincode::decode_from_slice(
&[4, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4],
bincode::config::legacy(),
)
.unwrap()
.0;
assert_eq!(
vec,
&[
Cow::Borrowed(&1),
Cow::Borrowed(&2),
Cow::Borrowed(&3),
Cow::Borrowed(&4)
]
);
}
#[test]
@ -59,12 +85,16 @@ fn test_alloc_commons() {
the_same(Box::<[u32]>::from(vec![1, 2, 3, 4, 5]));
the_same(Cow::<u32>::Owned(5));
the_same(Cow::<u32>::Borrowed(&5));
// Serde doesn't support Rc<u32>
#[cfg(not(feature = "serde"))]
{
// Serde doesn't support Rc or Arc
the_same(Rc::<u32>::new(5));
// serde doesn't support Arc<u32>
#[cfg(all(feature = "atomic", not(feature = "serde")))]
#[cfg(target_has_atomic = "ptr")]
{
the_same(Arc::<u32>::new(5));
}
}
the_same_with_comparer(
{
let mut map = BinaryHeap::<u32>::new();
@ -75,7 +105,7 @@ fn test_alloc_commons() {
map.push(5);
map
},
|a, b| a.into_iter().collect::<Vec<_>>() == b.into_iter().collect::<Vec<_>>(),
|a, b| a.iter().collect::<Vec<_>>() == b.iter().collect::<Vec<_>>(),
);
the_same({
let mut map = BTreeMap::<u32, i32>::new();
@ -97,7 +127,7 @@ fn test_alloc_commons() {
#[test]
fn test_container_limits() {
use bincode::{error::DecodeError, Decode};
use bincode::{error::DecodeError, BorrowDecode, Decode};
const DECODE_LIMIT: usize = 100_000;
@ -112,7 +142,7 @@ fn test_container_limits() {
bincode::encode_to_vec(DECODE_LIMIT as u64, bincode::config::standard()).unwrap(),
];
fn validate_fail<T: Decode + core::fmt::Debug>(slice: &[u8]) {
fn validate_fail<T: Decode + for<'de> BorrowDecode<'de> + core::fmt::Debug>(slice: &[u8]) {
let result = bincode::decode_from_slice::<T, _>(
slice,
bincode::config::standard().with_limit::<DECODE_LIMIT>(),
@ -134,7 +164,6 @@ fn test_container_limits() {
validate_fail::<VecDeque<i32>>(slice);
validate_fail::<Vec<i32>>(slice);
validate_fail::<String>(slice);
validate_fail::<Box<[u8]>>(slice);
#[cfg(feature = "std")]
{
validate_fail::<std::collections::HashMap<i32, i32>>(slice);
@ -142,3 +171,22 @@ fn test_container_limits() {
}
}
}
#[cfg(target_has_atomic = "ptr")]
#[test]
fn test_arc_str() {
use alloc::sync::Arc;
let start: Arc<str> = Arc::from("Example String");
let mut target = [0u8; 100];
let config = bincode::config::standard();
let len = {
let start: Arc<str> = Arc::clone(&start);
bincode::encode_into_slice(start, &mut target, config).unwrap()
};
let slice = &target[..len];
let decoded: Arc<str> = bincode::borrow_decode_from_slice(slice, config).unwrap().0;
assert_eq!(decoded, start);
}

View File

@ -1,48 +1,65 @@
#![cfg(feature = "atomic")]
mod utils;
use core::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
AtomicU64, AtomicU8, AtomicUsize, Ordering,
};
use core::sync::atomic::Ordering;
#[cfg(target_has_atomic = "8")]
use core::sync::atomic::{AtomicBool, AtomicI8, AtomicU8};
#[cfg(target_has_atomic = "16")]
use core::sync::atomic::{AtomicI16, AtomicU16};
#[cfg(target_has_atomic = "32")]
use core::sync::atomic::{AtomicI32, AtomicU32};
#[cfg(target_has_atomic = "64")]
use core::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(target_has_atomic = "ptr")]
use core::sync::atomic::{AtomicIsize, AtomicUsize};
use utils::the_same_with_comparer;
#[test]
fn test_atomic_commons() {
#[cfg(target_has_atomic = "8")]
the_same_with_comparer(AtomicBool::new(true), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "8")]
the_same_with_comparer(AtomicBool::new(false), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "8")]
the_same_with_comparer(AtomicU8::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "16")]
the_same_with_comparer(AtomicU16::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "32")]
the_same_with_comparer(AtomicU32::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "64")]
the_same_with_comparer(AtomicU64::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "ptr")]
the_same_with_comparer(AtomicUsize::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "8")]
the_same_with_comparer(AtomicI8::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "16")]
the_same_with_comparer(AtomicI16::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "32")]
the_same_with_comparer(AtomicI32::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "64")]
the_same_with_comparer(AtomicI64::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});
#[cfg(target_has_atomic = "ptr")]
the_same_with_comparer(AtomicIsize::new(0), |a, b| {
a.load(Ordering::SeqCst) == b.load(Ordering::SeqCst)
});

View File

@ -138,7 +138,7 @@ fn test_slice() {
assert_eq!(&buffer[..8], &[7, 1, 2, 3, 4, 5, 6, 7]);
let (output, len): (&[u8], usize) =
bincode::decode_from_slice(&mut buffer[..8], bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&buffer[..8], bincode::config::standard()).unwrap();
assert_eq!(input, output);
assert_eq!(len, 8);
}
@ -151,7 +151,7 @@ fn test_option_slice() {
assert_eq!(&buffer[..n], &[1, 7, 1, 2, 3, 4, 5, 6, 7]);
let (output, len): (Option<&[u8]>, usize) =
bincode::decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap();
assert_eq!(input, output);
assert_eq!(len, n);
@ -161,7 +161,7 @@ fn test_option_slice() {
assert_eq!(&buffer[..n], &[0]);
let (output, len): (Option<&[u8]>, usize) =
bincode::decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap();
assert_eq!(input, output);
assert_eq!(len, n);
}
@ -177,7 +177,7 @@ fn test_str() {
);
let (output, len): (&str, usize) =
bincode::decode_from_slice(&mut buffer[..12], bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&buffer[..12], bincode::config::standard()).unwrap();
assert_eq!(input, output);
assert_eq!(len, 12);
}
@ -193,7 +193,7 @@ fn test_option_str() {
);
let (output, len): (Option<&str>, usize) =
bincode::decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap();
assert_eq!(input, output);
assert_eq!(len, n);
@ -203,7 +203,7 @@ fn test_option_str() {
assert_eq!(&buffer[..n], &[0]);
let (output, len): (Option<&str>, usize) =
bincode::decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&buffer[..n], bincode::config::standard()).unwrap();
assert_eq!(input, output);
assert_eq!(len, n);
}
@ -219,7 +219,7 @@ fn test_array() {
);
let (output, len): ([u8; 10], usize) =
bincode::decode_from_slice(&mut buffer[..11], bincode::config::standard()).unwrap();
bincode::decode_from_slice(&buffer[..11], bincode::config::standard()).unwrap();
assert_eq!(input, output);
assert_eq!(len, 11);
@ -234,7 +234,7 @@ fn test_array() {
assert_eq!(&buffer[..9], &[1, 0, 0, 0, 0, 0, 0, 0, 1]);
let (output, len): (&[u8], usize) =
bincode::decode_from_slice(&mut buffer[..9], config).unwrap();
bincode::borrow_decode_from_slice(&buffer[..9], config).unwrap();
assert_eq!(input, output);
assert_eq!(len, 9);
}
@ -251,7 +251,7 @@ fn test_duration_out_of_range() {
.unwrap();
let result: Result<(std::time::Duration, usize), _> =
bincode::decode_from_slice(&mut input, bincode::config::standard());
bincode::decode_from_slice(&input, bincode::config::standard());
assert_eq!(
result.unwrap_err(),
@ -274,7 +274,7 @@ fn test_duration_wrapping() {
.unwrap();
let (result, _): (std::time::Duration, _) =
bincode::decode_from_slice(&mut input, bincode::config::standard()).unwrap();
bincode::decode_from_slice(&input, bincode::config::standard()).unwrap();
assert_eq!(result.as_secs(), u64::MAX);

View File

@ -20,12 +20,40 @@ fn test_encode() {
assert_eq!(bytes_written, 3);
assert_eq!(&slice[..bytes_written], &[10, 10, 20]);
}
#[derive(bincode::Decode, PartialEq, Debug, Eq)]
#[derive(PartialEq, Debug, Eq)]
pub struct Test2<T> {
a: T,
b: u32,
c: u32,
}
impl<T> ::bincode::Decode for Test2<T>
where
T: ::bincode::Decode,
{
fn decode<D: ::bincode::de::Decoder>(
decoder: &mut D,
) -> core::result::Result<Self, ::bincode::error::DecodeError> {
Ok(Self {
a: ::bincode::Decode::decode(decoder)?,
b: ::bincode::Decode::decode(decoder)?,
c: ::bincode::Decode::decode(decoder)?,
})
}
}
impl<'__de, T> ::bincode::BorrowDecode<'__de> for Test2<T>
where
T: ::bincode::BorrowDecode<'__de> + '__de,
{
fn borrow_decode<D: ::bincode::de::BorrowDecoder<'__de>>(
decoder: &mut D,
) -> core::result::Result<Self, ::bincode::error::DecodeError> {
Ok(Self {
a: ::bincode::BorrowDecode::borrow_decode(decoder)?,
b: ::bincode::BorrowDecode::borrow_decode(decoder)?,
c: ::bincode::BorrowDecode::borrow_decode(decoder)?,
})
}
}
#[test]
fn test_decode() {
@ -62,7 +90,7 @@ fn test_encode_decode_str() {
let len = bincode::encode_into_slice(&start, &mut slice, bincode::config::standard()).unwrap();
assert_eq!(len, 21);
let (end, len): (Test3, usize) =
bincode::decode_from_slice(&slice[..len], bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&slice[..len], bincode::config::standard()).unwrap();
assert_eq!(end, start);
assert_eq!(len, 21);
}
@ -83,9 +111,9 @@ fn test_encode_tuple() {
#[test]
fn test_decode_tuple() {
let start = TestTupleStruct(5, 10, 1024);
let mut slice = [5, 10, 251, 0, 4];
let slice = [5, 10, 251, 0, 4];
let (result, len): (TestTupleStruct, usize) =
bincode::decode_from_slice(&mut slice, bincode::config::standard()).unwrap();
bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap();
assert_eq!(result, start);
assert_eq!(len, 5);
}
@ -109,9 +137,9 @@ fn test_encode_enum_struct_variant() {
#[test]
fn test_decode_enum_struct_variant() {
let start = TestEnum::Bar { name: 5u32 };
let mut slice = [1, 5];
let slice = [1, 5];
let (result, len): (TestEnum, usize) =
bincode::decode_from_slice(&mut slice, bincode::config::standard()).unwrap();
bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap();
assert_eq!(result, start);
assert_eq!(len, 2);
}
@ -119,9 +147,9 @@ fn test_decode_enum_struct_variant() {
#[test]
fn test_decode_enum_unit_variant() {
let start = TestEnum::Foo;
let mut slice = [0];
let slice = [0];
let (result, len): (TestEnum, usize) =
bincode::decode_from_slice(&mut slice, bincode::config::standard()).unwrap();
bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap();
assert_eq!(result, start);
assert_eq!(len, 1);
}
@ -149,9 +177,9 @@ fn test_encode_enum_tuple_variant() {
#[test]
fn test_decode_enum_tuple_variant() {
let start = TestEnum::Baz(5, 10, 1024);
let mut slice = [2, 5, 10, 251, 0, 4];
let slice = [2, 5, 10, 251, 0, 4];
let (result, len): (TestEnum, usize) =
bincode::decode_from_slice(&mut slice, bincode::config::standard()).unwrap();
bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap();
assert_eq!(result, start);
assert_eq!(len, 6);
}
@ -176,9 +204,9 @@ fn test_encode_borrowed_enum_struct_variant() {
#[test]
fn test_decode_borrowed_enum_struct_variant() {
let start = TestEnum2::Bar { name: "foo" };
let mut slice = [1, 3, 102, 111, 111];
let slice = [1, 3, 102, 111, 111];
let (result, len): (TestEnum2, usize) =
bincode::decode_from_slice(&mut slice, bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&slice, bincode::config::standard()).unwrap();
assert_eq!(result, start);
assert_eq!(len, 5);
}
@ -186,9 +214,9 @@ fn test_decode_borrowed_enum_struct_variant() {
#[test]
fn test_decode_borrowed_enum_unit_variant() {
let start = TestEnum2::Foo;
let mut slice = [0];
let slice = [0];
let (result, len): (TestEnum2, usize) =
bincode::decode_from_slice(&mut slice, bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&slice, bincode::config::standard()).unwrap();
assert_eq!(result, start);
assert_eq!(len, 1);
}
@ -216,9 +244,9 @@ fn test_encode_borrowed_enum_tuple_variant() {
#[test]
fn test_decode_borrowed_enum_tuple_variant() {
let start = TestEnum2::Baz(5, 10, 1024);
let mut slice = [2, 5, 10, 251, 0, 4];
let slice = [2, 5, 10, 251, 0, 4];
let (result, len): (TestEnum2, usize) =
bincode::decode_from_slice(&mut slice, bincode::config::standard()).unwrap();
bincode::borrow_decode_from_slice(&slice, bincode::config::standard()).unwrap();
assert_eq!(result, start);
assert_eq!(len, 6);
}
@ -365,3 +393,45 @@ fn test_enum_with_generics_roundtrip() {
.0;
assert_eq!(start, decoded);
}
#[cfg(feature = "alloc")]
mod zoxide {
extern crate alloc;
use alloc::borrow::Cow;
use bincode::{Decode, Encode};
pub type Rank = f64;
pub type Epoch = u64;
#[derive(Encode, Decode)]
pub struct Dir<'a> {
pub path: Cow<'a, str>,
pub rank: Rank,
pub last_accessed: Epoch,
}
#[test]
fn test() {
let dirs = &[
Dir {
path: Cow::Borrowed("Foo"),
rank: 1.23,
last_accessed: 5,
},
Dir {
path: Cow::Owned(String::from("Bar")),
rank: 2.34,
last_accessed: 10,
},
];
let config = bincode::config::standard();
let slice = bincode::encode_to_vec(dirs, config).unwrap();
let decoded: Vec<Dir> = bincode::borrow_decode_from_slice(&slice, config).unwrap().0;
assert_eq!(decoded.len(), 2);
assert!(matches!(decoded[0].path, Cow::Borrowed("Foo")));
assert!(matches!(decoded[1].path, Cow::Borrowed("Bar")));
}
}

View File

@ -6,12 +6,14 @@ use bincode::{Decode, Encode};
use std::borrow::Cow;
use std::string::String;
#[derive(Encode, Decode, PartialEq, Debug)]
#[derive(Decode, Encode, PartialEq, Debug)]
#[bincode(borrow_decode_bounds = "&'__de U<'a, A>: ::bincode::de::BorrowDecode<'__de> + '__de")]
struct T<'a, A: Clone + Encode + Decode> {
t: Cow<'a, U<'a, A>>,
}
#[derive(Clone, Encode, Decode, PartialEq, Debug)]
#[derive(Clone, Decode, Encode, PartialEq, Debug)]
#[bincode(borrow_decode_bounds = "&'__de A: ::bincode::de::BorrowDecode<'__de> + '__de")]
struct U<'a, A: Clone + Encode + Decode> {
u: Cow<'a, A>,
}

View File

@ -66,7 +66,7 @@ impl MemCache {
let encoded = bincode::serde::encode_to_vec(&cache_data, config)?;
let cache_item = CacheItem::new(encoded, expire_seconds);
guard.insert(key.clone(), cache_item);
guard.insert(*key, cache_item);
Ok(())
}

View File

@ -178,7 +178,7 @@ mod derive {
assert_eq!(len, expected_len);
let slice = &slice[..len];
let (result, len): (T, usize) =
bincode::decode_from_slice(&slice, bincode::config::standard()).unwrap();
bincode::decode_from_slice(slice, bincode::config::standard()).unwrap();
assert_eq!(start, result);
assert_eq!(len, expected_len);

View File

@ -1,3 +1,4 @@
#![allow(clippy::blacklisted_name)]
#![cfg(feature = "std")]
mod utils;
@ -89,10 +90,10 @@ fn test_std_commons() {
0,
)));
the_same_with_comparer(Mutex::new("Hello world".to_string()), |a, b| {
&*a.lock().unwrap() == &*b.lock().unwrap()
*a.lock().unwrap() == *b.lock().unwrap()
});
the_same_with_comparer(RwLock::new("Hello world".to_string()), |a, b| {
&*a.read().unwrap() == &*b.read().unwrap()
*a.read().unwrap() == *b.read().unwrap()
});
let mut map = std::collections::HashMap::new();
@ -128,7 +129,7 @@ fn test_std_commons() {
let cstr = CStr::from_bytes_with_nul(b"Hello world\0").unwrap();
let len = bincode::encode_into_slice(cstr, &mut buffer, config).unwrap();
let (decoded, len): (CString, usize) =
bincode::decode_from_slice(&mut buffer[..len], config).unwrap();
bincode::decode_from_slice(&buffer[..len], config).unwrap();
assert_eq!(cstr, decoded.as_c_str());
assert_eq!(len, 12);
@ -136,17 +137,17 @@ fn test_std_commons() {
let path = Path::new("C:/Program Files/Foo");
let len = bincode::encode_into_slice(path, &mut buffer, config).unwrap();
let (decoded, len): (&Path, usize) =
bincode::decode_from_slice(&mut buffer[..len], config).unwrap();
bincode::borrow_decode_from_slice(&buffer[..len], config).unwrap();
assert_eq!(path, decoded);
assert_eq!(len, 21);
}
#[test]
fn test_system_time_out_of_range() {
let mut input = [0xfd, 0x90, 0x0c, 0xfd, 0xfd, 0x90, 0x0c, 0xfd, 0x90, 0x90];
let input = [0xfd, 0x90, 0x0c, 0xfd, 0xfd, 0x90, 0x0c, 0xfd, 0x90, 0x90];
let result: Result<(std::time::SystemTime, usize), _> =
bincode::decode_from_slice(&mut input, bincode::config::standard());
bincode::decode_from_slice(&input, bincode::config::standard());
assert_eq!(
result.unwrap_err(),

View File

@ -15,11 +15,10 @@ where
&buffer[..len],
core::any::type_name::<C>()
);
let (decoded, decoded_len): (V, usize) =
bincode::decode_from_slice(&mut buffer, config).unwrap();
let (decoded, decoded_len): (V, usize) = bincode::decode_from_slice(&buffer, config).unwrap();
assert!(
cmp(&element, &decoded),
cmp(element, &decoded),
"Comparison failed\nDecoded: {:?}\nExpected: {:?}\nBytes: {:?}",
decoded,
element,
@ -57,7 +56,7 @@ where
);
assert!(
cmp(&element, &decoded),
cmp(element, &decoded),
"Comparison failed\nDecoded: {:?}\nExpected: {:?}\nBytes: {:?}",
decoded,
element,