History

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.

Sebastian Thiel committed 10 months ago

Commit a93074d1 parent 691a2053 files · +88 −20Browse files

Unified · Split

3 files
  1. Cargo.lock +17 −16
  2. gix-hash/src/prefix.rs +12 −1
  3. gix-hash/tests/hash/prefix.rs +59 −3
Cargo.lock+17−16
@@ -420,9 +420,9 @@ dependencies = [ · 419 unmodified lines
420420
421421 [[package]]
422422 name = "cc"
423−version = "1.2.48"
423+version = "1.2.47"
424424 source = "registry+https://github.com/rust-lang/crates.io-index"
425−checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a"
425+checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07"
426426 dependencies = [
427427 "find-msvc-tools",
428428 "jobserver",
@@ -659,9 +659,9 @@ dependencies = [ · 230 unmodified lines
659659
660660 [[package]]
661661 name = "criterion"
662−version = "0.8.0"
662+version = "0.8.1"
663663 source = "registry+https://github.com/rust-lang/crates.io-index"
664−checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab"
664+checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf"
665665 dependencies = [
666666 "alloca",
667667 "anes",
@@ -684,9 +684,9 @@ dependencies = [ · 16 unmodified lines
684684
685685 [[package]]
686686 name = "criterion-plot"
687−version = "0.8.0"
687+version = "0.8.1"
688688 source = "registry+https://github.com/rust-lang/crates.io-index"
689−checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6"
689+checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4"
690690 dependencies = [
691691 "cast",
692692 "itertools 0.13.0",
@@ -2681,11 +2681,12 @@ checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" · 1988 unmodified lines
26812681
26822682 [[package]]
26832683 name = "http"
2684−version = "1.4.0"
2684+version = "1.3.1"
26852685 source = "registry+https://github.com/rust-lang/crates.io-index"
2686−checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
2686+checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
26872687 dependencies = [
26882688 "bytes",
2689+ "fnv",
26892690 "itoa",
26902691 ]
26912692
@@ -4043,9 +4044,9 @@ dependencies = [ · 1351 unmodified lines
40434044
40444045 [[package]]
40454046 name = "rustls-pki-types"
4046−version = "1.13.1"
4047+version = "1.13.0"
40474048 source = "registry+https://github.com/rust-lang/crates.io-index"
4048−checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c"
4049+checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a"
40494050 dependencies = [
40504051 "web-time",
40514052 "zeroize",
@@ -4756,9 +4757,9 @@ dependencies = [ · 704 unmodified lines
47564757
47574758 [[package]]
47584759 name = "tower-http"
4759−version = "0.6.7"
4760+version = "0.6.6"
47604761 source = "registry+https://github.com/rust-lang/crates.io-index"
4761−checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456"
4762+checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
47624763 dependencies = [
47634764 "bitflags 2.10.0",
47644765 "bytes",
@@ -5780,18 +5781,18 @@ dependencies = [ · 1015 unmodified lines
57805781
57815782 [[package]]
57825783 name = "zerocopy"
5783−version = "0.8.31"
5784+version = "0.8.28"
57845785 source = "registry+https://github.com/rust-lang/crates.io-index"
5785−checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
5786+checksum = "43fa6694ed34d6e57407afbccdeecfa268c470a7d2a5b0cf49ce9fcc345afb90"
57865787 dependencies = [
57875788 "zerocopy-derive",
57885789 ]
57895790
57905791 [[package]]
57915792 name = "zerocopy-derive"
5792−version = "0.8.31"
5793+version = "0.8.28"
57935794 source = "registry+https://github.com/rust-lang/crates.io-index"
5794−checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
5795+checksum = "c640b22cd9817fae95be82f0d2f90b11f7605f6c319d16705c459b27ac2cbc26"
57955796 dependencies = [
57965797 "proc-macro2",
57975798 "quote",
gix-hash/src/prefix.rs+12−1
@@ -93,12 +93,23 @@ impl Prefix { · 92 unmodified lines
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+59−3
@@ -80,7 +80,7 @@ mod try_from { · 79 unmodified lines
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 { · 3 unmodified lines
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 { · 10 unmodified lines
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 { · 8 unmodified lines
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+}