Skip to main content

gix_hash/
lib.rs

1//! This crate provides types for identifying git objects using a hash digest.
2//!
3//! These are provided in [borrowed versions][oid] as well as an [owned one][ObjectId].
4//!
5//! ## Examples
6//!
7//! ```
8//! use gix_hash::{hasher, Kind, ObjectId, Prefix};
9//!
10//! let id = ObjectId::from_hex(b"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391").unwrap();
11//! assert_eq!(id.kind(), Kind::Sha1);
12//! assert!(id.is_empty_blob());
13//!
14//! let prefix = Prefix::new(&id, 7).unwrap();
15//! assert_eq!(prefix.to_string(), "e69de29");
16//!
17//! let mut digest = hasher(Kind::Sha1);
18//! digest.update(id.as_slice());
19//! let hashed_bytes = digest.try_finalize().unwrap();
20//! assert_eq!(hashed_bytes.kind(), Kind::Sha1);
21//! assert_ne!(hashed_bytes, id);
22//! ```
23//! ## Feature Flags
24#![cfg_attr(
25    all(doc, feature = "document-features"),
26    doc = ::document_features::document_features!()
27)]
28#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]
29#![deny(missing_docs, unsafe_code)]
30
31#[cfg(all(not(feature = "sha1"), not(feature = "sha256")))]
32compile_error!("Please set either the `sha1` or the `sha256` feature flag");
33
34macro_rules! impl_partial_eq_str_one_way {
35    ($type:ty) => {
36        impl PartialEq<str> for $type {
37            fn eq(&self, other: &str) -> bool {
38                self.eq_str(other)
39            }
40        }
41
42        impl PartialEq<&str> for $type {
43            fn eq(&self, other: &&str) -> bool {
44                self.eq_str(other)
45            }
46        }
47
48        impl PartialEq<String> for $type {
49            fn eq(&self, other: &String) -> bool {
50                self.eq_str(other)
51            }
52        }
53    };
54}
55
56macro_rules! impl_partial_eq_str {
57    ($type:ty) => {
58        impl_partial_eq_str_one_way!($type);
59
60        impl PartialEq<$type> for str {
61            fn eq(&self, other: &$type) -> bool {
62                other.eq_str(self)
63            }
64        }
65
66        impl PartialEq<$type> for &str {
67            fn eq(&self, other: &$type) -> bool {
68                other.eq_str(self)
69            }
70        }
71
72        impl PartialEq<$type> for String {
73            fn eq(&self, other: &$type) -> bool {
74                other.eq_str(self)
75            }
76        }
77    };
78}
79
80#[path = "oid.rs"]
81mod borrowed;
82pub use borrowed::{Error, oid};
83
84/// Hash functions and hash utilities
85pub mod hasher;
86pub use hasher::_impl::{Hasher, hasher};
87
88/// Error types for utility hash functions
89pub mod io;
90pub use io::_impl::{bytes, bytes_of_file, bytes_with_hasher};
91
92mod object_id;
93pub use object_id::{ObjectId, decode};
94
95/// JJ-compatible change identifiers and their reverse-hex formatting.
96pub mod change_id;
97
98/// Object ID prefixes and their parsing and comparison.
99pub mod prefix;
100
101/// Object ID verification.
102pub mod verify;
103
104/// An object hash used as stable identifier for a change.
105///
106/// Its bytes are identical to the wrapped [`ObjectId`], but its textual form uses
107/// Jujutsu's reverse-hex alphabet `z` through `k` instead of `0` through `f`.
108#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Copy, Debug)]
109#[repr(transparent)]
110#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent))]
111pub struct ChangeId(
112    /// The object hash whose bytes represent this change identifier.
113    ObjectId,
114);
115
116/// A partial, owned hash possibly identifying an object uniquely, whose non-prefix bytes are zeroed.
117///
118/// An example would `0000000000000000000000000000000032bd3242`, where `32bd3242` is the prefix,
119/// which would be able to match all hashes that *start with* `32bd3242`.
120#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Copy, Debug)]
121#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
122pub struct Prefix {
123    bytes: ObjectId,
124    hex_len: usize,
125}
126
127/// The size of a SHA1 hash digest in bytes.
128#[cfg(feature = "sha1")]
129const SIZE_OF_SHA1_DIGEST: usize = 20;
130/// The size of a SHA1 hash digest in hex.
131#[cfg(feature = "sha1")]
132const SIZE_OF_SHA1_HEX_DIGEST: usize = 2 * SIZE_OF_SHA1_DIGEST;
133
134/// The size of a SHA256 hash digest in bytes.
135#[cfg(feature = "sha256")]
136const SIZE_OF_SHA256_DIGEST: usize = 32;
137/// The size of a SHA256 hash digest in hex.
138#[cfg(feature = "sha256")]
139const SIZE_OF_SHA256_HEX_DIGEST: usize = 2 * SIZE_OF_SHA256_DIGEST;
140
141#[cfg(feature = "sha1")]
142const EMPTY_BLOB_SHA1: &[u8; SIZE_OF_SHA1_DIGEST] =
143    b"\xe6\x9d\xe2\x9b\xb2\xd1\xd6\x43\x4b\x8b\x29\xae\x77\x5a\xd8\xc2\xe4\x8c\x53\x91";
144#[cfg(feature = "sha1")]
145const EMPTY_TREE_SHA1: &[u8; SIZE_OF_SHA1_DIGEST] =
146    b"\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04";
147
148#[cfg(feature = "sha256")]
149const 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";
150#[cfg(feature = "sha256")]
151const 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";
152
153/// Denotes the kind of function to produce a [`ObjectId`].
154#[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
155#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
156#[non_exhaustive]
157pub enum Kind {
158    /// The SHA1 hash with 160 bits.
159    #[cfg_attr(feature = "sha1", default)]
160    #[cfg(feature = "sha1")]
161    Sha1 = 1,
162    /// The SHA256 hash with 256 bits.
163    #[cfg_attr(all(not(feature = "sha1"), feature = "sha256"), default)]
164    #[cfg(feature = "sha256")]
165    Sha256 = 2,
166}
167
168mod kind;