Skip to content

Commit

Permalink
fix: add repr(C) to json-abi items (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes authored Jun 12, 2023
1 parent 7a557ba commit eba745c
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
4 changes: 2 additions & 2 deletions crates/json-abi/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ impl Serialize for AbiJson {
self.events
.values()
.flatten()
.try_for_each(|e| seq.serialize_element(&e))?;
.try_for_each(|e| seq.serialize_element(e))?;

self.errors
.values()
.flatten()
.try_for_each(|e| seq.serialize_element(&e))?;
.try_for_each(|e| seq.serialize_element(e))?;

seq.end()
}
Expand Down
23 changes: 20 additions & 3 deletions crates/json-abi/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};

// Serde order:
// Public items -> public enum -> private enum -> private items
//
// Items are duplicated to be able to make use of the derived `serde` impl,
// while enforcing that the public items emit their tag, as per the spec.
//
// They are all declared with `repr(C)` because the default repr (`Rust`) does
// not have any layout guarantees, which we need to be able to transmute between
// the private and public types.
macro_rules! abi_items {
($(
$(#[$attr:meta])*
Expand All @@ -15,6 +22,7 @@ macro_rules! abi_items {
$(
$(#[$attr])*
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
$vis struct $name {$(
$(#[$fattr])*
$fvis $field: $type,
Expand All @@ -39,26 +47,30 @@ macro_rules! abi_items {
}
)*

#[doc(hidden)]
mod private {
use super::*;

$(
#[derive(Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[repr(C)]
pub(super) struct $name {$(
$field: $type,
)*}
)*

#[derive(Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "lowercase")]
#[repr(C)]
pub(super) enum AbiItem<'a> {$(
$name(Cow<'a, self::$name>),
)*}
}

/// A JSON ABI item.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum AbiItem<'a> {$(
#[doc = concat!("A JSON ABI [`", stringify!($name), "`].")]
$name(Cow<'a, $name>),
Expand Down Expand Up @@ -148,29 +160,34 @@ impl AbiItem<'_> {
}
}

// SAFETY: `AbiItem` and `private::AbiItem` have the exact same variants.
// This is enforced by the macro.
// SAFETY: `AbiItem` and `private::AbiItem` have the exact same variants, and
// all the items use a non-Rust repr.
// This is enforced in the macro.
#[doc(hidden)]
impl<'a> From<private::AbiItem<'a>> for AbiItem<'a> {
#[inline(always)]
fn from(item: private::AbiItem<'a>) -> AbiItem<'a> {
unsafe { core::mem::transmute(item) }
}
}

#[doc(hidden)]
impl<'a> From<AbiItem<'a>> for private::AbiItem<'a> {
#[inline(always)]
fn from(item: AbiItem<'a>) -> private::AbiItem<'a> {
unsafe { core::mem::transmute(item) }
}
}

#[doc(hidden)]
impl<'a, 'r> From<&'r private::AbiItem<'a>> for &'r AbiItem<'a> {
#[inline(always)]
fn from(item: &'r private::AbiItem<'a>) -> &'r AbiItem<'a> {
unsafe { core::mem::transmute(item) }
}
}

#[doc(hidden)]
impl<'a, 'r> From<&'r AbiItem<'a>> for &'r private::AbiItem<'a> {
#[inline(always)]
fn from(item: &'r AbiItem<'a>) -> &'r private::AbiItem<'a> {
Expand Down Expand Up @@ -202,7 +219,7 @@ impl Function {
}
}

/// `format!("{name}({inputs})")`
/// `format!("{name}({inputs.join(",")})")`
fn preimage(name: &str, inputs: &[Param]) -> String {
let mut preimage = String::with_capacity(name.len() + 2 + inputs.len() * 32);
preimage.push_str(name);
Expand Down

0 comments on commit eba745c

Please sign in to comment.