use std::fmt;
macro_rules! u64_id {
($(#[$attr:meta])* $name:ident) => {
$(#[$attr])*
#[derive(
Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord,
serde::Serialize, serde::Deserialize,
)]
#[repr(transparent)]
pub struct $name(u64);
impl $name {
pub const fn new(inner: u64) -> Self { Self(inner) }
pub const fn as_u64(self) -> u64 { self.0 }
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}({})", stringify!($name), self.0)
}
}
impl From<u64> for $name {
fn from(inner: u64) -> Self { Self(inner) }
}
};
}
u64_id! {
RequestId
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ComponentTag(pub &'static str);
impl ComponentTag {
pub const fn new(tag: &'static str) -> Self {
Self(tag)
}
pub const fn as_str(self) -> &'static str {
self.0
}
}
impl fmt::Display for ComponentTag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ComponentTag({:?})", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct OpsetId {
pub domain: &'static str,
pub version: i64,
}
impl OpsetId {
pub const fn new(domain: &'static str, version: i64) -> Self {
Self { domain, version }
}
}
impl fmt::Display for OpsetId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} v{}", self.domain, self.version)
}
}
#[derive(
Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
)]
#[repr(transparent)]
pub struct PeerId(multihash::Multihash<64>);
impl PeerId {
pub const IDENTITY: u64 = 0x00;
pub const SHA2_256: u64 = 0x12;
pub const fn from_multihash(mh: multihash::Multihash<64>) -> Self {
Self(mh)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, multihash::Error> {
multihash::Multihash::from_bytes(bytes).map(Self)
}
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes()
}
pub fn code(&self) -> u64 {
self.0.code()
}
pub fn digest(&self) -> &[u8] {
self.0.digest()
}
pub fn as_multihash(&self) -> &multihash::Multihash<64> {
&self.0
}
pub fn as_identity_u64(&self) -> Option<u64> {
if self.0.code() == Self::IDENTITY {
let d = self.0.digest();
if d.len() == 8 {
return Some(u64::from_be_bytes(d.try_into().expect("checked len == 8")));
}
}
None
}
}
impl From<u64> for PeerId {
fn from(value: u64) -> Self {
let bytes = value.to_be_bytes();
let mh = multihash::Multihash::<64>::wrap(Self::IDENTITY, &bytes)
.expect("identity hash of 8 bytes always fits in 64");
Self(mh)
}
}
impl fmt::Display for PeerId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&bs58::encode(self.to_bytes()).into_string())
}
}