Skip to content

Commit a93074d

Browse files
committed
feat: add Prefix::from_hex_nonempty() to allow creating short prefixes.
This can be useful in certain situations where the set of candidate object ids is very small.
1 parent 691a205 commit a93074d

File tree

3 files changed

+88
-20
lines changed

3 files changed

+88
-20
lines changed

Cargo.lock

Lines changed: 17 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gix-hash/src/prefix.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,23 @@ impl Prefix {
9393
}
9494

9595
/// Create an instance from the given hexadecimal prefix `value`, e.g. `35e77c16` would yield a `Prefix` with `hex_len()` = 8.
96+
/// Note that the minimum hex length is `4` - use [`Self::from_hex_nonempty()`].
9697
pub fn from_hex(value: &str) -> Result<Self, from_hex::Error> {
9798
let hex_len = value.len();
99+
if hex_len < Self::MIN_HEX_LEN {
100+
return Err(from_hex::Error::TooShort { hex_len });
101+
}
102+
Self::from_hex_nonempty(value)
103+
}
104+
105+
/// Create an instance from the given hexadecimal prefix `value`, e.g. `35e` would yield a `Prefix` with `hex_len()` = 3.
106+
/// Note that this function supports all non-empty hex input - for a more typical implementation, use [`Self::from_hex()`].
107+
pub fn from_hex_nonempty(value: &str) -> Result<Self, from_hex::Error> {
108+
let hex_len = value.len();
98109

99110
if hex_len > crate::Kind::longest().len_in_hex() {
100111
return Err(from_hex::Error::TooLong { hex_len });
101-
} else if hex_len < Self::MIN_HEX_LEN {
112+
} else if hex_len == 0 {
102113
return Err(from_hex::Error::TooShort { hex_len });
103114
}
104115

gix-hash/tests/hash/prefix.rs

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ mod try_from {
8080
use crate::hex_to_id;
8181

8282
#[test]
83-
fn id_8_chars() {
83+
fn id_6_chars() {
8484
let oid_hex = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
8585
let input = "abcdef";
8686

@@ -90,7 +90,7 @@ mod try_from {
9090
}
9191

9292
#[test]
93-
fn id_9_chars() {
93+
fn id_7_chars() {
9494
let oid_hex = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
9595
let input = "abcdefa";
9696

@@ -107,7 +107,7 @@ mod try_from {
107107
}
108108

109109
#[test]
110-
fn id_to_long() {
110+
fn id_too_long() {
111111
let input = "abcdefabcdefabcdefabcdefabcdefabcdefabcd123123123123123123";
112112
let expected = Error::TooLong { hex_len: 58 };
113113
let actual = Prefix::try_from(input).unwrap_err();
@@ -122,3 +122,59 @@ mod try_from {
122122
assert_eq!(actual, expected);
123123
}
124124
}
125+
126+
mod from_hex_nonempty {
127+
use std::cmp::Ordering;
128+
129+
use gix_hash::{prefix::from_hex::Error, Prefix};
130+
131+
use crate::hex_to_id;
132+
133+
#[test]
134+
fn id_6_chars() {
135+
let oid_hex = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
136+
let input = "abcdef";
137+
138+
let expected = hex_to_id(oid_hex);
139+
let actual = Prefix::from_hex_nonempty(input).expect("No errors");
140+
assert_eq!(actual.cmp_oid(&expected), Ordering::Equal);
141+
}
142+
143+
#[test]
144+
fn id_7_chars() {
145+
let oid_hex = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
146+
let input = "abcdefa";
147+
148+
let expected = hex_to_id(oid_hex);
149+
let actual = Prefix::from_hex_nonempty(input).expect("No errors");
150+
assert_eq!(actual.cmp_oid(&expected), Ordering::Equal);
151+
}
152+
153+
#[test]
154+
fn id_2_chars_and_less() {
155+
let oid_hex = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
156+
157+
let oid = hex_to_id(oid_hex);
158+
let actual = Prefix::from_hex_nonempty("ab").expect("no errors");
159+
assert_eq!(actual.cmp_oid(&oid), Ordering::Equal);
160+
161+
let actual = Prefix::from_hex_nonempty("a").expect("no errors");
162+
assert_eq!(actual.cmp_oid(&oid), Ordering::Equal);
163+
}
164+
165+
#[test]
166+
fn id_empty() {
167+
let input = "";
168+
let expected = Error::TooShort { hex_len: 0 };
169+
let actual = Prefix::from_hex_nonempty(input).unwrap_err();
170+
assert_eq!(actual, expected);
171+
}
172+
173+
#[test]
174+
fn id_too_long() {
175+
let input = "abcdefabcdefabcdefabcdefabcdefabcdefabcd123123123123123123";
176+
let expected = Error::TooLong { hex_len: 58 };
177+
let actual = Prefix::from_hex_nonempty(input).unwrap_err();
178+
assert_eq!(actual, expected);
179+
}
180+
}

0 commit comments

Comments
 (0)