use std::ptr;
use armour_core::{KeyScheme, KeyType};
pub trait Key: Copy {
const KEY_SCHEME: KeyScheme;
const GROUP_BITS: u32 = 0;
fn as_bytes(&self) -> &[u8];
fn as_bytes_mut(&mut self) -> &mut [u8];
fn from_bytes(bytes: &[u8]) -> Self;
fn zeroed() -> Self;
}
pub trait Location: Copy + Send + Sync + 'static {
fn zeroed() -> Self;
}
impl Location for crate::disk_loc::DiskLoc {
fn zeroed() -> Self {
crate::disk_loc::DiskLoc::new(0, 0, 0, 0)
}
}
impl Location for u32 {
fn zeroed() -> Self {
0
}
}
#[macro_export]
macro_rules! impl_key_zerocopy {
($ty:ty, $scheme:expr) => {
impl $crate::Key for $ty {
const KEY_SCHEME: armour_core::KeyScheme = $scheme;
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
zerocopy::IntoBytes::as_bytes(self)
}
#[inline(always)]
fn as_bytes_mut(&mut self) -> &mut [u8] {
zerocopy::IntoBytes::as_mut_bytes(self)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Self {
debug_assert_eq!(bytes.len(), size_of::<Self>());
unsafe { std::ptr::read(bytes.as_ptr().cast()) }
}
#[inline(always)]
fn zeroed() -> Self {
zerocopy::FromZeros::new_zeroed()
}
}
};
($ty:ty, $scheme:expr, group_bits = $gb:expr) => {
impl $crate::Key for $ty {
const KEY_SCHEME: armour_core::KeyScheme = $scheme;
const GROUP_BITS: u32 = $gb;
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
zerocopy::IntoBytes::as_bytes(self)
}
#[inline(always)]
fn as_bytes_mut(&mut self) -> &mut [u8] {
zerocopy::IntoBytes::as_mut_bytes(self)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Self {
debug_assert_eq!(bytes.len(), size_of::<Self>());
unsafe { std::ptr::read(bytes.as_ptr().cast()) }
}
#[inline(always)]
fn zeroed() -> Self {
zerocopy::FromZeros::new_zeroed()
}
}
};
}
#[macro_export]
macro_rules! impl_key_bytemuck {
($ty:ty, $scheme:expr) => {
impl $crate::Key for $ty {
const KEY_SCHEME: armour_core::KeyScheme = $scheme;
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
bytemuck::bytes_of(self)
}
#[inline(always)]
fn as_bytes_mut(&mut self) -> &mut [u8] {
bytemuck::bytes_of_mut(self)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Self {
debug_assert_eq!(bytes.len(), size_of::<Self>());
unsafe { std::ptr::read(bytes.as_ptr().cast()) }
}
#[inline(always)]
fn zeroed() -> Self {
bytemuck::Zeroable::zeroed()
}
}
};
($ty:ty, $scheme:expr, group_bits = $gb:expr) => {
impl $crate::Key for $ty {
const KEY_SCHEME: armour_core::KeyScheme = $scheme;
const GROUP_BITS: u32 = $gb;
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
bytemuck::bytes_of(self)
}
#[inline(always)]
fn as_bytes_mut(&mut self) -> &mut [u8] {
bytemuck::bytes_of_mut(self)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Self {
debug_assert_eq!(bytes.len(), size_of::<Self>());
unsafe { std::ptr::read(bytes.as_ptr().cast()) }
}
#[inline(always)]
fn zeroed() -> Self {
bytemuck::Zeroable::zeroed()
}
}
};
}
impl<const N: usize> Key for [u8; N] {
const KEY_SCHEME: KeyScheme = KeyScheme::Typed(&[KeyType::Array(N)]);
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
self
}
#[inline(always)]
fn as_bytes_mut(&mut self) -> &mut [u8] {
self
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Self {
debug_assert_eq!(bytes.len(), N);
unsafe { ptr::read(bytes.as_ptr().cast()) }
}
#[inline(always)]
fn zeroed() -> Self {
[0u8; N]
}
}
#[cfg(feature = "armour")]
impl_key_zerocopy!(rend::u64_be, KeyScheme::Typed(&[KeyType::U64]));
impl<H> Key for armour_core::fuid::Fuid<H> {
const KEY_SCHEME: KeyScheme = KeyScheme::Typed(&[KeyType::Fuid]);
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
zerocopy::IntoBytes::as_bytes(self)
}
#[inline(always)]
fn as_bytes_mut(&mut self) -> &mut [u8] {
zerocopy::IntoBytes::as_mut_bytes(self)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Self {
debug_assert_eq!(bytes.len(), size_of::<Self>());
unsafe { ptr::read(bytes.as_ptr().cast()) }
}
#[inline(always)]
fn zeroed() -> Self {
zerocopy::FromZeros::new_zeroed()
}
}
impl<T> Key for armour_core::id64::Id64<T> {
const KEY_SCHEME: KeyScheme = KeyScheme::Typed(&[KeyType::U64]);
#[inline(always)]
fn as_bytes(&self) -> &[u8] {
zerocopy::IntoBytes::as_bytes(self)
}
#[inline(always)]
fn as_bytes_mut(&mut self) -> &mut [u8] {
zerocopy::IntoBytes::as_mut_bytes(self)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Self {
debug_assert_eq!(bytes.len(), size_of::<Self>());
unsafe { ptr::read(bytes.as_ptr().cast()) }
}
#[inline(always)]
fn zeroed() -> Self {
zerocopy::FromZeros::new_zeroed()
}
}
#[cfg(feature = "uuid")]
impl_key_bytemuck!(uuid::Uuid, KeyScheme::Typed(&[KeyType::Array(16)]));
#[cfg(feature = "solana")]
impl_key_bytemuck!(
solana_pubkey::Pubkey,
KeyScheme::Typed(&[KeyType::Array(32)])
);
#[cfg(feature = "solana")]
impl_key_bytemuck!(
solana_signature::Signature,
KeyScheme::Typed(&[KeyType::Array(64)])
);