use std::{fmt, mem::size_of};
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Serialize};
#[derive(
BorshSerialize,
BorshDeserialize,
Clone,
Copy,
Debug,
Default,
Deserialize,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
)]
#[serde(transparent)]
#[repr(transparent)]
pub struct DkgEpochId(u64);
impl DkgEpochId {
pub const BORSH_SERIALIZED_SIZE: usize = size_of::<u64>();
pub const fn new(epoch: u64) -> Self {
Self(epoch)
}
pub const fn as_u64(self) -> u64 {
self.0
}
}
impl fmt::Display for DkgEpochId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_as_u64_roundtrip() {
assert_eq!(DkgEpochId::new(42).as_u64(), 42);
assert_eq!(DkgEpochId::default(), DkgEpochId::new(0));
}
#[test]
fn borsh_matches_u64() {
let raw: u64 = 0x00ad_beef_dead_beef;
let e = DkgEpochId::new(raw);
assert_eq!(borsh::to_vec(&e).unwrap(), raw.to_le_bytes());
assert_eq!(
borsh::from_slice::<DkgEpochId>(&raw.to_le_bytes()).unwrap(),
e
);
assert_eq!(DkgEpochId::BORSH_SERIALIZED_SIZE, raw.to_le_bytes().len());
}
#[test]
fn bcs_matches_u64() {
let raw: u64 = 0x00ad_beef_dead_beef;
let e = DkgEpochId::new(raw);
assert_eq!(bcs::to_bytes(&e).unwrap(), bcs::to_bytes(&raw).unwrap());
assert_eq!(
bcs::from_bytes::<DkgEpochId>(&bcs::to_bytes(&raw).unwrap()).unwrap(),
e
);
}
#[test]
fn bincode_matches_u64() {
let raw: u64 = 0x00ad_beef_dead_beef;
let e = DkgEpochId::new(raw);
assert_eq!(
bincode::serialize(&e).unwrap(),
bincode::serialize(&raw).unwrap()
);
}
#[test]
fn serde_json_is_transparent() {
assert_eq!(serde_json::to_string(&DkgEpochId::new(7)).unwrap(), "7");
assert_eq!(
serde_json::from_str::<DkgEpochId>("7").unwrap(),
DkgEpochId::new(7)
);
}
}