smart_config/de/
param.rs

1//! Parameter deserializers.
2
3use std::{
4    any, fmt,
5    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
6    num::{
7        NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
8        NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
9    },
10    path::PathBuf,
11    str::FromStr,
12};
13
14use serde::{
15    Serialize,
16    de::{DeserializeOwned, Error as DeError},
17};
18
19use crate::{
20    de::{DeserializeContext, deserializer::ValueDeserializer},
21    error::ErrorWithOrigin,
22    metadata::{BasicTypes, ParamMetadata, TypeDescription},
23    value::{Value, WithOrigin},
24};
25
26/// Deserializes a parameter of the specified type.
27///
28/// # Implementations
29///
30/// ## Basic implementations
31///
32/// - [`Serde`] allows deserializing any type implementing [`serde::Deserialize`].
33/// - [`TimeUnit`](crate::metadata::TimeUnit) deserializes [`Duration`](std::time::Duration)
34///   from a numeric value that has the specified unit of measurement
35/// - [`SizeUnit`](crate::metadata::SizeUnit) similarly deserializes [`ByteSize`](crate::ByteSize)
36/// - [`WithUnit`](super::WithUnit) deserializes `Duration`s / `ByteSize`s as an integer + unit of measurement
37///   (either in a string or object form).
38///
39/// ## Decorators
40///
41/// - [`Optional`] decorates a deserializer for `T` turning it into a deserializer for `Option<T>`
42/// - [`WithDefault`] adds a default value used if the input is missing
43/// - [`Delimited`](super::Delimited) allows deserializing arrays from a delimited string (e.g., comma-delimited)
44/// - [`OrString`] allows to switch between structured and string deserialization
45pub trait DeserializeParam<T>: fmt::Debug + Send + Sync + 'static {
46    /// Describes which parameter this deserializer is expecting.
47    const EXPECTING: BasicTypes;
48
49    /// Additional info about the deserialized type, e.g., extended description.
50    #[allow(unused)]
51    fn describe(&self, description: &mut TypeDescription) {
52        // Do nothing
53    }
54
55    /// Performs deserialization given the context and param metadata.
56    ///
57    /// # Errors
58    ///
59    /// Returns an error if a param cannot be deserialized, e.g. if it has an incorrect type.
60    fn deserialize_param(
61        &self,
62        ctx: DeserializeContext<'_>,
63        param: &'static ParamMetadata,
64    ) -> Result<T, ErrorWithOrigin>;
65
66    /// Serializes the provided parameter to the JSON model.
67    ///
68    /// Serialization is considered infallible (`serde_json` serialization may fail on recursive or very deeply nested data types;
69    /// please don't use such data types for config params).
70    fn serialize_param(&self, param: &T) -> serde_json::Value;
71}
72
73/// Parameter type with well-known [deserializer](DeserializeParam).
74///
75/// Conceptually, this means that the type is known to behave well when deserializing data from a [`Value`]
76/// (ordinarily, using [`serde::Deserialize`]).
77///
78/// # Implementations
79///
80/// Basic well-known types include:
81///
82/// - `bool`
83/// - [`String`]
84/// - [`PathBuf`]
85/// - Signed and unsigned integers, including non-zero variants
86/// - `f32`, `f64`
87///
88/// These types use [`Serde`] deserializer. Integer types up to and including 64-bit ones
89/// only permit integer input. In contrast, `u128`, `i128` and their non-zero counterparts permit
90/// either integer or string input because the `serde_json` object model cannot represent large
91/// integers (`>u64::MAX` or `<i64::MIN`). **Importantly,** string representation must be used
92/// for such large integers because otherwise they will be converted (with precision loss!) to `f64`
93/// by internal `serde_json` logic before they ever enter the `smart-config` library.
94///
95/// `WellKnown` is also implemented for more complex types:
96///
97/// | Rust type | Deserializer | Expected JSON |
98/// |:-----------|:-------------|:----------------|
99/// | [`Duration`](std::time::Duration) | [`WithUnit`](super::WithUnit) | string or object |
100/// | [`ByteSize`](crate::ByteSize) | [`WithUnit`](super::WithUnit) | string or object |
101/// | [`Option`] | [`Optional`]† | value, or `null`, or nothing |
102/// | [`Vec`], `[_; N]`, [`HashSet`](std::collections::HashSet), [`BTreeSet`](std::collections::BTreeSet) | [`Repeated`](super::Repeated) | array |
103/// | [`HashMap`](std::collections::HashMap), [`BTreeMap`](std::collections::BTreeSet) | [`RepeatedEntries`](super::Entries) | object |
104///
105/// † `Option`s handling can be customized via [`WellKnownOption`] or [`CustomKnownOption`] traits.
106#[diagnostic::on_unimplemented(
107    message = "`{Self}` param cannot be deserialized",
108    note = "Add #[config(with = _)] attribute to specify deserializer to use",
109    note = "If `{Self}` is a config, add #[config(nest)] or #[config(flatten)]"
110)]
111pub trait WellKnown: 'static + Sized {
112    /// Type of the deserializer used for this type.
113    type Deserializer: DeserializeParam<Self>;
114    /// Deserializer instance.
115    const DE: Self::Deserializer;
116}
117
118/// Marker trait for types that use a conventional [`Optional`] deserializer for `Option<Self>`.
119///
120/// It's usually sound to implement this trait for custom types together with [`WellKnown`], unless:
121///
122/// - The type needs custom null coercion logic (e.g., coercing some structured values to null).
123///   In this case, implement [`CustomKnownOption`] instead. Note that `WellKnownOption` is tied to it
124///   via a blanket implementation.
125/// - It doesn't make sense to have optional type params.
126#[diagnostic::on_unimplemented(
127    message = "Optional `{Self}` param cannot be deserialized",
128    note = "Add #[config(with = _)] attribute to specify deserializer to use",
129    note = "If `{Self}` is a config, add #[config(nest)]",
130    note = "Embedded options (`Option<Option<_>>`) are not supported as param types"
131)]
132pub trait WellKnownOption: WellKnown {}
133
134/// Customizes the well-known deserializer for `Option<Self>`, similarly to [`WellKnown`].
135///
136/// This trait usually implemented automatically via the [`WellKnownOption`] blanket impl. A manual implementation
137/// is warranted for corner cases:
138///
139/// - Allow only `Option<T>` as a param type, but not `T` on its own.
140/// - Convert additional values to `None` when deserializing `Option<T>`.
141///
142/// **Tip:** It usually makes sense to have [`Optional`] wrapper for the used deserializer to handle missing / `null` values.
143///
144/// # Examples
145///
146/// ## Allow type only in `Option<_>` wrapper
147///
148/// ```
149/// # use serde::{Deserialize, Serialize};
150/// use smart_config::{de::{CustomKnownOption, Optional, Serde}, DescribeConfig};
151///
152/// #[derive(Serialize, Deserialize)]
153/// struct OnlyInOption(u64);
154///
155/// impl CustomKnownOption for OnlyInOption {
156///     type OptDeserializer = Optional<Serde![int]>;
157///     const OPT_DE: Self::OptDeserializer = Optional(Serde![int]);
158/// }
159///
160/// #[derive(DescribeConfig)]
161/// struct TestConfig {
162///     /// Valid parameter.
163///     param: Option<OnlyInOption>,
164/// }
165/// ```
166///
167/// ...while this fails:
168///
169/// ```compile_fail
170/// # use serde::{Deserialize, Serialize};
171/// # use smart_config::{de::{CustomKnownOption, Optional, Serde}, DescribeConfig};
172/// #
173/// # #[derive(Serialize, Deserialize)]
174/// # struct OnlyInOption(u64);
175/// #
176/// # impl CustomKnownOption for OnlyInOption {
177/// #     type OptDeserializer = Optional<Serde![int]>;
178/// #     const OPT_DE: Self::OptDeserializer = Optional(Serde![int]);
179/// # }
180/// #
181/// #[derive(DescribeConfig)]
182/// struct BogusConfig {
183///     /// Bogus parameter: `OnlyInOption` doesn't implement `WellKnown`
184///     bogus: OnlyInOption,
185/// }
186/// ```
187pub trait CustomKnownOption: 'static + Send + Sized {
188    /// Type of the deserializer used for `Option<Self>`.
189    type OptDeserializer: DeserializeParam<Option<Self>>;
190    /// Deserializer instance.
191    const OPT_DE: Self::OptDeserializer;
192}
193
194impl<T: WellKnownOption + Send> CustomKnownOption for T {
195    type OptDeserializer = Optional<T::Deserializer>;
196    const OPT_DE: Self::OptDeserializer = Optional(Self::DE);
197}
198
199impl<T: WellKnown> DeserializeParam<T> for () {
200    const EXPECTING: BasicTypes = <T::Deserializer as DeserializeParam<T>>::EXPECTING;
201
202    fn describe(&self, description: &mut TypeDescription) {
203        T::DE.describe(description);
204    }
205
206    fn deserialize_param(
207        &self,
208        ctx: DeserializeContext<'_>,
209        param: &'static ParamMetadata,
210    ) -> Result<T, ErrorWithOrigin> {
211        T::DE.deserialize_param(ctx, param)
212    }
213
214    fn serialize_param(&self, param: &T) -> serde_json::Value {
215        T::DE.serialize_param(param)
216    }
217}
218
219/// Deserializer powered by `serde`. Usually created with the help of [`Serde!`](crate::Serde!) macro;
220/// see its docs for the examples of usage.
221pub struct Serde<const EXPECTING: u8>;
222
223impl<const EXPECTING: u8> fmt::Debug for Serde<EXPECTING> {
224    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
225        formatter
226            .debug_tuple("Serde")
227            .field(&BasicTypes::from_raw(EXPECTING))
228            .finish()
229    }
230}
231
232impl<T: Serialize + DeserializeOwned, const EXPECTING: u8> DeserializeParam<T>
233    for Serde<EXPECTING>
234{
235    const EXPECTING: BasicTypes = BasicTypes::from_raw(EXPECTING);
236
237    fn describe(&self, _description: &mut TypeDescription) {
238        // Do nothing
239    }
240
241    fn deserialize_param(
242        &self,
243        ctx: DeserializeContext<'_>,
244        param: &'static ParamMetadata,
245    ) -> Result<T, ErrorWithOrigin> {
246        fn is_likely_large_integer(value: &Value) -> bool {
247            let Value::Number(num) = value else {
248                return false;
249            };
250            if !num.is_f64() {
251                // This check is stricter than implicit `num.as_f64().is_some()`!
252                return false;
253            }
254
255            #[allow(clippy::cast_precision_loss)] // acceptable in this case
256            num.as_f64().is_some_and(|num| {
257                // For `f64` numbers >= 2**53 in magnitude, all presentable numbers are integers,
258                // so it would be redundant to check `num.fract() == 0.0`.
259                num > u64::MAX as f64 || num < i64::MIN as f64
260            })
261        }
262
263        let expecting = BasicTypes::from_raw(EXPECTING);
264        let Some(current_value) = ctx.current_value() else {
265            return Err(DeError::missing_field(param.name));
266        };
267
268        let deserializer = ValueDeserializer::new(current_value, ctx.de_options);
269        let type_matches = deserializer.value().is_supported_by(expecting);
270        if !type_matches {
271            let tip = if expecting.contains(BasicTypes::INTEGER)
272                && expecting.contains(BasicTypes::STRING)
273                && is_likely_large_integer(deserializer.value())
274            {
275                // Provide a more helpful error message
276                ". Try enclosing the value into a string so that it's not coerced to floating-point"
277            } else {
278                ""
279            };
280
281            return Err(deserializer.invalid_type(&format!("{expecting}{tip}")));
282        }
283        T::deserialize(deserializer)
284    }
285
286    fn serialize_param(&self, param: &T) -> serde_json::Value {
287        serde_json::to_value(param).expect("failed serializing to JSON")
288    }
289}
290
291impl WellKnown for bool {
292    type Deserializer = super::Serde![bool];
293    const DE: Self::Deserializer = super::Serde![bool];
294}
295
296impl WellKnownOption for bool {}
297
298impl WellKnown for String {
299    type Deserializer = super::Serde![str];
300    const DE: Self::Deserializer = super::Serde![str];
301}
302
303impl WellKnownOption for String {}
304
305impl WellKnown for PathBuf {
306    type Deserializer = Qualified<super::Serde![str]>;
307    const DE: Self::Deserializer = Qualified::new(super::Serde![str], "filesystem path");
308}
309
310impl WellKnownOption for PathBuf {}
311
312impl WellKnown for IpAddr {
313    type Deserializer = Qualified<super::Serde![str]>;
314    const DE: Self::Deserializer = Qualified::new(super::Serde![str], "IP address");
315}
316
317impl WellKnownOption for IpAddr {}
318
319impl WellKnown for Ipv4Addr {
320    type Deserializer = Qualified<super::Serde![str]>;
321    const DE: Self::Deserializer = Qualified::new(super::Serde![str], "IPv4 address");
322}
323
324impl WellKnownOption for Ipv4Addr {}
325
326impl WellKnown for Ipv6Addr {
327    type Deserializer = Qualified<super::Serde![str]>;
328    const DE: Self::Deserializer = Qualified::new(super::Serde![str], "IPv6 address");
329}
330
331impl WellKnownOption for Ipv6Addr {}
332
333impl WellKnown for SocketAddr {
334    type Deserializer = Qualified<super::Serde![str]>;
335    const DE: Self::Deserializer = Qualified::new(super::Serde![str], "socket address");
336}
337
338impl WellKnownOption for SocketAddr {}
339
340impl WellKnown for SocketAddrV4 {
341    type Deserializer = Qualified<super::Serde![str]>;
342    const DE: Self::Deserializer = Qualified::new(super::Serde![str], "v4 socket address");
343}
344
345impl WellKnownOption for SocketAddrV4 {}
346
347impl WellKnown for SocketAddrV6 {
348    type Deserializer = Qualified<super::Serde![str]>;
349    const DE: Self::Deserializer = Qualified::new(super::Serde![str], "v6 socket address");
350}
351
352impl WellKnownOption for SocketAddrV6 {}
353
354impl WellKnown for f32 {
355    type Deserializer = super::Serde![float];
356    const DE: Self::Deserializer = super::Serde![float];
357}
358
359impl WellKnownOption for f32 {}
360
361impl WellKnown for f64 {
362    type Deserializer = super::Serde![float];
363    const DE: Self::Deserializer = super::Serde![float];
364}
365
366impl WellKnownOption for f64 {}
367
368macro_rules! impl_well_known_int {
369    ($($int:ty),+) => {
370        $(
371        impl WellKnown for $int {
372            type Deserializer = super::Serde![int];
373            const DE: Self::Deserializer = super::Serde![int];
374        }
375
376        impl WellKnownOption for $int {}
377        )+
378    };
379}
380
381impl_well_known_int!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize);
382
383/// Unlike other ints, we allow `str` inputs for 128-bit ints because `serde_json::Value` doesn't support
384/// representing 128-bit numbers natively.
385impl WellKnown for u128 {
386    type Deserializer = super::Serde![int, str];
387    const DE: Self::Deserializer = super::Serde![int, str];
388}
389
390impl WellKnownOption for u128 {}
391
392/// Unlike other ints, we allow `str` inputs for 128-bit ints because `serde_json::Value` doesn't support
393/// representing 128-bit numbers natively.
394impl WellKnown for i128 {
395    type Deserializer = super::Serde![int, str];
396    const DE: Self::Deserializer = super::Serde![int, str];
397}
398
399impl WellKnownOption for i128 {}
400
401macro_rules! impl_well_known_non_zero_int {
402    ($($int:ty),+) => {
403        $(
404        impl WellKnown for $int {
405            type Deserializer = Qualified<super::Serde![int]>;
406            const DE: Self::Deserializer = Qualified::new(super::Serde![int], "non-zero");
407        }
408
409        impl WellKnownOption for $int {}
410        )+
411    };
412}
413
414impl_well_known_non_zero_int!(
415    NonZeroU8,
416    NonZeroI8,
417    NonZeroU16,
418    NonZeroI16,
419    NonZeroU32,
420    NonZeroI32,
421    NonZeroU64,
422    NonZeroI64,
423    NonZeroUsize,
424    NonZeroIsize
425);
426
427/// Unlike other ints, we allow `str` inputs for 128-bit ints because `serde_json::Value` doesn't support
428/// representing 128-bit numbers natively.
429impl WellKnown for NonZeroU128 {
430    type Deserializer = Qualified<super::Serde![int, str]>;
431    const DE: Self::Deserializer = Qualified::new(super::Serde![int, str], "non-zero");
432}
433
434impl WellKnownOption for NonZeroU128 {}
435
436/// Unlike other ints, we allow `str` inputs for 128-bit ints because `serde_json::Value` doesn't support
437/// representing 128-bit numbers natively.
438impl WellKnown for NonZeroI128 {
439    type Deserializer = Qualified<super::Serde![int, str]>;
440    const DE: Self::Deserializer = Qualified::new(super::Serde![int, str], "non-zero");
441}
442
443impl WellKnownOption for NonZeroI128 {}
444
445impl<T: CustomKnownOption> WellKnown for Option<T> {
446    type Deserializer = T::OptDeserializer;
447    const DE: Self::Deserializer = T::OPT_DE;
448}
449
450/// [Deserializer](DeserializeParam) decorator that provides additional [details](TypeDescription)
451/// for the deserialized type.
452#[derive(Debug)]
453pub struct Qualified<De> {
454    inner: De,
455    // Cannot use `TypeDescription` directly because it wouldn't allow to drop the type in const contexts.
456    description: &'static str,
457}
458
459impl<De> Qualified<De> {
460    /// Creates a new instance with the extended type description.
461    pub const fn new(inner: De, description: &'static str) -> Self {
462        Self { inner, description }
463    }
464}
465
466impl<T, De> DeserializeParam<T> for Qualified<De>
467where
468    De: DeserializeParam<T>,
469{
470    const EXPECTING: BasicTypes = <De as DeserializeParam<T>>::EXPECTING;
471
472    fn describe(&self, description: &mut TypeDescription) {
473        description.set_details(self.description);
474    }
475
476    fn deserialize_param(
477        &self,
478        ctx: DeserializeContext<'_>,
479        param: &'static ParamMetadata,
480    ) -> Result<T, ErrorWithOrigin> {
481        self.inner.deserialize_param(ctx, param)
482    }
483
484    fn serialize_param(&self, param: &T) -> serde_json::Value {
485        self.inner.serialize_param(param)
486    }
487}
488
489/// Deserializer decorator that defaults to the provided value if the input for the param is missing.
490pub struct WithDefault<T, D> {
491    inner: D,
492    default: fn() -> T,
493}
494
495impl<T: 'static, D: fmt::Debug> fmt::Debug for WithDefault<T, D> {
496    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
497        formatter
498            .debug_struct("WithDefault")
499            .field("inner", &self.inner)
500            .field("type", &any::type_name::<T>())
501            .finish_non_exhaustive()
502    }
503}
504
505impl<T: 'static, De: DeserializeParam<T>> WithDefault<T, De> {
506    /// Creates a new instance.
507    pub const fn new(inner: De, default: fn() -> T) -> Self {
508        Self { inner, default }
509    }
510}
511
512impl<T: 'static, De: DeserializeParam<T>> DeserializeParam<T> for WithDefault<T, De> {
513    const EXPECTING: BasicTypes = De::EXPECTING;
514
515    fn describe(&self, description: &mut TypeDescription) {
516        self.inner.describe(description);
517    }
518
519    fn deserialize_param(
520        &self,
521        ctx: DeserializeContext<'_>,
522        param: &'static ParamMetadata,
523    ) -> Result<T, ErrorWithOrigin> {
524        if ctx.current_value().is_some() {
525            self.inner.deserialize_param(ctx, param)
526        } else {
527            Ok((self.default)())
528        }
529    }
530
531    fn serialize_param(&self, param: &T) -> serde_json::Value {
532        self.inner.serialize_param(param)
533    }
534}
535
536/// Deserializer decorator that wraps the output of the underlying decorator in `Some` and returns `None`
537/// if the input for the param is missing.
538///
539/// # Encoding nulls
540///
541/// For env variables, specifying null values can be tricky since natively, all env variable values are strings.
542/// There are the following was to avoid this issue:
543///
544/// - [JSON coercion](crate::Environment::coerce_json()) can be used to pass unambiguous JSON values (incl. `null`).
545/// - If the original deserializer doesn't expect string values, an empty string or `"null"` will be coerced
546///   to a null.
547/// - [`deserialize_if` attribute](macro@crate::DescribeConfig#deserialize_if) can help filtering out empty strings etc. for types
548///   that do expect string values.
549///
550/// # Transforms
551///
552/// The second generic param is the *transform* determining how the wrapped deserializer is delegated to.
553/// Regardless of the transform, missing and `null` values always result in `None`; any other value, will be passed
554/// to the wrapped deserializer.
555///
556/// - The default transform (`AND_THEN == false`) is similar to [`map`](Option::map()). It requires the underlying deserializer to return a non-optional value.
557/// - `AND_THEN == true` is similar to [`and_then`](Option::and_then()). It expects the underlying deserializer to return an `Option`.
558#[derive(Debug)]
559pub struct Optional<De, const AND_THEN: bool = false>(pub De);
560
561impl<De> Optional<De> {
562    /// Wraps a deserializer returning a non-optional value, similarly to [`Option::map()`].
563    pub const fn map(deserializer: De) -> Self {
564        Self(deserializer)
565    }
566}
567
568impl<De> Optional<De, true> {
569    /// Wraps a deserializer returning an optional value, similarly to [`Option::and_then()`].
570    pub const fn and_then(deserializer: De) -> Self {
571        Self(deserializer)
572    }
573}
574
575fn detect_null(ctx: &DeserializeContext<'_>) -> bool {
576    let current_value = ctx.current_value().map(|val| &val.inner);
577    matches!(current_value, None | Some(Value::Null))
578}
579
580impl<T, De: DeserializeParam<T>> DeserializeParam<Option<T>> for Optional<De> {
581    const EXPECTING: BasicTypes = De::EXPECTING;
582
583    fn describe(&self, description: &mut TypeDescription) {
584        self.0.describe(description);
585    }
586
587    fn deserialize_param(
588        &self,
589        ctx: DeserializeContext<'_>,
590        param: &'static ParamMetadata,
591    ) -> Result<Option<T>, ErrorWithOrigin> {
592        if detect_null(&ctx) {
593            return Ok(None);
594        }
595        self.0.deserialize_param(ctx, param).map(Some)
596    }
597
598    fn serialize_param(&self, param: &Option<T>) -> serde_json::Value {
599        if let Some(param) = param {
600            self.0.serialize_param(param)
601        } else {
602            serde_json::Value::Null
603        }
604    }
605}
606
607impl<T, De> DeserializeParam<Option<T>> for Optional<De, true>
608where
609    De: DeserializeParam<Option<T>>,
610{
611    const EXPECTING: BasicTypes = De::EXPECTING;
612
613    fn describe(&self, description: &mut TypeDescription) {
614        self.0.describe(description);
615    }
616
617    fn deserialize_param(
618        &self,
619        ctx: DeserializeContext<'_>,
620        param: &'static ParamMetadata,
621    ) -> Result<Option<T>, ErrorWithOrigin> {
622        if detect_null(&ctx) {
623            return Ok(None);
624        }
625        self.0.deserialize_param(ctx, param)
626    }
627
628    fn serialize_param(&self, param: &Option<T>) -> serde_json::Value {
629        if param.is_some() {
630            self.0.serialize_param(param)
631        } else {
632            // Force `null` representation regardless of the underlying deserializer
633            serde_json::Value::Null
634        }
635    }
636}
637
638/// Deserializer that supports parsing either from a default format (usually an object or array) via [`Deserialize`](serde::Deserialize),
639/// or from string via [`FromStr`].
640///
641/// # Examples
642///
643/// ```
644/// # use std::{collections::HashSet, str::FromStr};
645/// use anyhow::Context as _;
646/// # use serde::{Deserialize, Serialize};
647/// use smart_config::{de, testing, DescribeConfig, DeserializeConfig};
648///
649/// #[derive(Debug, Serialize, Deserialize)]
650/// #[serde(transparent)]
651/// struct MySet(HashSet<u64>);
652///
653/// impl FromStr for MySet {
654///     type Err = anyhow::Error;
655///
656///     fn from_str(s: &str) -> Result<Self, Self::Err> {
657///         s.split(',')
658///             .map(|part| part.trim().parse().context("invalid value"))
659///             .collect::<anyhow::Result<_>>()
660///             .map(Self)
661///     }
662/// }
663///
664/// #[derive(DescribeConfig, DeserializeConfig)]
665/// struct TestConfig {
666///     #[config(with = de::OrString(de::Serde![array]))]
667///     value: MySet,
668/// }
669///
670/// let sample = smart_config::config!("value": "2, 3, 2");
671/// let config: TestConfig = testing::test(sample)?;
672/// assert_eq!(config.value.0, HashSet::from([2, 3]));
673///
674/// // Parsing from array works, too
675/// let sample = smart_config::config!("value": [2, 3, 2]);
676/// let config: TestConfig = testing::test(sample)?;
677/// assert_eq!(config.value.0, HashSet::from([2, 3]));
678/// # anyhow::Ok(())
679/// ```
680#[derive(Debug)]
681pub struct OrString<De>(pub De);
682
683impl<T, De> DeserializeParam<T> for OrString<De>
684where
685    T: FromStr,
686    T::Err: fmt::Display,
687    De: DeserializeParam<T>,
688{
689    const EXPECTING: BasicTypes = <De as DeserializeParam<T>>::EXPECTING.or(BasicTypes::STRING);
690
691    fn describe(&self, description: &mut TypeDescription) {
692        self.0.describe(description);
693    }
694
695    fn deserialize_param(
696        &self,
697        ctx: DeserializeContext<'_>,
698        param: &'static ParamMetadata,
699    ) -> Result<T, ErrorWithOrigin> {
700        let Some(WithOrigin {
701            inner: Value::String(s),
702            origin,
703        }) = ctx.current_value()
704        else {
705            return self.0.deserialize_param(ctx, param);
706        };
707
708        T::from_str(s.expose()).map_err(|err| {
709            let err = serde_json::Error::custom(err);
710            ErrorWithOrigin::json(err, origin.clone())
711        })
712    }
713
714    fn serialize_param(&self, param: &T) -> serde_json::Value {
715        self.0.serialize_param(param)
716    }
717}