我正在研究这段代码,这是一个非常简单的库,只有一个文件,大部分是测试,所以它很短。我正在努力理解一个结构:
pub struct ChallengeFields(HashMap<UniCase<CowStr>, (String, Quote)>);
struct CowStr(Cow<'static, str>);
有一条线在做
pub fn get(&self, k: &str) -> Option<&String> {
self.0
.get(&UniCase(CowStr(Cow::Borrowed(unsafe {
mem::transmute::<&str, &'static str>(k)
}))))
.map(|&(ref s, _)| s)
}
我对unsafe
的操作感到恼火。我认为CowStr
是一个具有'static
生存期的Cow
,否则很难或不可能在映射中存储str
。正因为如此,当我试图在这个映射中获取一些东西时,有问题的str
必须有'static
的生存期。这就是transmute
的原因,对吧?如果是这样,为什么不使用String
,这样我们就可以去掉寿命,从而去掉transmute
?我不喜欢unsafe
,读到关于transmute
的文章,它看起来很不安全。
此外,我根本不明白为什么需要Cow
。
我认为
CowStr
是一个具有'static
生存期的Cow
,否则很难或不可能在映射中存储str。
是和否,您可以将&'static str
存储在哈希图中而没有问题,问题是您不能同时存储&'static str
和String
。
我说得对吗?如果是这样,为什么不简单地使用字符串,这样我们就可以摆脱生命,从而转化?
我认为这是一种优化:使用String
,每次您想在映射中插入挑战时都必须创建一个分配,但如果绝大多数挑战名称是Digest
和Basic
,那么这是浪费时间(和内存,但大部分时间(,但同时您必须为自定义身份验证方案支持String
。
现在,也许从总体来看,这不是一个真正重要的优化,我不能告诉你,最好不要这样做。
我不喜欢不安全,阅读关于transmit的文章看起来很不安全。
这是一件有争议的事情,但在这种情况下;"安全";,从这个意义上说,引用对整个HashMap::get
调用都有效,并且我们知道该调用并不能保持引用的有效性(它依赖于一个有点风险的实现细节,但这种情况发生变化的可能性基本为零,因为这没有多大意义(。
延长寿命本身并不是UB(mem::transmute
文档确实提供了一个这样做的示例(,但需要小心,因为您必须避免它导致UB(最有可能是悬空引用(。