1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
use std; use std::fmt; use std::str::FromStr; use enum_set::CLike; pub trait ToStaticStr { fn to_static_str(&self) -> &'static str; } pub trait ListAll: Sized { fn list_all() -> &'static [Self]; } macro_rules! static_str_enum { ( $name:ident { $($item:ident => $str:ident),* } ) => { #[derive(Clone, Copy)] #[repr(u32)] pub enum $name { $($item),* } impl ToStaticStr for $name { fn to_static_str(&self) -> &'static str { match *self { $($name::$item => stringify!($str)),* } } } impl fmt::Display for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.to_static_str()) } } impl ListAll for $name { fn list_all() -> &'static [Self] { static LIST: &'static [$name] = &[$($name::$item),+]; &LIST } } impl FromStr for $name { type Err = (); fn from_str(s: &str) -> Result<Self, Self::Err> { match s { $(stringify!($str) => Ok($name::$item)),*, _ => Err(()) } } } impl CLike for $name { fn to_u32(&self) -> u32 { *self as u32 } unsafe fn from_u32(v: u32) -> $name { std::mem::transmute(v) } } } } static_str_enum! { Category { Anime => anime, Book => book, Music => music, Game => game, Real => real } } static_str_enum! { State { Wish => wish, Collect => collect, Do => do, OnHold => on_hold, Dropped => dropped } } pub type Id = u32; pub type Rating = u8; pub const MAX_RATING: Rating = 10; pub struct Item { pub id: Id, pub title: String, pub rating: Option<Rating>, pub tags: Vec<String>, }