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/// Language codes defined in ISO 639 <https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes>,
35/// Country codes defined in ISO 3166 <https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2>
36#[non_exhaustive]
37#[derive(Clone, Eq, PartialEq, Debug)]
38// #[allow(variant_size_differences)]
39pub enum Language {
40    #[doc(hidden)]
41    __(Box<String>),
42    /// `en`: English
43    #[doc(hidden)]
44    En(Country),
45    /// `es`: Spanish
46    #[doc(hidden)]
47    Es(Country),
48}
49
50impl Language {
51    /// Retrieve the country code for this language dialect.
52    pub fn country(&self) -> Country {
53        match self {
54            Self::__(_) => Country::Any,
55            Self::En(country) | Self::Es(country) => *country,
56        }
57    }
58}
59
60impl Display for Language {
61    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
62        match self {
63            Self::__(code) => f.write_str(code.as_str()),
64            Self::En(country) => {
65                if *country != Country::Any {
66                    f.write_str("en/")?;
67                    <Country as Display>::fmt(country, f)
68                } else {
69                    f.write_str("en")
70                }
71            }
72            Self::Es(country) => {
73                if *country != Country::Any {
74                    f.write_str("es/")?;
75                    <Country as Display>::fmt(country, f)
76                } else {
77                    f.write_str("es")
78                }
79            }
80        }
81    }
82}