add hash_fromstr (#3476)

This commit is contained in:
Rob Walker 2019-03-25 12:23:19 -07:00 committed by GitHub
parent 51004881f8
commit 34c051f183
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 2 deletions

View File

@ -5,6 +5,8 @@ use generic_array::typenum::U32;
use generic_array::GenericArray;
use sha2::{Digest, Sha256};
use std::fmt;
use std::mem;
use std::str::FromStr;
#[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Hash(GenericArray<u8, U32>);
@ -50,11 +52,33 @@ impl fmt::Display for Hash {
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseHashError {
WrongSize,
Invalid,
}
impl FromStr for Hash {
type Err = ParseHashError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let bytes = bs58::decode(s)
.into_vec()
.map_err(|_| ParseHashError::Invalid)?;
if bytes.len() != mem::size_of::<Hash>() {
Err(ParseHashError::WrongSize)
} else {
Ok(Hash::new(&bytes))
}
}
}
impl Hash {
pub fn new(hash_slice: &[u8]) -> Self {
Hash(GenericArray::clone_from_slice(&hash_slice))
}
}
/// Return a Sha256 hash for the given data.
pub fn hashv(vals: &[&[u8]]) -> Hash {
let mut hasher = Hasher::default();
@ -73,3 +97,44 @@ pub fn extend_and_hash(id: &Hash, val: &[u8]) -> Hash {
hash_data.extend_from_slice(val);
hash(&hash_data)
}
#[cfg(test)]
mod tests {
use super::*;
use bs58;
#[test]
fn test_hash_fromstr() {
let hash = hash(&[1u8]);
let mut hash_base58_str = bs58::encode(hash).into_string();
assert_eq!(hash_base58_str.parse::<Hash>(), Ok(hash));
hash_base58_str.push_str(&bs58::encode(hash.0).into_string());
assert_eq!(
hash_base58_str.parse::<Hash>(),
Err(ParseHashError::WrongSize)
);
hash_base58_str.truncate(hash_base58_str.len() / 2);
assert_eq!(hash_base58_str.parse::<Hash>(), Ok(hash));
hash_base58_str.truncate(hash_base58_str.len() / 2);
assert_eq!(
hash_base58_str.parse::<Hash>(),
Err(ParseHashError::WrongSize)
);
let mut hash_base58_str = bs58::encode(hash.0).into_string();
assert_eq!(hash_base58_str.parse::<Hash>(), Ok(hash));
// throw some non-base58 stuff in there
hash_base58_str.replace_range(..1, "I");
assert_eq!(
hash_base58_str.parse::<Hash>(),
Err(ParseHashError::Invalid)
);
}
}

View File

@ -65,8 +65,6 @@ mod tests {
let pubkey = Keypair::new().pubkey();
let mut pubkey_base58_str = bs58::encode(pubkey.0).into_string();
dbg!(&pubkey_base58_str);
assert_eq!(pubkey_base58_str.parse::<Pubkey>(), Ok(pubkey));
pubkey_base58_str.push_str(&bs58::encode(pubkey.0).into_string());