Skip to content
This repository was archived by the owner on Nov 30, 2022. It is now read-only.

Commit a175a9e

Browse files
authored
Merge pull request #51 from rust-bitcoin/2019-06-hex-fix
fix hex iterator
2 parents e32d040 + 9e748d9 commit a175a9e

File tree

12 files changed

+93
-26
lines changed

12 files changed

+93
-26
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 0.5.0 - 2019-06-28
2+
3+
* Fix panic when parsing hashes that contain multibyte characters
4+
* Add `FromStr` to all hashes which hex-parses them
5+
16
# 0.4.0 - 2019-06-23
27

38
* [Add `from_inner` method](https://github.com/rust-bitcoin/bitcoin_hashes/pull/20) to all hashes

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bitcoin_hashes"
3-
version = "0.4.0"
3+
version = "0.5.0"
44
authors = ["Andrew Poelstra <[email protected]>"]
55
license = "CC0-1.0"
66
description = "Hash functions used by rust-bitcoin which support rustc 1.14.0"

src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::{error, fmt};
2121
#[derive(Copy, Clone, PartialEq, Eq)]
2222
pub enum Error {
2323
/// non-hexadecimal character
24-
InvalidChar(char),
24+
InvalidChar(u8),
2525
/// purported hex string had odd length
2626
OddLengthString(usize),
2727
/// tried to parse fixed-length hash from a string with the wrong type (expected, got)

src/hash160.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
//! # HASH160 (SHA256 then RIPEMD160)
2121
22+
use std::str;
23+
2224
use sha256;
2325
use ripemd160;
2426
use Hash as HashTrait;
@@ -35,6 +37,13 @@ index_impl!(Hash);
3537
serde_impl!(Hash, 20);
3638
borrow_slice_impl!(Hash, [u8; 20]);
3739

40+
impl str::FromStr for Hash {
41+
type Err = Error;
42+
fn from_str(s: &str) -> Result<Self, Error> {
43+
::hex::FromHex::from_hex(s)
44+
}
45+
}
46+
3847
impl HashTrait for Hash {
3948
type Engine = sha256::HashEngine;
4049
type Inner = [u8; 20];

src/hex.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//!
1717
1818
use std::fmt;
19-
use std::str::Chars;
19+
use std::str;
2020
use {Error, Hash};
2121

2222
/// Trait for objects that can be serialized as hex strings
@@ -64,9 +64,9 @@ impl<T: Hash> FromHex for T {
6464

6565
/// Iterator over a hex-encoded string slice which decodes hex and yields bytes.
6666
pub struct HexIterator<'a> {
67-
/// The `Chars` iterator whose first two characters will be decoded to yield
67+
/// The `Bytes` iterator whose next two bytes will be decoded to yield
6868
/// the next byte.
69-
chars: Chars<'a>,
69+
iter: str::Bytes<'a>,
7070
}
7171

7272
impl<'a> HexIterator<'a> {
@@ -76,18 +76,18 @@ impl<'a> HexIterator<'a> {
7676
if s.len() % 2 != 0 {
7777
Err(Error::OddLengthString(s.len()))
7878
} else {
79-
Ok(HexIterator {
80-
chars: s.chars()
81-
})
79+
Ok(HexIterator { iter: s.bytes() })
8280
}
8381
}
8482
}
8583

86-
fn chars_to_hex(hi: char, lo: char) -> Result<u8, Error> {
87-
let hih = hi.to_digit(16)
88-
.ok_or(Error::InvalidChar(hi))?;
89-
let loh = lo.to_digit(16)
90-
.ok_or(Error::InvalidChar(lo))?;
84+
fn chars_to_hex(hi: u8, lo: u8) -> Result<u8, Error> {
85+
let hih = (hi as char)
86+
.to_digit(16)
87+
.ok_or(Error::InvalidChar(hi))?;
88+
let loh = (lo as char)
89+
.to_digit(16)
90+
.ok_or(Error::InvalidChar(lo))?;
9191

9292
let ret = (hih << 4) + loh;
9393
Ok(ret as u8)
@@ -97,21 +97,21 @@ impl<'a> Iterator for HexIterator<'a> {
9797
type Item = Result<u8, Error>;
9898

9999
fn next(&mut self) -> Option<Result<u8, Error>> {
100-
let hi = self.chars.next()?;
101-
let lo = self.chars.next().unwrap();
100+
let hi = self.iter.next()?;
101+
let lo = self.iter.next().unwrap();
102102
Some(chars_to_hex(hi, lo))
103103
}
104104

105105
fn size_hint(&self) -> (usize, Option<usize>) {
106-
let len = self.chars.as_str().len() / 2;
107-
(len, Some(len))
106+
let (min, max) = self.iter.size_hint();
107+
(min / 2, max.map(|x| x /2))
108108
}
109109
}
110110

111111
impl<'a> DoubleEndedIterator for HexIterator<'a> {
112112
fn next_back(&mut self) -> Option<Result<u8, Error>> {
113-
let lo = self.chars.next_back()?;
114-
let hi = self.chars.next_back().unwrap();
113+
let lo = self.iter.next_back()?;
114+
let hi = self.iter.next_back().unwrap();
115115
Some(chars_to_hex(hi, lo))
116116
}
117117
}
@@ -330,15 +330,15 @@ mod tests {
330330
);
331331
assert_eq!(
332332
Vec::<u8>::from_hex(badchar1),
333-
Err(Error::InvalidChar('Z'))
333+
Err(Error::InvalidChar(b'Z'))
334334
);
335335
assert_eq!(
336336
Vec::<u8>::from_hex(badchar2),
337-
Err(Error::InvalidChar('Y'))
337+
Err(Error::InvalidChar(b'Y'))
338338
);
339339
assert_eq!(
340340
Vec::<u8>::from_hex(badchar3),
341-
Err(Error::InvalidChar('«'))
341+
Err(Error::InvalidChar(194))
342342
);
343343
}
344344
}

src/hmac.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
//! # HMAC support
2121
22-
use std::{borrow, fmt, io, ops};
22+
use std::{borrow, fmt, io, ops, str};
2323
#[cfg(feature="serde")]
2424
use serde::{Serialize, Serializer, Deserialize, Deserializer};
2525

@@ -29,6 +29,13 @@ use {Error, Hash, HashEngine};
2929
#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
3030
pub struct Hmac<T: Hash>(T);
3131

32+
impl<T: Hash + str::FromStr> str::FromStr for Hmac<T> {
33+
type Err = <T as str::FromStr>::Err;
34+
fn from_str(s: &str) -> Result<Self, Self::Err> {
35+
Ok(Hmac(str::FromStr::from_str(s)?))
36+
}
37+
}
38+
3239
/// Pair of underlying hash midstates which represent the current state
3340
/// of an `HmacEngine`
3441
pub struct HmacMidState<T: Hash> {

src/ripemd160.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
//! # RIPEMD160
2121
2222
use byteorder::{ByteOrder, LittleEndian};
23+
use std::str;
2324

2425
use HashEngine as EngineTrait;
2526
use Hash as HashTrait;
@@ -77,6 +78,13 @@ index_impl!(Hash);
7778
serde_impl!(Hash, 20);
7879
borrow_slice_impl!(Hash, [u8; 20]);
7980

81+
impl str::FromStr for Hash {
82+
type Err = Error;
83+
fn from_str(s: &str) -> Result<Self, Error> {
84+
::hex::FromHex::from_hex(s)
85+
}
86+
}
87+
8088
impl HashTrait for Hash {
8189
type Engine = HashEngine;
8290
type Inner = [u8; 20];

src/sha1.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//! # SHA1
1616
1717
use byteorder::{ByteOrder, BigEndian};
18+
use std::str;
1819

1920
use HashEngine as EngineTrait;
2021
use Hash as HashTrait;
@@ -64,6 +65,13 @@ index_impl!(Hash);
6465
serde_impl!(Hash, 20);
6566
borrow_slice_impl!(Hash, [u8; 20]);
6667

68+
impl str::FromStr for Hash {
69+
type Err = Error;
70+
fn from_str(s: &str) -> Result<Self, Error> {
71+
::hex::FromHex::from_hex(s)
72+
}
73+
}
74+
6775
impl HashTrait for Hash {
6876
type Engine = HashEngine;
6977
type Inner = [u8; 20];

src/sha256.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//! # SHA256
1616
1717
use byteorder::{ByteOrder, BigEndian};
18+
use std::str;
1819

1920
use hex;
2021
use HashEngine as EngineTrait;
@@ -66,6 +67,13 @@ impl EngineTrait for HashEngine {
6667
#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
6768
pub struct Hash([u8; 32]);
6869

70+
impl str::FromStr for Hash {
71+
type Err = Error;
72+
fn from_str(s: &str) -> Result<Self, Error> {
73+
::hex::FromHex::from_hex(s)
74+
}
75+
}
76+
6977
hex_fmt_impl!(Debug, Hash);
7078
hex_fmt_impl!(Display, Hash);
7179
hex_fmt_impl!(LowerHex, Hash);

src/sha256d.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
//! # SHA256d
1616
17+
use std::str;
18+
1719
use sha256;
1820
use Hash as HashTrait;
1921
use Error;
@@ -29,6 +31,13 @@ index_impl!(Hash);
2931
serde_impl!(Hash, 32);
3032
borrow_slice_impl!(Hash, [u8; 32]);
3133

34+
impl str::FromStr for Hash {
35+
type Err = Error;
36+
fn from_str(s: &str) -> Result<Self, Error> {
37+
::hex::FromHex::from_hex(s)
38+
}
39+
}
40+
3241
impl HashTrait for Hash {
3342
type Engine = sha256::HashEngine;
3443
type Inner = [u8; 32];

0 commit comments

Comments
 (0)