lib_humus/language/
unicode_language_identifier.rs1use std::{
6 fmt::Display,
7 ops::{Deref, DerefMut},
8 str::FromStr,
9};
10
11use serde::Deserialize;
12use unic_langid::{LanguageIdentifier, LanguageIdentifierError};
13
14#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub struct UnicodeLanguageIdentifier(LanguageIdentifier);
17
18impl From<LanguageIdentifier> for UnicodeLanguageIdentifier {
19 fn from(value: LanguageIdentifier) -> Self {
20 Self(value)
21 }
22}
23
24impl From<UnicodeLanguageIdentifier> for LanguageIdentifier {
25 fn from(value: UnicodeLanguageIdentifier) -> Self {
26 value.0
27 }
28}
29
30impl Deref for UnicodeLanguageIdentifier {
31 type Target = LanguageIdentifier;
32
33 fn deref(&self) -> &Self::Target {
34 &self.0
35 }
36}
37
38impl DerefMut for UnicodeLanguageIdentifier {
39 fn deref_mut(&mut self) -> &mut Self::Target {
40 &mut self.0
41 }
42}
43
44impl Display for UnicodeLanguageIdentifier {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 self.0.fmt(f)
47 }
48}
49
50impl FromStr for UnicodeLanguageIdentifier {
51 type Err = LanguageIdentifierError;
52
53 fn from_str(s: &str) -> Result<Self, Self::Err> {
54 Ok(Self(s.parse()?))
55 }
56}
57
58impl serde::Serialize for UnicodeLanguageIdentifier {
59 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
60 where
61 S: serde::Serializer,
62 {
63 serializer.serialize_str(self.0.to_string().as_str())
64 }
65}
66
67impl<'de> Deserialize<'de> for UnicodeLanguageIdentifier {
68 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69 where
70 D: serde::Deserializer<'de>,
71 {
72 deserializer.deserialize_str(UnicodeLanguageIdentifierVisitor)
73 }
74}
75
76struct UnicodeLanguageIdentifierVisitor;
77
78impl<'de> serde::de::Visitor<'de> for UnicodeLanguageIdentifierVisitor {
79 type Value = UnicodeLanguageIdentifier;
80
81 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
82 formatter.write_str(
83 "A language Tag as defined in Unicode TR35 (similar to BCP 47 i.e. en-US, zh-TW, de-Latn or fr)",
84 )
85 }
86
87 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
88 where
89 E: serde::de::Error,
90 {
91 let identifier: LanguageIdentifier = v.parse().map_err(|e| {
92 E::custom(format!(
93 "Unable to parse unicode TR35 language identifier from {v:?}: {e}"
94 ))
95 })?;
96 Ok(UnicodeLanguageIdentifier(identifier))
97 }
98}