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
420 420
421[[package]]421[[package]]
422name = "cc"422name = "cc"
423version = "1.2.48"423version = "1.2.47"
424source = "registry+https://github.com/rust-lang/crates.io-index"424source = "registry+https://github.com/rust-lang/crates.io-index"
425checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a"425checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07"
426dependencies = [426dependencies = [
427 "find-msvc-tools",427 "find-msvc-tools",
428 "jobserver",428 "jobserver",
@@ -659,9 +659,9 @@ dependencies = [ · 230 unmodified lines
659 659
660[[package]]660[[package]]
661name = "criterion"661name = "criterion"
662version = "0.8.0"662version = "0.8.1"
663source = "registry+https://github.com/rust-lang/crates.io-index"663source = "registry+https://github.com/rust-lang/crates.io-index"
664checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab"664checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf"
665dependencies = [665dependencies = [
666 "alloca",666 "alloca",
667 "anes",667 "anes",
@@ -684,9 +684,9 @@ dependencies = [ · 16 unmodified lines
684 684
685[[package]]685[[package]]
686name = "criterion-plot"686name = "criterion-plot"
687version = "0.8.0"687version = "0.8.1"
688source = "registry+https://github.com/rust-lang/crates.io-index"688source = "registry+https://github.com/rust-lang/crates.io-index"
689checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6"689checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4"
690dependencies = [690dependencies = [
691 "cast",691 "cast",
692 "itertools 0.13.0",692 "itertools 0.13.0",
@@ -2681,11 +2681,12 @@ checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" · 1988 unmodified lines
2681 2681
2682[[package]]2682[[package]]
2683name = "http"2683name = "http"
2684version = "1.4.0"2684version = "1.3.1"
2685source = "registry+https://github.com/rust-lang/crates.io-index"2685source = "registry+https://github.com/rust-lang/crates.io-index"
2686checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"2686checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
2687dependencies = [2687dependencies = [
2688 "bytes",2688 "bytes",
2689 "fnv",
2689 "itoa",2690 "itoa",
2690]2691]
2691 2692
@@ -4043,9 +4044,9 @@ dependencies = [ · 1351 unmodified lines
4043 4044
4044[[package]]4045[[package]]
4045name = "rustls-pki-types"4046name = "rustls-pki-types"
4046version = "1.13.1"4047version = "1.13.0"
4047source = "registry+https://github.com/rust-lang/crates.io-index"4048source = "registry+https://github.com/rust-lang/crates.io-index"
4048checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c"4049checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a"
4049dependencies = [4050dependencies = [
4050 "web-time",4051 "web-time",
4051 "zeroize",4052 "zeroize",
@@ -4756,9 +4757,9 @@ dependencies = [ · 704 unmodified lines
4756 4757
4757[[package]]4758[[package]]
4758name = "tower-http"4759name = "tower-http"
4759version = "0.6.7"4760version = "0.6.6"
4760source = "registry+https://github.com/rust-lang/crates.io-index"4761source = "registry+https://github.com/rust-lang/crates.io-index"
4761checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456"4762checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
4762dependencies = [4763dependencies = [
4763 "bitflags 2.10.0",4764 "bitflags 2.10.0",
4764 "bytes",4765 "bytes",
@@ -5780,18 +5781,18 @@ dependencies = [ · 1015 unmodified lines
5780 5781
5781[[package]]5782[[package]]
5782name = "zerocopy"5783name = "zerocopy"
5783version = "0.8.31"5784version = "0.8.28"
5784source = "registry+https://github.com/rust-lang/crates.io-index"5785source = "registry+https://github.com/rust-lang/crates.io-index"
5785checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"5786checksum = "43fa6694ed34d6e57407afbccdeecfa268c470a7d2a5b0cf49ce9fcc345afb90"
5786dependencies = [5787dependencies = [
5787 "zerocopy-derive",5788 "zerocopy-derive",
5788]5789]
5789 5790
5790[[package]]5791[[package]]
5791name = "zerocopy-derive"5792name = "zerocopy-derive"
5792version = "0.8.31"5793version = "0.8.28"
5793source = "registry+https://github.com/rust-lang/crates.io-index"5794source = "registry+https://github.com/rust-lang/crates.io-index"
5794checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"5795checksum = "c640b22cd9817fae95be82f0d2f90b11f7605f6c319d16705c459b27ac2cbc26"
5795dependencies = [5796dependencies = [
5796 "proc-macro2",5797 "proc-macro2",
5797 "quote",5798 "quote",
gix-hash/src/prefix.rs+12−1
@@ -93,12 +93,23 @@ impl Prefix { · 92 unmodified lines
93 }93 }
94 94
95 /// Create an instance from the given hexadecimal prefix `value`, e.g. `35e77c16` would yield a `Prefix` with `hex_len()` = 8.95 /// 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()`].
96 pub fn from_hex(value: &str) -> Result<Self, from_hex::Error> {97 pub fn from_hex(value: &str) -> Result<Self, from_hex::Error> {
97 let hex_len = value.len();98 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();
98 109
99 if hex_len > crate::Kind::longest().len_in_hex() {110 if hex_len > crate::Kind::longest().len_in_hex() {
100 return Err(from_hex::Error::TooLong { hex_len });111 return Err(from_hex::Error::TooLong { hex_len });
101 } else if hex_len < Self::MIN_HEX_LEN {112 } else if hex_len == 0 {
102 return Err(from_hex::Error::TooShort { hex_len });113 return Err(from_hex::Error::TooShort { hex_len });
103 }114 }
104 115
gix-hash/tests/hash/prefix.rs+59−3
@@ -80,7 +80,7 @@ mod try_from { · 79 unmodified lines
80 use crate::hex_to_id;80 use crate::hex_to_id;
81 81
82 #[test]82 #[test]
83 fn id_8_chars() {83 fn id_6_chars() {
84 let oid_hex = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";84 let oid_hex = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
85 let input = "abcdef";85 let input = "abcdef";
86 86
@@ -90,7 +90,7 @@ mod try_from { · 3 unmodified lines
90 }90 }
91 91
92 #[test]92 #[test]
93 fn id_9_chars() {93 fn id_7_chars() {
94 let oid_hex = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";94 let oid_hex = "abcdefabcdefabcdefabcdefabcdefabcdefabcd";
95 let input = "abcdefa";95 let input = "abcdefa";
96 96
@@ -107,7 +107,7 @@ mod try_from { · 10 unmodified lines
107 }107 }
108 108
109 #[test]109 #[test]
110 fn id_to_long() {110 fn id_too_long() {
111 let input = "abcdefabcdefabcdefabcdefabcdefabcdefabcd123123123123123123";111 let input = "abcdefabcdefabcdefabcdefabcdefabcdefabcd123123123123123123";
112 let expected = Error::TooLong { hex_len: 58 };112 let expected = Error::TooLong { hex_len: 58 };
113 let actual = Prefix::try_from(input).unwrap_err();113 let actual = Prefix::try_from(input).unwrap_err();
@@ -122,3 +122,59 @@ mod try_from { · 8 unmodified lines
122 assert_eq!(actual, expected);122 assert_eq!(actual, expected);
123 }123 }
124}124}
125
126mod 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}