Use `SmallString` on `Hashes` (#11756)

## Summary

We should use this consistently over `Box<str>`.
This commit is contained in:
Charlie Marsh 2025-02-24 10:32:00 -10:00 committed by GitHub
parent d9adba1cf5
commit 4611690745
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 88 additions and 89 deletions

View File

@ -41,19 +41,19 @@ impl From<Hasher> for HashDigest {
match hasher { match hasher {
Hasher::Md5(hasher) => HashDigest { Hasher::Md5(hasher) => HashDigest {
algorithm: HashAlgorithm::Md5, algorithm: HashAlgorithm::Md5,
digest: format!("{:x}", hasher.finalize()).into_boxed_str(), digest: format!("{:x}", hasher.finalize()).into(),
}, },
Hasher::Sha256(hasher) => HashDigest { Hasher::Sha256(hasher) => HashDigest {
algorithm: HashAlgorithm::Sha256, algorithm: HashAlgorithm::Sha256,
digest: format!("{:x}", hasher.finalize()).into_boxed_str(), digest: format!("{:x}", hasher.finalize()).into(),
}, },
Hasher::Sha384(hasher) => HashDigest { Hasher::Sha384(hasher) => HashDigest {
algorithm: HashAlgorithm::Sha384, algorithm: HashAlgorithm::Sha384,
digest: format!("{:x}", hasher.finalize()).into_boxed_str(), digest: format!("{:x}", hasher.finalize()).into(),
}, },
Hasher::Sha512(hasher) => HashDigest { Hasher::Sha512(hasher) => HashDigest {
algorithm: HashAlgorithm::Sha512, algorithm: HashAlgorithm::Sha512,
digest: format!("{:x}", hasher.finalize()).into_boxed_str(), digest: format!("{:x}", hasher.finalize()).into(),
}, },
} }
} }

View File

@ -68,8 +68,8 @@ pub enum PublishError {
HashMismatch { HashMismatch {
filename: Box<DistFilename>, filename: Box<DistFilename>,
hash_algorithm: HashAlgorithm, hash_algorithm: HashAlgorithm,
local: Box<str>, local: String,
remote: Box<str>, remote: String,
}, },
#[error("Hash is missing in index for {0}")] #[error("Hash is missing in index for {0}")]
MissingHash(Box<DistFilename>), MissingHash(Box<DistFilename>),
@ -547,8 +547,8 @@ pub async fn check_url(
Err(PublishError::HashMismatch { Err(PublishError::HashMismatch {
filename: Box::new(filename.clone()), filename: Box::new(filename.clone()),
hash_algorithm: remote_hash.algorithm, hash_algorithm: remote_hash.algorithm,
local: local_hash.digest, local: local_hash.digest.to_string(),
remote: remote_hash.digest.clone(), remote: remote_hash.digest.to_string(),
}) })
} }
} else { } else {

View File

@ -138,10 +138,10 @@ impl Default for Yanked {
/// PEP 691 says multiple hashes can be included and the interpretation is left to the client. /// PEP 691 says multiple hashes can be included and the interpretation is left to the client.
#[derive(Debug, Clone, Eq, PartialEq, Default, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, Default, Deserialize)]
pub struct Hashes { pub struct Hashes {
pub md5: Option<Box<str>>, pub md5: Option<SmallString>,
pub sha256: Option<Box<str>>, pub sha256: Option<SmallString>,
pub sha384: Option<Box<str>>, pub sha384: Option<SmallString>,
pub sha512: Option<Box<str>>, pub sha512: Option<SmallString>,
} }
impl Hashes { impl Hashes {
@ -163,42 +163,30 @@ impl Hashes {
} }
match name { match name {
"md5" => { "md5" => Ok(Hashes {
let md5 = value.to_owned().into_boxed_str(); md5: Some(SmallString::from(value)),
Ok(Hashes { sha256: None,
md5: Some(md5), sha384: None,
sha256: None, sha512: None,
sha384: None, }),
sha512: None, "sha256" => Ok(Hashes {
}) md5: None,
} sha256: Some(SmallString::from(value)),
"sha256" => { sha384: None,
let sha256 = value.to_owned().into_boxed_str(); sha512: None,
Ok(Hashes { }),
md5: None, "sha384" => Ok(Hashes {
sha256: Some(sha256), md5: None,
sha384: None, sha256: None,
sha512: None, sha384: Some(SmallString::from(value)),
}) sha512: None,
} }),
"sha384" => { "sha512" => Ok(Hashes {
let sha384 = value.to_owned().into_boxed_str(); md5: None,
Ok(Hashes { sha256: None,
md5: None, sha384: None,
sha256: None, sha512: Some(SmallString::from(value)),
sha384: Some(sha384), }),
sha512: None,
})
}
"sha512" => {
let sha512 = value.to_owned().into_boxed_str();
Ok(Hashes {
md5: None,
sha256: None,
sha384: None,
sha512: Some(sha512),
})
}
_ => Err(HashError::UnsupportedHashAlgorithm(fragment.to_string())), _ => Err(HashError::UnsupportedHashAlgorithm(fragment.to_string())),
} }
} }
@ -224,42 +212,30 @@ impl FromStr for Hashes {
} }
match name { match name {
"md5" => { "md5" => Ok(Hashes {
let md5 = value.to_owned().into_boxed_str(); md5: Some(SmallString::from(value)),
Ok(Hashes { sha256: None,
md5: Some(md5), sha384: None,
sha256: None, sha512: None,
sha384: None, }),
sha512: None, "sha256" => Ok(Hashes {
}) md5: None,
} sha256: Some(SmallString::from(value)),
"sha256" => { sha384: None,
let sha256 = value.to_owned().into_boxed_str(); sha512: None,
Ok(Hashes { }),
md5: None, "sha384" => Ok(Hashes {
sha256: Some(sha256), md5: None,
sha384: None, sha256: None,
sha512: None, sha384: Some(SmallString::from(value)),
}) sha512: None,
} }),
"sha384" => { "sha512" => Ok(Hashes {
let sha384 = value.to_owned().into_boxed_str(); md5: None,
Ok(Hashes { sha256: None,
md5: None, sha384: None,
sha256: None, sha512: Some(SmallString::from(value)),
sha384: Some(sha384), }),
sha512: None,
})
}
"sha512" => {
let sha512 = value.to_owned().into_boxed_str();
Ok(Hashes {
md5: None,
sha256: None,
sha384: None,
sha512: Some(sha512),
})
}
_ => Err(HashError::UnsupportedHashAlgorithm(s.to_string())), _ => Err(HashError::UnsupportedHashAlgorithm(s.to_string())),
} }
} }
@ -331,7 +307,7 @@ impl std::fmt::Display for HashAlgorithm {
#[rkyv(derive(Debug))] #[rkyv(derive(Debug))]
pub struct HashDigest { pub struct HashDigest {
pub algorithm: HashAlgorithm, pub algorithm: HashAlgorithm,
pub digest: Box<str>, pub digest: SmallString,
} }
impl HashDigest { impl HashDigest {
@ -367,11 +343,9 @@ impl FromStr for HashDigest {
} }
let algorithm = HashAlgorithm::from_str(name)?; let algorithm = HashAlgorithm::from_str(name)?;
let digest = SmallString::from(value);
Ok(HashDigest { Ok(Self { algorithm, digest })
algorithm,
digest: value.to_owned().into_boxed_str(),
})
} }
} }

View File

@ -83,6 +83,31 @@ impl serde::Serialize for SmallString {
} }
} }
impl<'de> serde::Deserialize<'de> for SmallString {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = deserializer.deserialize_str(SmallStringVisitor)?;
Ok(s)
}
}
struct SmallStringVisitor;
impl serde::de::Visitor<'_> for SmallStringVisitor {
type Value = SmallString;
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_str("a string")
}
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
Ok(v.into())
}
fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Self::Value, E> {
Ok(v.into())
}
}
/// An [`rkyv`] implementation for [`SmallString`]. /// An [`rkyv`] implementation for [`SmallString`].
impl rkyv::Archive for SmallString { impl rkyv::Archive for SmallString {
type Archived = rkyv::string::ArchivedString; type Archived = rkyv::string::ArchivedString;