Created
July 20, 2020 02:20
-
-
Save webern/3003f10e64564577dc1d83483b49f342 to your computer and use it in GitHub Desktop.
Generalizing a Struct that holds a Cow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![forbid(missing_debug_implementations, missing_copy_implementations)] | |
#![deny(rust_2018_idioms)] | |
#![deny(clippy::pedantic)] | |
#![allow(dead_code)] | |
use std::borrow::Cow; | |
use std::fmt::Debug; | |
/// A custom type. Clone is required by `Cow`. `Debug` is required by our example so that we can | |
/// easily print our results. `Copy` is added for completeness since `MyType` has no allocations. | |
#[derive(Debug, Clone, Copy)] | |
pub struct MyType { | |
pub myval: u64, | |
} | |
/// In order for this to work, we need `MyType` to easily convert into an owned `Cow`. | |
impl<'a> Into<Cow<'a, MyType>> for MyType { | |
fn into(self) -> Cow<'a, MyType> { | |
Cow::Owned(self) | |
} | |
} | |
/// In order for this to work, we need `&MyType` to easily convert into a borrowed `Cow`. | |
impl<'a> Into<Cow<'a, MyType>> for &'a MyType { | |
fn into(self) -> Cow<'a, MyType> { | |
Cow::Borrowed(self) | |
} | |
} | |
/// A struct that lets the user decide whether the struct should take ownership of `T` data or hold | |
/// a reference. | |
struct YouDecide<'a, T: Debug + Clone> { | |
s: Cow<'a, T>, | |
} | |
impl<'a, T: Debug + Clone> YouDecide<'a, T> { | |
/// Create a new struct from any type `U`, where U can be converted into `Cow<T>`. That is, we | |
/// allow the user to pass in either a reference or a moved/owned object, and the struct will | |
/// hold either the reference or the ownership. | |
fn new<U>(value: U) -> Self | |
where | |
U: Into<Cow<'a, T>>, | |
{ | |
Self { s: value.into() } | |
} | |
/// Return a reference to the underlying data. | |
fn value(&self) -> &T { | |
self.s.as_ref() | |
} | |
} | |
fn main() { | |
// create some objects and references of a custom type. | |
let x = MyType { myval: 1 }; | |
let y = &x; | |
let z = MyType { myval: 2 }; | |
// create some YouDecide objects from the above objects and references. | |
let a = YouDecide::new(x); | |
let b = YouDecide::new(y); | |
let c = YouDecide::new(z); | |
// print the values held by the YouDecide objects | |
println!("{:?}", a.value()); | |
println!("{:?}", b.value()); | |
println!("{:?}", c.value()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment