use crate::id::{
Id,
marker::{EmojiMarker, TagMarker},
};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct DefaultReaction {
pub emoji_id: Option<Id<EmojiMarker>>,
pub emoji_name: Option<String>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[non_exhaustive]
#[serde(from = "u8", into = "u8")]
pub enum ForumLayout {
GalleryView,
ListView,
NotSet,
Unknown(u8),
}
impl ForumLayout {
pub const fn name(self) -> &'static str {
match self {
Self::ListView => "ListView",
Self::NotSet => "NotSet",
Self::GalleryView => "GalleryView",
Self::Unknown(_) => "Unknown",
}
}
}
impl From<u8> for ForumLayout {
fn from(value: u8) -> Self {
match value {
0 => Self::NotSet,
1 => Self::ListView,
2 => Self::GalleryView,
unknown => Self::Unknown(unknown),
}
}
}
impl From<ForumLayout> for u8 {
fn from(value: ForumLayout) -> Self {
match value {
ForumLayout::NotSet => 0,
ForumLayout::ListView => 1,
ForumLayout::GalleryView => 2,
ForumLayout::Unknown(unknown) => unknown,
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[non_exhaustive]
#[serde(from = "u8", into = "u8")]
pub enum ForumSortOrder {
CreationDate,
LatestActivity,
Unknown(u8),
}
impl ForumSortOrder {
pub const fn name(self) -> &'static str {
match self {
Self::CreationDate => "CreationDate",
Self::LatestActivity => "LatestActivity",
Self::Unknown(_) => "Unknown",
}
}
}
impl From<u8> for ForumSortOrder {
fn from(value: u8) -> Self {
match value {
0 => Self::LatestActivity,
1 => Self::CreationDate,
unknown => Self::Unknown(unknown),
}
}
}
impl From<ForumSortOrder> for u8 {
fn from(value: ForumSortOrder) -> Self {
match value {
ForumSortOrder::LatestActivity => 0,
ForumSortOrder::CreationDate => 1,
ForumSortOrder::Unknown(unknown) => unknown,
}
}
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ForumTag {
#[serde(with = "crate::visitor::zeroable_id")]
pub emoji_id: Option<Id<EmojiMarker>>,
pub emoji_name: Option<String>,
pub id: Id<TagMarker>,
pub moderated: bool,
pub name: String,
}
#[cfg(test)]
mod tests {
use super::{DefaultReaction, ForumLayout, ForumSortOrder, ForumTag};
use crate::id::{
Id,
marker::{EmojiMarker, TagMarker},
};
use serde::{Deserialize, Serialize};
use serde_test::{Token, assert_tokens};
use static_assertions::assert_impl_all;
use std::{fmt::Debug, hash::Hash};
assert_impl_all!(
ForumLayout: Clone,
Copy,
Debug,
Deserialize<'static>,
Eq,
Hash,
PartialEq,
Send,
Serialize,
Sync
);
assert_impl_all!(
ForumSortOrder: Clone,
Copy,
Debug,
Deserialize<'static>,
Eq,
Hash,
PartialEq,
Send,
Serialize,
Sync
);
const EMOJI_ID: Id<EmojiMarker> = Id::new(1);
const TAG_ID: Id<TagMarker> = Id::new(2);
#[test]
fn default_reaction() {
let value = DefaultReaction {
emoji_id: None,
emoji_name: Some("name".to_owned()),
};
serde_test::assert_tokens(
&value,
&[
Token::Struct {
name: "DefaultReaction",
len: 2,
},
Token::Str("emoji_id"),
Token::None,
Token::Str("emoji_name"),
Token::Some,
Token::Str("name"),
Token::StructEnd,
],
);
}
#[test]
fn forum_layout() {
const MAP: &[(ForumLayout, u8, &str)] = &[
(ForumLayout::NotSet, 0, "NotSet"),
(ForumLayout::ListView, 1, "ListView"),
(ForumLayout::GalleryView, 2, "GalleryView"),
(ForumLayout::Unknown(3), 3, "Unknown"),
];
for (layout, number, name) in MAP {
assert_eq!(layout.name(), *name);
assert_eq!(u8::from(*layout), *number);
assert_eq!(ForumLayout::from(*number), *layout);
assert_tokens(layout, &[Token::U8(*number)]);
}
}
#[test]
fn forum_sort_order() {
const MAP: &[(ForumSortOrder, u8, &str)] = &[
(ForumSortOrder::LatestActivity, 0, "LatestActivity"),
(ForumSortOrder::CreationDate, 1, "CreationDate"),
(ForumSortOrder::Unknown(100), 100, "Unknown"),
];
for (layout, number, name) in MAP {
assert_eq!(layout.name(), *name);
assert_eq!(u8::from(*layout), *number);
assert_eq!(ForumSortOrder::from(*number), *layout);
assert_tokens(layout, &[Token::U8(*number)]);
}
}
#[test]
fn forum_tag_emoji_name() {
let value = ForumTag {
emoji_id: None,
emoji_name: Some("emoji".to_owned()),
id: TAG_ID,
moderated: true,
name: "tag".into(),
};
serde_test::assert_tokens(
&value,
&[
Token::Struct {
name: "ForumTag",
len: 5,
},
Token::Str("emoji_id"),
Token::None,
Token::Str("emoji_name"),
Token::Some,
Token::Str("emoji"),
Token::Str("id"),
Token::NewtypeStruct { name: "Id" },
Token::Str("2"),
Token::Str("moderated"),
Token::Bool(true),
Token::Str("name"),
Token::Str("tag"),
Token::StructEnd,
],
);
}
#[test]
fn forum_tag() {
let value = ForumTag {
emoji_id: Some(EMOJI_ID),
emoji_name: None,
id: TAG_ID,
moderated: false,
name: "other".into(),
};
serde_test::assert_tokens(
&value,
&[
Token::Struct {
name: "ForumTag",
len: 5,
},
Token::Str("emoji_id"),
Token::Some,
Token::NewtypeStruct { name: "Id" },
Token::Str("1"),
Token::Str("emoji_name"),
Token::None,
Token::Str("id"),
Token::NewtypeStruct { name: "Id" },
Token::Str("2"),
Token::Str("moderated"),
Token::Bool(false),
Token::Str("name"),
Token::Str("other"),
Token::StructEnd,
],
);
}
#[test]
fn forum_tag_emoji_id_zero() {
let value = ForumTag {
emoji_id: None,
emoji_name: None,
id: TAG_ID,
moderated: true,
name: "tag".into(),
};
serde_test::assert_de_tokens(
&value,
&[
Token::Struct {
name: "ForumTag",
len: 5,
},
Token::Str("emoji_id"),
Token::U64(0),
Token::Str("emoji_name"),
Token::None,
Token::Str("id"),
Token::NewtypeStruct { name: "Id" },
Token::Str("2"),
Token::Str("moderated"),
Token::Bool(true),
Token::Str("name"),
Token::Str("tag"),
Token::StructEnd,
],
);
serde_test::assert_de_tokens(
&value,
&[
Token::Struct {
name: "ForumTag",
len: 5,
},
Token::Str("emoji_id"),
Token::Unit,
Token::Str("emoji_name"),
Token::None,
Token::Str("id"),
Token::NewtypeStruct { name: "Id" },
Token::Str("2"),
Token::Str("moderated"),
Token::Bool(true),
Token::Str("name"),
Token::Str("tag"),
Token::StructEnd,
],
);
}
}