Skip to main content

git_core/
hash.rs

1use crate::error::{GitError, Result};
2use std::fmt;
3
4#[derive(Clone, Copy, PartialEq, Eq, Hash)]
5pub struct GitHash(pub [u8; 20]);
6
7impl GitHash {
8    pub fn from_hex(s: &str) -> Result<Self> {
9        if s.len() != 40 {
10            return Err(GitError::InvalidHash(format!(
11                "expected 40 hex chars, got {}: {:?}",
12                s.len(),
13                s
14            )));
15        }
16        let mut bytes = [0u8; 20];
17        hex::decode_to_slice(s, &mut bytes)
18            .map_err(|e| GitError::InvalidHash(format!("{e}: {s:?}")))?;
19        Ok(Self(bytes))
20    }
21
22    pub fn from_bytes(b: &[u8]) -> Result<Self> {
23        b.try_into()
24            .map(|arr: [u8; 20]| Self(arr))
25            .map_err(|_| GitError::InvalidHash(format!("expected 20 bytes, got {}", b.len())))
26    }
27
28    pub fn as_bytes(&self) -> &[u8; 20] {
29        &self.0
30    }
31
32    pub fn to_hex(&self) -> String {
33        hex::encode(self.0)
34    }
35
36    pub fn object_path(&self) -> (String, String) {
37        let hex = self.to_hex();
38        (hex[..2].to_string(), hex[2..].to_string())
39    }
40}
41
42impl fmt::Debug for GitHash {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        write!(f, "GitHash({})", self.to_hex())
45    }
46}
47
48impl fmt::Display for GitHash {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        write!(f, "{}", self.to_hex())
51    }
52}