1use super::{Format, MultiFormat, template::FormatTemplate};
2use crate::errors::*;
3use itertools::Itertools as _;
4use serde::de::{MapAccess, Visitor};
5use serde::{Deserialize, Deserializer, de};
6use smart_default::SmartDefault;
7use std::fmt;
8use std::str::FromStr;
9
10#[derive(Debug, Default, Clone)]
11pub struct Config {
12 pub full: Option<FormatTemplate>,
13 pub short: Option<FormatTemplate>,
14}
15
16impl Config {
17 pub fn with_default(&self, default_full: &str) -> Result<Format> {
18 self.with_defaults(default_full, "")
19 }
20
21 pub fn with_defaults(&self, default_full: &str, default_short: &str) -> Result<Format> {
22 let full = match self.full.clone() {
23 Some(full) => full,
24 None => default_full.parse()?,
25 };
26
27 let short = match self.short.clone() {
28 Some(short) => short,
29 None => default_short.parse()?,
30 };
31
32 Ok(Format::new(full, short))
33 }
34
35 pub fn with_default_config(&self, default_config: &Self) -> Format {
36 let full = self
37 .full
38 .clone()
39 .or_else(|| default_config.full.clone())
40 .unwrap_or_default();
41 let short = self
42 .short
43 .clone()
44 .or_else(|| default_config.short.clone())
45 .unwrap_or_default();
46
47 Format::new(full, short)
48 }
49
50 pub fn with_default_format(&self, default_format: &Format) -> Format {
51 let full = self
52 .full
53 .clone()
54 .unwrap_or_else(|| default_format.full.clone());
55 let short = self
56 .short
57 .clone()
58 .unwrap_or_else(|| default_format.short.clone());
59
60 Format::new(full, short)
61 }
62}
63
64impl From<Config> for Format {
65 fn from(config: Config) -> Self {
66 let full = config.full.unwrap_or_default();
67 let short = config.short.unwrap_or_default();
68
69 Format::new(full, short)
70 }
71}
72
73#[derive(Debug, Clone, SmartDefault)]
133pub enum MaybeMultiConfig {
134 #[default]
135 Split {
136 config: Option<Config>,
137 config_alt: Option<Config>,
138 },
139 Multiple {
140 configs: Vec<Config>,
141 },
142}
143
144impl MaybeMultiConfig {
145 pub fn with_default(&self, default_full: &str) -> Result<MultiFormat> {
146 self.with_defaults(default_full, "")
147 }
148
149 pub fn with_defaults(&self, default_full: &str, default_short: &str) -> Result<MultiFormat> {
150 Ok(MultiFormat::new(match self.clone() {
151 MaybeMultiConfig::Multiple { configs } => configs
152 .into_iter()
153 .enumerate()
154 .map(|(i, config)| {
155 if i == 0 {
156 config.with_defaults(default_full, default_short)
157 } else {
158 Ok(config.into())
159 }
160 })
161 .collect::<Result<Vec<_>>>()?,
162 MaybeMultiConfig::Split { config, config_alt } => {
163 let mut formats = vec![
164 config
165 .unwrap_or_default()
166 .with_defaults(default_full, default_short)?,
167 ];
168
169 if let Some(config_alt) = config_alt {
170 formats.push(config_alt.into());
171 }
172 formats
173 }
174 }))
175 }
176
177 pub fn with_default_formats(&self, default_formats: &[Format]) -> MultiFormat {
178 MultiFormat::new(
179 match self.clone() {
180 MaybeMultiConfig::Multiple { configs } => configs,
181 MaybeMultiConfig::Split { config, config_alt } => {
182 vec![config.unwrap_or_default(), config_alt.unwrap_or_default()]
183 }
184 }
185 .into_iter()
186 .zip_longest(default_formats)
187 .filter_map(|pair| match pair {
188 itertools::EitherOrBoth::Both(config, default_format) => {
189 Some(config.with_default_format(default_format))
190 }
191 itertools::EitherOrBoth::Left(config) => Some(config.into()),
192 itertools::EitherOrBoth::Right(_) => None,
193 })
194 .collect(),
195 )
196 }
197}
198
199impl FromStr for Config {
200 type Err = Error;
201
202 fn from_str(s: &str) -> Result<Self, Self::Err> {
203 Ok(Self {
204 full: Some(s.parse()?),
205 short: None,
206 })
207 }
208}
209
210impl<'de> Deserialize<'de> for Config {
211 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
212 where
213 D: Deserializer<'de>,
214 {
215 #[derive(Deserialize)]
216 #[serde(field_identifier, rename_all = "lowercase")]
217 enum Field {
218 Full,
219 Short,
220 }
221
222 struct FormatTemplateVisitor;
223
224 impl<'de> Visitor<'de> for FormatTemplateVisitor {
225 type Value = Config;
226
227 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
228 formatter.write_str("format structure")
229 }
230
231 fn visit_str<E>(self, full: &str) -> Result<Config, E>
237 where
238 E: de::Error,
239 {
240 full.parse().serde_error()
241 }
242
243 fn visit_map<V>(self, mut map: V) -> Result<Config, V::Error>
251 where
252 V: MapAccess<'de>,
253 {
254 let mut full: Option<FormatTemplate> = None;
255 let mut short: Option<FormatTemplate> = None;
256 while let Some(key) = map.next_key()? {
257 match key {
258 Field::Full => {
259 if full.is_some() {
260 return Err(de::Error::duplicate_field("full"));
261 }
262 full = Some(map.next_value::<String>()?.parse().serde_error()?);
263 }
264 Field::Short => {
265 if short.is_some() {
266 return Err(de::Error::duplicate_field("short"));
267 }
268 short = Some(map.next_value::<String>()?.parse().serde_error()?);
269 }
270 }
271 }
272 Ok(Config { full, short })
273 }
274 }
275
276 deserializer.deserialize_any(FormatTemplateVisitor)
277 }
278}
279
280impl<'de> Deserialize<'de> for MaybeMultiConfig {
281 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
282 where
283 D: Deserializer<'de>,
284 {
285 #[derive(Deserialize)]
286 #[serde(untagged)]
287 enum MaybeVecConfig {
288 Multiple(Vec<Config>),
289 Single(Config),
290 }
291
292 struct MaybeMultiConfigVisitor;
293
294 impl<'de> Visitor<'de> for MaybeMultiConfigVisitor {
295 type Value = MaybeMultiConfig;
296
297 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
298 f.write_str("multiformat structure")
299 }
300
301 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
302 where
303 A: MapAccess<'de>,
304 {
305 let mut format: Option<MaybeVecConfig> = None;
306 let mut format_alt: Option<Config> = None;
307
308 while let Some(key) = map.next_key::<String>()? {
309 match key.as_str() {
310 "format" => {
311 if format.is_some() {
312 return Err(de::Error::duplicate_field("format"));
313 }
314
315 let maybe_vec_config = match map.next_value()? {
317 serde_json::Value::Array(arr) => MaybeVecConfig::Multiple(
318 serde_json::from_value(serde_json::Value::Array(arr))
319 .serde_error()?,
320 ),
321 value => MaybeVecConfig::Single(
322 serde_json::from_value(value).serde_error()?,
323 ),
324 };
325 format = Some(maybe_vec_config);
326 }
327 "format_alt" => {
328 if format_alt.is_some() {
329 return Err(de::Error::duplicate_field("format_alt"));
330 }
331 format_alt = Some(map.next_value()?);
332 }
333 unknown => {
334 return Err(de::Error::unknown_field(
335 unknown,
336 &["format", "format_alt"],
337 ));
338 }
339 }
340 }
341
342 match format {
343 Some(MaybeVecConfig::Multiple(configs)) => {
344 if format_alt.is_some() {
345 return Err(de::Error::custom(
346 "data did not match any variant of untagged enum MaybeMultiConfig",
347 ));
348 }
349 if configs.is_empty() {
350 return Err(de::Error::custom(
351 "An empty list of configs is not allowed",
352 ));
353 }
354 Ok(MaybeMultiConfig::Multiple { configs })
355 }
356 Some(MaybeVecConfig::Single(config)) => Ok(MaybeMultiConfig::Split {
357 config: Some(config),
358 config_alt: format_alt,
359 }),
360 None => Ok(MaybeMultiConfig::Split {
361 config: None,
362 config_alt: format_alt,
363 }),
364 }
365 }
366 }
367
368 deserializer.deserialize_map(MaybeMultiConfigVisitor)
369 }
370}