diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 0ed555e392fa1..03d9445b9b94b 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -17,6 +17,7 @@ Core encoding and decoding interfaces. use std::path; use std::rc::Rc; use std::gc::{Gc, GC}; +use std::cell::{Cell, RefCell}; pub trait Encoder { // Primitive types: @@ -536,6 +537,35 @@ impl> Decodable for path::windows::Path { } } +impl, T: Encodable + Copy> Encodable for Cell { + fn encode(&self, s: &mut S) -> Result<(), E> { + self.get().encode(s) + } +} + +impl, T: Decodable + Copy> Decodable for Cell { + fn decode(d: &mut D) -> Result, E> { + Ok(Cell::new(try!(Decodable::decode(d)))) + } +} + +// FIXME: #15036 +// Should use `try_borrow`, returning a +// `encoder.error("attempting to Encode borrowed RefCell")` +// from `encode` when `try_borrow` returns `None`. + +impl, T: Encodable> Encodable for RefCell { + fn encode(&self, s: &mut S) -> Result<(), E> { + self.borrow().encode(s) + } +} + +impl, T: Decodable> Decodable for RefCell { + fn decode(d: &mut D) -> Result, E> { + Ok(RefCell::new(try!(Decodable::decode(d)))) + } +} + // ___________________________________________________________________________ // Helper routines // diff --git a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs new file mode 100644 index 0000000000000..a7738bb803cf5 --- /dev/null +++ b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs @@ -0,0 +1,55 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This briefuly tests the capability of `Cell` and `RefCell` to implement the +// `Encodable` and `Decodable` traits via `#[deriving(Encodable, Decodable)]` + +extern crate serialize; + +use std::cell::{Cell, RefCell}; +use std::io::MemWriter; +use serialize::{Encodable, Decodable}; +use serialize::ebml; +use serialize::ebml::writer::Encoder; +use serialize::ebml::reader::Decoder; + +#[deriving(Encodable, Decodable)] +struct A { + baz: int +} + +#[deriving(Encodable, Decodable)] +struct B { + foo: Cell, + bar: RefCell, +} + +fn main() { + let obj = B { + foo: Cell::new(true), + bar: RefCell::new( A { baz: 2 } ) + }; + let mut w = MemWriter::new(); + { + let mut e = Encoder::new(&mut w); + match obj.encode(&mut e) { + Ok(()) => (), + Err(e) => fail!("Failed to encode: {}", e) + }; + } + let doc = ebml::Doc::new(w.get_ref()); + let mut dec = Decoder::new(doc); + let obj2: B = match Decodable::decode(&mut dec) { + Ok(v) => v, + Err(e) => fail!("Failed to decode: {}", e) + }; + assert!(obj.foo.get() == obj2.foo.get()); + assert!(obj.bar.borrow().baz == obj2.bar.borrow().baz); +}