From 4611690745c2358aaec407bcd620ac1255520255 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 24 Feb 2025 10:32:00 -1000 Subject: [PATCH] Use `SmallString` on `Hashes` (#11756) ## Summary We should use this consistently over `Box`. --- crates/uv-extract/src/hash.rs | 8 +- crates/uv-publish/src/lib.rs | 8 +- crates/uv-pypi-types/src/simple_json.rs | 136 ++++++++++-------------- crates/uv-small-str/src/lib.rs | 25 +++++ 4 files changed, 88 insertions(+), 89 deletions(-) diff --git a/crates/uv-extract/src/hash.rs b/crates/uv-extract/src/hash.rs index 626911c11..008b2bfa8 100644 --- a/crates/uv-extract/src/hash.rs +++ b/crates/uv-extract/src/hash.rs @@ -41,19 +41,19 @@ impl From for HashDigest { match hasher { Hasher::Md5(hasher) => HashDigest { algorithm: HashAlgorithm::Md5, - digest: format!("{:x}", hasher.finalize()).into_boxed_str(), + digest: format!("{:x}", hasher.finalize()).into(), }, Hasher::Sha256(hasher) => HashDigest { algorithm: HashAlgorithm::Sha256, - digest: format!("{:x}", hasher.finalize()).into_boxed_str(), + digest: format!("{:x}", hasher.finalize()).into(), }, Hasher::Sha384(hasher) => HashDigest { algorithm: HashAlgorithm::Sha384, - digest: format!("{:x}", hasher.finalize()).into_boxed_str(), + digest: format!("{:x}", hasher.finalize()).into(), }, Hasher::Sha512(hasher) => HashDigest { algorithm: HashAlgorithm::Sha512, - digest: format!("{:x}", hasher.finalize()).into_boxed_str(), + digest: format!("{:x}", hasher.finalize()).into(), }, } } diff --git a/crates/uv-publish/src/lib.rs b/crates/uv-publish/src/lib.rs index 4d65fc11d..adebe4dec 100644 --- a/crates/uv-publish/src/lib.rs +++ b/crates/uv-publish/src/lib.rs @@ -68,8 +68,8 @@ pub enum PublishError { HashMismatch { filename: Box, hash_algorithm: HashAlgorithm, - local: Box, - remote: Box, + local: String, + remote: String, }, #[error("Hash is missing in index for {0}")] MissingHash(Box), @@ -547,8 +547,8 @@ pub async fn check_url( Err(PublishError::HashMismatch { filename: Box::new(filename.clone()), hash_algorithm: remote_hash.algorithm, - local: local_hash.digest, - remote: remote_hash.digest.clone(), + local: local_hash.digest.to_string(), + remote: remote_hash.digest.to_string(), }) } } else { diff --git a/crates/uv-pypi-types/src/simple_json.rs b/crates/uv-pypi-types/src/simple_json.rs index eef5889f2..73422d9ed 100644 --- a/crates/uv-pypi-types/src/simple_json.rs +++ b/crates/uv-pypi-types/src/simple_json.rs @@ -138,10 +138,10 @@ impl Default for Yanked { /// PEP 691 says multiple hashes can be included and the interpretation is left to the client. #[derive(Debug, Clone, Eq, PartialEq, Default, Deserialize)] pub struct Hashes { - pub md5: Option>, - pub sha256: Option>, - pub sha384: Option>, - pub sha512: Option>, + pub md5: Option, + pub sha256: Option, + pub sha384: Option, + pub sha512: Option, } impl Hashes { @@ -163,42 +163,30 @@ impl Hashes { } match name { - "md5" => { - let md5 = value.to_owned().into_boxed_str(); - Ok(Hashes { - md5: Some(md5), - sha256: None, - sha384: None, - sha512: None, - }) - } - "sha256" => { - let sha256 = value.to_owned().into_boxed_str(); - Ok(Hashes { - md5: None, - sha256: Some(sha256), - sha384: None, - sha512: None, - }) - } - "sha384" => { - let sha384 = value.to_owned().into_boxed_str(); - Ok(Hashes { - md5: None, - sha256: None, - 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), - }) - } + "md5" => Ok(Hashes { + md5: Some(SmallString::from(value)), + sha256: None, + sha384: None, + sha512: None, + }), + "sha256" => Ok(Hashes { + md5: None, + sha256: Some(SmallString::from(value)), + sha384: None, + sha512: None, + }), + "sha384" => Ok(Hashes { + md5: None, + sha256: None, + sha384: Some(SmallString::from(value)), + sha512: None, + }), + "sha512" => Ok(Hashes { + md5: None, + sha256: None, + sha384: None, + sha512: Some(SmallString::from(value)), + }), _ => Err(HashError::UnsupportedHashAlgorithm(fragment.to_string())), } } @@ -224,42 +212,30 @@ impl FromStr for Hashes { } match name { - "md5" => { - let md5 = value.to_owned().into_boxed_str(); - Ok(Hashes { - md5: Some(md5), - sha256: None, - sha384: None, - sha512: None, - }) - } - "sha256" => { - let sha256 = value.to_owned().into_boxed_str(); - Ok(Hashes { - md5: None, - sha256: Some(sha256), - sha384: None, - sha512: None, - }) - } - "sha384" => { - let sha384 = value.to_owned().into_boxed_str(); - Ok(Hashes { - md5: None, - sha256: None, - 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), - }) - } + "md5" => Ok(Hashes { + md5: Some(SmallString::from(value)), + sha256: None, + sha384: None, + sha512: None, + }), + "sha256" => Ok(Hashes { + md5: None, + sha256: Some(SmallString::from(value)), + sha384: None, + sha512: None, + }), + "sha384" => Ok(Hashes { + md5: None, + sha256: None, + sha384: Some(SmallString::from(value)), + sha512: None, + }), + "sha512" => Ok(Hashes { + md5: None, + sha256: None, + sha384: None, + sha512: Some(SmallString::from(value)), + }), _ => Err(HashError::UnsupportedHashAlgorithm(s.to_string())), } } @@ -331,7 +307,7 @@ impl std::fmt::Display for HashAlgorithm { #[rkyv(derive(Debug))] pub struct HashDigest { pub algorithm: HashAlgorithm, - pub digest: Box, + pub digest: SmallString, } impl HashDigest { @@ -367,11 +343,9 @@ impl FromStr for HashDigest { } let algorithm = HashAlgorithm::from_str(name)?; + let digest = SmallString::from(value); - Ok(HashDigest { - algorithm, - digest: value.to_owned().into_boxed_str(), - }) + Ok(Self { algorithm, digest }) } } diff --git a/crates/uv-small-str/src/lib.rs b/crates/uv-small-str/src/lib.rs index f8e78d521..40324426f 100644 --- a/crates/uv-small-str/src/lib.rs +++ b/crates/uv-small-str/src/lib.rs @@ -83,6 +83,31 @@ impl serde::Serialize for SmallString { } } +impl<'de> serde::Deserialize<'de> for SmallString { + fn deserialize>(deserializer: D) -> Result { + 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(self, v: &str) -> Result { + Ok(v.into()) + } + + fn visit_string(self, v: String) -> Result { + Ok(v.into()) + } +} + /// An [`rkyv`] implementation for [`SmallString`]. impl rkyv::Archive for SmallString { type Archived = rkyv::string::ArchivedString;