1use super::*;
6use alloc::borrow::Cow;
7use alloc::vec::Vec;
8
9use ::serde::{Deserialize, Deserializer, Serialize, Serializer};
10
11#[doc(hidden)]
12pub fn deserialize_option_borrowed_cow<'de, 'data, B, D: Deserializer<'de>>(
13 deserializer: D,
14) -> Result<Option<Cow<'data, Pattern<B>>>, D::Error>
15where
16 'de: 'data,
17 B: PatternBackend<Store = str>,
18 B::PlaceholderKeyCow<'data>: Deserialize<'de>,
19 &'data B::Store: Deserialize<'de>,
20{
21 #[derive(Deserialize)]
22 #[serde(transparent)]
23 struct CowPatternWrap<'data1, B: PatternBackend<Store = str>>
25 where
26 Box<B::Store>: for<'a> From<&'a B::Store>,
27 {
28 #[serde(
29 borrow,
30 deserialize_with = "deserialize_borrowed_cow::<B, _>",
31 bound = "B::PlaceholderKeyCow<'data1>: Deserialize<'de>, &'data1 B::Store: Deserialize<'de>"
32 )]
33 pub cow: Cow<'data1, Pattern<B>>,
34 }
35
36 Option::<CowPatternWrap<'data, B>>::deserialize(deserializer)
37 .map(|option| option.map(|wrap| wrap.cow))
38}
39
40type HumanReadablePattern<'a, B> =
41 Vec<PatternItemCow<'a, <B as PatternBackend>::PlaceholderKeyCow<'a>>>;
42
43#[derive(Debug, PartialEq)]
44#[allow(clippy::exhaustive_structs)] pub struct PatternString<B: PatternBackend>(pub Box<Pattern<B>>);
46
47impl<B: PatternBackend> Clone for PatternString<B>
48where
49 Box<B::Store>: for<'a> From<&'a B::Store>,
50{
51 fn clone(&self) -> Self {
52 Self(self.0.clone())
53 }
54}
55
56impl<B: PatternBackend> core::ops::Deref for PatternString<B> {
57 type Target = Pattern<B>;
58
59 fn deref(&self) -> &Self::Target {
60 &self.0
61 }
62}
63
64impl<B: PatternBackend> Default for PatternString<B>
65where
66 Box<B::Store>: for<'a> From<&'a B::Store>,
67{
68 fn default() -> Self {
69 Self(Box::<Pattern<B>>::default())
70 }
71}
72
73#[cfg(feature = "serde")]
74impl<'de, B: PatternBackend> serde::Deserialize<'de> for PatternString<B>
75where
76 B::PlaceholderKeyCow<'de>: core::str::FromStr,
77 <B::PlaceholderKeyCow<'de> as core::str::FromStr>::Err: core::fmt::Debug,
78{
79 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
80 where
81 D: serde::Deserializer<'de>,
82 {
83 let pattern_str = String::deserialize(deserializer)?;
84 let pattern = Pattern::<B>::try_from_str(&pattern_str, Default::default())
85 .map_err(<D::Error as ::serde::de::Error>::custom)?;
86 Ok(Self(pattern))
87 }
88}
89
90#[doc(hidden)]
91pub fn deserialize_borrowed_cow<'de, 'data, B, D: Deserializer<'de>>(
92 deserializer: D,
93) -> Result<Cow<'data, Pattern<B>>, D::Error>
94where
95 'de: 'data,
96 B: PatternBackend<Store = str>,
97 B::PlaceholderKeyCow<'data>: Deserialize<'de>,
98 &'data B::Store: Deserialize<'de>,
99{
100 if deserializer.is_human_readable() {
101 Box::<Pattern<B>>::deserialize(deserializer).map(Cow::Owned)
102 } else {
103 <&Pattern<B>>::deserialize(deserializer).map(Cow::Borrowed)
104 }
105}
106
107impl<'de, 'data, B> Deserialize<'de> for Box<Pattern<B>>
108where
109 'de: 'data,
110 B: PatternBackend<Store = str>,
111 B::PlaceholderKeyCow<'data>: Deserialize<'de>,
112{
113 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
114 where
115 D: Deserializer<'de>,
116 {
117 if deserializer.is_human_readable() {
118 Pattern::<B>::try_from_items(
119 <HumanReadablePattern<B>>::deserialize(deserializer)?.into_iter(),
120 )
121 } else {
122 let store = Box::<B::Store>::deserialize(deserializer)?;
123 B::validate_store(&store).map(|()| Pattern::<B>::from_boxed_store_unchecked(store))
124 }
125 .map_err(<D::Error as ::serde::de::Error>::custom)
126 }
127}
128
129impl<'de, 'data, B: PatternBackend> Deserialize<'de> for &'data Pattern<B>
130where
131 'de: 'data,
132 &'data B::Store: Deserialize<'de>,
133{
134 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
135 where
136 D: Deserializer<'de>,
137 {
138 if deserializer.is_human_readable() {
139 Err(<D::Error as ::serde::de::Error>::custom(
140 "human readable format cannot be borrowed",
141 ))
142 } else {
143 let store = <&B::Store>::deserialize(deserializer)?;
144 B::validate_store(store).map_err(<D::Error as ::serde::de::Error>::custom)?;
145 Ok(Pattern::from_ref_store_unchecked(store))
146 }
147 }
148}
149
150impl<B: PatternBackend> Serialize for Pattern<B>
151where
152 B::Store: Serialize,
153 for<'a> B::PlaceholderKeyCow<'a>: Serialize + From<B::PlaceholderKey<'a>>,
154{
155 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
156 where
157 S: Serializer,
158 {
159 if serializer.is_human_readable() {
160 B::iter_items(&self.store)
161 .map(|x| x.into())
162 .collect::<HumanReadablePattern<B>>()
163 .serialize(serializer)
164 } else {
165 self.store.serialize(serializer)
166 }
167 }
168}
169
170#[cfg(test)]
171mod tests {
172 use super::*;
173 use crate::SinglePlaceholder;
174 use crate::SinglePlaceholderPattern;
175 use alloc::borrow::Cow;
176
177 #[test]
178 fn test_json() {
179 let pattern_owned =
180 SinglePlaceholderPattern::try_from_str("Hello, {0}!", Default::default()).unwrap();
181 let pattern_cow: Cow<SinglePlaceholderPattern> = Cow::Owned(pattern_owned);
182 let pattern_json = serde_json::to_string(&pattern_cow).unwrap();
183 assert_eq!(
184 pattern_json,
185 r#"[{"Literal":"Hello, "},{"Placeholder":"Singleton"},{"Literal":"!"}]"#
186 );
187 let pattern_deserialized: Cow<SinglePlaceholderPattern> =
188 deserialize_borrowed_cow::<SinglePlaceholder, _>(
189 &mut serde_json::Deserializer::from_str(&pattern_json),
190 )
191 .unwrap();
192 assert_eq!(pattern_cow, pattern_deserialized);
193 assert!(matches!(pattern_deserialized, Cow::Owned(_)));
194 }
195
196 #[test]
197 fn test_postcard() {
198 let pattern_owned =
199 SinglePlaceholderPattern::try_from_str("Hello, {0}!", Default::default()).unwrap();
200 let pattern_cow: Cow<SinglePlaceholderPattern> = Cow::Owned(pattern_owned);
201 let pattern_postcard = postcard::to_stdvec(&pattern_cow).unwrap();
202 assert_eq!(pattern_postcard, b"\x09\x08Hello, !");
203 let pattern_deserialized = deserialize_borrowed_cow::<SinglePlaceholder, _>(
204 &mut postcard::Deserializer::from_bytes(&pattern_postcard),
205 )
206 .unwrap();
207 assert_eq!(pattern_cow, pattern_deserialized);
208 assert!(matches!(pattern_deserialized, Cow::Borrowed(_)));
209 }
210
211 #[test]
212 fn test_rmp() {
213 let pattern_owned =
214 SinglePlaceholderPattern::try_from_str("Hello, {0}!", Default::default()).unwrap();
215 let pattern_cow: Cow<SinglePlaceholderPattern> = Cow::Owned(pattern_owned);
216 let pattern_rmp = rmp_serde::to_vec(&pattern_cow).unwrap();
217 assert_eq!(pattern_rmp, b"\xA9\x08Hello, !");
218 let pattern_deserialized = deserialize_borrowed_cow::<SinglePlaceholder, _>(
219 &mut rmp_serde::Deserializer::from_read_ref(&pattern_rmp),
220 )
221 .unwrap();
222 assert_eq!(pattern_cow, pattern_deserialized);
223 assert!(matches!(pattern_deserialized, Cow::Borrowed(_)));
224 }
225}