1use std::str::FromStr;
2
3use crate::{oid, Kind, ObjectId};
4
5#[cfg(feature = "sha1")]
6use crate::{SIZE_OF_SHA1_DIGEST, SIZE_OF_SHA1_HEX_DIGEST};
7
8#[cfg(feature = "sha256")]
9use crate::{SIZE_OF_SHA256_DIGEST, SIZE_OF_SHA256_HEX_DIGEST};
10
11impl TryFrom<u8> for Kind {
12 type Error = u8;
13
14 fn try_from(value: u8) -> Result<Self, Self::Error> {
15 Ok(match value {
16 #[cfg(feature = "sha1")]
17 1 => Kind::Sha1,
18 #[cfg(feature = "sha256")]
19 2 => Kind::Sha256,
20 unknown => return Err(unknown),
21 })
22 }
23}
24
25impl FromStr for Kind {
26 type Err = String;
27
28 fn from_str(s: &str) -> Result<Self, Self::Err> {
29 Ok(match s {
30 #[cfg(feature = "sha1")]
31 "sha1" | "SHA1" | "SHA-1" => Kind::Sha1,
32 #[cfg(feature = "sha256")]
33 "sha256" | "SHA256" | "SHA-256" => Kind::Sha256,
34 other => return Err(other.into()),
35 })
36 }
37}
38
39impl std::fmt::Display for Kind {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 match self {
42 #[cfg(feature = "sha1")]
43 Kind::Sha1 => f.write_str("sha1"),
44 #[cfg(feature = "sha256")]
45 Kind::Sha256 => f.write_str("sha256"),
46 }
47 }
48}
49
50impl Kind {
51 #[inline]
53 pub const fn shortest() -> Self {
54 #[cfg(all(not(feature = "sha1"), feature = "sha256"))]
55 {
56 Self::Sha256
57 }
58 #[cfg(feature = "sha1")]
59 {
60 Self::Sha1
61 }
62 }
63
64 #[inline]
66 pub const fn longest() -> Self {
67 #[cfg(feature = "sha256")]
68 {
69 Self::Sha256
70 }
71 #[cfg(all(not(feature = "sha256"), feature = "sha1"))]
72 {
73 Self::Sha1
74 }
75 }
76
77 #[inline]
79 pub const fn hex_buf() -> [u8; Kind::longest().len_in_hex()] {
80 [0u8; Kind::longest().len_in_hex()]
81 }
82
83 #[inline]
85 pub const fn buf() -> [u8; Kind::longest().len_in_bytes()] {
86 [0u8; Kind::longest().len_in_bytes()]
87 }
88
89 #[inline]
91 pub const fn len_in_hex(&self) -> usize {
92 match self {
93 #[cfg(feature = "sha1")]
94 Kind::Sha1 => SIZE_OF_SHA1_HEX_DIGEST,
95 #[cfg(feature = "sha256")]
96 Kind::Sha256 => SIZE_OF_SHA256_HEX_DIGEST,
97 }
98 }
99
100 #[inline]
102 pub const fn len_in_bytes(&self) -> usize {
103 match self {
104 #[cfg(feature = "sha1")]
105 Kind::Sha1 => SIZE_OF_SHA1_DIGEST,
106 #[cfg(feature = "sha256")]
107 Kind::Sha256 => SIZE_OF_SHA256_DIGEST,
108 }
109 }
110
111 #[inline]
115 pub const fn from_hex_len(hex_len: usize) -> Option<Self> {
116 Some(match hex_len {
117 #[cfg(feature = "sha1")]
118 0..=SIZE_OF_SHA1_HEX_DIGEST => Kind::Sha1,
119 #[cfg(feature = "sha256")]
120 0..=SIZE_OF_SHA256_HEX_DIGEST => Kind::Sha256,
121 _ => return None,
122 })
123 }
124
125 #[inline]
134 pub(crate) fn from_len_in_bytes(bytes: usize) -> Self {
135 match bytes {
136 #[cfg(feature = "sha1")]
137 SIZE_OF_SHA1_DIGEST => Kind::Sha1,
138 #[cfg(feature = "sha256")]
139 SIZE_OF_SHA256_DIGEST => Kind::Sha256,
140 _ => panic!("BUG: must be called only with valid hash lengths produced by len_in_bytes()"),
141 }
142 }
143
144 #[inline]
146 pub fn null_ref(&self) -> &'static oid {
147 match self {
148 #[cfg(feature = "sha1")]
149 Kind::Sha1 => oid::null_sha1(),
150 #[cfg(feature = "sha256")]
151 Kind::Sha256 => oid::null_sha256(),
152 }
153 }
154
155 #[inline]
157 pub const fn null(&self) -> ObjectId {
158 match self {
159 #[cfg(feature = "sha1")]
160 Kind::Sha1 => ObjectId::null_sha1(),
161 #[cfg(feature = "sha256")]
162 Kind::Sha256 => ObjectId::null_sha256(),
163 }
164 }
165
166 #[inline]
168 pub const fn empty_blob(&self) -> ObjectId {
169 ObjectId::empty_blob(*self)
170 }
171
172 #[inline]
174 pub const fn empty_tree(&self) -> ObjectId {
175 ObjectId::empty_tree(*self)
176 }
177}