Skip to content

Instantly share code, notes, and snippets.

@aturon
Last active August 29, 2015 14:01
Show Gist options
  • Save aturon/4634b4b9215f0d50acf3 to your computer and use it in GitHub Desktop.
Save aturon/4634b4b9215f0d50acf3 to your computer and use it in GitHub Desktop.
Copy-on-write smart pointer
// A copy-on-write smart pointer
// See also http://stlab.adobe.com/classadobe_1_1version__1_1_1copy__on__write.html
enum CowCell<'a, T> {
Shared(&'a T),
Owned(T)
}
pub struct Cow<'a, T> {
cell: CowCell<'a, T>
}
impl<'a, T: Clone> Cow<'a, T> {
pub fn new<'a>(x: &'a T) -> Cow<'a, T> {
Cow { cell: Shared(x) }
}
// note: return type has ANY lifetime
pub fn from_owned<'b>(x: T) -> Cow<'b, T> {
Cow { cell: Owned(x) }
}
pub fn to_mut<'b>(&'b mut self) -> &'b mut T {
match self.cell {
Shared(x) => {
self.cell = Owned(x.clone());
self.to_mut()
},
Owned(ref mut x) => x
}
}
}
impl<'a, T> Deref<T> for Cow<'a, T> {
fn deref<'a>(&'a self) -> &'a T {
match self.cell {
Shared(x) => x,
Owned(ref x) => x
}
}
}
/*
impl<'a, T: Clone> DerefMut<T> for Cow<'a, T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
self.to_mut()
}
}
*/
fn main() {
let mut v = vec!(1,2,3,4);
{
let cv = Cow::new(&v);
// v.push(1); // not allowed here
cv;
}
v.push(1); // fine here
let mut cv1 = Cow::new(&v);
let cv2 = Cow::new(&v);
println!("{}", cv1.as_slice()); // Note: using Vec method here
cv1.to_mut().push(5);
cv1.to_mut().push(6);
println!("{}", cv1.as_slice());
println!("{}", cv2.as_slice());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment