pub const ADDRESS_BYTES: usize = 32;
pub const MAX_SEED_LEN: usize = 32;
pub const MAX_SEEDS: usize = 16;
pub const PDA_MARKER: &[u8; 21] = b"ProgramDerivedAddress";
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord)]
pub struct Address(pub(crate) [u8; 32]);
#[cfg(feature = "hopper-native-backend")]
unsafe impl bytemuck::Zeroable for Address {}
#[cfg(feature = "hopper-native-backend")]
unsafe impl bytemuck::Pod for Address {}
unsafe impl crate::pod::Pod for Address {}
unsafe impl crate::zerocopy::__sealed::HopperZeroCopySealed for Address {}
impl Address {
#[inline(always)]
pub const fn new(bytes: [u8; 32]) -> Self {
Self(bytes)
}
#[inline(always)]
pub const fn new_from_array(bytes: [u8; 32]) -> Self {
Self(bytes)
}
#[inline(always)]
pub const fn to_bytes(&self) -> [u8; 32] {
self.0
}
#[inline(always)]
pub const fn as_array(&self) -> &[u8; 32] {
&self.0
}
#[inline(always)]
pub const fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
#[cfg(target_os = "solana")]
pub fn find_program_address(seeds: &[&[u8]], program_id: &Address) -> (Address, u8) {
crate::compat::find_program_address(seeds, program_id)
}
#[cfg(target_os = "solana")]
pub fn create_program_address(
seeds: &[&[u8]],
program_id: &Address,
) -> Result<Address, crate::ProgramError> {
crate::compat::create_program_address(seeds, program_id)
}
}
impl From<[u8; 32]> for Address {
#[inline(always)]
fn from(bytes: [u8; 32]) -> Self {
Self(bytes)
}
}
impl From<Address> for [u8; 32] {
#[inline(always)]
fn from(addr: Address) -> [u8; 32] {
addr.0
}
}
impl TryFrom<&[u8]> for Address {
type Error = core::array::TryFromSliceError;
#[inline]
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
let arr: [u8; 32] = slice.try_into()?;
Ok(Self(arr))
}
}
impl AsRef<[u8]> for Address {
#[inline(always)]
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl AsMut<[u8]> for Address {
#[inline(always)]
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl AsRef<[u8; 32]> for Address {
#[inline(always)]
fn as_ref(&self) -> &[u8; 32] {
&self.0
}
}
impl core::hash::Hash for Address {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl core::fmt::Debug for Address {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Address({:?})", &self.0[..4])
}
}
impl core::fmt::Display for Address {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
for byte in &self.0[..4] {
write!(f, "{byte:02x}")?;
}
write!(f, "..")
}
}
#[inline(always)]
pub fn address_eq(a: &Address, b: &Address) -> bool {
let a_ptr = a.0.as_ptr() as *const u64;
let b_ptr = b.0.as_ptr() as *const u64;
unsafe {
core::ptr::read_unaligned(a_ptr) == core::ptr::read_unaligned(b_ptr)
&& core::ptr::read_unaligned(a_ptr.add(1)) == core::ptr::read_unaligned(b_ptr.add(1))
&& core::ptr::read_unaligned(a_ptr.add(2)) == core::ptr::read_unaligned(b_ptr.add(2))
&& core::ptr::read_unaligned(a_ptr.add(3)) == core::ptr::read_unaligned(b_ptr.add(3))
}
}