fake-rs icon indicating copy to clipboard operation
fake-rs copied to clipboard

Dynamic locale

Open dbr opened this issue 4 years ago • 2 comments

All the examples I can find fix the locale to a specific one:

let val: String = Name(EN).fake();
let val: String = Name(ZH_TW).fake();

I'd like to generate data based on user-supplied argument, e.g

enum Locale {
    English,
    Taiwan,
    ...etc..
}

fn enthusiastic_fake_data(lo: Locale) -> String {
    format!("{}!!!", ...)
}

I couldn't find a neat way to do this - I can of course just do

let val: String = match {
    English => Name(EN).fake(),
    Taiwan => Name(ZH_TW).fake(),
}

..but this gets very repetitive if you also have a similar match for type of data (e.g Name, Country, etc)

I was hoping to do something like

let lo = match locale_arg {
    Locale::English => fake::locales::EN,
    Locale::Taiwan => fake::Local::ZH_TW,
};
let val: String = Name(lo).fake();

However this doesn't work as each local is it's own struct. I tried let lo: Box<dyn fake::locale::Data> = match ... and started running into more complex errors, so I started wondering if I was missing a simpler way to do this

Thanks!

dbr avatar Nov 19 '21 02:11 dbr

I take sometime to think how to implement using const generic but not succeed. An other approach maybe something like below.

use rand::seq::SliceRandom;
use rand::Rng;
use fake::{Dummy, Fake};


#[derive(PartialEq, Eq)]
pub enum Locale {
    EN,
    FR,
    ZH_TW,
}

impl Locale {
    fn name_title(&self) -> &'static[&'static str] {
        match self {
            Locale::ZH_TW => &["先生", "女士", "女士", "小姐", "博士"],
            Locale::FR => &["M.", "Mme.", "Mme.", "Mlle", "Dr."],
            _ =>  &["Mr.", "Mrs.", "Ms.", "Miss", "Dr."]
        }
    }
}


pub struct Title(Locale);

impl Dummy<Title> for String {
    fn dummy_with_rng<R: Rng + ?Sized>(title: &Title, rng: &mut R) -> Self {
        let s = *title.0.name_title().choose(rng).unwrap();
        s.into()
    }
}

fn main() {
    println!("{:?}",  Title(Locale::EN).fake::<String>());
    println!("{:?}",  Title(Locale::ZH_TW).fake::<String>());
    println!("{:?}",  Title(Locale::FR).fake::<String>());
}

But it will be an breaking change and change get data from static dispatch to runtime dispatch. @llogiq What do you think?

cksac avatar Dec 09 '21 13:12 cksac

That enum is a lot like what synth does. To me it's the obvious easy choice.

Note that we can have both an enum and static dispatch if we align the traits right. That would avoid breaking the API.

llogiq avatar Dec 11 '21 11:12 llogiq