From 1d6379e7158961a65592508086dee1a0e192b009 Mon Sep 17 00:00:00 2001 From: Victor Koenders Date: Sat, 16 Oct 2021 12:04:23 +0200 Subject: [PATCH] Added support for Cell and RefCell --- src/de/impls.rs | 22 ++++++++++++++++++++++ src/enc/impls.rs | 35 +++++++++++++++++++++++++++++++++++ src/error.rs | 8 ++++++++ tests/basic_types.rs | 23 ++++++++++++++++++++++- 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/de/impls.rs b/src/de/impls.rs index b5b0933..fc6170d 100644 --- a/src/de/impls.rs +++ b/src/de/impls.rs @@ -1,3 +1,5 @@ +use core::cell::{Cell, RefCell}; + use super::{BorrowDecodable, BorrowDecode, Decodable, Decode}; use crate::error::DecodeError; @@ -175,6 +177,26 @@ where } } +impl<'de, T> Decodable for Cell +where + T: Decodable, +{ + fn decode(decoder: D) -> Result { + let t = T::decode(decoder)?; + Ok(Cell::new(t)) + } +} + +impl<'de, T> Decodable for RefCell +where + T: Decodable, +{ + fn decode(decoder: D) -> Result { + let t = T::decode(decoder)?; + Ok(RefCell::new(t)) + } +} + impl<'a, 'de, T> Decode for &'a mut T where T: Decode, diff --git a/src/enc/impls.rs b/src/enc/impls.rs index 7a05569..912f101 100644 --- a/src/enc/impls.rs +++ b/src/enc/impls.rs @@ -1,3 +1,5 @@ +use core::cell::{Cell, RefCell}; + use super::{Encode, Encodeable}; use crate::error::EncodeError; @@ -169,6 +171,39 @@ where } } +impl Encodeable for Cell +where + T: Encodeable + Copy, +{ + fn encode(&self, encoder: E) -> Result<(), EncodeError> { + T::encode(&self.get(), encoder) + } +} + +impl Encodeable for RefCell +where + T: Encodeable, +{ + fn encode(&self, encoder: E) -> Result<(), EncodeError> { + let borrow_guard = self + .try_borrow() + .map_err(|e| EncodeError::RefCellAlreadyBorrowed { + inner: e, + type_name: core::any::type_name::>(), + })?; + T::encode(&borrow_guard, encoder) + } +} + +impl<'a, T> Encodeable for &'a T +where + T: Encodeable, +{ + fn encode(&self, encoder: E) -> Result<(), EncodeError> { + T::encode(self, encoder) + } +} + impl<'a, T> Encode for &'a mut T where T: Encode, diff --git a/src/error.rs b/src/error.rs index e687cac..e3e7969 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,6 +7,14 @@ pub enum EncodeError { /// The writer ran out of storage. UnexpectedEnd, + /// The RefCell is already borrowed + RefCellAlreadyBorrowed { + /// The inner borrow error + inner: core::cell::BorrowError, + /// the type name of the RefCell being encoded that is currently borrowed. + type_name: &'static str, + }, + /// The targetted writer encountered an `std::io::Error` #[cfg(feature = "std")] Io { diff --git a/tests/basic_types.rs b/tests/basic_types.rs index 8e7781f..87adb15 100644 --- a/tests/basic_types.rs +++ b/tests/basic_types.rs @@ -1,5 +1,7 @@ mod utils; +use core::cell::Cell; +use std::cell::RefCell; use utils::the_same; #[test] @@ -63,12 +65,31 @@ fn test_numbers() { 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 ]); - // Option and Result + // Common types the_same(Option::::None); the_same(Option::::Some(1234)); the_same(Result::::Ok(1555)); the_same(Result::::Err(15)); + + the_same(Cell::::new(15)); + the_same(RefCell::::new(15)); +} + +#[test] +fn test_refcell_already_borrowed() { + let cell = RefCell::new(5u32); + // first get a mutable reference to the cell + let _mutable_guard = cell.borrow_mut(); + // now try to encode it + let mut slice = [0u8; 10]; + let result = bincode::encode_into_slice(&cell, &mut slice) + .expect_err("Encoding a borrowed refcell should fail"); + + match result { + bincode::error::EncodeError::RefCellAlreadyBorrowed { .. } => {} // ok + x => panic!("Expected a RefCellAlreadyBorrowed error, found {:?}", x), + } } #[test]