multihash_derive/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3//! A procedural macro for custom Multihash code tables.
4//!
5//! This proc macro derives a custom Multihash code table from a list of hashers. It also
6//! generates a public type called `Multihash` which corresponds to the specified `alloc_size`.
7//!
8//! The digests are stack allocated with a fixed size. That size needs to be big enough to hold any
9//! of the specified hash digests. This cannot be determined reliably on compile-time, hence it
10//! needs to set manually via the `alloc_size` attribute. Also you might want to set it to bigger
11//! sizes then necessarily needed for backwards/forward compatibility.
12//!
13//! If you set `#mh(alloc_size = …)` to a too low value, you will get compiler errors. Please note
14//! the the sizes are checked only on a syntactic level and *not* on the type level. This means
15//! that digest need to have a size const generic, which is a valid `usize`, for example `32` or
16//! `64`.
17//!
18//! You can disable those compiler errors with setting the `no_alloc_size_errors` attribute. This
19//! can be useful if you e.g. have specified type aliases for your hash digests and you are sure
20//! you use the correct value for `alloc_size`.
21//!
22//! When you want to define your own codetable, you should only depend on `multihash-derive`.
23//! It re-exports the `multihash` crate for you.
24//!
25//! # Example
26//!
27//! ```ignore : `proc-macro-crate` does not work in docs, see https://github.com/bkchr/proc-macro-crate/issues/14
28//! use multihash_derive::{Hasher, MultihashDigest};
29//!
30//! struct FooHasher;
31//!
32//! impl Hasher for FooHasher {
33//!     // Implement hasher ...
34//! #    fn update(&mut self, input: &[u8]) {
35//! #
36//! #    }
37//! #
38//! #    fn finalize(&mut self) -> &[u8] {
39//! #        &[]
40//! #    }
41//! #
42//! #    fn reset(&mut self) {
43//! #
44//! #    }
45//! }
46//!
47//! #[derive(Clone, Copy, Debug, Eq, MultihashDigest, PartialEq)]
48//! #[mh(alloc_size = 64)]
49//! pub enum Code {
50//!     #[mh(code = 0x01, hasher = FooHasher)]
51//!     Foo
52//! }
53//!
54//! let hash = Code::Foo.digest(b"hello world!");
55//!
56//! println!("{:02x?}", hash);
57//! ```
58
59mod hasher;
60
61use core::convert::TryFrom;
62use core::fmt;
63
64pub use hasher::Hasher;
65pub use multihash::Error;
66pub use multihash::Multihash;
67#[doc(inline)]
68pub use multihash_derive_impl::Multihash; // This one is deprecated.
69pub use multihash_derive_impl::MultihashDigest;
70
71/// The given code is not supported by this codetable.
72#[derive(Debug)]
73pub struct UnsupportedCode(pub u64);
74
75impl fmt::Display for UnsupportedCode {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        write!(f, "the code {} is not supported by this codetable", self.0)
78    }
79}
80
81impl core2::error::Error for UnsupportedCode {}
82
83/// Trait that implements hashing.
84///
85/// Typically, you won't implement this yourself but use the [`MultihashDigest`](multihash_derive_impl::MultihashDigest) custom-derive.
86pub trait MultihashDigest<const S: usize>:
87    TryFrom<u64, Error = UnsupportedCode>
88    + Into<u64>
89    + Send
90    + Sync
91    + Unpin
92    + Copy
93    + Eq
94    + fmt::Debug
95    + 'static
96{
97    /// Calculate the hash of some input data.
98    fn digest(&self, input: &[u8]) -> Multihash<S>;
99
100    /// Create a multihash from an existing multihash digest.
101    fn wrap(&self, digest: &[u8]) -> Result<Multihash<S>, Error>;
102}