-
-
Notifications
You must be signed in to change notification settings - Fork 412
Add ObjectId::Sha256 and Kind::Sha256
#2292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,13 +1,18 @@ | ||||||
| use std::str::FromStr; | ||||||
|
|
||||||
| use crate::{oid, Kind, ObjectId}; | ||||||
| use crate::{oid, Kind, ObjectId, SIZE_OF_SHA1_DIGEST, SIZE_OF_SHA1_HEX_DIGEST}; | ||||||
|
|
||||||
| #[cfg(feature = "sha256")] | ||||||
| use crate::{SIZE_OF_SHA256_DIGEST, SIZE_OF_SHA256_HEX_DIGEST}; | ||||||
|
|
||||||
| impl TryFrom<u8> for Kind { | ||||||
| type Error = u8; | ||||||
|
|
||||||
| fn try_from(value: u8) -> Result<Self, Self::Error> { | ||||||
| Ok(match value { | ||||||
| 1 => Kind::Sha1, | ||||||
| #[cfg(feature = "sha256")] | ||||||
| 2 => Kind::Sha256, | ||||||
| unknown => return Err(unknown), | ||||||
| }) | ||||||
| } | ||||||
|
|
@@ -18,7 +23,9 @@ impl FromStr for Kind { | |||||
|
|
||||||
| fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||||
| Ok(match s { | ||||||
| "sha1" | "SHA1" => Kind::Sha1, | ||||||
| "sha1" | "SHA1" | "SHA-1" => Kind::Sha1, | ||||||
| #[cfg(feature = "sha256")] | ||||||
| "sha256" | "SHA256" | "SHA-256" => Kind::Sha256, | ||||||
| other => return Err(other.into()), | ||||||
| }) | ||||||
| } | ||||||
|
|
@@ -27,7 +34,9 @@ impl FromStr for Kind { | |||||
| impl std::fmt::Display for Kind { | ||||||
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
| match self { | ||||||
| Kind::Sha1 => f.write_str("SHA1"), | ||||||
| Kind::Sha1 => f.write_str("sha1"), | ||||||
| #[cfg(feature = "sha256")] | ||||||
| Kind::Sha256 => f.write_str("sha256"), | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
@@ -36,13 +45,27 @@ impl Kind { | |||||
| /// Returns the shortest hash we support. | ||||||
| #[inline] | ||||||
| pub const fn shortest() -> Self { | ||||||
| Self::Sha1 | ||||||
| #[cfg(all(not(feature = "sha1"), feature = "sha256"))] | ||||||
| { | ||||||
| Self::Sha256 | ||||||
| } | ||||||
| #[cfg(feature = "sha1")] | ||||||
| { | ||||||
| Self::Sha1 | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /// Returns the longest hash we support. | ||||||
| #[inline] | ||||||
| pub const fn longest() -> Self { | ||||||
| Self::Sha1 | ||||||
| #[cfg(feature = "sha256")] | ||||||
| { | ||||||
| Self::Sha256 | ||||||
| } | ||||||
| #[cfg(all(not(feature = "sha256"), feature = "sha1"))] | ||||||
| { | ||||||
| Self::Sha1 | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /// Returns a buffer suitable to hold the longest possible hash in hex. | ||||||
|
|
@@ -61,23 +84,31 @@ impl Kind { | |||||
| #[inline] | ||||||
| pub const fn len_in_hex(&self) -> usize { | ||||||
| match self { | ||||||
| Kind::Sha1 => 40, | ||||||
| Kind::Sha1 => SIZE_OF_SHA1_HEX_DIGEST, | ||||||
| #[cfg(feature = "sha256")] | ||||||
| Kind::Sha256 => SIZE_OF_SHA256_HEX_DIGEST, | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /// Returns the amount of bytes taken up by the hash of this instance. | ||||||
| #[inline] | ||||||
| pub const fn len_in_bytes(&self) -> usize { | ||||||
| match self { | ||||||
| Kind::Sha1 => 20, | ||||||
| Kind::Sha1 => SIZE_OF_SHA1_DIGEST, | ||||||
| #[cfg(feature = "sha256")] | ||||||
| Kind::Sha256 => SIZE_OF_SHA256_DIGEST, | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /// Returns the kind of hash that would fit the given `hex_len`, or `None` if there is no fitting hash. | ||||||
| /// Note that `0` as `hex_len` up to 40 always yields `Sha1`. | ||||||
| /// Note that `0` as `hex_len` up to 40 always yields SHA-1 while anything in the range 41..64 | ||||||
| /// always yields SHA-256 if it is enabled. | ||||||
| #[inline] | ||||||
| pub const fn from_hex_len(hex_len: usize) -> Option<Self> { | ||||||
| Some(match hex_len { | ||||||
| 0..=40 => Kind::Sha1, | ||||||
| 0..=SIZE_OF_SHA1_HEX_DIGEST => Kind::Sha1, | ||||||
| #[cfg(feature = "sha256")] | ||||||
| 0..=SIZE_OF_SHA256_HEX_DIGEST => Kind::Sha256, | ||||||
|
||||||
| 0..=SIZE_OF_SHA256_HEX_DIGEST => Kind::Sha256, | |
| SIZE_OF_SHA1_HEX_DIGEST + 1..=SIZE_OF_SHA256_HEX_DIGEST => Kind::Sha256, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not how it works.
It matches Sha1 while it can, then it matches Sha256.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,7 @@ | |
| #![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))] | ||
| #![deny(missing_docs, rust_2018_idioms, unsafe_code)] | ||
|
|
||
| // Remove this once other hashes (e.g., SHA-256, and potentially others) | ||
| // Remove this once other hashes (e.g., SHA256, and potentially others) | ||
Byron marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // are supported, and this crate can build without [`ObjectId::Sha1`]. | ||
| #[cfg(not(feature = "sha1"))] | ||
| compile_error!("Please set the `sha1` feature flag"); | ||
|
|
@@ -48,15 +48,37 @@ pub struct Prefix { | |
|
|
||
| /// The size of a SHA1 hash digest in bytes. | ||
| const SIZE_OF_SHA1_DIGEST: usize = 20; | ||
| /// The size of a SHA1 hash digest in hex. | ||
| const SIZE_OF_SHA1_HEX_DIGEST: usize = 2 * SIZE_OF_SHA1_DIGEST; | ||
|
|
||
| /// The size of a SHA256 hash digest in bytes. | ||
| #[cfg(feature = "sha256")] | ||
| const SIZE_OF_SHA256_DIGEST: usize = 32; | ||
| /// The size of a SHA256 hash digest in hex. | ||
| #[cfg(feature = "sha256")] | ||
| const SIZE_OF_SHA256_HEX_DIGEST: usize = 2 * SIZE_OF_SHA256_DIGEST; | ||
|
|
||
| const EMPTY_BLOB_SHA1: &[u8; SIZE_OF_SHA1_DIGEST] = | ||
| b"\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91"; | ||
| const EMPTY_TREE_SHA1: &[u8; SIZE_OF_SHA1_DIGEST] = | ||
| b"\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"; | ||
|
Comment on lines
+63
to
+64
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Finally there is all the constants that were scattered before in one place. |
||
|
|
||
| #[cfg(feature = "sha256")] | ||
| const EMPTY_BLOB_SHA256: &[u8; SIZE_OF_SHA256_DIGEST] = b"\x47\x3a\x0f\x4c\x3b\xe8\xa9\x36\x81\xa2\x67\xe3\xb1\xe9\xa7\xdc\xda\x11\x85\x43\x6f\xe1\x41\xf7\x74\x91\x20\xa3\x03\x72\x18\x13"; | ||
| #[cfg(feature = "sha256")] | ||
| const EMPTY_TREE_SHA256: &[u8; SIZE_OF_SHA256_DIGEST] = b"\x6e\xf1\x9b\x41\x22\x5c\x53\x69\xf1\xc1\x04\xd4\x5d\x8d\x85\xef\xa9\xb0\x57\xb5\x3b\x14\xb4\xb9\xb9\x39\xdd\x74\xde\xcc\x53\x21"; | ||
|
|
||
| /// Denotes the kind of function to produce a [`ObjectId`]. | ||
| #[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] | ||
| #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] | ||
| #[non_exhaustive] | ||
| pub enum Kind { | ||
| /// The Sha1 hash with 160 bits. | ||
| /// The SHA1 hash with 160 bits. | ||
| #[default] | ||
| Sha1 = 1, | ||
| /// The SHA256 hash with 256 bits. | ||
| #[cfg(feature = "sha256")] | ||
| Sha256 = 2, | ||
| } | ||
|
|
||
| mod kind; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that there is this logic, it feels like tests for
longest/shortestwould be good. They'd have to repeat the feature flags so I am not a huge fan, but it really feels like there should be something in place to prevent this from going wrong, ever.I'd be OK if you said 'better not' as this seems to be correct and when Git introduces a new hash in 10y+, we'd be looking at a completely different environment anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.