Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Bincode 2 support #297

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -26,6 +26,7 @@ debugger_visualizer = []
[dependencies]
serde = { version = "1", optional = true, default-features = false }
arbitrary = { version = "1", optional = true }
bincode2 = { package = "bincode", version = "2.0.0-rc", optional = true, default-features = false }

[dev_dependencies]
bincode = "1.0.1"
Expand Down
70 changes: 70 additions & 0 deletions src/lib.rs
Expand Up @@ -21,6 +21,11 @@
//! When this optional dependency is enabled, `SmallVec` implements the `serde::Serialize` and
//! `serde::Deserialize` traits.
//!
//! ### `bincode2`
//!
//! When this optional dependency is enabled, `SmallVec` implements the `bincode::Encode`,
//! `bincode::Decode` and `bincode::BorrowDecode` traits from Bincode 2.
//!
//! ### `write`
//!
//! When this feature is enabled, `SmallVec<[u8; _]>` implements the `std::io::Write` trait.
Expand Down Expand Up @@ -119,6 +124,14 @@ use serde::{
ser::{Serialize, SerializeSeq, Serializer},
};

#[cfg(feature = "bincode2")]
use bincode2::{
de::{BorrowDecoder, Decode, Decoder},
enc::{Encode, Encoder},
error::{DecodeError, EncodeError},
BorrowDecode,
};

#[cfg(feature = "serde")]
use core::marker::PhantomData;

Expand Down Expand Up @@ -1670,6 +1683,63 @@ where
}
}

#[cfg(feature = "bincode2")]
impl<A> Decode for SmallVec<A>
where
A: Array,
A::Item: Decode,
{
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = usize::decode(decoder)?;
decoder.claim_container_read::<A::Item>(len)?;

let mut vec = SmallVec::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::<A::Item>());

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

#[cfg(feature = "bincode2")]
impl<'de, A> BorrowDecode<'de> for SmallVec<A>
where
A: Array,
A::Item: BorrowDecode<'de>,
{
fn borrow_decode<D: BorrowDecoder<'de>>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = usize::decode(decoder)?;
decoder.claim_container_read::<A::Item>(len)?;

let mut vec = SmallVec::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::<A::Item>());

vec.push(A::Item::borrow_decode(decoder)?);
}
Ok(vec)
}
}

#[cfg(feature = "bincode2")]
impl<A> Encode for SmallVec<A>
where
A: Array,
A::Item: Encode,
{
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
self.len().encode(encoder)?;
for item in self.iter() {
item.encode(encoder)?;
}
Ok(())
}
}

#[cfg(feature = "specialization")]
trait SpecFrom<A: Array, S> {
fn spec_from(slice: S) -> SmallVec<A>;
Expand Down
24 changes: 24 additions & 0 deletions src/tests.rs
Expand Up @@ -983,3 +983,27 @@ fn test_clone_from() {
b.clone_from(&c);
assert_eq!(&*b, &[20, 21, 22]);
}

#[cfg(feature = "bincode2")]
#[test]
fn test_bincode2() {
let config = bincode2::config::standard();
let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new();
let mut buffer = [0u8; 128];
small_vec.push(1);
let bytes_written = bincode2::encode_into_slice(&small_vec, &mut buffer, config).unwrap();
let (decoded, bytes_read) =
bincode2::decode_from_slice::<SmallVec<[i32; 2]>, _>(&buffer, config).unwrap();
assert_eq!(bytes_written, bytes_read);
assert_eq!(small_vec, decoded);
small_vec.push(2);
// Spill the vec
small_vec.push(3);
small_vec.push(4);
// Check again after spilling.
let bytes_written = bincode2::encode_into_slice(&small_vec, &mut buffer, config).unwrap();
let (decoded, bytes_read) =
bincode2::decode_from_slice::<SmallVec<[i32; 2]>, _>(&buffer, config).unwrap();
assert_eq!(bytes_written, bytes_read);
assert_eq!(small_vec, decoded);
}