Added support for atomic integers

This commit is contained in:
Victor Koenders 2021-10-16 14:49:18 +02:00
parent 8ab730eb87
commit 1f261cede3
7 changed files with 253 additions and 28 deletions

View File

@ -23,9 +23,10 @@ description = "A binary serialization / deserialization strategy for transformin
edition = "2018"
[features]
default = ["std", "derive"]
default = ["std", "derive", "atomic"]
std = ["alloc"]
alloc = []
atomic = []
derive = ["bincode_derive"]
[dependencies]

137
src/features/atomic.rs Normal file
View File

@ -0,0 +1,137 @@
use crate::{de::Decodable, enc::Encodeable};
use core::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
AtomicU64, AtomicU8, AtomicUsize, Ordering,
};
impl Encodeable for AtomicBool {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicBool {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicBool::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicU8 {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicU8 {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicU8::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicU16 {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicU16 {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicU16::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicU32 {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicU32 {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicU32::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicU64 {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicU64 {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicU64::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicUsize {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicUsize {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicUsize::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicI8 {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicI8 {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicI8::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicI16 {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicI16 {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicI16::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicI32 {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicI32 {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicI32::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicI64 {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicI64 {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicI64::new(Decodable::decode(decoder)?))
}
}
impl Encodeable for AtomicIsize {
fn encode<E: crate::enc::Encode>(&self, encoder: E) -> Result<(), crate::error::EncodeError> {
self.load(Ordering::SeqCst).encode(encoder)
}
}
impl Decodable for AtomicIsize {
fn decode<D: crate::de::Decode>(decoder: D) -> Result<Self, crate::error::DecodeError> {
Ok(AtomicIsize::new(Decodable::decode(decoder)?))
}
}

View File

@ -1,3 +1,8 @@
#[cfg(feature = "atomic")]
mod atomic;
#[cfg(feature = "atomic")]
pub use self::atomic::*;
#[cfg(feature = "alloc")]
mod impl_alloc;
#[cfg(feature = "alloc")]

View File

@ -8,7 +8,7 @@ use alloc::borrow::Cow;
use alloc::collections::*;
use alloc::rc::Rc;
use alloc::sync::Arc;
use utils::the_same;
use utils::{the_same, the_same_with_comparer};
struct Foo {
pub a: u32,
@ -55,6 +55,18 @@ fn test_alloc_commons() {
the_same(Cow::<u32>::Borrowed(&5));
the_same(Rc::<u32>::new(5));
the_same(Arc::<u32>::new(5));
the_same_with_comparer(
{
let mut map = BinaryHeap::<u32>::new();
map.push(1);
map.push(2);
map.push(3);
map.push(4);
map.push(5);
map
},
|a, b| a.into_iter().collect::<Vec<_>>() == b.into_iter().collect::<Vec<_>>(),
);
the_same({
let mut map = BTreeMap::<u32, i32>::new();
map.insert(5, -5);

49
tests/atomic.rs Normal file
View File

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

View File

@ -11,6 +11,8 @@ use std::{
};
use utils::the_same;
use crate::utils::the_same_with_comparer;
struct Foo {
pub a: u32,
pub b: u32,
@ -79,7 +81,14 @@ fn test_std_commons() {
0,
0,
)));
the_same_with_comparer(Mutex::new("Hello world".to_string()), |a, b| {
&*a.lock().unwrap() == &*b.lock().unwrap()
});
the_same_with_comparer(RwLock::new("Hello world".to_string()), |a, b| {
&*a.read().unwrap() == &*b.read().unwrap()
});
// Borrowed values
let config = bincode::config::Default;
let mut buffer = [0u8; 1024];
@ -89,18 +98,6 @@ fn test_std_commons() {
let decoded: &CStr = bincode::decode_with_config(&mut buffer[..len], config).unwrap();
assert_eq!(cstr, decoded);
// Mutex<T>
let mutex = Mutex::new("Hello world".to_string());
let len = bincode::encode_into_slice_with_config(&mutex, &mut buffer, config).unwrap();
let decoded: Mutex<String> = bincode::decode_with_config(&mut buffer[..len], config).unwrap();
assert_eq!(&*mutex.lock().unwrap(), &*decoded.lock().unwrap());
// RwLock<T>
let rwlock = RwLock::new("Hello world".to_string());
let len = bincode::encode_into_slice_with_config(&rwlock, &mut buffer, config).unwrap();
let decoded: RwLock<String> = bincode::decode_with_config(&mut buffer[..len], config).unwrap();
assert_eq!(&*rwlock.read().unwrap(), &*decoded.read().unwrap());
// Path
let path = Path::new("C:/Program Files/Foo");
let len = bincode::encode_into_slice_with_config(path, &mut buffer, config).unwrap();

View File

@ -1,13 +1,14 @@
use bincode::config::{self, Config};
use core::fmt::Debug;
fn the_same_with_config<V, C>(element: V, config: C)
fn the_same_with_config<V, C, CMP>(element: &V, config: C, cmp: CMP)
where
V: bincode::enc::Encodeable + bincode::de::Decodable + PartialEq + Debug + Clone + 'static,
V: bincode::enc::Encodeable + bincode::de::Decodable + Debug + 'static,
C: Config,
CMP: Fn(&V, &V) -> bool,
{
let mut buffer = [0u8; 1024];
let len = bincode::encode_into_slice_with_config(element.clone(), &mut buffer, config).unwrap();
let len = bincode::encode_into_slice_with_config(&element, &mut buffer, config).unwrap();
println!(
"{:?}: {:?} ({:?})",
element,
@ -16,68 +17,91 @@ where
);
let decoded: V = bincode::decode_with_config(&mut buffer, config).unwrap();
assert_eq!(element, decoded);
assert!(
cmp(&element, &decoded),
"Comparison failed\nDecoded: {:?}\nExpected: {:?}\nBytes: {:?}",
decoded,
element,
&buffer[..len],
);
}
pub fn the_same<V>(element: V)
pub fn the_same_with_comparer<V, CMP>(element: V, cmp: CMP)
where
V: bincode::enc::Encodeable + bincode::de::Decodable + PartialEq + Debug + Clone + 'static,
V: bincode::enc::Encodeable + bincode::de::Decodable + Debug + 'static,
CMP: Fn(&V, &V) -> bool,
{
// A matrix of each different config option possible
the_same_with_config(
element.clone(),
&element,
config::Default
.with_little_endian()
.with_fixed_int_encoding()
.skip_fixed_array_length(),
&cmp,
);
the_same_with_config(
element.clone(),
&element,
config::Default
.with_big_endian()
.with_fixed_int_encoding()
.skip_fixed_array_length(),
&cmp,
);
the_same_with_config(
element.clone(),
&element,
config::Default
.with_little_endian()
.with_variable_int_encoding()
.skip_fixed_array_length(),
&cmp,
);
the_same_with_config(
element.clone(),
&element,
config::Default
.with_big_endian()
.with_variable_int_encoding()
.skip_fixed_array_length(),
&cmp,
);
the_same_with_config(
element.clone(),
&element,
config::Default
.with_little_endian()
.with_fixed_int_encoding()
.write_fixed_array_length(),
&cmp,
);
the_same_with_config(
element.clone(),
&element,
config::Default
.with_big_endian()
.with_fixed_int_encoding()
.write_fixed_array_length(),
&cmp,
);
the_same_with_config(
element.clone(),
&element,
config::Default
.with_little_endian()
.with_variable_int_encoding()
.write_fixed_array_length(),
&cmp,
);
the_same_with_config(
element,
&element,
config::Default
.with_big_endian()
.with_variable_int_encoding()
.write_fixed_array_length(),
&cmp,
);
}
#[allow(dead_code)] // This is not used in every test
pub fn the_same<V>(element: V)
where
V: bincode::enc::Encodeable + bincode::de::Decodable + PartialEq + Debug + 'static,
{
the_same_with_comparer(element, |a, b| a == b);
}