gimei 0.2.0

Generate fake name for Japanese
Documentation
use lazy_static::lazy_static;
use rand::seq::SliceRandom;
use serde::Deserialize;
use std::{convert, fmt};

use crate::Item;

#[derive(Debug, Deserialize)]
struct FirstName {
  male: Vec<Item>,
  female: Vec<Item>,
}

#[derive(Debug, Deserialize)]
struct Data {
  first_name: FirstName,
  last_name: Vec<Item>,
}

lazy_static! {
  static ref DATA: Data = serde_yaml::from_str(include_str!("data/names.yml")).unwrap();
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Gender {
  Male,
  Female,
}

impl fmt::Display for Gender {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match *self {
      Gender::Male => write!(f, ""),
      Gender::Female => write!(f, ""),
    }
  }
}

#[derive(Debug)]
struct MaleName {
  first: Item,
  last: Item,
}

impl rand::distributions::Distribution<MaleName> for rand::distributions::Standard {
  fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> MaleName {
    MaleName {
      first: DATA.first_name.male.choose(rng).cloned().unwrap(),
      last: DATA.last_name.choose(rng).cloned().unwrap(),
    }
  }
}

#[derive(Debug)]
struct FemaleName {
  first: Item,
  last: Item,
}

impl rand::distributions::Distribution<FemaleName> for rand::distributions::Standard {
  fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> FemaleName {
    FemaleName {
      first: DATA.first_name.female.choose(rng).cloned().unwrap(),
      last: DATA.last_name.choose(rng).cloned().unwrap(),
    }
  }
}

#[derive(Clone, Debug)]
pub struct Name {
  pub first: Item,
  pub last: Item,
  pub gender: Gender,
}

impl Name {
  pub fn to_kanji(&self) -> String {
    format!("{} {}", self.last.kanji, self.first.kanji)
  }

  pub fn to_hiragana(&self) -> String {
    format!("{} {}", self.last.hiragana, self.first.hiragana)
  }

  pub fn to_katakana(&self) -> String {
    format!("{} {}", self.last.katakana, self.first.katakana)
  }

  pub fn is_male(&self) -> bool {
    self.gender == Gender::Male
  }

  pub fn is_female(&self) -> bool {
    self.gender == Gender::Female
  }
}

impl convert::From<MaleName> for Name {
  fn from(name: MaleName) -> Self {
    Self {
      first: name.first,
      last: name.last,
      gender: Gender::Male,
    }
  }
}

impl convert::From<FemaleName> for Name {
  fn from(name: FemaleName) -> Self {
    Self {
      first: name.first,
      last: name.last,
      gender: Gender::Female,
    }
  }
}

impl fmt::Display for Name {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", self.to_kanji())
  }
}

pub fn male() -> Name {
  rand::random::<MaleName>().into()
}

pub fn female() -> Name {
  rand::random::<FemaleName>().into()
}

pub fn name() -> Name {
  if rand::random() {
    male()
  } else {
    female()
  }
}