History

Merge pull request #2332 from cruessler/make-sha-1-optional

Make sha1 optional in `gix-hash`

Sebastian Thiel committed 10 months ago

Commit 41502032 parents 9e1ba5e aed5b669 files · +81 −12Browse files

Unified · Split

9 files
  1. gix-hash/Cargo.toml +2 −2
  2. gix-hash/src/hasher.rs +9 −0
  3. gix-hash/src/io.rs +1 −0
  4. gix-hash/src/kind.rs +13 −1
  5. gix-hash/src/lib.rs +9 −5
  6. gix-hash/src/object_id.rs +24 −2
  7. gix-hash/src/oid.rs +21 −1
  8. gix-hash/tests/hash/kind.rs +0 −1
  9. justfile +2 −0
gix-hash/Cargo.toml+2−2
@@ -18,7 +18,7 @@ test = false · 17 unmodified lines
18[features]18[features]
19default = ["sha1"]19default = ["sha1"]
20## Support for SHA1 hashes and digests.20## Support for SHA1 hashes and digests.
21sha1 = []21sha1 = ["dep:sha1-checked"]
22## Support for SHA256 hashes and digests.22## Support for SHA256 hashes and digests.
23sha256 = ["dep:sha2"]23sha256 = ["dep:sha2"]
24## Data structures implement `serde::Serialize` and `serde::Deserialize`.24## Data structures implement `serde::Serialize` and `serde::Deserialize`.
@@ -30,7 +30,7 @@ gix-features = { version = "^0.45.1", path = "../gix-features", features = ["pro · 5 unmodified lines
30thiserror = "2.0.17"30thiserror = "2.0.17"
31faster-hex = { version = "0.10.0", default-features = false, features = ["std"] }31faster-hex = { version = "0.10.0", default-features = false, features = ["std"] }
32serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }32serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }
33sha1-checked = { version = "0.10.0", default-features = false }33sha1-checked = { version = "0.10.0", optional = true, default-features = false }
34sha2 = { version = "0.10.0", optional = true, default-features = false }34sha2 = { version = "0.10.0", optional = true, default-features = false }
35 35
36document-features = { version = "0.2.0", optional = true }36document-features = { version = "0.2.0", optional = true }
gix-hash/src/hasher.rs+9−0
@@ -7,8 +7,12 @@ pub enum Error { · 6 unmodified lines
7}7}
8 8
9pub(super) mod _impl {9pub(super) mod _impl {
10 #[cfg(feature = "sha1")]
10 use sha1_checked::{CollisionResult, Digest};11 use sha1_checked::{CollisionResult, Digest};
11 12
13 #[cfg(all(not(feature = "sha1"), feature = "sha256"))]
14 use sha2::Digest;
15
12 use crate::hasher::Error;16 use crate::hasher::Error;
13 17
14 /// Hash implementations that can be used once.18 /// Hash implementations that can be used once.
@@ -17,6 +21,7 @@ pub(super) mod _impl { · 2 unmodified lines
17 /// An implementation of the SHA1 hash.21 /// An implementation of the SHA1 hash.
18 ///22 ///
19 /// We use [`sha1_checked`] to implement the same collision detection algorithm as Git.23 /// We use [`sha1_checked`] to implement the same collision detection algorithm as Git.
24 #[cfg(feature = "sha1")]
20 Sha1(sha1_checked::Sha1),25 Sha1(sha1_checked::Sha1),
21 /// An implementation of the SHA256 hash.26 /// An implementation of the SHA256 hash.
22 #[cfg(feature = "sha256")]27 #[cfg(feature = "sha256")]
@@ -25,6 +30,7 @@ pub(super) mod _impl { · 2 unmodified lines
25 30
26 impl Hasher {31 impl Hasher {
27 /// Let's not make this public to force people to go through [`hasher()`].32 /// Let's not make this public to force people to go through [`hasher()`].
33 #[cfg(feature = "sha1")]
28 fn new_sha1() -> Self {34 fn new_sha1() -> Self {
29 // This matches the configuration used by Git, which only uses35 // This matches the configuration used by Git, which only uses
30 // the collision detection to bail out, rather than computing36 // the collision detection to bail out, rather than computing
@@ -44,6 +50,7 @@ pub(super) mod _impl { · 13 unmodified lines
44 /// Digest the given `bytes`.50 /// Digest the given `bytes`.
45 pub fn update(&mut self, bytes: &[u8]) {51 pub fn update(&mut self, bytes: &[u8]) {
46 match self {52 match self {
53 #[cfg(feature = "sha1")]
47 Hasher::Sha1(sha1) => sha1.update(bytes),54 Hasher::Sha1(sha1) => sha1.update(bytes),
48 #[cfg(feature = "sha256")]55 #[cfg(feature = "sha256")]
49 Hasher::Sha256(sha256) => sha256.update(bytes),56 Hasher::Sha256(sha256) => sha256.update(bytes),
@@ -59,6 +66,7 @@ pub(super) mod _impl { · 9 unmodified lines
59 #[inline]66 #[inline]
60 pub fn try_finalize(self) -> Result<crate::ObjectId, Error> {67 pub fn try_finalize(self) -> Result<crate::ObjectId, Error> {
61 match self {68 match self {
69 #[cfg(feature = "sha1")]
62 Hasher::Sha1(sha1) => match sha1.try_finalize() {70 Hasher::Sha1(sha1) => match sha1.try_finalize() {
63 CollisionResult::Ok(digest) => Ok(crate::ObjectId::Sha1(digest.into())),71 CollisionResult::Ok(digest) => Ok(crate::ObjectId::Sha1(digest.into())),
64 CollisionResult::Mitigated(_) => {72 CollisionResult::Mitigated(_) => {
@@ -89,6 +97,7 @@ pub(super) mod _impl { · 24 unmodified lines
89 #[inline]97 #[inline]
90 pub fn hasher(kind: crate::Kind) -> Hasher {98 pub fn hasher(kind: crate::Kind) -> Hasher {
91 match kind {99 match kind {
100 #[cfg(feature = "sha1")]
92 crate::Kind::Sha1 => Hasher::new_sha1(),101 crate::Kind::Sha1 => Hasher::new_sha1(),
93 #[cfg(feature = "sha256")]102 #[cfg(feature = "sha256")]
94 crate::Kind::Sha256 => Hasher::new_sha256(),103 crate::Kind::Sha256 => Hasher::new_sha256(),
gix-hash/src/io.rs+1−0
@@ -114,6 +114,7 @@ pub(super) mod _impl { · 113 unmodified lines
114 /// Create a new hash writer which hashes all bytes written to `inner` with a hash of `kind`.114 /// Create a new hash writer which hashes all bytes written to `inner` with a hash of `kind`.
115 pub fn new(inner: T, object_hash: crate::Kind) -> Self {115 pub fn new(inner: T, object_hash: crate::Kind) -> Self {
116 match object_hash {116 match object_hash {
117 #[cfg(feature = "sha1")]
117 crate::Kind::Sha1 => Write {118 crate::Kind::Sha1 => Write {
118 inner,119 inner,
119 hash: crate::hasher(object_hash),120 hash: crate::hasher(object_hash),
gix-hash/src/kind.rs+13−1
@@ -1,6 +1,9 @@
1use std::str::FromStr;1use std::str::FromStr;
2 2
3use crate::{oid, Kind, ObjectId, SIZE_OF_SHA1_DIGEST, SIZE_OF_SHA1_HEX_DIGEST};3use crate::{oid, Kind, ObjectId};
4
5#[cfg(feature = "sha1")]
6use crate::{SIZE_OF_SHA1_DIGEST, SIZE_OF_SHA1_HEX_DIGEST};
4 7
5#[cfg(feature = "sha256")]8#[cfg(feature = "sha256")]
6use crate::{SIZE_OF_SHA256_DIGEST, SIZE_OF_SHA256_HEX_DIGEST};9use crate::{SIZE_OF_SHA256_DIGEST, SIZE_OF_SHA256_HEX_DIGEST};
@@ -10,6 +13,7 @@ impl TryFrom<u8> for Kind { · 3 unmodified lines
10 13
11 fn try_from(value: u8) -> Result<Self, Self::Error> {14 fn try_from(value: u8) -> Result<Self, Self::Error> {
12 Ok(match value {15 Ok(match value {
16 #[cfg(feature = "sha1")]
13 1 => Kind::Sha1,17 1 => Kind::Sha1,
14 #[cfg(feature = "sha256")]18 #[cfg(feature = "sha256")]
15 2 => Kind::Sha256,19 2 => Kind::Sha256,
@@ -23,6 +27,7 @@ impl FromStr for Kind { · 7 unmodified lines
23 27
24 fn from_str(s: &str) -> Result<Self, Self::Err> {28 fn from_str(s: &str) -> Result<Self, Self::Err> {
25 Ok(match s {29 Ok(match s {
30 #[cfg(feature = "sha1")]
26 "sha1" | "SHA1" | "SHA-1" => Kind::Sha1,31 "sha1" | "SHA1" | "SHA-1" => Kind::Sha1,
27 #[cfg(feature = "sha256")]32 #[cfg(feature = "sha256")]
28 "sha256" | "SHA256" | "SHA-256" => Kind::Sha256,33 "sha256" | "SHA256" | "SHA-256" => Kind::Sha256,
@@ -34,6 +39,7 @@ impl FromStr for Kind { · 5 unmodified lines
34impl std::fmt::Display for Kind {39impl std::fmt::Display for Kind {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 match self {41 match self {
42 #[cfg(feature = "sha1")]
37 Kind::Sha1 => f.write_str("sha1"),43 Kind::Sha1 => f.write_str("sha1"),
38 #[cfg(feature = "sha256")]44 #[cfg(feature = "sha256")]
39 Kind::Sha256 => f.write_str("sha256"),45 Kind::Sha256 => f.write_str("sha256"),
@@ -84,6 +90,7 @@ impl Kind { · 44 unmodified lines
84 #[inline]90 #[inline]
85 pub const fn len_in_hex(&self) -> usize {91 pub const fn len_in_hex(&self) -> usize {
86 match self {92 match self {
93 #[cfg(feature = "sha1")]
87 Kind::Sha1 => SIZE_OF_SHA1_HEX_DIGEST,94 Kind::Sha1 => SIZE_OF_SHA1_HEX_DIGEST,
88 #[cfg(feature = "sha256")]95 #[cfg(feature = "sha256")]
89 Kind::Sha256 => SIZE_OF_SHA256_HEX_DIGEST,96 Kind::Sha256 => SIZE_OF_SHA256_HEX_DIGEST,
@@ -94,6 +101,7 @@ impl Kind { · 4 unmodified lines
94 #[inline]101 #[inline]
95 pub const fn len_in_bytes(&self) -> usize {102 pub const fn len_in_bytes(&self) -> usize {
96 match self {103 match self {
104 #[cfg(feature = "sha1")]
97 Kind::Sha1 => SIZE_OF_SHA1_DIGEST,105 Kind::Sha1 => SIZE_OF_SHA1_DIGEST,
98 #[cfg(feature = "sha256")]106 #[cfg(feature = "sha256")]
99 Kind::Sha256 => SIZE_OF_SHA256_DIGEST,107 Kind::Sha256 => SIZE_OF_SHA256_DIGEST,
@@ -106,6 +114,7 @@ impl Kind { · 6 unmodified lines
106 #[inline]114 #[inline]
107 pub const fn from_hex_len(hex_len: usize) -> Option<Self> {115 pub const fn from_hex_len(hex_len: usize) -> Option<Self> {
108 Some(match hex_len {116 Some(match hex_len {
117 #[cfg(feature = "sha1")]
109 0..=SIZE_OF_SHA1_HEX_DIGEST => Kind::Sha1,118 0..=SIZE_OF_SHA1_HEX_DIGEST => Kind::Sha1,
110 #[cfg(feature = "sha256")]119 #[cfg(feature = "sha256")]
111 0..=SIZE_OF_SHA256_HEX_DIGEST => Kind::Sha256,120 0..=SIZE_OF_SHA256_HEX_DIGEST => Kind::Sha256,
@@ -124,6 +133,7 @@ impl Kind { · 12 unmodified lines
124 #[inline]133 #[inline]
125 pub(crate) fn from_len_in_bytes(bytes: usize) -> Self {134 pub(crate) fn from_len_in_bytes(bytes: usize) -> Self {
126 match bytes {135 match bytes {
136 #[cfg(feature = "sha1")]
127 SIZE_OF_SHA1_DIGEST => Kind::Sha1,137 SIZE_OF_SHA1_DIGEST => Kind::Sha1,
128 #[cfg(feature = "sha256")]138 #[cfg(feature = "sha256")]
129 SIZE_OF_SHA256_DIGEST => Kind::Sha256,139 SIZE_OF_SHA256_DIGEST => Kind::Sha256,
@@ -135,6 +145,7 @@ impl Kind { · 5 unmodified lines
135 #[inline]145 #[inline]
136 pub fn null_ref(&self) -> &'static oid {146 pub fn null_ref(&self) -> &'static oid {
137 match self {147 match self {
148 #[cfg(feature = "sha1")]
138 Kind::Sha1 => oid::null_sha1(),149 Kind::Sha1 => oid::null_sha1(),
139 #[cfg(feature = "sha256")]150 #[cfg(feature = "sha256")]
140 Kind::Sha256 => oid::null_sha256(),151 Kind::Sha256 => oid::null_sha256(),
@@ -145,6 +156,7 @@ impl Kind { · 4 unmodified lines
145 #[inline]156 #[inline]
146 pub const fn null(&self) -> ObjectId {157 pub const fn null(&self) -> ObjectId {
147 match self {158 match self {
159 #[cfg(feature = "sha1")]
148 Kind::Sha1 => ObjectId::null_sha1(),160 Kind::Sha1 => ObjectId::null_sha1(),
149 #[cfg(feature = "sha256")]161 #[cfg(feature = "sha256")]
150 Kind::Sha256 => ObjectId::null_sha256(),162 Kind::Sha256 => ObjectId::null_sha256(),
gix-hash/src/lib.rs+9−5
@@ -9,10 +9,8 @@ · 8 unmodified lines
9#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]9#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]
10#![deny(missing_docs, rust_2018_idioms, unsafe_code)]10#![deny(missing_docs, rust_2018_idioms, unsafe_code)]
11 11
12// Remove this once other hashes (e.g., SHA256, and potentially others)12#[cfg(all(not(feature = "sha1"), not(feature = "sha256")))]
13// are supported, and this crate can build without [`ObjectId::Sha1`].13compile_error!("Please set either the `sha1` or the `sha256` feature flag");
14#[cfg(not(feature = "sha1"))]
15compile_error!("Please set the `sha1` feature flag");
16 14
17#[path = "oid.rs"]15#[path = "oid.rs"]
18mod borrowed;16mod borrowed;
@@ -47,8 +45,10 @@ pub struct Prefix { · 28 unmodified lines
47}45}
48 46
49/// The size of a SHA1 hash digest in bytes.47/// The size of a SHA1 hash digest in bytes.
48#[cfg(feature = "sha1")]
50const SIZE_OF_SHA1_DIGEST: usize = 20;49const SIZE_OF_SHA1_DIGEST: usize = 20;
51/// The size of a SHA1 hash digest in hex.50/// The size of a SHA1 hash digest in hex.
51#[cfg(feature = "sha1")]
52const SIZE_OF_SHA1_HEX_DIGEST: usize = 2 * SIZE_OF_SHA1_DIGEST;52const SIZE_OF_SHA1_HEX_DIGEST: usize = 2 * SIZE_OF_SHA1_DIGEST;
53 53
54/// The size of a SHA256 hash digest in bytes.54/// The size of a SHA256 hash digest in bytes.
@@ -58,8 +58,10 @@ const SIZE_OF_SHA256_DIGEST: usize = 32; · 3 unmodified lines
58#[cfg(feature = "sha256")]58#[cfg(feature = "sha256")]
59const SIZE_OF_SHA256_HEX_DIGEST: usize = 2 * SIZE_OF_SHA256_DIGEST;59const SIZE_OF_SHA256_HEX_DIGEST: usize = 2 * SIZE_OF_SHA256_DIGEST;
60 60
61#[cfg(feature = "sha1")]
61const EMPTY_BLOB_SHA1: &[u8; SIZE_OF_SHA1_DIGEST] =62const EMPTY_BLOB_SHA1: &[u8; SIZE_OF_SHA1_DIGEST] =
62 b"\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91";63 b"\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91";
64#[cfg(feature = "sha1")]
63const EMPTY_TREE_SHA1: &[u8; SIZE_OF_SHA1_DIGEST] =65const EMPTY_TREE_SHA1: &[u8; SIZE_OF_SHA1_DIGEST] =
64 b"\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04";66 b"\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04";
65 67
@@ -74,9 +76,11 @@ const EMPTY_TREE_SHA256: &[u8; SIZE_OF_SHA256_DIGEST] = b"\x6e\xf1\x9b\x41\x22\x · 8 unmodified lines
74#[non_exhaustive]76#[non_exhaustive]
75pub enum Kind {77pub enum Kind {
76 /// The SHA1 hash with 160 bits.78 /// The SHA1 hash with 160 bits.
77 #[default]79 #[cfg_attr(feature = "sha1", default)]
80 #[cfg(feature = "sha1")]
78 Sha1 = 1,81 Sha1 = 1,
79 /// The SHA256 hash with 256 bits.82 /// The SHA256 hash with 256 bits.
83 #[cfg_attr(all(not(feature = "sha1"), feature = "sha256"), default)]
80 #[cfg(feature = "sha256")]84 #[cfg(feature = "sha256")]
81 Sha256 = 2,85 Sha256 = 2,
82}86}
gix-hash/src/object_id.rs+24−2
@@ -4,7 +4,10 @@ use std::{ · 3 unmodified lines
4 ops::Deref,4 ops::Deref,
5};5};
6 6
7use crate::{borrowed::oid, Kind, EMPTY_BLOB_SHA1, EMPTY_TREE_SHA1, SIZE_OF_SHA1_DIGEST};7use crate::{borrowed::oid, Kind};
8
9#[cfg(feature = "sha1")]
10use crate::{EMPTY_BLOB_SHA1, EMPTY_TREE_SHA1, SIZE_OF_SHA1_DIGEST};
8 11
9#[cfg(feature = "sha256")]12#[cfg(feature = "sha256")]
10use crate::{EMPTY_BLOB_SHA256, EMPTY_TREE_SHA256, SIZE_OF_SHA256_DIGEST};13use crate::{EMPTY_BLOB_SHA256, EMPTY_TREE_SHA256, SIZE_OF_SHA256_DIGEST};
@@ -15,6 +18,7 @@ use crate::{EMPTY_BLOB_SHA256, EMPTY_TREE_SHA256, SIZE_OF_SHA256_DIGEST}; · 4 unmodified lines
15#[non_exhaustive]18#[non_exhaustive]
16pub enum ObjectId {19pub enum ObjectId {
17 /// A SHA1 hash digest20 /// A SHA1 hash digest
21 #[cfg(feature = "sha1")]
18 Sha1([u8; SIZE_OF_SHA1_DIGEST]),22 Sha1([u8; SIZE_OF_SHA1_DIGEST]),
19 /// A SHA256 hash digest23 /// A SHA256 hash digest
20 #[cfg(feature = "sha256")]24 #[cfg(feature = "sha256")]
@@ -38,7 +42,10 @@ impl Hash for ObjectId { · 17 unmodified lines
38pub mod decode {42pub mod decode {
39 use std::str::FromStr;43 use std::str::FromStr;
40 44
41 use crate::{object_id::ObjectId, SIZE_OF_SHA1_DIGEST, SIZE_OF_SHA1_HEX_DIGEST};45 use crate::object_id::ObjectId;
46
47 #[cfg(feature = "sha1")]
48 use crate::{SIZE_OF_SHA1_DIGEST, SIZE_OF_SHA1_HEX_DIGEST};
42 49
43 #[cfg(feature = "sha256")]50 #[cfg(feature = "sha256")]
44 use crate::{SIZE_OF_SHA256_DIGEST, SIZE_OF_SHA256_HEX_DIGEST};51 use crate::{SIZE_OF_SHA256_DIGEST, SIZE_OF_SHA256_HEX_DIGEST};
@@ -62,6 +69,7 @@ pub mod decode { · 17 unmodified lines
62 /// Such a buffer can be obtained using [`oid::write_hex_to(buffer)`][super::oid::write_hex_to()]69 /// Such a buffer can be obtained using [`oid::write_hex_to(buffer)`][super::oid::write_hex_to()]
63 pub fn from_hex(buffer: &[u8]) -> Result<ObjectId, Error> {70 pub fn from_hex(buffer: &[u8]) -> Result<ObjectId, Error> {
64 match buffer.len() {71 match buffer.len() {
72 #[cfg(feature = "sha1")]
65 SIZE_OF_SHA1_HEX_DIGEST => Ok({73 SIZE_OF_SHA1_HEX_DIGEST => Ok({
66 ObjectId::Sha1({74 ObjectId::Sha1({
67 let mut buf = [0; SIZE_OF_SHA1_DIGEST];75 let mut buf = [0; SIZE_OF_SHA1_DIGEST];
@@ -107,6 +115,7 @@ impl ObjectId { · 39 unmodified lines
107 #[inline]115 #[inline]
108 pub fn kind(&self) -> Kind {116 pub fn kind(&self) -> Kind {
109 match self {117 match self {
118 #[cfg(feature = "sha1")]
110 ObjectId::Sha1(_) => Kind::Sha1,119 ObjectId::Sha1(_) => Kind::Sha1,
111 #[cfg(feature = "sha256")]120 #[cfg(feature = "sha256")]
112 ObjectId::Sha256(_) => Kind::Sha256,121 ObjectId::Sha256(_) => Kind::Sha256,
@@ -116,6 +125,7 @@ impl ObjectId { · 3 unmodified lines
116 #[inline]125 #[inline]
117 pub fn as_slice(&self) -> &[u8] {126 pub fn as_slice(&self) -> &[u8] {
118 match self {127 match self {
128 #[cfg(feature = "sha1")]
119 Self::Sha1(b) => b.as_ref(),129 Self::Sha1(b) => b.as_ref(),
120 #[cfg(feature = "sha256")]130 #[cfg(feature = "sha256")]
121 Self::Sha256(b) => b.as_ref(),131 Self::Sha256(b) => b.as_ref(),
@@ -125,6 +135,7 @@ impl ObjectId { · 3 unmodified lines
125 #[inline]135 #[inline]
126 pub fn as_mut_slice(&mut self) -> &mut [u8] {136 pub fn as_mut_slice(&mut self) -> &mut [u8] {
127 match self {137 match self {
138 #[cfg(feature = "sha1")]
128 Self::Sha1(b) => b.as_mut(),139 Self::Sha1(b) => b.as_mut(),
129 #[cfg(feature = "sha256")]140 #[cfg(feature = "sha256")]
130 Self::Sha256(b) => b.as_mut(),141 Self::Sha256(b) => b.as_mut(),
@@ -135,6 +146,7 @@ impl ObjectId { · 4 unmodified lines
135 #[inline]146 #[inline]
136 pub const fn empty_blob(hash: Kind) -> ObjectId {147 pub const fn empty_blob(hash: Kind) -> ObjectId {
137 match hash {148 match hash {
149 #[cfg(feature = "sha1")]
138 Kind::Sha1 => ObjectId::Sha1(*EMPTY_BLOB_SHA1),150 Kind::Sha1 => ObjectId::Sha1(*EMPTY_BLOB_SHA1),
139 #[cfg(feature = "sha256")]151 #[cfg(feature = "sha256")]
140 Kind::Sha256 => ObjectId::Sha256(*EMPTY_BLOB_SHA256),152 Kind::Sha256 => ObjectId::Sha256(*EMPTY_BLOB_SHA256),
@@ -145,6 +157,7 @@ impl ObjectId { · 4 unmodified lines
145 #[inline]157 #[inline]
146 pub const fn empty_tree(hash: Kind) -> ObjectId {158 pub const fn empty_tree(hash: Kind) -> ObjectId {
147 match hash {159 match hash {
160 #[cfg(feature = "sha1")]
148 Kind::Sha1 => ObjectId::Sha1(*EMPTY_TREE_SHA1),161 Kind::Sha1 => ObjectId::Sha1(*EMPTY_TREE_SHA1),
149 #[cfg(feature = "sha256")]162 #[cfg(feature = "sha256")]
150 Kind::Sha256 => ObjectId::Sha256(*EMPTY_TREE_SHA256),163 Kind::Sha256 => ObjectId::Sha256(*EMPTY_TREE_SHA256),
@@ -156,6 +169,7 @@ impl ObjectId { · 5 unmodified lines
156 #[doc(alias = "zero", alias = "git2")]169 #[doc(alias = "zero", alias = "git2")]
157 pub const fn null(kind: Kind) -> ObjectId {170 pub const fn null(kind: Kind) -> ObjectId {
158 match kind {171 match kind {
172 #[cfg(feature = "sha1")]
159 Kind::Sha1 => Self::null_sha1(),173 Kind::Sha1 => Self::null_sha1(),
160 #[cfg(feature = "sha256")]174 #[cfg(feature = "sha256")]
161 Kind::Sha256 => Self::null_sha256(),175 Kind::Sha256 => Self::null_sha256(),
@@ -167,6 +181,7 @@ impl ObjectId { · 5 unmodified lines
167 #[doc(alias = "is_zero", alias = "git2")]181 #[doc(alias = "is_zero", alias = "git2")]
168 pub fn is_null(&self) -> bool {182 pub fn is_null(&self) -> bool {
169 match self {183 match self {
184 #[cfg(feature = "sha1")]
170 ObjectId::Sha1(digest) => &digest[..] == oid::null_sha1().as_bytes(),185 ObjectId::Sha1(digest) => &digest[..] == oid::null_sha1().as_bytes(),
171 #[cfg(feature = "sha256")]186 #[cfg(feature = "sha256")]
172 ObjectId::Sha256(digest) => &digest[..] == oid::null_sha256().as_bytes(),187 ObjectId::Sha256(digest) => &digest[..] == oid::null_sha256().as_bytes(),
@@ -193,6 +208,7 @@ impl ObjectId { · 20 unmodified lines
193 /// Use `Self::try_from(bytes)` for a fallible version.208 /// Use `Self::try_from(bytes)` for a fallible version.
194 pub fn from_bytes_or_panic(bytes: &[u8]) -> Self {209 pub fn from_bytes_or_panic(bytes: &[u8]) -> Self {
195 match bytes.len() {210 match bytes.len() {
211 #[cfg(feature = "sha1")]
196 SIZE_OF_SHA1_DIGEST => Self::Sha1(bytes.try_into().expect("prior length validation")),212 SIZE_OF_SHA1_DIGEST => Self::Sha1(bytes.try_into().expect("prior length validation")),
197 #[cfg(feature = "sha256")]213 #[cfg(feature = "sha256")]
198 SIZE_OF_SHA256_DIGEST => Self::Sha256(bytes.try_into().expect("prior length validation")),214 SIZE_OF_SHA256_DIGEST => Self::Sha256(bytes.try_into().expect("prior length validation")),
@@ -205,6 +221,7 @@ impl ObjectId { · 6 unmodified lines
205impl ObjectId {221impl ObjectId {
206 /// Instantiate an `ObjectId` from a 20 bytes SHA1 digest.222 /// Instantiate an `ObjectId` from a 20 bytes SHA1 digest.
207 #[inline]223 #[inline]
224 #[cfg(feature = "sha1")]
208 fn new_sha1(id: [u8; SIZE_OF_SHA1_DIGEST]) -> Self {225 fn new_sha1(id: [u8; SIZE_OF_SHA1_DIGEST]) -> Self {
209 ObjectId::Sha1(id)226 ObjectId::Sha1(id)
210 }227 }
@@ -220,6 +237,7 @@ impl ObjectId { · 9 unmodified lines
220 ///237 ///
221 /// Panics if the slice doesn't have a length of 20.238 /// Panics if the slice doesn't have a length of 20.
222 #[inline]239 #[inline]
240 #[cfg(feature = "sha1")]
223 pub(crate) fn from_20_bytes(b: &[u8]) -> ObjectId {241 pub(crate) fn from_20_bytes(b: &[u8]) -> ObjectId {
224 let mut id = [0; SIZE_OF_SHA1_DIGEST];242 let mut id = [0; SIZE_OF_SHA1_DIGEST];
225 id.copy_from_slice(b);243 id.copy_from_slice(b);
@@ -239,6 +257,7 @@ impl ObjectId { · 13 unmodified lines
239 257
240 /// Returns an `ObjectId` representing a SHA1 whose memory is zeroed.258 /// Returns an `ObjectId` representing a SHA1 whose memory is zeroed.
241 #[inline]259 #[inline]
260 #[cfg(feature = "sha1")]
242 pub(crate) const fn null_sha1() -> ObjectId {261 pub(crate) const fn null_sha1() -> ObjectId {
243 ObjectId::Sha1([0u8; SIZE_OF_SHA1_DIGEST])262 ObjectId::Sha1([0u8; SIZE_OF_SHA1_DIGEST])
244 }263 }
@@ -254,6 +273,7 @@ impl ObjectId { · 9 unmodified lines
254impl std::fmt::Debug for ObjectId {273impl std::fmt::Debug for ObjectId {
255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {274 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 match self {275 match self {
276 #[cfg(feature = "sha1")]
257 ObjectId::Sha1(_hash) => f.write_str("Sha1(")?,277 ObjectId::Sha1(_hash) => f.write_str("Sha1(")?,
258 #[cfg(feature = "sha256")]278 #[cfg(feature = "sha256")]
259 ObjectId::Sha256(_) => f.write_str("Sha256(")?,279 ObjectId::Sha256(_) => f.write_str("Sha256(")?,
@@ -265,6 +285,7 @@ impl std::fmt::Debug for ObjectId { · 5 unmodified lines
265 }285 }
266}286}
267 287
288#[cfg(feature = "sha1")]
268impl From<[u8; SIZE_OF_SHA1_DIGEST]> for ObjectId {289impl From<[u8; SIZE_OF_SHA1_DIGEST]> for ObjectId {
269 fn from(v: [u8; SIZE_OF_SHA1_DIGEST]) -> Self {290 fn from(v: [u8; SIZE_OF_SHA1_DIGEST]) -> Self {
270 Self::new_sha1(v)291 Self::new_sha1(v)
@@ -281,6 +302,7 @@ impl From<[u8; SIZE_OF_SHA256_DIGEST]> for ObjectId { · 10 unmodified lines
281impl From<&oid> for ObjectId {302impl From<&oid> for ObjectId {
282 fn from(v: &oid) -> Self {303 fn from(v: &oid) -> Self {
283 match v.kind() {304 match v.kind() {
305 #[cfg(feature = "sha1")]
284 Kind::Sha1 => ObjectId::from_20_bytes(v.as_bytes()),306 Kind::Sha1 => ObjectId::from_20_bytes(v.as_bytes()),
285 #[cfg(feature = "sha256")]307 #[cfg(feature = "sha256")]
286 Kind::Sha256 => ObjectId::from_32_bytes(v.as_bytes()),308 Kind::Sha256 => ObjectId::from_32_bytes(v.as_bytes()),
gix-hash/src/oid.rs+21−1
@@ -1,6 +1,9 @@
1use std::hash;1use std::hash;
2 2
3use crate::{Kind, ObjectId, EMPTY_BLOB_SHA1, EMPTY_TREE_SHA1, SIZE_OF_SHA1_DIGEST};3use crate::{Kind, ObjectId};
4
5#[cfg(feature = "sha1")]
6use crate::{EMPTY_BLOB_SHA1, EMPTY_TREE_SHA1, SIZE_OF_SHA1_DIGEST};
4 7
5#[cfg(feature = "sha256")]8#[cfg(feature = "sha256")]
6use crate::{EMPTY_BLOB_SHA256, EMPTY_TREE_SHA256, SIZE_OF_SHA256_DIGEST};9use crate::{EMPTY_BLOB_SHA256, EMPTY_TREE_SHA256, SIZE_OF_SHA256_DIGEST};
@@ -59,6 +62,7 @@ impl std::fmt::Debug for oid { · 52 unmodified lines
59 f,62 f,
60 "{}({})",63 "{}({})",
61 match self.kind() {64 match self.kind() {
65 #[cfg(feature = "sha1")]
62 Kind::Sha1 => "Sha1",66 Kind::Sha1 => "Sha1",
63 #[cfg(feature = "sha256")]67 #[cfg(feature = "sha256")]
64 Kind::Sha256 => "Sha256",68 Kind::Sha256 => "Sha256",
@@ -82,6 +86,7 @@ impl oid { · 17 unmodified lines
82 #[inline]86 #[inline]
83 pub fn try_from_bytes(digest: &[u8]) -> Result<&Self, Error> {87 pub fn try_from_bytes(digest: &[u8]) -> Result<&Self, Error> {
84 match digest.len() {88 match digest.len() {
89 #[cfg(feature = "sha1")]
85 SIZE_OF_SHA1_DIGEST => Ok(90 SIZE_OF_SHA1_DIGEST => Ok(
86 #[allow(unsafe_code)]91 #[allow(unsafe_code)]
87 unsafe {92 unsafe {
@@ -178,6 +183,7 @@ impl oid { · 90 unmodified lines
178 #[doc(alias = "is_zero", alias = "git2")]183 #[doc(alias = "is_zero", alias = "git2")]
179 pub fn is_null(&self) -> bool {184 pub fn is_null(&self) -> bool {
180 match self.kind() {185 match self.kind() {
186 #[cfg(feature = "sha1")]
181 Kind::Sha1 => &self.bytes == oid::null_sha1().as_bytes(),187 Kind::Sha1 => &self.bytes == oid::null_sha1().as_bytes(),
182 #[cfg(feature = "sha256")]188 #[cfg(feature = "sha256")]
183 Kind::Sha256 => &self.bytes == oid::null_sha256().as_bytes(),189 Kind::Sha256 => &self.bytes == oid::null_sha256().as_bytes(),
@@ -188,6 +194,7 @@ impl oid { · 4 unmodified lines
188 #[inline]194 #[inline]
189 pub fn is_empty_blob(&self) -> bool {195 pub fn is_empty_blob(&self) -> bool {
190 match self.kind() {196 match self.kind() {
197 #[cfg(feature = "sha1")]
191 Kind::Sha1 => &self.bytes == oid::empty_blob_sha1().as_bytes(),198 Kind::Sha1 => &self.bytes == oid::empty_blob_sha1().as_bytes(),
192 #[cfg(feature = "sha256")]199 #[cfg(feature = "sha256")]
193 Kind::Sha256 => &self.bytes == oid::empty_blob_sha256().as_bytes(),200 Kind::Sha256 => &self.bytes == oid::empty_blob_sha256().as_bytes(),
@@ -198,6 +205,7 @@ impl oid { · 4 unmodified lines
198 #[inline]205 #[inline]
199 pub fn is_empty_tree(&self) -> bool {206 pub fn is_empty_tree(&self) -> bool {
200 match self.kind() {207 match self.kind() {
208 #[cfg(feature = "sha1")]
201 Kind::Sha1 => &self.bytes == oid::empty_tree_sha1().as_bytes(),209 Kind::Sha1 => &self.bytes == oid::empty_tree_sha1().as_bytes(),
202 #[cfg(feature = "sha256")]210 #[cfg(feature = "sha256")]
203 Kind::Sha256 => &self.bytes == oid::empty_tree_sha256().as_bytes(),211 Kind::Sha256 => &self.bytes == oid::empty_tree_sha256().as_bytes(),
@@ -209,6 +217,7 @@ impl oid { · 5 unmodified lines
209impl oid {217impl oid {
210 /// Returns a SHA1 digest with all bytes being initialized to zero.218 /// Returns a SHA1 digest with all bytes being initialized to zero.
211 #[inline]219 #[inline]
220 #[cfg(feature = "sha1")]
212 pub(crate) fn null_sha1() -> &'static Self {221 pub(crate) fn null_sha1() -> &'static Self {
213 oid::from_bytes([0u8; SIZE_OF_SHA1_DIGEST].as_ref())222 oid::from_bytes([0u8; SIZE_OF_SHA1_DIGEST].as_ref())
214 }223 }
@@ -222,6 +231,7 @@ impl oid { · 7 unmodified lines
222 231
223 /// Returns an `oid` representing the SHA1 hash of an empty blob.232 /// Returns an `oid` representing the SHA1 hash of an empty blob.
224 #[inline]233 #[inline]
234 #[cfg(feature = "sha1")]
225 pub(crate) fn empty_blob_sha1() -> &'static Self {235 pub(crate) fn empty_blob_sha1() -> &'static Self {
226 oid::from_bytes(EMPTY_BLOB_SHA1)236 oid::from_bytes(EMPTY_BLOB_SHA1)
227 }237 }
@@ -235,6 +245,7 @@ impl oid { · 7 unmodified lines
235 245
236 /// Returns an `oid` representing the SHA1 hash of an empty tree.246 /// Returns an `oid` representing the SHA1 hash of an empty tree.
237 #[inline]247 #[inline]
248 #[cfg(feature = "sha1")]
238 pub(crate) fn empty_tree_sha1() -> &'static Self {249 pub(crate) fn empty_tree_sha1() -> &'static Self {
239 oid::from_bytes(EMPTY_TREE_SHA1)250 oid::from_bytes(EMPTY_TREE_SHA1)
240 }251 }
@@ -266,6 +277,7 @@ impl ToOwned for oid { · 25 unmodified lines
266 277
267 fn to_owned(&self) -> Self::Owned {278 fn to_owned(&self) -> Self::Owned {
268 match self.kind() {279 match self.kind() {
280 #[cfg(feature = "sha1")]
269 Kind::Sha1 => ObjectId::Sha1(self.bytes.try_into().expect("no bug in hash detection")),281 Kind::Sha1 => ObjectId::Sha1(self.bytes.try_into().expect("no bug in hash detection")),
270 #[cfg(feature = "sha256")]282 #[cfg(feature = "sha256")]
271 Kind::Sha256 => ObjectId::Sha256(self.bytes.try_into().expect("no bug in hash detection")),283 Kind::Sha256 => ObjectId::Sha256(self.bytes.try_into().expect("no bug in hash detection")),
@@ -273,12 +285,20 @@ impl ToOwned for oid { · 1 unmodified line
273 }285 }
274}286}
275 287
288#[cfg(feature = "sha1")]
276impl<'a> From<&'a [u8; SIZE_OF_SHA1_DIGEST]> for &'a oid {289impl<'a> From<&'a [u8; SIZE_OF_SHA1_DIGEST]> for &'a oid {
277 fn from(v: &'a [u8; SIZE_OF_SHA1_DIGEST]) -> Self {290 fn from(v: &'a [u8; SIZE_OF_SHA1_DIGEST]) -> Self {
278 oid::from_bytes(v.as_ref())291 oid::from_bytes(v.as_ref())
279 }292 }
280}293}
281 294
295#[cfg(feature = "sha256")]
296impl<'a> From<&'a [u8; SIZE_OF_SHA256_DIGEST]> for &'a oid {
297 fn from(v: &'a [u8; SIZE_OF_SHA256_DIGEST]) -> Self {
298 oid::from_bytes(v.as_ref())
299 }
300}
301
282impl std::fmt::Display for &oid {302impl std::fmt::Display for &oid {
283 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {303 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
284 let mut buf = Kind::hex_buf();304 let mut buf = Kind::hex_buf();
gix-hash/tests/hash/kind.rs+0−1
@@ -90,7 +90,6 @@ fn longest_sha1() { · 89 unmodified lines
90 assert_eq!(longest, Kind::Sha1);90 assert_eq!(longest, Kind::Sha1);
91}91}
92 92
93// TODO: make sure to test all permutations once `sha1` is fully optional
94#[test]93#[test]
95#[cfg(all(not(feature = "sha1"), feature = "sha256"))]94#[cfg(all(not(feature = "sha1"), feature = "sha256"))]
96fn longest_sha256() {95fn longest_sha256() {
justfile+2−0
@@ -71,6 +71,7 @@ check: · 70 unmodified lines
71 cargo check -p gix-hash --all-features71 cargo check -p gix-hash --all-features
72 cargo check -p gix-hash72 cargo check -p gix-hash
73 cargo check -p gix-hash --features sha25673 cargo check -p gix-hash --features sha256
74 cargo check -p gix-hash --no-default-features --features sha256
74 cargo check -p gix-object --all-features75 cargo check -p gix-object --all-features
75 cargo check -p gix-object --features verbose-object-parsing-errors76 cargo check -p gix-object --features verbose-object-parsing-errors
76 cargo check -p gix-attributes --features serde77 cargo check -p gix-attributes --features serde
@@ -158,6 +159,7 @@ unit-tests: · 81 unmodified lines
158 cargo nextest run -p gix-worktree-tests --features gix-features-parallel --no-fail-fast159 cargo nextest run -p gix-worktree-tests --features gix-features-parallel --no-fail-fast
159 cargo nextest run -p gix-hash --no-fail-fast160 cargo nextest run -p gix-hash --no-fail-fast
160 cargo nextest run -p gix-hash --features sha256 --no-fail-fast161 cargo nextest run -p gix-hash --features sha256 --no-fail-fast
162 cargo nextest run -p gix-hash --no-default-features --features sha256 --no-fail-fast # TODO: make this actually work by removing 'sha1' from default features.
161 cargo nextest run -p gix-object --no-fail-fast163 cargo nextest run -p gix-object --no-fail-fast
162 cargo nextest run -p gix-object --features verbose-object-parsing-errors --no-fail-fast164 cargo nextest run -p gix-object --features verbose-object-parsing-errors --no-fail-fast
163 cargo nextest run -p gix-tempfile --features signals --no-fail-fast165 cargo nextest run -p gix-tempfile --features signals --no-fail-fast

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t