Skip to content

Commit 19a44ff

Browse files
committed
fix: make derive macro work
1 parent 18f51a2 commit 19a44ff

File tree

2 files changed

+49
-72
lines changed

2 files changed

+49
-72
lines changed

derive/src/multihash.rs

Lines changed: 34 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl Parse for MhAttr {
4343
/// Attributes of the top-level derive.
4444
#[derive(Debug)]
4545
enum DeriveAttr {
46-
AllocSize(utils::Attr<kw::alloc_size, syn::Type>),
46+
AllocSize(utils::Attr<kw::alloc_size, syn::LitInt>),
4747
NoAllocSizeErrors(kw::no_alloc_size_errors),
4848
}
4949

@@ -161,7 +161,7 @@ impl<'a> From<&'a VariantInfo<'a>> for Hash {
161161
/// Parse top-level enum [#mh()] attributes.
162162
///
163163
/// Returns the `alloc_size` and whether errors regarding to `alloc_size` should be reported or not.
164-
fn parse_code_enum_attrs(ast: &syn::DeriveInput) -> (syn::Type, bool) {
164+
fn parse_code_enum_attrs(ast: &syn::DeriveInput) -> (syn::LitInt, bool) {
165165
let mut alloc_size = None;
166166
let mut no_alloc_size_errors = false;
167167

@@ -226,33 +226,12 @@ fn error_code_duplicates(hashes: &[Hash]) {
226226
#[derive(Debug)]
227227
struct ParseError(proc_macro2::Span);
228228

229-
/// Parse a path containing a `typenum` unsigned integer (e.g. `U64`) into a u64
230-
fn parse_unsigned_typenum(typenum_path: &syn::Type) -> Result<u64, ParseError> {
231-
match typenum_path {
232-
syn::Type::Path(type_path) => match type_path.path.segments.last() {
233-
Some(path_segment) => {
234-
let typenum_ident = &path_segment.ident;
235-
let typenum = typenum_ident.to_string();
236-
match typenum.as_str().split_at(1) {
237-
("U", byte_size) => byte_size
238-
.parse::<u64>()
239-
.map_err(|_| ParseError(typenum_ident.span())),
240-
_ => Err(ParseError(typenum_ident.span())),
241-
}
242-
}
243-
None => Err(ParseError(type_path.path.span())),
244-
},
245-
_ => Err(ParseError(typenum_path.span())),
246-
}
247-
}
248-
249229
/// Returns the max size as u64.
250230
///
251-
/// Emits an error if the `#mh(alloc_size)` attribute doesn't contain a valid unsigned integer
252-
/// `typenum`.
253-
fn parse_alloc_size_attribute(alloc_size: &syn::Type) -> u64 {
254-
parse_unsigned_typenum(&alloc_size).unwrap_or_else(|_| {
255-
let msg = "`alloc_size` attribute must be a `typenum`, e.g. #[mh(alloc_size = U64)]";
231+
/// Emits an error if the `#mh(alloc_size)` attribute doesn't contain a valid unsigned integer.
232+
fn parse_alloc_size_attribute(alloc_size: &syn::LitInt) -> u64 {
233+
alloc_size.base10_parse().unwrap_or_else(|_| {
234+
let msg = "`alloc_size` attribute must be an integer, e.g. #[mh(alloc_size = 64)]";
256235
#[cfg(test)]
257236
panic!(msg);
258237
#[cfg(not(test))]
@@ -261,38 +240,39 @@ fn parse_alloc_size_attribute(alloc_size: &syn::Type) -> u64 {
261240
}
262241

263242
/// Return a warning/error if the specified alloc_size is smaller than the biggest digest
264-
fn error_alloc_size(hashes: &[Hash], expected_alloc_size_type: &syn::Type) {
243+
fn error_alloc_size(hashes: &[Hash], expected_alloc_size_type: &syn::LitInt) {
265244
let expected_alloc_size = parse_alloc_size_attribute(expected_alloc_size_type);
266245

267246
let maybe_error: Result<(), ParseError> = hashes
268247
.iter()
269248
.try_for_each(|hash| {
270-
// The digest type must have a size parameter of the shape `U<number>`, else we error.
249+
// The digest type must have an integer as size parameter, else we error.
271250
match hash.digest.segments.last() {
272251
Some(path_segment) => match &path_segment.arguments {
273252
syn::PathArguments::AngleBracketed(arguments) => match arguments.args.last() {
274-
Some(syn::GenericArgument::Type(path)) => {
275-
match parse_unsigned_typenum(&path) {
276-
Ok(max_digest_size) => {
277-
if max_digest_size > expected_alloc_size {
278-
let msg = format!("The `#mh(alloc_size) attribute must be bigger than the maximum defined digest size (U{})",
279-
max_digest_size);
280-
#[cfg(test)]
281-
panic!(msg);
282-
#[cfg(not(test))]
283-
{
284-
let digest = &hash.digest.to_token_stream().to_string().replace(" ", "");
285-
let line = &hash.digest.span().start().line;
286-
proc_macro_error::emit_error!(
287-
&expected_alloc_size_type, msg;
288-
note = "the bigger digest is `{}` at line {}", digest, line;
289-
);
290-
}
291-
}
292-
Ok(())
293-
},
294-
Err(err) => Err(err),
295-
}
253+
Some(syn::GenericArgument::Const(syn::Expr::Lit(expr_lit))) => match &expr_lit.lit {
254+
syn::Lit::Int(lit_int) => match lit_int.base10_parse::<u64>() {
255+
Ok(max_digest_size) => {
256+
if max_digest_size > expected_alloc_size {
257+
let msg = format!("The `#mh(alloc_size) attribute must be bigger than the maximum defined digest size ({})",
258+
max_digest_size);
259+
#[cfg(test)]
260+
panic!(msg);
261+
#[cfg(not(test))]
262+
{
263+
let digest = &hash.digest.to_token_stream().to_string().replace(" ", "");
264+
let line = &hash.digest.span().start().line;
265+
proc_macro_error::emit_error!(
266+
&expected_alloc_size_type, msg;
267+
note = "the bigger digest is `{}` at line {}", digest, line;
268+
);
269+
}
270+
}
271+
Ok(())
272+
},
273+
_ => Err(ParseError(lit_int.span())),
274+
},
275+
_ => Err(ParseError(expr_lit.span())),
296276
},
297277
_ => Err(ParseError(arguments.args.span())),
298278
},
@@ -338,9 +318,7 @@ pub fn multihash(s: Structure) -> TokenStream {
338318
/// A Multihash with the same allocated size as the Multihashes produces by this derive.
339319
pub type Multihash = #mh_crate::MultihashGeneric::<#alloc_size>;
340320

341-
impl #mh_crate::MultihashDigest for #code_enum {
342-
type AllocSize = #alloc_size;
343-
321+
impl #mh_crate::MultihashDigest<#alloc_size> for #code_enum {
344322
fn digest(&self, input: &[u8]) -> Multihash {
345323
use #mh_crate::Hasher;
346324
match self {
@@ -349,10 +327,9 @@ pub fn multihash(s: Structure) -> TokenStream {
349327
}
350328
}
351329

352-
fn multihash_from_digest<'a, S, D>(digest: &'a D) -> Multihash
330+
fn multihash_from_digest<'a, D>(digest: &'a D) -> Multihash
353331
where
354-
S: #mh_crate::Size,
355-
D: #mh_crate::Digest<S>,
332+
D: #mh_crate::Digest<#alloc_size>,
356333
Self: From<&'a D>,
357334
{
358335
let code = Self::from(&digest);

src/multihash_impl.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use multihash_derive::Multihash;
77
///
88
/// [`Multihash` derive]: crate::derive
99
#[derive(Copy, Clone, Debug, Eq, Multihash, PartialEq)]
10-
#[mh(alloc_size = U64)]
10+
#[mh(alloc_size = 64)]
1111
pub enum Code {
1212
/// SHA-256 (32-byte hash size)
1313
#[cfg(feature = "sha2")]
@@ -19,61 +19,61 @@ pub enum Code {
1919
Sha2_512,
2020
/// SHA3-224 (28-byte hash size)
2121
#[cfg(feature = "sha3")]
22-
#[mh(code = 0x17, hasher = crate::Sha3_224, digest = crate::Sha3Digest<crate::U28>)]
22+
#[mh(code = 0x17, hasher = crate::Sha3_224, digest = crate::Sha3Digest<28>)]
2323
Sha3_224,
2424
/// SHA3-256 (32-byte hash size)
2525
#[cfg(feature = "sha3")]
26-
#[mh(code = 0x16, hasher = crate::Sha3_256, digest = crate::Sha3Digest<crate::U32>)]
26+
#[mh(code = 0x16, hasher = crate::Sha3_256, digest = crate::Sha3Digest<32>)]
2727
Sha3_256,
2828
/// SHA3-384 (48-byte hash size)
2929
#[cfg(feature = "sha3")]
30-
#[mh(code = 0x15, hasher = crate::Sha3_384, digest = crate::Sha3Digest<crate::U48>)]
30+
#[mh(code = 0x15, hasher = crate::Sha3_384, digest = crate::Sha3Digest<48>)]
3131
Sha3_384,
3232
/// SHA3-512 (64-byte hash size)
3333
#[cfg(feature = "sha3")]
34-
#[mh(code = 0x14, hasher = crate::Sha3_512, digest = crate::Sha3Digest<crate::U64>)]
34+
#[mh(code = 0x14, hasher = crate::Sha3_512, digest = crate::Sha3Digest<64>)]
3535
Sha3_512,
3636
/// Keccak-224 (28-byte hash size)
3737
#[cfg(feature = "sha3")]
38-
#[mh(code = 0x1a, hasher = crate::Keccak224, digest = crate::KeccakDigest<crate::U28>)]
38+
#[mh(code = 0x1a, hasher = crate::Keccak224, digest = crate::KeccakDigest<28>)]
3939
Keccak224,
4040
/// Keccak-256 (32-byte hash size)
4141
#[cfg(feature = "sha3")]
42-
#[mh(code = 0x1b, hasher = crate::Keccak256, digest = crate::KeccakDigest<crate::U32>)]
42+
#[mh(code = 0x1b, hasher = crate::Keccak256, digest = crate::KeccakDigest<32>)]
4343
Keccak256,
4444
/// Keccak-384 (48-byte hash size)
4545
#[cfg(feature = "sha3")]
46-
#[mh(code = 0x1c, hasher = crate::Keccak384, digest = crate::KeccakDigest<crate::U48>)]
46+
#[mh(code = 0x1c, hasher = crate::Keccak384, digest = crate::KeccakDigest<48>)]
4747
Keccak384,
4848
/// Keccak-512 (64-byte hash size)
4949
#[cfg(feature = "sha3")]
50-
#[mh(code = 0x1d, hasher = crate::Keccak512, digest = crate::KeccakDigest<crate::U64>)]
50+
#[mh(code = 0x1d, hasher = crate::Keccak512, digest = crate::KeccakDigest<64>)]
5151
Keccak512,
5252
/// BLAKE2b-256 (32-byte hash size)
5353
#[cfg(feature = "blake2b")]
54-
#[mh(code = 0xb220, hasher = crate::Blake2b256, digest = crate::Blake2bDigest<crate::U32>)]
54+
#[mh(code = 0xb220, hasher = crate::Blake2b256, digest = crate::Blake2bDigest<32>)]
5555
Blake2b256,
5656
/// BLAKE2b-512 (64-byte hash size)
5757
#[cfg(feature = "blake2b")]
58-
#[mh(code = 0xb240, hasher = crate::Blake2b512, digest = crate::Blake2bDigest<crate::U64>)]
58+
#[mh(code = 0xb240, hasher = crate::Blake2b512, digest = crate::Blake2bDigest<64>)]
5959
Blake2b512,
6060
/// BLAKE2s-128 (16-byte hash size)
6161
#[cfg(feature = "blake2s")]
62-
#[mh(code = 0xb250, hasher = crate::Blake2s128, digest = crate::Blake2sDigest<crate::U16>)]
62+
#[mh(code = 0xb250, hasher = crate::Blake2s128, digest = crate::Blake2sDigest<16>)]
6363
Blake2s128,
6464
/// BLAKE2s-256 (32-byte hash size)
6565
#[cfg(feature = "blake2s")]
66-
#[mh(code = 0xb260, hasher = crate::Blake2s256, digest = crate::Blake2sDigest<crate::U32>)]
66+
#[mh(code = 0xb260, hasher = crate::Blake2s256, digest = crate::Blake2sDigest<32>)]
6767
Blake2s256,
6868
/// BLAKE3-256 (32-byte hash size)
6969
#[cfg(feature = "blake3")]
70-
#[mh(code = 0x1e, hasher = crate::Blake3_256, digest = crate::Blake3Digest<crate::U32>)]
70+
#[mh(code = 0x1e, hasher = crate::Blake3_256, digest = crate::Blake3Digest<32>)]
7171
Blake3_256,
7272

7373
// The following hashes are not cryptographically secure hashes and are not enabled by default
7474
/// Identity hash (max. 64 bytes)
7575
#[cfg(feature = "identity")]
76-
#[mh(code = 0x00, hasher = crate::IdentityHasher::<crate::U64>, digest = crate::IdentityDigest<crate::U64>)]
76+
#[mh(code = 0x00, hasher = crate::IdentityHasher::<crate::U64>, digest = crate::IdentityDigest<64>)]
7777
Identity,
7878
}
7979

0 commit comments

Comments
 (0)