use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Version(pub u64, pub u64);
impl fmt::Display for Version {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}.{}", self.0, self.1)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum Tone {
Light,
MediumLight,
Medium,
MediumDark,
Dark,
}
impl Tone {
pub const ALL: [Tone; 5] = [
Self::Light,
Self::MediumLight,
Self::Medium,
Self::MediumDark,
Self::Dark,
];
pub const fn name(self) -> &'static str {
match self {
Self::Light => "light skin tone",
Self::MediumLight => "medium-light skin tone",
Self::Medium => "medium skin tone",
Self::MediumDark => "medium-dark skin tone",
Self::Dark => "dark skin tone",
}
}
}
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TonePair {
pub left: Tone,
pub right: Tone,
}
impl TonePair {
pub(crate) const fn to_id(self) -> usize {
self.left as usize * Tone::ALL.len() + self.right as usize
}
}
impl From<Tone> for TonePair {
fn from(both: Tone) -> Self {
TonePair {
left: both,
right: both,
}
}
}
impl From<(Tone, Tone)> for TonePair {
fn from((left, right): (Tone, Tone)) -> Self {
TonePair { left, right }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum Gender {
Male,
Female,
}
impl Gender {
pub const ALL: [Gender; 2] = [Self::Male, Self::Female];
pub fn with_children(self, children: impl Into<OneOrTwo>) -> Family {
(self, children).into()
}
pub const fn name_adults(self) -> &'static str {
match self {
Self::Male => "man",
Self::Female => "woman",
}
}
pub const fn name_children(self) -> &'static str {
match self {
Self::Male => "boy",
Self::Female => "girl",
}
}
}
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum Pair {
Males,
Mixed,
Females,
}
impl Pair {
pub const ALL: [Pair; 3] = [Self::Males, Self::Mixed, Self::Females];
pub fn with_children(self, children: impl Into<OneOrTwo>) -> Family {
(self, children).into()
}
pub const fn name_adults(self) -> &'static str {
match self {
Self::Males => "men",
Self::Mixed => "man & woman",
Self::Females => "women",
}
}
pub const fn name_children(self) -> &'static str {
match self {
Self::Males => "boys",
Self::Mixed => "boy & girl",
Self::Females => "girls",
}
}
}
impl From<(Gender, Gender)> for Pair {
fn from(pair: (Gender, Gender)) -> Self {
match pair {
(Gender::Male, Gender::Male) => Pair::Males,
(Gender::Male, Gender::Female) => Pair::Mixed,
(Gender::Female, Gender::Male) => Pair::Mixed,
(Gender::Female, Gender::Female) => Pair::Females,
}
}
}
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum OneOrTwo {
One(Gender),
Two(Pair),
}
impl OneOrTwo {
pub const ALL: [OneOrTwo; 5] = [
Self::One(Gender::Male),
Self::One(Gender::Female),
Self::Two(Pair::Males),
Self::Two(Pair::Mixed),
Self::Two(Pair::Females),
];
pub(crate) const fn to_id(self) -> usize {
match self {
Self::One(Gender::Male) => 0,
Self::One(Gender::Female) => 1,
Self::Two(Pair::Males) => 2,
Self::Two(Pair::Mixed) => 3,
Self::Two(Pair::Females) => 4,
}
}
pub fn with_children(self, children: impl Into<OneOrTwo>) -> Family {
(self, children).into()
}
pub const fn name_adults(self) -> &'static str {
match self {
Self::One(one) => one.name_adults(),
Self::Two(two) => two.name_adults(),
}
}
pub const fn name_children(self) -> &'static str {
match self {
Self::One(one) => one.name_children(),
Self::Two(two) => two.name_children(),
}
}
}
impl From<Gender> for OneOrTwo {
fn from(g: Gender) -> Self {
Self::One(g)
}
}
impl From<Pair> for OneOrTwo {
fn from(couple: Pair) -> Self {
Self::Two(couple)
}
}
impl From<(Gender, Gender)> for OneOrTwo {
fn from(pair: (Gender, Gender)) -> Self {
Self::Two(Pair::from(pair))
}
}
impl From<(Gender, Option<Gender>)> for OneOrTwo {
fn from(pair: (Gender, Option<Gender>)) -> Self {
if let Some(g2) = pair.1 {
Self::from((pair.0, g2))
} else {
Self::from(pair.0)
}
}
}
#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Family {
pub parents: OneOrTwo,
pub children: OneOrTwo,
}
impl Family {
pub(crate) const fn to_id(self) -> usize {
self.parents.to_id() * OneOrTwo::ALL.len() + self.children.to_id()
}
}
impl<A: Into<OneOrTwo>, B: Into<OneOrTwo>> From<(A, B)> for Family {
fn from((parents, children): (A, B)) -> Self {
Family {
parents: parents.into(),
children: children.into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum Hair {
Beard,
Blond,
Red,
Curly,
White,
Bald,
}
impl Hair {
pub const ALL: [Hair; 6] = [
Self::Beard,
Self::Blond,
Self::Red,
Self::Curly,
Self::White,
Self::Bald,
];
pub const fn name(self) -> &'static str {
match self {
Self::Beard => "beard",
Self::Bald => "no hair",
Self::Blond => "blond hair",
Self::Red => "red hair",
Self::Curly => "curly hair",
Self::White => "white hair",
}
}
}