From 9cf577d9bcebc36e64660580c4b13a986f21b279 Mon Sep 17 00:00:00 2001 From: Victor Koenders Date: Sat, 16 Oct 2021 13:19:30 +0200 Subject: [PATCH] Added support for String, Mutex and RwLock --- src/error.rs | 7 ++++++ src/features/impl_alloc.rs | 15 +++++++++++- src/features/impl_std.rs | 49 +++++++++++++++++++++++++++++++++++++- tests/alloc.rs | 1 + tests/std.rs | 16 +++++++++++-- 5 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/error.rs b/src/error.rs index 5884c1b..e466120 100644 --- a/src/error.rs +++ b/src/error.rs @@ -23,6 +23,13 @@ pub enum EncodeError { /// The amount of bytes that were written before the error occured index: usize, }, + + /// The encoder tried to encode a `Mutex` or `RwLock`, but the locking failed + #[cfg(feature = "std")] + LockFailed { + /// The type name of the mutex for debugging purposes + type_name: &'static str, + }, } /// Errors that can be encounted by decoding a type diff --git a/src/features/impl_alloc.rs b/src/features/impl_alloc.rs index 30e707a..4132a2f 100644 --- a/src/features/impl_alloc.rs +++ b/src/features/impl_alloc.rs @@ -5,7 +5,7 @@ use crate::{ error::{DecodeError, EncodeError}, Config, }; -use alloc::{borrow::Cow, boxed::Box, collections::*, rc::Rc, sync::Arc, vec::Vec}; +use alloc::{borrow::Cow, boxed::Box, collections::*, rc::Rc, string::String, sync::Arc, vec::Vec}; #[derive(Default)] struct VecWriter { @@ -178,6 +178,19 @@ where } } +impl Decodable for String { + fn decode(decoder: D) -> Result { + let bytes = Vec::::decode(decoder)?; + String::from_utf8(bytes).map_err(|e| DecodeError::Utf8(e.utf8_error())) + } +} + +impl Encodeable for String { + fn encode(&self, encoder: E) -> Result<(), EncodeError> { + self.as_bytes().encode(encoder) + } +} + impl Decodable for Box where T: Decodable, diff --git a/src/features/impl_std.rs b/src/features/impl_std.rs index 4099208..cd9bff4 100644 --- a/src/features/impl_std.rs +++ b/src/features/impl_std.rs @@ -4,7 +4,10 @@ use crate::{ enc::{write::Writer, Encode, Encodeable, Encoder}, error::{DecodeError, EncodeError}, }; -use std::ffi::{CStr, CString}; +use std::{ + ffi::{CStr, CString}, + sync::{Mutex, RwLock}, +}; /// Decode type `D` from the given reader. The reader can be any type that implements `std::io::Read`, e.g. `std::fs::File`. pub fn decode_from(src: &mut R) -> Result { @@ -105,3 +108,47 @@ impl Decodable for CString { Ok(cstr.into()) } } + +impl Encodeable for Mutex +where + T: Encodeable, +{ + fn encode(&self, encoder: E) -> Result<(), EncodeError> { + let t = self.lock().map_err(|_| EncodeError::LockFailed { + type_name: core::any::type_name::>(), + })?; + t.encode(encoder) + } +} + +impl Decodable for Mutex +where + T: Decodable, +{ + fn decode(decoder: D) -> Result { + let t = T::decode(decoder)?; + Ok(Mutex::new(t)) + } +} + +impl Encodeable for RwLock +where + T: Encodeable, +{ + fn encode(&self, encoder: E) -> Result<(), EncodeError> { + let t = self.read().map_err(|_| EncodeError::LockFailed { + type_name: core::any::type_name::>(), + })?; + t.encode(encoder) + } +} + +impl Decodable for RwLock +where + T: Decodable, +{ + fn decode(decoder: D) -> Result { + let t = T::decode(decoder)?; + Ok(RwLock::new(t)) + } +} diff --git a/tests/alloc.rs b/tests/alloc.rs index f096b5f..211284a 100644 --- a/tests/alloc.rs +++ b/tests/alloc.rs @@ -48,6 +48,7 @@ fn test_vec() { #[test] fn test_alloc_commons() { the_same::>(vec![1, 2, 3, 4, 5]); + the_same(String::from("Hello world")); the_same(Box::::new(5)); the_same(Box::<[u32]>::from(vec![1, 2, 3, 4, 5])); the_same(Cow::::Owned(5)); diff --git a/tests/std.rs b/tests/std.rs index d9365a2..7646a4a 100644 --- a/tests/std.rs +++ b/tests/std.rs @@ -2,6 +2,8 @@ mod utils; +use std::sync::{Mutex, RwLock}; + use utils::the_same; struct Foo { @@ -60,10 +62,20 @@ fn test_std_commons() { the_same(CString::new("Hello world").unwrap()); let config = bincode::config::Default; - let cstr = CStr::from_bytes_with_nul(b"Hello world\0").unwrap(); let mut buffer = [0u8; 1024]; + + let cstr = CStr::from_bytes_with_nul(b"Hello world\0").unwrap(); let len = bincode::encode_into_slice_with_config(cstr, &mut buffer, config).unwrap(); let decoded: &CStr = bincode::decode_with_config(&mut buffer[..len], config).unwrap(); - assert_eq!(cstr, decoded); + + let mutex = Mutex::new("Hello world".to_string()); + let len = bincode::encode_into_slice_with_config(&mutex, &mut buffer, config).unwrap(); + let decoded: Mutex = bincode::decode_with_config(&mut buffer[..len], config).unwrap(); + assert_eq!(&*mutex.lock().unwrap(), &*decoded.lock().unwrap()); + + let rwlock = RwLock::new("Hello world".to_string()); + let len = bincode::encode_into_slice_with_config(&mutex, &mut buffer, config).unwrap(); + let decoded: RwLock = bincode::decode_with_config(&mut buffer[..len], config).unwrap(); + assert_eq!(&*rwlock.read().unwrap(), &*decoded.read().unwrap()); }