diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bef588d..5b39d19 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -100,7 +100,7 @@ jobs: name: Code Coverage runs-on: ubuntu-latest container: - image: xd009642/tarpaulin:0.30.0 + image: xd009642/tarpaulin:0.31.2 options: --security-opt seccomp=unconfined steps: - name: Checkout repository diff --git a/codetable/Cargo.toml b/codetable/Cargo.toml index 975a656..4ed06d2 100644 --- a/codetable/Cargo.toml +++ b/codetable/Cargo.toml @@ -29,7 +29,7 @@ digest = { version = "0.10.1", default-features = false, optional = true } sha1 = { version = "0.10.5", default-features = false, optional = true } sha2 = { version = "0.10.0", default-features = false, optional = true } sha3 = { version = "0.10.0", default-features = false, optional = true } -strobe-rs = { version = "0.8.1", default-features = false, optional = true } +strobe-rs = { version = "0.10.0", default-features = false, optional = true } ripemd = { version = "0.1.1", default-features = false, optional = true } multihash-derive = { version = "0.9.0", path = "../derive", default-features = false } core2 = { version = "0.4.0", default-features = false } diff --git a/codetable/src/hasher_impl.rs b/codetable/src/hasher_impl.rs index 0870455..b00c4e4 100644 --- a/codetable/src/hasher_impl.rs +++ b/codetable/src/hasher_impl.rs @@ -1,6 +1,5 @@ #[cfg(any( feature = "strobe", - feature = "identity", feature = "blake2b", feature = "blake2s", feature = "blake3" diff --git a/codetable/src/lib.rs b/codetable/src/lib.rs index e9c11a8..893e4dd 100644 --- a/codetable/src/lib.rs +++ b/codetable/src/lib.rs @@ -1,5 +1,5 @@ #![cfg_attr(feature = "arb", allow(unreachable_code))] // Otherwise the "Cargo Hack" check fails since "arb" includes no hash algos by default -#![cfg_attr(docs_rs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(not(feature = "std"), no_std)] //! A batteries-included code table of multihashes. @@ -15,30 +15,30 @@ mod hasher_impl; pub use multihash_derive::MultihashDigest; #[cfg(feature = "blake2b")] -#[cfg_attr(docs_rs, doc(cfg(feature = "blake2b")))] +#[cfg_attr(docsrs, doc(cfg(feature = "blake2b")))] pub use crate::hasher_impl::blake2b::{Blake2b256, Blake2b512, Blake2bHasher}; #[cfg(feature = "blake2s")] -#[cfg_attr(docs_rs, doc(cfg(feature = "blake2s")))] +#[cfg_attr(docsrs, doc(cfg(feature = "blake2s")))] pub use crate::hasher_impl::blake2s::{Blake2s128, Blake2s256, Blake2sHasher}; #[cfg(feature = "blake3")] -#[cfg_attr(docs_rs, doc(cfg(feature = "blake3")))] +#[cfg_attr(docsrs, doc(cfg(feature = "blake3")))] pub use crate::hasher_impl::blake3::{Blake3Hasher, Blake3_256}; #[cfg(feature = "ripemd")] -#[cfg_attr(docs_rs, doc(cfg(feature = "ripemd")))] +#[cfg_attr(docsrs, doc(cfg(feature = "ripemd")))] pub use crate::hasher_impl::ripemd::{Ripemd160, Ripemd256, Ripemd320}; #[cfg(feature = "sha1")] -#[cfg_attr(docs_rs, doc(cfg(feature = "sha1")))] +#[cfg_attr(docsrs, doc(cfg(feature = "sha1")))] pub use crate::hasher_impl::sha1::Sha1; #[cfg(feature = "sha2")] -#[cfg_attr(docs_rs, doc(cfg(feature = "sha2")))] +#[cfg_attr(docsrs, doc(cfg(feature = "sha2")))] pub use crate::hasher_impl::sha2::{Sha2_256, Sha2_512}; #[cfg(feature = "sha3")] -#[cfg_attr(docs_rs, doc(cfg(feature = "sha3")))] +#[cfg_attr(docsrs, doc(cfg(feature = "sha3")))] pub use crate::hasher_impl::sha3::{ Keccak224, Keccak256, Keccak384, Keccak512, Sha3_224, Sha3_256, Sha3_384, Sha3_512, }; #[cfg(feature = "strobe")] -#[cfg_attr(docs_rs, doc(cfg(feature = "strobe")))] +#[cfg_attr(docsrs, doc(cfg(feature = "strobe")))] pub use crate::hasher_impl::strobe::{Strobe256, Strobe512, StrobeHasher}; /// Default (cryptographically secure) Multihash implementation. @@ -54,92 +54,92 @@ pub use crate::hasher_impl::strobe::{Strobe256, Strobe512, StrobeHasher}; pub enum Code { /// SHA-256 (32-byte hash size) #[cfg(feature = "sha2")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha2")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha2")))] #[mh(code = 0x12, hasher = crate::Sha2_256)] Sha2_256, /// SHA-512 (64-byte hash size) #[cfg(feature = "sha2")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha2")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha2")))] #[mh(code = 0x13, hasher = crate::Sha2_512)] Sha2_512, /// SHA3-224 (28-byte hash size) #[cfg(feature = "sha3")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha3")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))] #[mh(code = 0x17, hasher = crate::Sha3_224)] Sha3_224, /// SHA3-256 (32-byte hash size) #[cfg(feature = "sha3")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha3")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))] #[mh(code = 0x16, hasher = crate::Sha3_256)] Sha3_256, /// SHA3-384 (48-byte hash size) #[cfg(feature = "sha3")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha3")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))] #[mh(code = 0x15, hasher = crate::Sha3_384)] Sha3_384, /// SHA3-512 (64-byte hash size) #[cfg(feature = "sha3")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha3")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))] #[mh(code = 0x14, hasher = crate::Sha3_512)] Sha3_512, /// Keccak-224 (28-byte hash size) #[cfg(feature = "sha3")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha3")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))] #[mh(code = 0x1a, hasher = crate::Keccak224)] Keccak224, /// Keccak-256 (32-byte hash size) #[cfg(feature = "sha3")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha3")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))] #[mh(code = 0x1b, hasher = crate::Keccak256)] Keccak256, /// Keccak-384 (48-byte hash size) #[cfg(feature = "sha3")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha3")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))] #[mh(code = 0x1c, hasher = crate::Keccak384)] Keccak384, /// Keccak-512 (64-byte hash size) #[cfg(feature = "sha3")] - #[cfg_attr(docs_rs, doc(cfg(feature = "sha3")))] + #[cfg_attr(docsrs, doc(cfg(feature = "sha3")))] #[mh(code = 0x1d, hasher = crate::Keccak512)] Keccak512, /// BLAKE2b-256 (32-byte hash size) #[cfg(feature = "blake2b")] - #[cfg_attr(docs_rs, doc(cfg(feature = "blake2b")))] + #[cfg_attr(docsrs, doc(cfg(feature = "blake2b")))] #[mh(code = 0xb220, hasher = crate::Blake2b256)] Blake2b256, /// BLAKE2b-512 (64-byte hash size) #[cfg(feature = "blake2b")] - #[cfg_attr(docs_rs, doc(cfg(feature = "blake2b")))] + #[cfg_attr(docsrs, doc(cfg(feature = "blake2b")))] #[mh(code = 0xb240, hasher = crate::Blake2b512)] Blake2b512, /// BLAKE2s-128 (16-byte hash size) #[cfg(feature = "blake2s")] - #[cfg_attr(docs_rs, doc(cfg(feature = "blake2s")))] + #[cfg_attr(docsrs, doc(cfg(feature = "blake2s")))] #[mh(code = 0xb250, hasher = crate::Blake2s128)] Blake2s128, /// BLAKE2s-256 (32-byte hash size) #[cfg(feature = "blake2s")] - #[cfg_attr(docs_rs, doc(cfg(feature = "blake2s")))] + #[cfg_attr(docsrs, doc(cfg(feature = "blake2s")))] #[mh(code = 0xb260, hasher = crate::Blake2s256)] Blake2s256, /// BLAKE3-256 (32-byte hash size) #[cfg(feature = "blake3")] - #[cfg_attr(docs_rs, doc(cfg(feature = "blake3")))] + #[cfg_attr(docsrs, doc(cfg(feature = "blake3")))] #[mh(code = 0x1e, hasher = crate::Blake3_256)] Blake3_256, /// RIPEMD-160 (20-byte hash size) #[cfg(feature = "ripemd")] - #[cfg_attr(docs_rs, doc(cfg(feature = "ripemd")))] + #[cfg_attr(docsrs, doc(cfg(feature = "ripemd")))] #[mh(code = 0x1053, hasher = crate::Ripemd160)] Ripemd160, /// RIPEMD-256 (32-byte hash size) #[cfg(feature = "ripemd")] - #[cfg_attr(docs_rs, doc(cfg(feature = "ripemd")))] + #[cfg_attr(docsrs, doc(cfg(feature = "ripemd")))] #[mh(code = 0x1054, hasher = crate::Ripemd256)] Ripemd256, /// RIPEMD-320 (40-byte hash size) #[cfg(feature = "ripemd")] - #[cfg_attr(docs_rs, doc(cfg(feature = "ripemd")))] + #[cfg_attr(docsrs, doc(cfg(feature = "ripemd")))] #[mh(code = 0x1055, hasher = crate::Ripemd320)] Ripemd320, } diff --git a/deny.toml b/deny.toml index 011ca91..5ee1e08 100644 --- a/deny.toml +++ b/deny.toml @@ -1,32 +1,11 @@ - -[advisories] -ignore = [ - # https://rustsec.org/advisories/RUSTSEC-2021-0145 - # 1. On windows, `atty` dereferences a potentially unaligned pointer. - # 2. Last release of `atty` was almost 3 years ago. - "RUSTSEC-2021-0145", - - # https://rustsec.org/advisories/RUSTSEC-2021-0127 - # 1. serde_cbor is unmaintained - "RUSTSEC-2021-0127" -] -notice = "deny" -unmaintained = "warn" -vulnerability = "deny" -yanked = "deny" - [licenses] allow = [ "Apache-2.0", - "BSD-2-Clause", "BSD-3-Clause", - "CC0-1.0", "MIT", "Unicode-DFS-2016", ] -default = "deny" confidence-threshold = 1.0 -unlicensed = "deny" [bans] allow = [] @@ -35,10 +14,11 @@ deny = [] # * Resolve duplicate versions of itoa (used by criterion) # * Remove atty from criterion # * Resolve duplicate versions of constant_time_eq (used by blake2_sid and blake3) -multiple-versions = "warn" +multiple-versions = "deny" skip = [] skip-tree = [] -wildcards = "warn" +wildcards = "deny" +allow-wildcard-paths = true [sources] allow-git = [] diff --git a/derive-impl/Cargo.toml b/derive-impl/Cargo.toml index 8e81fba..e0bcfae 100644 --- a/derive-impl/Cargo.toml +++ b/derive-impl/Cargo.toml @@ -13,7 +13,6 @@ proc-macro = true [dependencies] proc-macro2 = { version = "1.0.24", features = ["span-locations"] } proc-macro-crate = "3.1.0" -proc-macro-error = "1.0.4" quote = "1.0.7" syn = "2.0.66" synstructure = "0.13.1" diff --git a/derive-impl/src/lib.rs b/derive-impl/src/lib.rs index 7fd1c3c..abad0a0 100644 --- a/derive-impl/src/lib.rs +++ b/derive-impl/src/lib.rs @@ -10,13 +10,11 @@ mod multihash; mod utils; use proc_macro::TokenStream; -use proc_macro_error::proc_macro_error; use synstructure::macros::{parse, DeriveInput}; use synstructure::{MacroResult, Structure}; #[proc_macro_derive(Multihash, attributes(mh))] #[allow(non_snake_case)] -#[proc_macro_error] #[deprecated(since = "0.8.1", note = "Use `MultihashDigest` derive instead.")] pub fn Multihash(i: TokenStream) -> TokenStream { match parse::(i) { @@ -31,7 +29,6 @@ pub fn Multihash(i: TokenStream) -> TokenStream { /// Custom derive for the `MultihashDigest` trait. #[proc_macro_derive(MultihashDigest, attributes(mh))] #[allow(non_snake_case)] -#[proc_macro_error] pub fn MultihashDigest(i: TokenStream) -> TokenStream { #[allow(deprecated)] Multihash(i) diff --git a/derive-impl/src/multihash.rs b/derive-impl/src/multihash.rs index 9b8a15a..0250be6 100644 --- a/derive-impl/src/multihash.rs +++ b/derive-impl/src/multihash.rs @@ -1,10 +1,10 @@ use std::collections::HashSet; +use std::convert::TryFrom; use crate::utils; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; use syn::parse::{Parse, ParseStream}; -#[cfg(not(test))] use syn::spanned::Spanned; use synstructure::{Structure, VariantInfo}; @@ -90,8 +90,9 @@ impl Hash { } } -impl<'a> From<&'a VariantInfo<'a>> for Hash { - fn from(bi: &'a VariantInfo<'a>) -> Self { +impl<'a> TryFrom<&'a VariantInfo<'a>> for Hash { + type Error = syn::Error; + fn try_from(bi: &'a VariantInfo<'a>) -> Result { let mut code = None; let mut hasher = None; for attr in bi.ast().attrs { @@ -107,32 +108,32 @@ impl<'a> From<&'a VariantInfo<'a>> for Hash { } let ident = bi.ast().ident.clone(); - let code = code.unwrap_or_else(|| { + let code = code.ok_or_else(|| -> syn::Error { let msg = "Missing code attribute: e.g. #[mh(code = multihash::SHA3_256)]"; #[cfg(test)] panic!("{}", msg); #[cfg(not(test))] - proc_macro_error::abort!(ident, msg); - }); - let hasher = hasher.unwrap_or_else(|| { + syn::Error::new(bi.ast().ident.span(), msg) + })?; + let hasher = hasher.ok_or_else(|| -> syn::Error { let msg = "Missing hasher attribute: e.g. #[mh(hasher = multihash::Sha2_256)]"; #[cfg(test)] panic!("{}", msg); #[cfg(not(test))] - proc_macro_error::abort!(ident, msg); - }); - Self { + syn::Error::new(bi.ast().ident.span(), msg) + })?; + Ok(Self { ident, code, hasher, - } + }) } } /// Parse top-level enum [#mh()] attributes. /// /// Returns the `alloc_size` and whether errors regarding to `alloc_size` should be reported or not. -fn parse_code_enum_attrs(ast: &syn::DeriveInput) -> syn::LitInt { +fn parse_code_enum_attrs(ast: &syn::DeriveInput) -> syn::Result { let mut alloc_size = None; for attr in &ast.attrs { @@ -149,63 +150,69 @@ fn parse_code_enum_attrs(ast: &syn::DeriveInput) -> syn::LitInt { } } } - match alloc_size { - Some(alloc_size) => alloc_size, - None => { - let msg = "enum is missing `alloc_size` attribute: e.g. #[mh(alloc_size = 64)]"; - #[cfg(test)] - panic!("{}", msg); - #[cfg(not(test))] - proc_macro_error::abort!(&ast.ident, msg); - } - } + alloc_size.ok_or_else(|| -> syn::Error { + let msg = "enum is missing `alloc_size` attribute: e.g. #[mh(alloc_size = 64)]"; + #[cfg(test)] + panic!("{}", msg); + #[cfg(not(test))] + syn::Error::new(ast.span(), msg) + }) } /// Return an error if the same code is used several times. /// /// This only checks for string equality, though this should still catch most errors caused by /// copy and pasting. -fn error_code_duplicates(hashes: &[Hash]) { +fn check_error_code_duplicates(hashes: &[Hash]) -> Result<(), syn::Error> { // Use a temporary store to determine whether a certain value is unique or not let mut uniq = HashSet::new(); - hashes.iter().for_each(|hash| { + let mut errors = hashes.iter().filter_map(|hash| -> Option { let code = &hash.code; + // It's a duplicate + if uniq.insert(code) { + return None; + } + + let already_defined = uniq.get(code).unwrap(); + let line = already_defined.to_token_stream().span().start().line; + let msg = format!( - "the #mh(code) attribute `{}` is defined multiple times", - quote!(#code) + "the #mh(code) attribute `{}` is defined multiple times, previous definition at line {}", + quote!(#code), line ); - // It's a duplicate - if !uniq.insert(code) { - #[cfg(test)] - panic!("{}", msg); - #[cfg(not(test))] - { - let already_defined = uniq.get(code).unwrap(); - let line = already_defined.to_token_stream().span().start().line; - proc_macro_error::emit_error!( - &hash.code, msg; - note = "previous definition of `{}` at line {}", quote!(#code), line; - ); - } - } + #[cfg(test)] + panic!("{}", msg); + #[cfg(not(test))] + Some(syn::Error::new(hash.code.span(), msg)) }); + if let Some(mut error) = errors.next() { + error.extend(errors); + Err(error) + } else { + Ok(()) + } } pub fn multihash(s: Structure) -> TokenStream { - let mh_crate = match utils::use_crate("multihash-derive") { - Ok(ident) => ident, - Err(e) => { - let err = syn::Error::new(Span::call_site(), e).to_compile_error(); - return quote!(#err); - } - }; + match multihash_inner(s) { + Ok(ts) => ts, + Err(e) => e.to_compile_error(), + } +} +fn multihash_inner(s: Structure) -> syn::Result { + let mh_crate = + utils::use_crate("multihash-derive").map_err(|e| syn::Error::new(Span::call_site(), e))?; let code_enum = &s.ast().ident; - let alloc_size = parse_code_enum_attrs(s.ast()); - let hashes: Vec<_> = s.variants().iter().map(Hash::from).collect(); + let alloc_size = parse_code_enum_attrs(s.ast())?; + let hashes: Vec<_> = s + .variants() + .iter() + .map(Hash::try_from) + .collect::>()?; - error_code_duplicates(&hashes); + check_error_code_duplicates(&hashes)?; let params = Params { code_enum: code_enum.clone(), @@ -215,7 +222,7 @@ pub fn multihash(s: Structure) -> TokenStream { let code_from_u64 = hashes.iter().map(|h| h.code_from_u64()); let code_digest = hashes.iter().map(|h| h.code_digest()); - quote! { + Ok(quote! { /// A Multihash with the same allocated size as the Multihashes produces by this derive. pub type Multihash = #mh_crate::Multihash<#alloc_size>; @@ -252,5 +259,5 @@ pub fn multihash(s: Structure) -> TokenStream { } } } - } + }) } diff --git a/derive/tests/fail/no_allow_same_code_twice.stderr b/derive/tests/fail/no_allow_same_code_twice.stderr index f8d8c29..8caa6d8 100644 --- a/derive/tests/fail/no_allow_same_code_twice.stderr +++ b/derive/tests/fail/no_allow_same_code_twice.stderr @@ -1,7 +1,4 @@ -error: the #mh(code) attribute `0x0` is defined multiple times - - = note: previous definition of `0x0` at line 0 - +error: the #mh(code) attribute `0x0` is defined multiple times, previous definition at line 0 --> tests/fail/no_allow_same_code_twice.rs:21:17 | 21 | #[mh(code = 0x0, hasher = FooHasher)] diff --git a/derive/tests/fail/no_allow_same_name_twice.stderr b/derive/tests/fail/no_allow_same_name_twice.stderr index 6a5002c..125a442 100644 --- a/derive/tests/fail/no_allow_same_name_twice.stderr +++ b/derive/tests/fail/no_allow_same_name_twice.stderr @@ -37,12 +37,14 @@ note: `Code` defined here warning: unreachable pattern --> tests/fail/no_allow_same_name_twice.rs:18:10 | -18 | pub enum Code { - | __________^ -19 | | #[mh(code = 0x0, hasher = FooHasher)] -20 | | Foo, -21 | | #[mh(code = 0x1, hasher = FooHasher)] -22 | | Foo, - | |_______^ +18 | pub enum Code { + | __________^ + | |__________| +19 | || #[mh(code = 0x0, hasher = FooHasher)] +20 | || Foo, + | ||_______- matches all the relevant values +21 | | #[mh(code = 0x1, hasher = FooHasher)] +22 | | Foo, + | |________^ no value can reach this | = note: `#[warn(unreachable_patterns)]` on by default