Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gix-hash/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ test = false
default = ["sha1"]
## Support for SHA-1 digests.
sha1 = []
## Support for SHA256 digests.
sha256 = []
## Data structures implement `serde::Serialize` and `serde::Deserialize`.
serde = ["dep:serde", "faster-hex/serde"]

Expand Down
2 changes: 2 additions & 0 deletions gix-hash/src/hasher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub(super) mod _impl {
pub fn hasher(kind: crate::Kind) -> Hasher {
match kind {
crate::Kind::Sha1 => Hasher::default(),
#[cfg(feature = "sha256")]
crate::Kind::Sha256 => Hasher::default(),
}
}
}
5 changes: 5 additions & 0 deletions gix-hash/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ pub(super) mod _impl {
inner,
hash: crate::hasher(object_hash),
},
#[cfg(feature = "sha256")]
crate::Kind::Sha256 => Write {
inner,
hash: crate::hasher(object_hash),
},
}
}
}
Expand Down
50 changes: 43 additions & 7 deletions gix-hash/src/kind.rs
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),
})
}
Expand All @@ -19,6 +24,8 @@ impl FromStr for Kind {
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"sha1" | "SHA1" => Kind::Sha1,
#[cfg(feature = "sha256")]
"sha256" | "SHA256" => Kind::Sha256,
other => return Err(other.into()),
})
}
Expand All @@ -28,6 +35,8 @@ 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"),
#[cfg(feature = "sha256")]
Kind::Sha256 => f.write_str("SHA256"),
}
}
}
Expand All @@ -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.
Expand All @@ -61,14 +84,19 @@ 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,
}
}

Expand All @@ -77,7 +105,9 @@ impl Kind {
#[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,
_ => return None,
})
}
Expand All @@ -93,7 +123,9 @@ impl Kind {
#[inline]
pub(crate) fn from_len_in_bytes(bytes: usize) -> Self {
match bytes {
20 => Kind::Sha1,
SIZE_OF_SHA1_DIGEST => Kind::Sha1,
#[cfg(feature = "sha256")]
SIZE_OF_SHA256_DIGEST => Kind::Sha256,
_ => panic!("BUG: must be called only with valid hash lengths produced by len_in_bytes()"),
}
}
Expand All @@ -103,6 +135,8 @@ impl Kind {
pub fn null_ref(&self) -> &'static oid {
match self {
Kind::Sha1 => oid::null_sha1(),
#[cfg(feature = "sha256")]
Kind::Sha256 => oid::null_sha256(),
}
}

Expand All @@ -111,6 +145,8 @@ impl Kind {
pub const fn null(&self) -> ObjectId {
match self {
Kind::Sha1 => ObjectId::null_sha1(),
#[cfg(feature = "sha256")]
Kind::Sha256 => ObjectId::null_sha256(),
}
}

Expand Down
22 changes: 22 additions & 0 deletions gix-hash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,25 @@ 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";

#[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)]
Expand All @@ -57,6 +76,9 @@ pub enum Kind {
/// The Sha1 hash with 160 bits.
#[default]
Sha1 = 1,
/// The Sha256 hash with 256 bits.
#[cfg(feature = "sha256")]
Sha256 = 2,
}

mod kind;
Loading
Loading