Skip to content

Commit 4a4fa0f

Browse files
committed
Merge branch 'faster-hex'
2 parents 9f4dfe0 + 145125a commit 4a4fa0f

File tree

14 files changed

+80
-58
lines changed

14 files changed

+80
-58
lines changed

Cargo.lock

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

gix-hash/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ serde= ["dep:serde"]
1919

2020
[dependencies]
2121
thiserror = "1.0.33"
22-
hex = "0.4.2"
22+
faster-hex = "0.8.0"
2323
serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }
2424

2525
document-features = { version = "0.2.0", optional = true }

gix-hash/src/object_id.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ pub mod decode {
4040
pub enum Error {
4141
#[error("A hash sized {0} hexadecimal characters is invalid")]
4242
InvalidHexEncodingLength(usize),
43-
#[error("Invalid character {c} at position {index}")]
44-
Invalid { c: char, index: usize },
43+
#[error("Invalid character encountered")]
44+
Invalid,
4545
}
4646

4747
/// Hash decoding
@@ -50,16 +50,19 @@ pub mod decode {
5050
///
5151
/// Such a buffer can be obtained using [`oid::write_hex_to(buffer)`][super::oid::write_hex_to()]
5252
pub fn from_hex(buffer: &[u8]) -> Result<ObjectId, Error> {
53-
use hex::FromHex;
5453
match buffer.len() {
55-
40 => Ok(ObjectId::Sha1(<[u8; 20]>::from_hex(buffer).map_err(
56-
|err| match err {
57-
hex::FromHexError::InvalidHexCharacter { c, index } => Error::Invalid { c, index },
58-
hex::FromHexError::OddLength | hex::FromHexError::InvalidStringLength => {
59-
unreachable!("BUG: This is already checked")
60-
}
61-
},
62-
)?)),
54+
40 => Ok({
55+
ObjectId::Sha1({
56+
let mut buf = [0; 20];
57+
faster_hex::hex_decode(buffer, &mut buf).map_err(|err| match err {
58+
faster_hex::Error::InvalidChar => Error::Invalid,
59+
faster_hex::Error::InvalidLength(_) => {
60+
unreachable!("BUG: This is already checked")
61+
}
62+
})?;
63+
buf
64+
})
65+
}),
6366
len => Err(Error::InvalidHexEncodingLength(len)),
6467
}
6568
}

gix-hash/src/oid.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl oid {
148148
#[must_use]
149149
pub fn hex_to_buf(&self, buf: &mut [u8]) -> usize {
150150
let num_hex_bytes = self.bytes.len() * 2;
151-
hex::encode_to_slice(&self.bytes, &mut buf[..num_hex_bytes]).expect("to count correctly");
151+
faster_hex::hex_encode(&self.bytes, &mut buf[..num_hex_bytes]).expect("to count correctly");
152152
num_hex_bytes
153153
}
154154

gix-hash/src/prefix.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ pub mod from_hex {
2828
TooShort { hex_len: usize },
2929
#[error("An id cannot be larger than {} chars in hex, but {hex_len} was requested", crate::Kind::longest().len_in_hex())]
3030
TooLong { hex_len: usize },
31-
#[error("Invalid character {c} at position {index}")]
32-
Invalid { c: char, index: usize },
31+
#[error("Invalid hex character")]
32+
Invalid,
3333
}
3434
}
3535

@@ -95,7 +95,6 @@ impl Prefix {
9595

9696
/// Create an instance from the given hexadecimal prefix `value`, e.g. `35e77c16` would yield a `Prefix` with `hex_len()` = 8.
9797
pub fn from_hex(value: &str) -> Result<Self, from_hex::Error> {
98-
use hex::FromHex;
9998
let hex_len = value.len();
10099

101100
if hex_len > crate::Kind::longest().len_in_hex() {
@@ -105,16 +104,20 @@ impl Prefix {
105104
};
106105

107106
let src = if value.len() % 2 == 0 {
108-
Vec::from_hex(value)
107+
let mut out = Vec::from_iter(std::iter::repeat(0).take(value.len() / 2));
108+
faster_hex::hex_decode(value.as_bytes(), &mut out).map(move |_| out)
109109
} else {
110+
// TODO(perf): do without heap allocation here.
110111
let mut buf = [0u8; crate::Kind::longest().len_in_hex()];
111112
buf[..value.len()].copy_from_slice(value.as_bytes());
112113
buf[value.len()] = b'0';
113-
Vec::from_hex(&buf[..=value.len()])
114+
let src = &buf[..=value.len()];
115+
let mut out = Vec::from_iter(std::iter::repeat(0).take(src.len() / 2));
116+
faster_hex::hex_decode(src, &mut out).map(move |_| out)
114117
}
115118
.map_err(|e| match e {
116-
hex::FromHexError::InvalidHexCharacter { c, index } => from_hex::Error::Invalid { c, index },
117-
hex::FromHexError::OddLength | hex::FromHexError::InvalidStringLength => panic!("This is already checked"),
119+
faster_hex::Error::InvalidChar => from_hex::Error::Invalid,
120+
faster_hex::Error::InvalidLength(_) => panic!("This is already checked"),
118121
})?;
119122

120123
let mut bytes = ObjectId::null(crate::Kind::from_hex_len(value.len()).expect("hex-len is already checked"));

gix-hash/tests/object_id/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ mod from_hex {
2121
fn non_hex_characters() {
2222
assert!(matches!(
2323
ObjectId::from_hex(b"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz").unwrap_err(),
24-
decode::Error::Invalid { index: 0, c: 'z' }
24+
decode::Error::Invalid
2525
));
2626
}
2727

gix-hash/tests/prefix/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ mod try_from {
117117
#[test]
118118
fn invalid_chars() {
119119
let input = "abcdfOsd";
120-
let expected = Error::Invalid { c: 'O', index: 5 };
120+
let expected = Error::Invalid;
121121
let actual = Prefix::try_from(input).unwrap_err();
122122
assert_eq!(actual, expected);
123123
}

gix-object/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ gix-date = { version = "^0.7.2", path = "../gix-date" }
3131
btoi = "0.4.2"
3232
itoa = "1.0.1"
3333
thiserror = "1.0.34"
34-
hex = "0.4.2"
3534
bstr = { version = "1.3.0", default-features = false, features = ["std", "unicode"] }
3635
nom = { version = "7", default-features = false, features = ["std"]}
3736
smallvec = { version = "1.4.0", features = ["write"] }

gix-packetline-blocking/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ serde = ["dep:serde", "bstr/serde"]
2626
[dependencies]
2727
serde = { version = "1.0.114", optional = true, default-features = false, features = ["std", "derive"]}
2828
thiserror = "1.0.34"
29-
hex = "0.4.2"
29+
faster-hex = "0.8.0"
3030
bstr = { version = "1.3.0", default-features = false, features = ["std"] }
3131

3232
document-features = { version = "0.2.0", optional = true }

gix-packetline/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ required-features = ["blocking-io", "maybe-async/is_sync"]
4141
[dependencies]
4242
serde = { version = "1.0.114", optional = true, default-features = false, features = ["std", "derive"]}
4343
thiserror = "1.0.34"
44-
hex = "0.4.2"
44+
faster-hex = "0.8.0"
4545
bstr = { version = "1.3.0", default-features = false, features = ["std"] }
4646
# async support
4747
futures-io = { version = "0.3.16", optional = true }

0 commit comments

Comments
 (0)