T包装借来的数据时如何实现Borrow<T>?

How to implement Borrow<T> when T wraps borrowed data?

给出以下来自 的定义:

#[derive(Serialize)]
struct SerializeThing<'a> {
    small_header: (u64, u64, u64),
    big_body: &'a str,
}

#[derive(Deserialize)]
struct DeserializeThing {
    small_header: (u64, u64, u64),
    big_body: String,
}

我如何实现 Borrow 特征以便将拥有的数据自然地存储在(例如)HashMap 中并通过它们或它们借来的对应物查询它们?最接近的可能如下:

impl DeserializeThing {
    fn as_serialize(&self) -> SerializeThing<'_> {
        let DeserializeThing { small_header, big_body } = self;
        let small_header = *small_header;
        let big_body = big_body.as_str();
        SerializeThing { small_header, big_body }
    }
}

这还不够。

你不能。

Borrow::borrow 必须 return 一个引用,并且您无法从对 DeserializeThing 的引用中获取对 SerializeThing 的引用,因为这些类型是根本不兼容 ABI。


如果性能很重要并且您不能为 DeserializeThing instances/allocation 字符串的构造付费,那么您可以使用 hashbrown::HashMap 而不是 std::collections::HashMap

hashbrown 是标准库用于其自身 HashMap 实现的库,但它有一些更有用的方法。

现在对您有用的一个是 raw entry API (and mutable raw entry)。

特别是,它允许您从其哈希和匹配函数中获取映射条目:

pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a > V)> where
   F: FnMut(&K) -> bool

Access an entry by hash.

由于您可以为 DeserializeThingSerializeThing 实现 Hash 以获得相同值的相同哈希值,因此 API 在你的情况。