Skip to main content

hopper_runtime/
interop.rs

1//! Type interop for Hopper-owned address values.
2//!
3//! Hopper keeps its own `Address` and `AccountView` types because they
4//! carry segment metadata, layout fingerprints, and borrow-tracking that
5//! external types lack. This module provides `From`/`Into` conversions
6//! so Hopper code can interoperate with the wider Solana ecosystem
7//! without loss of type safety.
8//!
9//! # Layout-compatible reference casts
10//!
11//! Hopper's `Address` is `#[repr(transparent)]` over `[u8; 32]`. This means
12//! reference casts to other transparent 32-byte address wrappers are valid
13//! when the caller opts into the marker trait:
14//!
15//! ```ignore
16//! let hopper_addr: &Address = Address::from_ref(upstream_addr);
17//! let upstream_ref: &[u8; 32] = hopper_addr.as_array();
18//! ```
19//!
20//! # By-value conversions
21//!
22//! Hopper's runtime uses its own canonical `Address`. By-value conversions to
23//! Hopper Native's address live in the direct runtime bridge.
24//!
25//! # Backend-agnostic conversions
26//!
27//! Hopper `Address` always converts to/from `[u8; 32]`, making it trivially
28//! interoperable with any type that also wraps 32 bytes.
29
30use crate::address::Address;
31
32// ── Zero-cost reference conversions ──────────────────────────────────
33
34impl Address {
35    /// Zero-cost borrow as a reference to any `#[repr(transparent)]`
36    /// 32-byte type that shares layout with `[u8; 32]`.
37    ///
38    /// This is the preferred way to pass a Hopper `Address` where an
39    /// upstream reference is expected.
40    ///
41    /// # Safety
42    ///
43    /// Safe because `Address` is `#[repr(transparent)]` over `[u8; 32]`
44    /// and any upstream 32-byte address type shares this layout.
45    #[inline(always)]
46    pub fn as_upstream<T>(&self) -> &T
47    where
48        T: TransparentAddress,
49    {
50        // SAFETY: Both types are #[repr(transparent)] over [u8; 32].
51        unsafe { &*(self as *const Address as *const T) }
52    }
53
54    /// Construct a Hopper `Address` reference from any `#[repr(transparent)]`
55    /// 32-byte address type.
56    #[inline(always)]
57    pub fn from_upstream<T>(upstream: &T) -> &Address
58    where
59        T: TransparentAddress,
60    {
61        // SAFETY: Both types are #[repr(transparent)] over [u8; 32].
62        unsafe { &*(upstream as *const T as *const Address) }
63    }
64}
65
66/// Marker trait for types that are `#[repr(transparent)]` over `[u8; 32]`.
67///
68/// # Safety
69///
70/// Implementors must be `#[repr(transparent)]` wrappers around `[u8; 32]`
71/// with no additional invariants. This enables zero-cost reference casts.
72pub unsafe trait TransparentAddress: Sized {}
73
74// Hopper's own Address is trivially transparent.
75unsafe impl TransparentAddress for Address {}
76
77unsafe impl TransparentAddress for hopper_native::address::Address {}