1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. // // Copyright (c) DUSK NETWORK. All rights reserved. //! ![Build Status](https://github.com/dusk-network/rusk/workflows/Continuous%20integration/badge.svg) //! [![Repository](https://img.shields.io/badge/github-code--hasher-blueviolet?logo=github)](https://github.com/dusk-network/code-hasher) //! [![Documentation](https://img.shields.io/badge/docs-code--hasher-blue?logo=rust)](https://docs.rs/code-hasher/) //! # code-hasher //! //! Tiny proc macro library designed to hash a code block generating a unique //! identifier for it which will get written into a `const` inside of the code //! block. //! //! ## Example //! ```rust //! #[code_hasher::hash(SOME_CONST_NAME, version = "0.1.0")] //! pub mod testing_module { //! //! pub fn this_does_something() -> [u8; 32] { //! SOME_CONST_NAME //! } //! } //! ``` //! //! Here, `SOME_CONST_NAME` has assigned as value the resulting hash of: //! - The code contained inside `testing_module`. //! - The version passed by the user (is optional). Not adding it will basically //! not hash this attribute and **WILL NOT** use any default alternatives. //! //! ## Licensing //! This code is licensed under Mozilla Public License Version 2.0 (MPL-2.0). //! Please see [LICENSE](https://github.com/dusk-network/rusk/tree/master/macros/code-hasher/LICENSE) for further info. use blake3::Hasher; use proc_macro::TokenStream; #[proc_macro_attribute] pub fn hash(attr: TokenStream, input: TokenStream) -> TokenStream { let mut hasher = Hasher::new(); // We need to `let` this otherways it gets freed while borrowed. let attrs_string = format!("{}", attr.to_string()); let attrs_split: Vec<&str> = attrs_string.split(",").collect(); // Add the code version (passed as attribute) to the hasher. hasher.update(attrs_split.get(1).unwrap_or(&"").as_bytes()); // Add code-block to the hasher. hasher.update(input.to_string().as_bytes()); let id = hasher.finalize().as_bytes().clone(); let mut token_stream = format!("{}", input.to_string()); token_stream.pop(); token_stream.push_str(&format!( " const {}: [u8; 32] = {:?};", attrs_split.get(0).expect("Missing const name"), id )); token_stream.push_str(" }"); token_stream.parse().expect( "Error parsing the output of the code-hasher macro as TokenStream", ) }