1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
pub mod errors; pub mod extensions; pub mod parser; use errors::LocaleError; pub use extensions::{ExtensionType, ExtensionsMap}; use std::str::FromStr; use tinystr::{TinyStr4, TinyStr8}; pub use unic_langid_impl::CharacterDirection; pub use unic_langid_impl::LanguageIdentifier; #[derive(Debug, Default, PartialEq, Clone)] pub struct Locale { pub langid: LanguageIdentifier, pub extensions: extensions::ExtensionsMap, } type RawPartsTuple = ( Option<u64>, Option<u32>, Option<u32>, Option<Box<[u64]>>, String, ); impl Locale { pub fn from_parts<S: AsRef<str>>( language: Option<S>, script: Option<S>, region: Option<S>, variants: &[S], extensions: Option<extensions::ExtensionsMap>, ) -> Result<Self, LocaleError> { let langid = LanguageIdentifier::from_parts(language, script, region, variants)?; Ok(Locale { langid, extensions: extensions.unwrap_or_default(), }) } pub fn into_raw_parts(self) -> RawPartsTuple { let (lang, region, script, variants) = self.langid.into_raw_parts(); (lang, region, script, variants, self.extensions.to_string()) } #[inline(always)] pub unsafe fn from_raw_parts_unchecked( language: Option<TinyStr8>, script: Option<TinyStr4>, region: Option<TinyStr4>, variants: Option<Box<[TinyStr8]>>, extensions: extensions::ExtensionsMap, ) -> Self { let langid = LanguageIdentifier::from_raw_parts_unchecked(language, script, region, variants); Self { langid, extensions } } pub fn matches<O: AsRef<Self>>( &self, other: &O, self_as_range: bool, other_as_range: bool, ) -> bool { let other = other.as_ref(); if !self.extensions.private.is_empty() || !other.extensions.private.is_empty() { return false; } self.langid .matches(&other.langid, self_as_range, other_as_range) } pub fn get_language(&self) -> &str { self.langid.get_language() } pub fn set_language(&mut self, language: Option<&str>) -> Result<(), LocaleError> { self.langid .set_language(language) .map_err(std::convert::Into::into) } pub fn get_script(&self) -> Option<&str> { self.langid.get_script() } pub fn set_script(&mut self, script: Option<&str>) -> Result<(), LocaleError> { self.langid .set_script(script) .map_err(std::convert::Into::into) } pub fn get_region(&self) -> Option<&str> { self.langid.get_region() } pub fn set_region(&mut self, region: Option<&str>) -> Result<(), LocaleError> { self.langid .set_region(region) .map_err(std::convert::Into::into) } pub fn get_variants(&self) -> Vec<&str> { self.langid.get_variants() } pub fn set_variants(&mut self, variants: &[&str]) -> Result<(), LocaleError> { self.langid .set_variants(variants) .map_err(std::convert::Into::into) } #[cfg(feature = "likelysubtags")] pub fn add_likely_subtags(&mut self) -> bool { self.langid.add_likely_subtags() } #[cfg(feature = "likelysubtags")] pub fn remove_likely_subtags(&mut self) -> bool { self.langid.remove_likely_subtags() } pub fn get_character_direction(&self) -> CharacterDirection { self.langid.get_character_direction() } } impl FromStr for Locale { type Err = LocaleError; fn from_str(source: &str) -> Result<Self, Self::Err> { parser::parse_locale(source).map_err(std::convert::Into::into) } } impl From<LanguageIdentifier> for Locale { fn from(langid: LanguageIdentifier) -> Self { Locale { langid, extensions: ExtensionsMap::default(), } } } impl Into<LanguageIdentifier> for Locale { fn into(self) -> LanguageIdentifier { self.langid } } impl AsRef<LanguageIdentifier> for Locale { fn as_ref(&self) -> &LanguageIdentifier { &self.langid } } impl AsRef<Locale> for Locale { #[inline(always)] fn as_ref(&self) -> &Locale { self } } impl std::fmt::Display for Locale { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}{}", self.langid, self.extensions) } } pub fn canonicalize(input: &str) -> Result<String, LocaleError> { let locale: Locale = input.parse()?; Ok(locale.to_string()) }