use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct KeyId(u64);
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Generation(u32);
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct SlotIndex(u32);
pub const ADMIN_KEY_ID: KeyId = KeyId(0);
impl KeyId {
pub const fn new(generation: Generation, slot: SlotIndex) -> Self {
Self(((generation.0 as u64) << 32) | slot.0 as u64)
}
pub const fn generation(self) -> Generation {
Generation((self.0 >> 32) as u32)
}
pub const fn slot(self) -> SlotIndex {
SlotIndex(self.0 as u32)
}
pub const fn is_admin(self) -> bool {
self.0 == ADMIN_KEY_ID.0
}
pub const fn to_be_bytes(self) -> [u8; 8] {
self.0.to_be_bytes()
}
pub const fn as_u64(self) -> u64 {
self.0
}
pub const fn from_u64(raw: u64) -> Self {
Self(raw)
}
}
impl Generation {
pub const FIRST: Self = Self(0);
pub fn next(self) -> Option<Self> {
self.0.checked_add(1).map(Self)
}
pub const fn as_u32(self) -> u32 {
self.0
}
pub const fn from_u32(raw: u32) -> Self {
Self(raw)
}
}
impl SlotIndex {
pub const fn as_index(self) -> usize {
self.0 as usize
}
pub fn from_index(index: usize) -> Self {
match u32::try_from(index) {
Ok(index) => Self(index),
Err(_) => panic!("slot index exceeds the addressable slot table"),
}
}
}
impl fmt::Display for KeyId {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}
impl fmt::Display for Generation {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}
impl fmt::Display for SlotIndex {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}