Mik*_*sov 6 reference traits rust
想象一下一些事件源,它产生表示为枚举的事件.当然,为了获得最佳效率,此生产者是零拷贝,即它返回对其内部缓冲区的引用:
enum Variant<'a> {
Nothing,
SomeInt(u64),
SomeBytes(&'a [u8])
}
impl Producer {
fn next(&'a mut self) -> Variant<'a> { ... }
}
Run Code Online (Sandbox Code Playgroud)
这对于不需要前瞻或回溯的消费者来说非常好,但有时需要保存一些事件序列.因此,我们的Variant类型变为通用:
enum Variant<BytesT> {
Nothing,
SomeInt(u64),
SomeBytes(BytesT)
}
type OwnedVariant = Variant<Vec<u8>>;
type BorrowedVariant<'a> = Variant<&'a [u8]>;
Run Code Online (Sandbox Code Playgroud)
在这里,我们最终得到两种具有"所有者 - 参考"关系的类型,它类似于对Vec<T>- &[T],String- &str.文档建议内置特征Borrow,ToOwned除了微妙的细微差别外,它提供了所需的内容:
trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
// this: -----------^
}
pub trait ToOwned {
type Owned: Borrow<Self>;
fn to_owned(&self) -> Self::Owned;
}
Run Code Online (Sandbox Code Playgroud)
结果borrow必须是对某事物的参考,这BorrowedVariant<'a>显然不是.删除此要求可以解决此问题(此处,名称以alt为前缀,以强调这是一个替代接口):
trait AltBorrow<'a, AltBorrowed> {
fn alt_borrow(&'a self) -> AltBorrowed;
}
trait AltToOwned<'a> {
type AltOwned: AltBorrow<'a, Self>;
fn alt_to_owned(&'a self) -> Self::AltOwned;
}
Run Code Online (Sandbox Code Playgroud)
然后可以针对标准类型实现此特征,例如Vec:
impl<'a, T> AltBorrow<'a, &'a [T]> for Vec<T> {
fn alt_borrow(&'a self) -> &'a [T] {
self.as_slice()
}
}
impl<'a, T> AltToOwned<'a> for &'a [T]
where T: Clone
{
type AltOwned = Vec<T>;
fn alt_to_owned(&'a self) -> Vec<T> {
self.to_vec()
}
}
Run Code Online (Sandbox Code Playgroud)
以及有Variant问题的枚举:
impl<'a> AltBorrow<'a, BorrowedVariant<'a>> for OwnedVariant {
fn alt_borrow(&'a self) -> BorrowedVariant<'a> {
match self {
&Variant::Nothing => Variant::Nothing,
&Variant::SomeInt(value) => Variant::SomeInt(value),
&Variant::SomeBytes(ref value) => Variant::SomeBytes(value.alt_borrow()),
}
}
}
impl<'a> AltToOwned<'a> for BorrowedVariant<'a> {
type AltOwned = OwnedVariant;
fn alt_to_owned(&'a self) -> OwnedVariant {
match self {
&Variant::Nothing => Variant::Nothing,
&Variant::SomeInt(value) => Variant::SomeInt(value),
&Variant::SomeBytes(value) => Variant::SomeBytes(value.alt_to_owned()),
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后,问题:
Borrow/ ToOwned概念?我应该用别的东西来实现这个目标吗?std::borrow可能是首选的原因是什么?