use std::fmt::{self, Debug, Display};
use std::hash::Hash;
use std::ops::Deref;
use serde::{Deserialize, Serialize};
use crate::model::channel::guild::{
Category, NewsChannel, StoreChannel, TextChannel, VoiceChannel,
};
use crate::model::channel::message::Attachment;
use crate::model::channel::{DMChannel, Group, Message};
use crate::model::guild::{CustomEmoji, Emoji, Guild, PartialGuild, Role};
use crate::model::snowflake::{Snowflake, ToSnowflake};
use crate::model::user::{ClientUser, User};
macro_rules! id_type {
($(
$(#[$attr:meta])*
$Id:ident;
)*) => {$(
$(#[$attr])*
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
pub struct $Id(Snowflake);
impl Display for $Id {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl Deref for $Id {
type Target = Snowflake;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<Snowflake> for $Id {
fn as_ref(&self) -> &Snowflake {
&self.0
}
}
impl From<u64> for $Id {
fn from(n: u64) -> Self {
Self(Snowflake::from(n))
}
}
impl From<Snowflake> for $Id {
fn from(snowflake: Snowflake) -> Self {
Self(snowflake)
}
}
impl From<$Id> for Snowflake {
fn from(id: $Id) -> Self {
id.0
}
}
#[doc(hidden)]
impl $crate::model::snowflake::private::Sealed for $Id {}
impl ToSnowflake for $Id {
fn snowflake(self) -> Snowflake {
self.0
}
}
)*};
}
id_type! {
ApplicationId;
AttachmentId;
AuditLogEntryId;
ChannelId;
EmojiId;
GuildId;
IntegrationId;
MessageId;
RoleId;
UserId;
WebhookId;
}
pub(crate) mod private {
pub trait Sealed {}
}
pub trait ToSnowflakeId: private::Sealed {
type Id: ToSnowflake + Debug + Display + Eq + Hash;
fn id(&self) -> Self::Id;
}
macro_rules! impl_to_id {
($Parent:ident => $field:ident: $Id:ident) => {
#[doc(hidden)]
impl private::Sealed for $Parent {}
impl ToSnowflakeId for $Parent {
type Id = $Id;
fn id(&self) -> Self::Id {
self.$field
}
}
};
($(
$Parent:ident => $field:ident: $Id:ident;
)*) => {$(
impl_to_id!($Parent => $field: $Id);
)*};
}
impl_to_id! {
Attachment => id: AttachmentId;
Emoji => id: EmojiId;
CustomEmoji => id: EmojiId;
Guild => id: GuildId;
PartialGuild => id: GuildId;
Message => id: MessageId;
Role => id: RoleId;
User => id: UserId;
ClientUser => id: UserId;
}
impl_to_id! {
Category => id: ChannelId;
DMChannel => id: ChannelId;
Group => id: ChannelId;
NewsChannel => id: ChannelId;
StoreChannel => id: ChannelId;
TextChannel => id: ChannelId;
VoiceChannel => id: ChannelId;
}