Reverted 'static constraint on T in Vec<T> and [T; N] (#663)
This commit is contained in:
parent
0d7e7950cb
commit
70fefd6dcc
|
|
@ -8,7 +8,6 @@ use crate::{
|
||||||
impl_borrow_decode,
|
impl_borrow_decode,
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
any::TypeId,
|
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
num::{
|
num::{
|
||||||
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
|
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
|
||||||
|
|
@ -442,63 +441,65 @@ impl<'a, 'de: 'a> BorrowDecode<'de> for &'a str {
|
||||||
|
|
||||||
impl<T, const N: usize> Decode for [T; N]
|
impl<T, const N: usize> Decode for [T; N]
|
||||||
where
|
where
|
||||||
T: Decode + Sized + 'static,
|
T: Decode + Sized,
|
||||||
{
|
{
|
||||||
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
|
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
|
||||||
decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?;
|
decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?;
|
||||||
|
|
||||||
// Optimize for `[u8; N]`
|
// TODO: we can't limit `T: 'static` because that would break other things
|
||||||
if TypeId::of::<u8>() == TypeId::of::<T>() {
|
// but we want to have this optimization
|
||||||
let mut buf = [0u8; N];
|
// This will be another contendor for specialization implementation
|
||||||
decoder.reader().read(&mut buf)?;
|
// if TypeId::of::<u8>() == TypeId::of::<T>() {
|
||||||
let ptr = &mut buf as *mut _ as *mut [T; N];
|
// 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
|
// // Safety: we know that T is a u8, so it is perfectly safe to
|
||||||
// translate an array of u8 into an array of T
|
// // translate an array of u8 into an array of T
|
||||||
let res = unsafe { ptr.read() };
|
// let res = unsafe { ptr.read() };
|
||||||
Ok(res)
|
// Ok(res)
|
||||||
} else {
|
// }
|
||||||
let result = super::impl_core::collect_into_array(&mut (0..N).map(|_| {
|
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
|
// See the documentation on `unclaim_bytes_read` as to why we're doing this here
|
||||||
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
|
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
|
||||||
T::decode(decoder)
|
T::decode(decoder)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// result is only None if N does not match the values of `(0..N)`, which it always should
|
// result is only None if N does not match the values of `(0..N)`, which it always should
|
||||||
// So this unwrap should never occur
|
// So this unwrap should never occur
|
||||||
result.unwrap()
|
result.unwrap()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, T, const N: usize> BorrowDecode<'de> for [T; N]
|
impl<'de, T, const N: usize> BorrowDecode<'de> for [T; N]
|
||||||
where
|
where
|
||||||
T: BorrowDecode<'de> + Sized + 'static,
|
T: BorrowDecode<'de> + Sized,
|
||||||
{
|
{
|
||||||
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
|
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
|
||||||
decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?;
|
decoder.claim_bytes_read(core::mem::size_of::<[T; N]>())?;
|
||||||
|
|
||||||
// Optimize for `[u8; N]`
|
// TODO: we can't limit `T: 'static` because that would break other things
|
||||||
if TypeId::of::<u8>() == TypeId::of::<T>() {
|
// but we want to have this optimization
|
||||||
let mut buf = [0u8; N];
|
// This will be another contendor for specialization implementation
|
||||||
decoder.reader().read(&mut buf)?;
|
// if TypeId::of::<u8>() == TypeId::of::<T>() {
|
||||||
let ptr = &mut buf as *mut _ as *mut [T; N];
|
// 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
|
// // Safety: we know that T is a u8, so it is perfectly safe to
|
||||||
// translate an array of u8 into an array of T
|
// // translate an array of u8 into an array of T
|
||||||
let res = unsafe { ptr.read() };
|
// let res = unsafe { ptr.read() };
|
||||||
Ok(res)
|
// Ok(res)
|
||||||
} else {
|
// }
|
||||||
let result = super::impl_core::collect_into_array(&mut (0..N).map(|_| {
|
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
|
// See the documentation on `unclaim_bytes_read` as to why we're doing this here
|
||||||
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
|
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
|
||||||
T::borrow_decode(decoder)
|
T::borrow_decode(decoder)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// result is only None if N does not match the values of `(0..N)`, which it always should
|
// result is only None if N does not match the values of `(0..N)`, which it always should
|
||||||
// So this unwrap should never occur
|
// So this unwrap should never occur
|
||||||
result.unwrap()
|
result.unwrap()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
de::{read::Reader, BorrowDecoder, Decode, Decoder},
|
de::{BorrowDecoder, Decode, Decoder},
|
||||||
enc::{
|
enc::{
|
||||||
self,
|
self,
|
||||||
write::{SizeWriter, Writer},
|
write::{SizeWriter, Writer},
|
||||||
|
|
@ -278,20 +278,23 @@ where
|
||||||
|
|
||||||
impl<T> Decode for Vec<T>
|
impl<T> Decode for Vec<T>
|
||||||
where
|
where
|
||||||
T: Decode + 'static,
|
T: Decode,
|
||||||
{
|
{
|
||||||
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
|
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
|
||||||
let len = crate::de::decode_slice_len(decoder)?;
|
let len = crate::de::decode_slice_len(decoder)?;
|
||||||
|
|
||||||
if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
|
// TODO: we can't limit `T: 'static` because that would break other things
|
||||||
decoder.claim_container_read::<T>(len)?;
|
// but we want to have this optimization
|
||||||
// optimize for reading u8 vecs
|
// This will be another contendor for specialization implementation
|
||||||
let mut vec = Vec::new();
|
// if core::any::TypeId::of::<T>() == core::any::TypeId::of::<u8>() {
|
||||||
vec.resize(len, 0u8);
|
// decoder.claim_container_read::<T>(len)?;
|
||||||
decoder.reader().read(&mut vec)?;
|
// // optimize for reading u8 vecs
|
||||||
// Safety: Vec<T> is Vec<u8>
|
// let mut vec = Vec::new();
|
||||||
return Ok(unsafe { core::mem::transmute(vec) });
|
// 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)?;
|
decoder.claim_container_read::<T>(len)?;
|
||||||
|
|
||||||
let mut vec = Vec::with_capacity(len);
|
let mut vec = Vec::with_capacity(len);
|
||||||
|
|
|
||||||
21
tests/std.rs
21
tests/std.rs
|
|
@ -179,3 +179,24 @@ impl std::hash::Hasher for ExampleCustomHasher {
|
||||||
self.hash
|
self.hash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_borrow_str_in_array() {
|
||||||
|
let (strs, _): (Vec<&str>, usize) = bincode::borrow_decode_from_slice(
|
||||||
|
&[
|
||||||
|
3, 3, b'a', b'b', b'c', 3, b'd', b'e', b'f', 3, b'g', b'h', b'i',
|
||||||
|
],
|
||||||
|
bincode::config::standard(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(strs, vec!["abc", "def", "ghi"]);
|
||||||
|
|
||||||
|
let (strs, _): ([&str; 3], usize) = bincode::borrow_decode_from_slice(
|
||||||
|
&[
|
||||||
|
3, b'a', b'b', b'c', 3, b'd', b'e', b'f', 3, b'g', b'h', b'i',
|
||||||
|
],
|
||||||
|
bincode::config::standard(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(strs, ["abc", "def", "ghi"]);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue