Added support for Cell and RefCell

This commit is contained in:
Victor Koenders 2021-10-16 12:04:23 +02:00
parent 07f49e878e
commit 1d6379e715
4 changed files with 87 additions and 1 deletions

View File

@ -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<T>
where
T: Decodable,
{
fn decode<D: Decode>(decoder: D) -> Result<Self, DecodeError> {
let t = T::decode(decoder)?;
Ok(Cell::new(t))
}
}
impl<'de, T> Decodable for RefCell<T>
where
T: Decodable,
{
fn decode<D: Decode>(decoder: D) -> Result<Self, DecodeError> {
let t = T::decode(decoder)?;
Ok(RefCell::new(t))
}
}
impl<'a, 'de, T> Decode for &'a mut T
where
T: Decode,

View File

@ -1,3 +1,5 @@
use core::cell::{Cell, RefCell};
use super::{Encode, Encodeable};
use crate::error::EncodeError;
@ -169,6 +171,39 @@ where
}
}
impl<T> Encodeable for Cell<T>
where
T: Encodeable + Copy,
{
fn encode<E: Encode>(&self, encoder: E) -> Result<(), EncodeError> {
T::encode(&self.get(), encoder)
}
}
impl<T> Encodeable for RefCell<T>
where
T: Encodeable,
{
fn encode<E: 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::<RefCell<T>>(),
})?;
T::encode(&borrow_guard, encoder)
}
}
impl<'a, T> Encodeable for &'a T
where
T: Encodeable,
{
fn encode<E: Encode>(&self, encoder: E) -> Result<(), EncodeError> {
T::encode(self, encoder)
}
}
impl<'a, T> Encode for &'a mut T
where
T: Encode,

View File

@ -7,6 +7,14 @@ pub enum EncodeError {
/// The writer ran out of storage.
UnexpectedEnd,
/// The RefCell<T> 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 {

View File

@ -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::<u32>::None);
the_same(Option::<u32>::Some(1234));
the_same(Result::<u32, u8>::Ok(1555));
the_same(Result::<u32, u8>::Err(15));
the_same(Cell::<u32>::new(15));
the_same(RefCell::<u32>::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]