Unverified Commit 725c2f70 authored by Robin Freyler's avatar Robin Freyler Committed by GitHub
Browse files

Expand selectors as hex-encoded literals in metadata (#927)

* add HexLiteral utility trait to expand hex-encoded integer literals

* add ir::Selector::hex_lits method

* expand into hex-encoded integer literals for metadata selectors

* simplify Selector::hex_lits method using array::map API

* add unit test for Selector::hex_lits method
parent 9bab4838
Pipeline #158275 passed with stages
in 26 minutes and 58 seconds
......@@ -138,8 +138,7 @@ impl Metadata<'_> {
let span = constructor.span();
let attrs = constructor.attrs();
let docs = Self::extract_doc_comments(attrs);
let selector = constructor.composed_selector();
let selector_bytes = selector.as_bytes();
let selector_bytes = constructor.composed_selector().hex_lits();
let constructor = constructor.callable();
let ident = constructor.ident();
let ident_lit = ident.to_string();
......@@ -230,8 +229,7 @@ impl Metadata<'_> {
let span = message.span();
let attrs = message.attrs();
let docs = Self::extract_doc_comments(attrs);
let selector = message.composed_selector();
let selector_bytes = selector.as_bytes();
let selector_bytes = message.composed_selector().hex_lits();
let is_payable = message.is_payable();
let message = message.callable();
let mutates = message.receiver().is_ref_mut();
......
......@@ -13,6 +13,7 @@
// limitations under the License.
use super::blake2::blake2b_256;
use crate::literal::HexLiteral;
/// A function selector.
///
......@@ -46,6 +47,11 @@ impl Selector {
pub fn unique_id(self) -> usize {
u32::from_le_bytes(self.bytes) as usize
}
/// Returns the 4 bytes that make up the selector as hex encoded bytes.
pub fn hex_lits(self) -> [syn::LitInt; 4] {
self.bytes.map(<u8 as HexLiteral>::hex_padded_suffixed)
}
}
impl From<[u8; 4]> for Selector {
......@@ -53,3 +59,22 @@ impl From<[u8; 4]> for Selector {
Self::from_bytes(bytes)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hex_lits_works() {
let hex_lits = Selector::from_bytes([0xC0, 0xDE, 0xCA, 0xFE]).hex_lits();
assert_eq!(
hex_lits,
[
syn::parse_quote! { 0xC0_u8 },
syn::parse_quote! { 0xDE_u8 },
syn::parse_quote! { 0xCA_u8 },
syn::parse_quote! { 0xFE_u8 },
]
)
}
}
......@@ -32,6 +32,7 @@ mod error;
mod ast;
mod ir;
mod literal;
pub use self::ir::{
Callable,
......
// Copyright 2018-2021 Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
mod private {
/// Used to prevent external direct usage of `HexLiteral::hex_impl_`.
pub struct Sealed;
}
/// Used to convert literal values into their hex representations for code generation.
pub trait HexLiteral {
/// Shared implementation details.
///
/// # Note
///
/// Users shall not use this trait method directly hence it is hidden.
#[doc(hidden)]
fn hex_impl_(
self,
fmt: ::core::fmt::Arguments,
sealed: private::Sealed,
) -> syn::LitInt;
/// Converts the given value into a hex represented literal with type suffix.
fn hex_suffixed(self) -> syn::LitInt;
/// Converts the given value into a hex represented literal without type suffix.
fn hex_unsuffixed(self) -> syn::LitInt;
/// Converts the given value into a hex represented literal with type suffix.
///
/// The resulting hex encoded literal is padded with zeros.
fn hex_padded_suffixed(self) -> syn::LitInt;
/// Converts the given value into a hex represented literal without type suffix.
///
/// The resulting hex encoded literal is padded with zeros.
fn hex_padded_unsuffixed(self) -> syn::LitInt;
}
macro_rules! generate_hex_literal_impls {
( $( ($ty:ty, $name:literal, $fmt_suffixed:literal, $fmt_unsuffixed:literal) ),* $(,)? ) => {
$(
impl HexLiteral for $ty {
fn hex_impl_(self, fmt: ::core::fmt::Arguments, _sealed: private::Sealed) -> syn::LitInt {
::syn::LitInt::new(
&::std::format!("{}", fmt),
proc_macro2::Span::call_site()
)
}
fn hex_suffixed(self) -> syn::LitInt {
self.hex_impl_(::core::format_args!("0x{:X}_{}", self, $name), private::Sealed)
}
fn hex_unsuffixed(self) -> syn::LitInt {
self.hex_impl_(::core::format_args!("0x{:X}", self), private::Sealed)
}
fn hex_padded_suffixed(self) -> syn::LitInt {
self.hex_impl_(::core::format_args!($fmt_suffixed, self, $name), private::Sealed)
}
fn hex_padded_unsuffixed(self) -> syn::LitInt {
self.hex_impl_(::core::format_args!($fmt_unsuffixed, self), private::Sealed)
}
}
)*
};
}
#[rustfmt::skip]
generate_hex_literal_impls!(
(::core::primitive::i8 , "i8", "0x{:02X}_{}", "0x{:02X}"),
(::core::primitive::u8 , "u8", "0x{:02X}_{}", "0x{:02X}"),
(::core::primitive::i16, "i16", "0x{:04X}_{}", "0x{:04X}"),
(::core::primitive::u16, "u16", "0x{:04X}_{}", "0x{:04X}"),
(::core::primitive::i32, "i32", "0x{:08X}_{}", "0x{:08X}"),
(::core::primitive::u32, "u32", "0x{:08X}_{}", "0x{:08X}"),
(::core::primitive::i64, "i64", "0x{:016X}_{}", "0x{:016X}"),
(::core::primitive::u64, "u64", "0x{:016X}_{}", "0x{:016X}"),
(::core::primitive::i128, "i128", "0x{:032X}_{}", "0x{:032X}"),
(::core::primitive::u128, "u128", "0x{:032X}_{}", "0x{:032X}"),
);
#[cfg(target_pointer_width = "16")]
generate_hex_literal_impls!(
(::core::primitive::usize, "usize", "0x{:04X}_{}", "0x{:04X}"),
(::core::primitive::isize, "isize", "0x{:04X}_{}", "0x{:04X}"),
);
#[cfg(target_pointer_width = "32")]
generate_hex_literal_impls!(
(::core::primitive::usize, "usize", "0x{:08X}_{}", "0x{:08X}"),
(::core::primitive::isize, "isize", "0x{:08X}_{}", "0x{:08X}"),
);
#[cfg(target_pointer_width = "64")]
generate_hex_literal_impls!(
(::core::primitive::usize, "usize", "0x{:16X}_{}", "0x{:16X}"),
(::core::primitive::isize, "isize", "0x{:16X}_{}", "0x{:16X}"),
);
#[cfg(test)]
mod tests {
use super::HexLiteral as _;
use quote::quote;
fn assert_quote(given: syn::LitInt, expected: &str) {
assert_eq!(quote!(#given).to_string(), expected);
}
#[test]
fn simple() {
let value = 0x42_i32;
assert_eq!(quote!(#value).to_string(), "66i32");
assert_quote(value.hex_suffixed(), "0x42_i32");
assert_quote(value.hex_unsuffixed(), "0x42");
assert_quote(value.hex_padded_suffixed(), "0x00000042_i32");
assert_quote(value.hex_padded_unsuffixed(), "0x00000042");
}
#[test]
fn code_cafe() {
let value = 0xC0DE_CAFE_u32;
assert_quote(value.hex_suffixed(), "0xC0DECAFE_u32");
assert_quote(value.hex_padded_suffixed(), "0xC0DECAFE_u32");
assert_quote(value.hex_unsuffixed(), "0xC0DECAFE");
assert_quote(value.hex_padded_unsuffixed(), "0xC0DECAFE");
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment