Skip to content

Commit

Permalink
more improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire committed Jun 20, 2019
1 parent 318da55 commit 12bbaaa
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 57 deletions.
10 changes: 5 additions & 5 deletions multihash_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ fn impl_multihash_digest(ast: &syn::DeriveInput) -> proc_macro2::TokenStream {
.expect("Please provide the code as discriminant")
as u32;

quote!{ #code => Some(Code::#name), }
quote! { #code => Some(Code::#name), }
});

let code_matches_into_str = data.variants.iter().map(|variant| {
let name = &variant.ident;

quote!{ Code::#name => stringify!(#name), }
quote! { Code::#name => stringify!(#name), }
});

let res = quote!{
let res = quote! {
/// Decodes the raw value into a `Multihash`. If the input data is not a valid
/// multihash an error is returned.
pub fn decode(raw: &[u8]) -> Result<Multihash, Error> {
Expand Down Expand Up @@ -111,7 +111,7 @@ fn impl_variant(_code_name: &syn::Ident, variant: &syn::Variant) -> proc_macro2:
// TODO: actually derive this from the encoded size of the size.
let prefix_len = 1 + code_len;

quote!{
quote! {
#[derive(Debug, Default, Clone)]
pub struct #name(#original_digest);

Expand Down Expand Up @@ -161,7 +161,7 @@ fn impl_variant(_code_name: &syn::Ident, variant: &syn::Variant) -> proc_macro2:

out[#prefix_len..].copy_from_slice(re);

Multihash(out.into())
Multihash::from_box(out.into())
}

fn result(self) -> Multihash {
Expand Down
61 changes: 61 additions & 0 deletions src/code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use digest::{BlockInput, Digest, Input, Reset};

use crate::digests::Multihash;
use crate::errors::Error;
use crate::multihash_digest::MultihashDigest;

#[derive(Clone, Debug, PartialEq, MultihashDigest)]
#[repr(u32)]
pub enum Code {
#[Size = "20"]
#[Digest = "sha1::Sha1"]
Sha1 = 0x11,

#[Size = "32"]
#[Digest = "sha2::Sha256"]
Sha2_256 = 0x12,

#[Size = "64"]
#[Digest = "sha2::Sha512"]
Sha2_512 = 0x13,

#[Size = "28"]
#[Digest = "sha3::Sha3_224"]
Sha3_224 = 0x17,

#[Size = "32"]
#[Digest = "sha3::Sha3_256"]
Sha3_256 = 0x16,

#[Size = "48"]
#[Digest = "sha3::Sha3_384"]
Sha3_384 = 0x15,

#[Size = "64"]
#[Digest = "sha3::Sha3_512"]
Sha3_512 = 0x14,

#[Size = "28"]
#[Digest = "sha3::Keccak224"]
Keccak224 = 0x1A,

#[Size = "32"]
#[Digest = "sha3::Keccak256"]
Keccak256 = 0x1B,

#[Size = "48"]
#[Digest = "sha3::Keccak384"]
Keccak384 = 0x1C,

#[Size = "64"]
#[Digest = "sha3::Keccak512"]
Keccak512 = 0x1D,

#[Size = "64"]
#[Digest = "blake2::Blake2b"]
Blake2b = 0xb240,

#[Size = "32"]
#[Digest = "blake2::Blake2s"]
Blake2s = 0xb260,
}
122 changes: 71 additions & 51 deletions src/digests.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::convert::TryFrom;

use digest::{BlockInput, Digest, Input, Reset};
use integer_encoding::VarInt;

use crate::errors::Error;
use crate::multihash_digest::MultihashDigest;
use crate::Code;

/// Representation of a valid multihash. This enforces validity on construction,
/// so it can be assumed this is always a valid multihash.
Expand Down Expand Up @@ -93,6 +92,11 @@ impl Multihash {
Ok(Multihash(raw.into_boxed_slice()))
}

/// Create a new Multihash from a boxed slice, without validating.
pub fn from_box(raw: Box<[u8]>) -> Self {
Multihash(raw)
}

/// Creates a new `Multihash` from a slice.
/// If the input data is not a valid multihash an error is returned.
///
Expand Down Expand Up @@ -153,66 +157,82 @@ impl Multihash {
}
}

#[derive(Clone, Debug, PartialEq, MultihashDigest)]
#[repr(u32)]
pub enum Code {
#[Size = "20"]
#[Digest = "sha1::Sha1"]
Sha1 = 0x11,

#[Size = "32"]
#[Digest = "sha2::Sha256"]
Sha2_256 = 0x12,

#[Size = "64"]
#[Digest = "sha2::Sha512"]
Sha2_512 = 0x13,

#[Size = "28"]
#[Digest = "sha3::Sha3_224"]
Sha3_224 = 0x17,

#[Size = "32"]
#[Digest = "sha3::Sha3_256"]
Sha3_256 = 0x16,

#[Size = "48"]
#[Digest = "sha3::Sha3_384"]
Sha3_384 = 0x15,

#[Size = "64"]
#[Digest = "sha3::Sha3_512"]
Sha3_512 = 0x14,
impl<'a> MultihashRef<'a> {
/// Creates a new `MultihashRef` from a `&[u8]`.
/// If the input data is not a valid multihash an error is returned.
///
/// # Example
///
/// ```
/// use multihash::{Sha2_256, MultihashDigest, Multihash, MultihashRef, Code};
///
/// let mh = Sha2_256::digest(b"hello world");
///
/// // valid multihash
/// let mh2 = MultihashRef::from_slice(&mh).unwrap();
///
/// // invalid multihash
/// assert!(Multihash::from_slice(&vec![1,2,3]).is_err());
/// ```
pub fn from_slice(raw: &'a [u8]) -> Result<Self, Error> {
// validate code
let (raw_code, code_size) = u32::decode_var(raw);
Code::from_u32(raw_code).ok_or_else(|| Error::Invalid)?;

#[Size = "28"]
#[Digest = "sha3::Keccak224"]
Keccak224 = 0x1A,
// validate size
let (size, size_size) = u64::decode_var(&raw[code_size..]);
if size != (raw.len() - code_size - size_size) as u64 {
return Err(Error::BadInputLength);
}

#[Size = "32"]
#[Digest = "sha3::Keccak256"]
Keccak256 = 0x1B,
Ok(MultihashRef(raw))
}

#[Size = "48"]
#[Digest = "sha3::Keccak384"]
Keccak384 = 0x1C,
/// Creates a new `Vec<u8>`.
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_vec()
}

#[Size = "64"]
#[Digest = "sha3::Keccak512"]
Keccak512 = 0x1D,
/// Returns the `Code` of this multihash.
///
/// # Example
///
/// ```
/// use multihash::{Sha2_256, MultihashDigest, Code};
///
/// let mh = Sha2_256::digest(b"hello world");
/// assert_eq!(mh.code(), Code::Sha2_256);
/// ```
pub fn code(&self) -> Code {
let (raw_code, _) = u32::decode_var(&self.0);
Code::from_u32(raw_code).unwrap()
}

#[Size = "64"]
#[Digest = "blake2::Blake2b"]
Blake2b = 0xb240,
/// Returns the algorithm used in this multihash as a string.
///
/// # Example
///
/// ```
/// use multihash::{Sha2_256, MultihashDigest};
///
/// let mh = Sha2_256::digest(b"hello world");
/// assert_eq!(mh.algorithm(), "Sha2_256");
/// ```
pub fn algorithm(&self) -> &'static str {
self.code().into()
}

#[Size = "32"]
#[Digest = "blake2::Blake2s"]
Blake2s = 0xb260,
/// Create a `Multihash` matching this `MultihashRef`.
pub fn to_owned(&self) -> Multihash {
Multihash(self.0.to_vec().into_boxed_slice())
}
}

#[cfg(test)]
mod tests {
use super::super::MultihashDigest;
use super::{decode, Code, Sha2_256};
use super::*;
use crate::{decode, Sha2_256};
use digest::{Digest, Input};

use hex;
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ extern crate multihash_derive;
#[macro_use]
extern crate failure;

mod code;
mod digests;
mod errors;
mod multihash_digest;

pub use crate::code::*;
pub use crate::digests::*;
pub use crate::errors::Error;
pub use crate::multihash_digest::MultihashDigest;
Expand Down
3 changes: 2 additions & 1 deletion src/multihash_digest.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use digest::{BlockInput, Input, Reset};

use crate::digests::{Code, Multihash};
use crate::digests::Multihash;
use crate::Code;

/// The `MultihashDigest` trait specifies an interface common for
/// all multihash functions. It is heavily based on the `digest::Digest` trait.
Expand Down

0 comments on commit 12bbaaa

Please sign in to comment.