Experimenting with more structured ways to handle command-line input/output in Rust
use std::env;

pub enum LocaleCategory {
    CType,
    Collate,
    Messages,
    Monetary,
    Numeric,
    Time,
    Address,
    Identification,
    Measurement,
    Name,
    Paper,
    Telephone,
}

impl LocaleCategory {
    fn as_str(&self) -> &str {
        match self {
            Self::CType => "LC_CTYPE",
            Self::Collate => "LC_COLLATE",
            Self::Messages => "LC_MESSAGES",
            Self::Monetary => "LC_MONETARY",
            Self::Numeric => "LC_NUMERIC",
            Self::Time => "LC_TIME",
            Self::Address => "LC_ADDRESS",
            Self::Identification => "LC_IDENTIFICATION",
            Self::Measurement => "LC_MEASUREMENT",
            Self::Name => "LC_NAME",
            Self::Paper => "LC_PAPER",
            Self::Telephone => "LC_TELEPHONE",
        }
    }

    /// Query the locale following the POSIX spec:
    /// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02
    ///
    /// Order of precedence:
    /// 1. LC_ALL
    /// 2. LC_{NUMERIC, TIME, etc}
    /// 3. LANG
    /// 4. Default locale (handled by caller, this function will return None)
    pub fn get_locales(&self) -> Vec<String> {
        let mut locales = Vec::with_capacity(3);

        if let Ok(global_locale) = env::var("LC_ALL") {
            locales.push(global_locale);
        }

        if let Ok(category_locale) = env::var(self.as_str()) {
            locales.push(category_locale);
        }

        if let Ok(lang) = env::var("LANG") {
            locales.push(lang);
        }

        locales
    }
}