#![allow(deprecated)]
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::{fmt, mem};
const NUM_GENRES: u8 = 84;
macro_rules! genres {
( $( $( #[$meta:meta] )* $id:literal => $Genre:ident, )* ) => {
#[derive(Deserialize_repr, Serialize_repr, Eq, Ord, PartialEq, PartialOrd, Clone, Copy, Debug)]
#[repr(u8)]
pub enum Genre {
$(
$( #[$meta] )* $Genre = $id,
)*
#[serde(other)]
Unknown = 0,
}
impl Default for Genre { fn default() -> Self { 0u8.into() } }
};
}
genres! {
1 => FourKoma,
2 => Action,
3 => Adventure,
4 => AwardWinning,
5 => Comedy,
6 => Cooking,
7 => Doujinshi,
8 => Drama,
9 => Ecchi,
10 => Fantasy,
11 => Gyaru,
12 => Harem,
13 => Historical,
14 => Horror,
#[deprecated]
15 => ShounenDemographic,
16 => MartialArts,
17 => Mecha,
18 => Medical,
19 => Music,
20 => Mystery,
21 => Oneshot,
22 => Psychological,
23 => Romance,
24 => SchoolLife,
25 => SciFi,
#[deprecated]
26 => ShoujoDemographic,
#[deprecated]
27 => SeinenDemographic,
28 => ShoujoAi,
#[deprecated]
29 => JoseiDemographic,
30 => ShounenAi,
31 => SliceOfLife,
32 => Smut,
33 => Sports,
34 => Supernatural,
35 => Tragedy,
36 => LongStrip,
37 => Yaoi,
38 => Yuri,
#[deprecated]
39 => GenderBenderTheme,
40 => VideoGames,
41 => Isekai,
42 => Adaptation,
43 => Anthology,
44 => WebComic,
45 => FullColor,
46 => UserCreated,
47 => OfficialColored,
48 => FanColored,
49 => Gore,
50 => SexualViolence,
51 => Crime,
52 => MagicalGirls,
53 => Philosophical,
54 => Superhero,
55 => Thriller,
56 => Wuxia,
57 => Aliens,
58 => Animals,
59 => Crossdressing,
60 => Demons,
61 => Delinquents,
62 => Genderswap,
63 => Ghosts,
64 => MonsterGirls,
65 => Loli,
66 => Magic,
67 => Military,
68 => Monsters,
69 => Ninja,
70 => OfficeWorkers,
71 => Police,
72 => PostApocalyptic,
73 => Reincarnation,
74 => ReverseHarem,
75 => Samurai,
76 => Shota,
77 => Survival,
78 => TimeTravel,
79 => Vampires,
80 => TraditionalGames,
81 => VirtualReality,
82 => Zombies,
83 => Incest,
84 => Mafia,
}
impl From<u8> for Genre {
fn from(v: u8) -> Genre {
if v <= NUM_GENRES {
unsafe { mem::transmute(v) }
} else {
Genre::Unknown
}
}
}
crate::make_set_type!(GenreSet(u128) / Genre);
impl fmt::Debug for GenreSet {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt
.debug_set()
.entries((0..=NUM_GENRES).filter_map(|v| {
let genre = Genre::from(v);
if self.has(genre) { Some(genre) } else { None }
}))
.finish()
}
}
#[cfg(test)]
pub mod tests {
use super::*;
#[test]
fn genre_produces_unknown_from_0() {
let genre = Genre::from(0);
assert_eq!(genre, Genre::Unknown);
}
#[test]
fn new_genre_set_is_empty() {
let genres = GenreSet::new();
assert_eq!(genres.0, 0);
let set_tx = format!("{:?}", genres);
assert_eq!(set_tx, "{}");
for i in 0..=NUM_GENRES {
assert!(!genres.has(i));
}
}
#[test]
fn full_genre_set_contains_all() {
let genres = GenreSet(u128::max_value() & !1);
for i in 1..=NUM_GENRES {
assert!(genres.has(i));
}
eprintln!("{:?}", genres);
}
#[test]
fn part_genre_set_is_contained_by_full() {
let genres = GenreSet(u128::max_value());
let less_genres = GenreSet(u128::max_value() & !1);
assert!(genres != less_genres);
assert!(less_genres.contained(genres));
}
#[test]
fn part_genre_set_contains_other() {
let genres = GenreSet(u128::max_value());
let less_genres = GenreSet(u128::max_value() & !1);
assert!(genres != less_genres);
assert!(genres.contains(less_genres));
}
#[test]
fn genre_set_from_vector_of_genres() {
use Genre::*;
let genres: GenreSet = vec![FourKoma, Action, Adventure].into();
assert_eq!(genres, GenreSet(14));
eprintln!("{:?}", genres);
}
#[test]
fn genre_set_from_vector_of_u8() {
let genres: GenreSet = vec![1, 2, 3].into();
assert_eq!(genres, GenreSet(14));
eprintln!("{:?}", genres);
}
}