summaryrefslogtreecommitdiff
path: root/src/library/text/lang.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/text/lang.rs')
-rw-r--r--src/library/text/lang.rs55
1 files changed, 45 insertions, 10 deletions
diff --git a/src/library/text/lang.rs b/src/library/text/lang.rs
index 343359d1..360827fa 100644
--- a/src/library/text/lang.rs
+++ b/src/library/text/lang.rs
@@ -1,24 +1,30 @@
use crate::eval::Value;
use crate::geom::Dir;
-/// A natural language.
+/// A code for a natural language.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-pub struct Lang([u8; 2]);
+pub struct Lang([u8; 3], u8);
impl Lang {
/// The code for the english language.
- pub const ENGLISH: Self = Self(*b"en");
+ pub const ENGLISH: Self = Self(*b"en ", 2);
- /// Construct a language from a two-byte ISO 639-1 code.
+ /// Construct a language from a two- or three-byte ISO 639-1/2/3 code.
pub fn from_str(iso: &str) -> Option<Self> {
- let mut bytes: [u8; 2] = iso.as_bytes().try_into().ok()?;
- bytes.make_ascii_lowercase();
- Some(Self(bytes))
+ let len = iso.len();
+ if matches!(len, 2 ..= 3) && iso.is_ascii() {
+ let mut bytes = [b' '; 3];
+ bytes[.. len].copy_from_slice(iso.as_bytes());
+ bytes.make_ascii_lowercase();
+ Some(Self(bytes, len as u8))
+ } else {
+ None
+ }
}
- /// Return the language code as a string slice.
+ /// Return the language code as an all lowercase string slice.
pub fn as_str(&self) -> &str {
- std::str::from_utf8(&self.0).unwrap_or_default()
+ std::str::from_utf8(&self.0[.. usize::from(self.1)]).unwrap_or_default()
}
/// The default direction for the language.
@@ -35,5 +41,34 @@ castable! {
Lang,
Expected: "string",
Value::Str(string) => Self::from_str(&string)
- .ok_or("expected two letter language code")?,
+ .ok_or("expected two or three letter language code (ISO 639-1/2/3)")?,
+}
+
+/// A code for a region somewhere in the world.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub struct Region([u8; 2]);
+
+impl Region {
+ /// Construct a region from its two-byte ISO 3166-1 alpha-2 code.
+ pub fn from_str(iso: &str) -> Option<Self> {
+ if iso.is_ascii() {
+ let mut bytes: [u8; 2] = iso.as_bytes().try_into().ok()?;
+ bytes.make_ascii_uppercase();
+ Some(Self(bytes))
+ } else {
+ None
+ }
+ }
+
+ /// Return the region code as an all uppercase string slice.
+ pub fn as_str(&self) -> &str {
+ std::str::from_utf8(&self.0).unwrap_or_default()
+ }
+}
+
+castable! {
+ Region,
+ Expected: "string",
+ Value::Str(string) => Self::from_str(&string)
+ .ok_or("expected two letter region code (ISO 3166-1 alpha-2)")?,
}