Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic locale #74

Open
dbr opened this issue Nov 19, 2021 · 2 comments
Open

Dynamic locale #74

dbr opened this issue Nov 19, 2021 · 2 comments

Comments

@dbr
Copy link

dbr commented Nov 19, 2021

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!

@cksac
Copy link
Owner

cksac commented Dec 9, 2021

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?

@llogiq
Copy link
Collaborator

llogiq commented Dec 11, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants