mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-11 00:11:05 +00:00
url_utils: hash Extension by what equality compares
This commit is contained in:
1 parent
1218293fe2
commit
f7e1ae94b7
1 file changed
+26
-1
@@ -1,5 +1,6 @@
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
/// A file extension that can be either a compile-time constant or a runtime-parsed value.
|
||||
///
|
||||
@@ -16,7 +17,7 @@ use std::fmt;
|
||||
/// assert_eq!(ext.without_period(), "mp4");
|
||||
/// assert_eq!(ext.with_period(), ".mp4");
|
||||
/// ```
|
||||
#[derive(Clone, Eq, Hash)]
|
||||
#[derive(Clone, Eq)]
|
||||
pub struct Extension {
|
||||
/// The extension without the leading period, e.g. "png", "mp4".
|
||||
value: Cow<'static, str>,
|
||||
@@ -67,6 +68,14 @@ impl PartialEq for Extension {
|
||||
}
|
||||
}
|
||||
|
||||
// Hashes what `eq` compares, so equal extensions always hash alike (a derived `Hash` would also
|
||||
// hash `dotted`, which `eq` ignores).
|
||||
impl Hash for Extension {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.value.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Extension {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Extension(\"{}\")", self.value)
|
||||
@@ -126,6 +135,22 @@ mod tests {
|
||||
assert_eq!(a, PNG);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn equal_extensions_hash_alike() {
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
fn hash_of(ext: &Extension) -> u64 {
|
||||
let mut h = DefaultHasher::new();
|
||||
ext.hash(&mut h);
|
||||
h.finish()
|
||||
}
|
||||
// `eq` looks only at the bare extension, so a constant whose dotted form was written
|
||||
// differently is still equal, and must land in the same hash bucket.
|
||||
const ODD: Extension = Extension::from_static("png", "PNG");
|
||||
assert_eq!(ODD, PNG);
|
||||
assert_eq!(hash_of(&ODD), hash_of(&PNG));
|
||||
assert_eq!(hash_of(&Extension::new("png")), hash_of(&PNG));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone() {
|
||||
let a = Extension::new("wav");
|
||||
|
||||
Reference in new issue
Block a user