Skip to content

Commit

Permalink
common: use bytemuck to remove unsafe (#90)
Browse files Browse the repository at this point in the history
The unsafe is of course still there but now hidden in bytemuck crate.
The advantage is that bytemuck checks all the necessary conditions
when deriving TransparentWrapper rather than them only being described
in a comment.
  • Loading branch information
mina86 authored Nov 14, 2023
1 parent b2f0eb4 commit fb3da69
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 12 deletions.
1 change: 1 addition & 0 deletions common/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
base64.workspace = true
borsh = { workspace = true, optional = true }
bytemuck.workspace = true
derive_more.workspace = true

stdx.workspace = true
Expand Down
13 changes: 4 additions & 9 deletions common/lib/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use base64::engine::general_purpose::STANDARD as BASE64_ENGINE;
use base64::Engine;
#[cfg(feature = "borsh")]
use borsh::maybestd::io;
use bytemuck::TransparentWrapper;

/// A cryptographic hash.
#[derive(
Expand All @@ -13,6 +14,7 @@ use borsh::maybestd::io;
derive_more::AsMut,
derive_more::From,
derive_more::Into,
bytemuck::TransparentWrapper,
)]
#[cfg_attr(
feature = "borsh",
Expand Down Expand Up @@ -120,21 +122,14 @@ impl From<&'_ CryptoHash> for [u8; CryptoHash::LENGTH] {
impl<'a> From<&'a [u8; CryptoHash::LENGTH]> for &'a CryptoHash {
#[inline]
fn from(hash: &'a [u8; CryptoHash::LENGTH]) -> Self {
let hash =
(hash as *const [u8; CryptoHash::LENGTH]).cast::<CryptoHash>();
// SAFETY: CryptoHash is repr(transparent) over [u8; CryptoHash::LENGTH]
// thus transmuting is safe.
unsafe { &*hash }
CryptoHash::wrap_ref(hash)
}
}

impl<'a> From<&'a mut [u8; CryptoHash::LENGTH]> for &'a mut CryptoHash {
#[inline]
fn from(hash: &'a mut [u8; CryptoHash::LENGTH]) -> Self {
let hash = (hash as *mut [u8; CryptoHash::LENGTH]).cast::<CryptoHash>();
// SAFETY: CryptoHash is repr(transparent) over [u8; CryptoHash::LENGTH]
// thus transmuting is safe.
unsafe { &mut *hash }
CryptoHash::wrap_mut(hash)
}
}

Expand Down
1 change: 1 addition & 0 deletions common/sealable-trie/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2021"
ascii.workspace = true
base64.workspace = true
borsh = { workspace = true, optional = true }
bytemuck.workspace = true
derive_more.workspace = true
sha2.workspace = true
strum.workspace = true
Expand Down
8 changes: 5 additions & 3 deletions common/sealable-trie/src/nodes.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use bytemuck::TransparentWrapper;
use lib::hash::CryptoHash;
use memory::Ptr;

Expand Down Expand Up @@ -107,7 +108,9 @@ pub enum Node<'a, P = Option<Ptr>, S = bool> {
// ```
//
// The actual pointer value is therefore 30-bit long.
#[derive(Clone, Copy, PartialEq, derive_more::Deref)]
#[derive(
Clone, Copy, PartialEq, derive_more::Deref, bytemuck::TransparentWrapper,
)]
#[repr(transparent)]
pub struct RawNode(pub(crate) [u8; RawNode::SIZE]);

Expand Down Expand Up @@ -494,8 +497,7 @@ impl<'a> ValueRef<'a, bool> {

impl<'a> From<&'a [u8; RawNode::SIZE]> for &'a RawNode {
fn from(bytes: &'a [u8; RawNode::SIZE]) -> &'a RawNode {
// SAFETY: RawNode is repr(transparent).
unsafe { &*bytes.as_ptr().cast() }
RawNode::wrap_ref(bytes)
}
}

Expand Down

0 comments on commit fb3da69

Please sign in to comment.