icu_locale_core/preferences/extensions/unicode/macros/
struct_keyword.rs1#[macro_export]
29#[doc(hidden)]
30macro_rules! __struct_keyword {
31 ($(#[$doc:meta])* $([$derive_attrs:ty])? $name:ident, $ext_key:literal, $value:ty, $try_from:expr, $into:expr) => {
32 $(#[$doc])*
33 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
34 $(#[derive($derive_attrs)])?
35 #[allow(clippy::exhaustive_structs)] pub struct $name(pub(crate) $value);
37
38 impl TryFrom<$crate::extensions::unicode::Value> for $name {
39 type Error = $crate::preferences::extensions::unicode::errors::PreferencesParseError;
40
41 fn try_from(
42 input: $crate::extensions::unicode::Value,
43 ) -> Result<Self, Self::Error> {
44 Self::try_from(&input)
45 }
46 }
47
48 impl TryFrom<&$crate::extensions::unicode::Value> for $name {
49 type Error = $crate::preferences::extensions::unicode::errors::PreferencesParseError;
50
51 fn try_from(
52 input: &$crate::extensions::unicode::Value,
53 ) -> Result<Self, Self::Error> {
54 $try_from(input)
55 }
56 }
57
58 impl From<$name> for $crate::extensions::unicode::Value {
59 fn from(input: $name) -> $crate::extensions::unicode::Value {
60 (&input).into()
61 }
62 }
63
64 impl From<&$name> for $crate::extensions::unicode::Value {
65 fn from(input: &$name) -> $crate::extensions::unicode::Value {
66 $into(input)
67 }
68 }
69
70 impl $crate::preferences::PreferenceKey for $name {
71 fn unicode_extension_key() -> Option<$crate::extensions::unicode::Key> {
72 Some(Self::UNICODE_EXTENSION_KEY)
73 }
74
75 fn try_from_key_value(
76 key: &$crate::extensions::unicode::Key,
77 value: &$crate::extensions::unicode::Value,
78 ) -> Result<Option<Self>, $crate::preferences::extensions::unicode::errors::PreferencesParseError> {
79 if Self::UNICODE_EXTENSION_KEY == *key {
80 let result = Self::try_from(value.clone())?;
81 Ok(Some(result))
82 } else {
83 Ok(None)
84 }
85 }
86
87 fn unicode_extension_value(
88 &self,
89 ) -> Option<$crate::extensions::unicode::Value> {
90 Some(self.clone().into())
91 }
92 }
93
94 impl $name {
95 pub(crate) const UNICODE_EXTENSION_KEY: $crate::extensions::unicode::Key = $crate::extensions::unicode::key!($ext_key);
96 }
97
98 impl core::ops::Deref for $name {
99 type Target = $value;
100
101 fn deref(&self) -> &Self::Target {
102 &self.0
103 }
104 }
105 };
106}
107pub use __struct_keyword as struct_keyword;
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112 use crate::{
113 extensions::unicode,
114 subtags::{Subtag, subtag},
115 };
116 use core::str::FromStr;
117
118 #[test]
119 fn struct_keywords_test() {
120 struct_keyword!(
121 DummyKeyword,
122 "dk",
123 Subtag,
124 |input: &unicode::Value| {
125 if let Some(&subtag) = input.as_single_subtag()
126 && subtag.len() == 3
127 {
128 return Ok(DummyKeyword(subtag));
129 }
130 Err(crate::preferences::extensions::unicode::errors::PreferencesParseError::InvalidKeywordValue)
131 },
132 |input: &DummyKeyword| { unicode::Value::from_subtag(Some(input.0)) }
133 );
134
135 let v = unicode::Value::from_str("foo").unwrap();
136 let dk: DummyKeyword = v.clone().try_into().unwrap();
137 assert_eq!(dk, DummyKeyword(subtag!("foo")));
138 assert_eq!(unicode::Value::from(dk), v);
139
140 let v = unicode::Value::from_str("foobar").unwrap();
141 let dk: Result<DummyKeyword, _> = v.clone().try_into();
142 assert!(dk.is_err());
143 }
144}