oid: SHA1_DIGEST_LEN → Oid::LEN_SHA1

A small refactor to move this constant closer to the `enum` that it is
about. An associated constant constant fits more nicely.

Reason for changing the name from `SHA1_*_LEN` to `LEN_SHA1`: As we
think about the object format in the future becoming variable, we
would have that the length of an OID is parameterized by the object
format. So, we imagine a function `fn len(format: ObjectFormat)`, to
be called as `Oid::len(ObjectFormat::Sha1)`. This is the new order
we use.
This commit is contained in:
Lorenz Leutgeb 2026-04-23 21:42:36 +02:00 committed by Lorenz Leutgeb
parent 4c605c0671
commit f46624b81c
1 changed files with 20 additions and 15 deletions

View File

@ -74,12 +74,10 @@ extern crate alloc;
#[cfg(not(feature = "sha1"))] #[cfg(not(feature = "sha1"))]
compile_error!("The `sha1` feature is required."); compile_error!("The `sha1` feature is required.");
const SHA1_DIGEST_LEN: usize = 20;
#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Copy)] #[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Copy)]
#[non_exhaustive] #[non_exhaustive]
pub enum Oid { pub enum Oid {
Sha1([u8; SHA1_DIGEST_LEN]), Sha1([u8; Self::LEN_SHA1]),
} }
/// Conversions to/from SHA-1. /// Conversions to/from SHA-1.
@ -87,18 +85,21 @@ pub enum Oid {
// for forwards compatibility: What if another hash with digests of the same // for forwards compatibility: What if another hash with digests of the same
// length becomes popular? // length becomes popular?
impl Oid { impl Oid {
/// The length of a SHA-1 object identifier in bytes.
const SHA1_LEN: usize = 20;
/// A SHA-1 object identifier with all digest bytes set to zero. /// A SHA-1 object identifier with all digest bytes set to zero.
/// This is sometimes used as a sentinel value to indicate the absence of /// This is sometimes used as a sentinel value to indicate the absence of
/// an object. /// an object.
/// To compare whether an object identifier is zero, prefer the method /// To compare whether an object identifier is zero, prefer the method
/// [`Oid::is_zero`] over checking equality with this constant. /// [`Oid::is_zero`] over checking equality with this constant.
pub const ZERO_SHA1: Self = Self::Sha1([0u8; SHA1_DIGEST_LEN]); pub const ZERO_SHA1: Self = Self::Sha1([0u8; Self::LEN_SHA1]);
pub fn from_sha1(digest: [u8; SHA1_DIGEST_LEN]) -> Self { pub fn from_sha1(digest: [u8; Self::LEN_SHA1]) -> Self {
Self::Sha1(digest) Self::Sha1(digest)
} }
pub fn into_sha1(&self) -> Option<[u8; SHA1_DIGEST_LEN]> { pub fn into_sha1(&self) -> Option<[u8; Self::LEN_SHA1]> {
match self { match self {
Oid::Sha1(digest) => Some(*digest), Oid::Sha1(digest) => Some(*digest),
} }
@ -133,11 +134,11 @@ impl From<Oid> for alloc::boxed::Box<[u8]> {
} }
pub mod str { pub mod str {
use super::{Oid, SHA1_DIGEST_LEN}; use super::Oid;
use core::str; use core::str;
/// Length of the string representation of a SHA-1 digest in hexadecimal notation. /// Length of the string representation of a SHA-1 digest in hexadecimal notation.
pub(super) const SHA1_DIGEST_STR_LEN: usize = SHA1_DIGEST_LEN * 2; pub(super) const SHA1_DIGEST_STR_LEN: usize = Oid::LEN_SHA1 * 2;
impl str::FromStr for Oid { impl str::FromStr for Oid {
type Err = error::ParseOidError; type Err = error::ParseOidError;
@ -150,8 +151,8 @@ pub mod str {
return Err(Len(len)); return Err(Len(len));
} }
let mut bytes = [0u8; SHA1_DIGEST_LEN]; let mut bytes = [0u8; Oid::LEN_SHA1];
for i in 0..SHA1_DIGEST_LEN { for i in 0..Oid::LEN_SHA1 {
bytes[i] = u8::from_str_radix(&s[i * 2..=i * 2 + 1], 16) bytes[i] = u8::from_str_radix(&s[i * 2..=i * 2 + 1], 16)
.map_err(|source| At { index: i, source })?; .map_err(|source| At { index: i, source })?;
} }
@ -468,7 +469,7 @@ mod test {
impl Arbitrary for Oid { impl Arbitrary for Oid {
fn arbitrary(g: &mut Gen) -> Self { fn arbitrary(g: &mut Gen) -> Self {
let slice = [0u8; SHA1_DIGEST_LEN]; let slice = [0u8; Oid::SHA1_LEN];
g.fill(slice); g.fill(slice);
Self::Sha1(slice) Self::Sha1(slice)
} }
@ -511,10 +512,11 @@ mod serde {
type Value = Oid; type Value = Oid;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
use crate::str::SHA1_DIGEST_STR_LEN;
write!( write!(
f, f,
"a Git object identifier (SHA-1 digest in hexadecimal notation; {SHA1_DIGEST_STR_LEN} characters; {SHA1_DIGEST_LEN} bytes)" "a Git object identifier (SHA-1 digest in hexadecimal notation; {} characters; {} bytes)",
crate::str::SHA1_DIGEST_STR_LEN,
Oid::LEN_SHA1
) )
} }
@ -571,9 +573,12 @@ mod schemars {
} }
fn json_schema(_: &mut SchemaGenerator) -> Schema { fn json_schema(_: &mut SchemaGenerator) -> Schema {
use crate::{SHA1_DIGEST_LEN, str::SHA1_DIGEST_STR_LEN}; use crate::str::SHA1_DIGEST_STR_LEN;
json_schema!({ json_schema!({
"description": format!("A Git object identifier (SHA-1 digest in hexadecimal notation; {SHA1_DIGEST_STR_LEN} characters; {SHA1_DIGEST_LEN} bytes)"), "description": format!(
"A Git object identifier (SHA-1 digest in hexadecimal notation; {SHA1_DIGEST_STR_LEN} characters; {} bytes)",
Oid::LEN_SHA1,
),
"type": "string", "type": "string",
"maxLength": SHA1_DIGEST_STR_LEN, "maxLength": SHA1_DIGEST_STR_LEN,
"minLength": SHA1_DIGEST_STR_LEN, "minLength": SHA1_DIGEST_STR_LEN,