use core::num::{NonZeroU32, NonZeroU64};
use arrayvec::ArrayString;
use rend::u64_be;
use uuid::Uuid;
use crate::types::{ArmourError, Result};
pub use armour_core::key_part::{MILLISECOND_BITS, SEQ_BITS, SEQ64_BITS};
pub use armour_core::key_type::{KeyScheme, KeyType};
use armour_core::{
fuid::Fuid,
id64::Id64,
num_ops::{g4bits, g8bits, g16bits},
};
pub trait Cid: Sized {
type B: Sized + AsRef<[u8]> + for<'a> TryFrom<&'a [u8]>;
const TY: KeyScheme;
const SIZE: usize = match Self::TY.static_size() {
Some(size) => size,
None => 0,
};
const GROUP_BITS: u32;
fn encode(&self) -> Self::B;
#[inline]
fn encode_owned(self) -> Self::B {
self.encode()
}
#[inline]
fn check_bytes(bytes: &[u8]) -> Result<()> {
debug_assert!(Self::GROUP_BITS <= 32);
match Self::TY {
KeyScheme::Bytes => {
Self::from_bytes(bytes)?;
}
_ => {
if bytes.len() != Self::SIZE {
return Err(ArmourError::BytesLenError);
}
}
}
Ok(())
}
fn decode(bytes: &Self::B) -> Result<Self>;
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
Self::decode(&bytes)
}
#[inline]
fn from_bytes(bytes: &[u8]) -> Result<Self> {
debug_assert!(Self::GROUP_BITS <= 32);
let bytes: Self::B = bytes.try_into().map_err(|_| ArmourError::FromBytesError)?;
Self::decode(&bytes)
}
#[inline]
unsafe fn from_bytes_unsafe(bytes: &[u8]) -> Self {
Self::from_bytes(bytes).expect("from_bytes error")
}
fn group_id(&self) -> u32;
}
impl Cid for NonZeroU32 {
type B = [u8; 4];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::U32]);
const GROUP_BITS: u32 = SEQ_BITS;
#[inline]
fn encode(&self) -> Self::B {
self.get().to_be_bytes()
}
#[inline]
fn encode_owned(self) -> Self::B {
self.get().to_be_bytes()
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
let u = u32::from_be_bytes(*bytes);
let u = NonZeroU32::new(u).ok_or(ArmourError::NonZeroError)?;
Ok(u)
}
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
let u = u32::from_be_bytes(bytes);
let u = NonZeroU32::new(u).ok_or(ArmourError::NonZeroError)?;
Ok(u)
}
#[inline]
fn group_id(&self) -> u32 {
g4bits(self.get(), Self::GROUP_BITS)
}
}
impl Cid for NonZeroU64 {
type B = [u8; 8];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::U64]);
const GROUP_BITS: u32 = SEQ64_BITS;
#[inline]
fn encode(&self) -> Self::B {
self.get().to_be_bytes()
}
#[inline]
fn encode_owned(self) -> Self::B {
self.get().to_be_bytes()
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
let u = u64::from_be_bytes(*bytes);
let u = NonZeroU64::new(u).ok_or(ArmourError::NonZeroError)?;
Ok(u)
}
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
let u = u64::from_be_bytes(bytes);
let u = NonZeroU64::new(u).ok_or(ArmourError::NonZeroError)?;
Ok(u)
}
#[inline]
fn group_id(&self) -> u32 {
let id = self.get();
g8bits(id, Self::GROUP_BITS)
}
}
impl Cid for u64 {
type B = [u8; 8];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::U64]);
const GROUP_BITS: u32 = SEQ64_BITS;
#[inline]
fn encode(&self) -> Self::B {
self.to_be_bytes()
}
#[inline]
fn encode_owned(self) -> Self::B {
self.to_be_bytes()
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
let u = u64::from_be_bytes(*bytes);
Ok(u)
}
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
let u = u64::from_be_bytes(bytes);
Ok(u)
}
#[inline]
fn group_id(&self) -> u32 {
g8bits(*self, Self::GROUP_BITS)
}
}
impl Cid for u64_be {
type B = [u8; 8];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::U64]);
const GROUP_BITS: u32 = SEQ64_BITS;
#[inline]
fn encode(&self) -> Self::B {
zerocopy::transmute!(*self)
}
#[inline]
fn encode_owned(self) -> Self::B {
zerocopy::transmute!(self)
}
#[inline]
fn from_bytes(bytes: &[u8]) -> Result<Self> {
let bytes: &[u8; 8] = bytes
.get(..8)
.ok_or(ArmourError::BytesLenError)?
.try_into()?;
Self::decode(bytes)
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
Ok(zerocopy::transmute!(*bytes))
}
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
Ok(zerocopy::transmute!(bytes))
}
#[inline]
fn group_id(&self) -> u32 {
let id = self.to_native();
g8bits(id, Self::GROUP_BITS)
}
}
const STR_GROUP_BITS: u32 = 8;
impl Cid for String {
type B = Vec<u8>;
const TY: KeyScheme = KeyScheme::Bytes;
const GROUP_BITS: u32 = STR_GROUP_BITS;
#[inline]
fn encode(&self) -> Self::B {
self.as_bytes().to_vec()
}
#[inline]
fn encode_owned(self) -> Self::B {
self.into_bytes()
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
let s = String::from_utf8(bytes.to_vec())?;
Ok(s)
}
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
let s = String::from_utf8(bytes)?;
Ok(s)
}
#[inline]
fn group_id(&self) -> u32 {
self.as_bytes().first().copied().unwrap_or_default() as u32
}
}
impl<const CAP: usize> Cid for ArrayString<CAP> {
type B = [u8; CAP];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::Array(CAP)]);
const GROUP_BITS: u32 = STR_GROUP_BITS;
#[inline]
fn encode(&self) -> Self::B {
let mut result = [0u8; CAP];
let bytes = self.as_bytes();
result[..bytes.len()].copy_from_slice(bytes);
result
}
#[inline]
fn encode_owned(self) -> Self::B {
let mut result = [0u8; CAP];
let bytes = self.as_bytes();
result[..bytes.len()].copy_from_slice(bytes);
result
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
let s = Self::from_byte_string(bytes)?;
Ok(s)
}
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
let s = Self::from_byte_string(&bytes)?;
Ok(s)
}
#[inline]
fn group_id(&self) -> u32 {
self.as_bytes().first().copied().unwrap_or_default() as u32
}
}
impl Cid for Uuid {
type B = [u8; 16];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::Array(16)]);
const GROUP_BITS: u32 = MILLISECOND_BITS;
#[inline]
fn encode(&self) -> Self::B {
self.into_bytes()
}
#[inline]
fn encode_owned(self) -> Self::B {
self.into_bytes()
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
Ok(Uuid::from_bytes(*bytes))
}
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
Ok(Uuid::from_bytes(bytes))
}
#[inline]
fn group_id(&self) -> u32 {
g16bits(self.as_u128(), Self::GROUP_BITS)
}
}
impl<H> Cid for Fuid<H> {
type B = [u8; 8];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::Fuid]);
const GROUP_BITS: u32 = MILLISECOND_BITS;
#[inline]
fn encode(&self) -> Self::B {
zerocopy::transmute!(*self)
}
#[inline]
fn encode_owned(self) -> Self::B {
zerocopy::transmute!(self)
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
Ok(zerocopy::transmute!(*bytes))
}
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
Ok(zerocopy::transmute!(bytes))
}
#[inline]
fn group_id(&self) -> u32 {
self.group_id()
}
}
impl<T> Cid for Id64<T> {
type B = [u8; 8];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::U64]);
const GROUP_BITS: u32 = SEQ64_BITS;
#[inline]
fn encode(&self) -> Self::B {
zerocopy::transmute!(*self)
}
#[inline]
fn encode_owned(self) -> Self::B {
zerocopy::transmute!(self)
}
#[inline]
fn from_bytes(bytes: &[u8]) -> Result<Self> {
let bytes: &[u8; 8] = bytes
.get(..8)
.ok_or(ArmourError::BytesLenError)?
.try_into()?;
Self::decode(bytes)
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
Ok(zerocopy::transmute!(*bytes))
}
#[inline]
fn decode_owned(bytes: Self::B) -> Result<Self> {
Ok(zerocopy::transmute!(bytes))
}
#[inline]
fn group_id(&self) -> u32 {
self.group_id()
}
}
#[cfg(feature = "solana")]
impl Cid for solana_pubkey::Pubkey {
type B = [u8; 32];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::Array(32)]);
const GROUP_BITS: u32 = 8;
#[inline]
fn encode(&self) -> Self::B {
self.to_bytes()
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
Ok(Self::new_from_array(*bytes))
}
#[inline]
fn group_id(&self) -> u32 {
self.as_array()[0] as u32
}
}
#[cfg(feature = "solana")]
impl Cid for solana_signature::Signature {
type B = [u8; 64];
const TY: KeyScheme = KeyScheme::Typed(&[KeyType::Array(64)]);
const GROUP_BITS: u32 = 8;
#[inline]
fn encode(&self) -> Self::B {
<[u8; 64]>::from(*self)
}
#[inline]
fn decode(bytes: &Self::B) -> Result<Self> {
Ok(Self::from(*bytes))
}
#[inline]
fn group_id(&self) -> u32 {
self.as_ref()[0] as u32
}
}