whoami/
language.rs

1use std::fmt::{self, Display, Formatter};
2
3/// Country code for a [`Language`] dialect
4///
5/// Uses <https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2>
6#[non_exhaustive]
7#[repr(u32)]
8#[derive(Copy, Clone, Eq, PartialEq, Debug)]
9pub enum Country {
10    // FIXME: V2: u32::from_ne_bytes for country codes, with `\0` for unused
11    // FIXME: Add aliases up to 3-4 letters, but hidden
12    /// Any dialect
13    Any,
14    /// `US`: United States of America
15    #[doc(hidden)]
16    Us,
17}
18
19impl Display for Country {
20    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
21        f.write_str(match self {
22            Self::Any => "**",
23            Self::Us => "US",
24        })
25    }
26}
27
28/// A spoken language
29///
30/// Use [`ToString::to_string()`] to convert to string of two letter lowercase
31/// language code followed an forward slash and uppercase country code (example:
32/// `en/US`).
33///
34/// Uses <https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes>
35#[non_exhaustive]
36#[derive(Clone, Eq, PartialEq, Debug)]
37// #[allow(variant_size_differences)]
38pub enum Language {
39    #[doc(hidden)]
40    __(Box<String>),
41    /// `en`: English
42    #[doc(hidden)]
43    En(Country),
44    /// `es`: Spanish
45    #[doc(hidden)]
46    Es(Country),
47}
48
49impl Language {
50    /// Retrieve the country code for this language dialect.
51    pub fn country(&self) -> Country {
52        match self {
53            Self::__(_) => Country::Any,
54            Self::En(country) | Self::Es(country) => *country,
55        }
56    }
57}
58
59impl Display for Language {
60    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
61        match self {
62            Self::__(code) => f.write_str(code.as_str()),
63            Self::En(country) => {
64                if *country != Country::Any {
65                    f.write_str("en/")?;
66                    <Country as Display>::fmt(country, f)
67                } else {
68                    f.write_str("en")
69                }
70            }
71            Self::Es(country) => {
72                if *country != Country::Any {
73                    f.write_str("es/")?;
74                    <Country as Display>::fmt(country, f)
75                } else {
76                    f.write_str("es")
77                }
78            }
79        }
80    }
81}