use std::fmt;
use serde::{Deserialize, Serialize};
macro_rules! id_type {
($(#[$meta:meta])* $name:ident) => {
$(#[$meta])*
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct $name(pub i64);
impl $name {
pub const fn new(value: i64) -> Self {
Self(value)
}
pub const fn get(self) -> i64 {
self.0
}
}
impl From<i64> for $name {
fn from(value: i64) -> Self {
Self(value)
}
}
impl From<$name> for i64 {
fn from(id: $name) -> Self {
id.0
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
};
}
id_type!(
UserId
);
id_type!(
RoomId
);
id_type!(
MessageId
);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ids_are_plain_numbers() {
assert_eq!(serde_json::to_string(&UserId(42)).ok().as_deref(), Some("42"));
assert_eq!(serde_json::from_str::<RoomId>("-7").ok(), Some(RoomId(-7)));
assert_eq!(serde_json::from_str::<MessageId>(&i64::MAX.to_string()).ok(), Some(MessageId(i64::MAX)));
assert!(serde_json::from_str::<UserId>("\"42\"").is_err());
assert_eq!(UserId::new(5).get(), 5);
assert_eq!(i64::from(UserId::from(9)), 9);
assert_eq!(RoomId(3).to_string(), "3");
}
}