Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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);
}