Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 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