1use std::{
4 borrow::Cow,
5 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
6 fmt,
7 hash::{BuildHasher, Hash},
8 marker::PhantomData,
9 sync::Arc,
10};
11
12use serde::de::Error as DeError;
13
14use crate::{
15 de::{DeserializeContext, DeserializeParam, WellKnown, WellKnownOption},
16 error::{ErrorWithOrigin, LowLevelError},
17 metadata::{BasicTypes, ParamMetadata, TypeDescription},
18 pat::Split,
19 utils::const_eq,
20 value::{StrValue, Value, ValueOrigin, WithOrigin},
21};
22
23#[derive(Debug)]
27pub struct Repeated<De>(pub De);
28
29impl<De> Repeated<De> {
30 fn deserialize_array<T, C>(
31 &self,
32 mut ctx: DeserializeContext<'_>,
33 param: &'static ParamMetadata,
34 expected_len: Option<usize>,
35 ) -> Result<C, ErrorWithOrigin>
36 where
37 De: DeserializeParam<T>,
38 C: FromIterator<T>,
39 {
40 let deserializer = ctx.current_value_deserializer(param.name)?;
41 let Value::Array(items) = deserializer.value() else {
42 return Err(deserializer.invalid_type("array"));
43 };
44
45 if let Some(expected_len) = expected_len
46 && items.len() != expected_len
47 {
48 let err = DeError::invalid_length(items.len(), &expected_len.to_string().as_str());
49 return Err(deserializer.enrich_err(err));
50 }
51
52 let mut has_errors = false;
53 let items = items.iter().enumerate().filter_map(|(i, item)| {
54 let coerced = item.coerce_value_type(De::EXPECTING);
55 let mut child_ctx = ctx.child(&i.to_string(), ctx.location_in_config);
56 let mut child_ctx = child_ctx.patched(coerced.as_ref().unwrap_or(item));
57 match self.0.deserialize_param(child_ctx.borrow(), param) {
58 Ok(val) if !has_errors => Some(val),
59 Ok(_) => None, Err(err) => {
61 has_errors = true;
62 child_ctx.push_error(err);
63 None
64 }
65 }
66 });
67 let items: C = items.collect();
68
69 if has_errors {
70 let origin = deserializer.origin().clone();
71 Err(ErrorWithOrigin::new(LowLevelError::InvalidArray, origin))
72 } else {
73 Ok(items)
74 }
75 }
76}
77
78macro_rules! impl_serialization_for_repeated {
79 ($param:ty) => {
80 fn deserialize_param(
81 &self,
82 ctx: DeserializeContext<'_>,
83 param: &'static ParamMetadata,
84 ) -> Result<$param, ErrorWithOrigin> {
85 self.deserialize_array(ctx, param, None)
86 }
87
88 fn serialize_param(&self, param: &$param) -> serde_json::Value {
89 let array = param
90 .iter()
91 .map(|item| self.0.serialize_param(item))
92 .collect();
93 serde_json::Value::Array(array)
94 }
95 };
96}
97
98impl<T: 'static, De> DeserializeParam<Vec<T>> for Repeated<De>
99where
100 De: DeserializeParam<T>,
101{
102 const EXPECTING: BasicTypes = BasicTypes::ARRAY;
103
104 fn describe(&self, description: &mut TypeDescription) {
105 description.set_items(&self.0);
106 }
107
108 impl_serialization_for_repeated!(Vec<T>);
109}
110
111impl<T, S, De> DeserializeParam<HashSet<T, S>> for Repeated<De>
112where
113 T: 'static + Eq + Hash,
114 S: 'static + Default + BuildHasher,
115 De: DeserializeParam<T>,
116{
117 const EXPECTING: BasicTypes = BasicTypes::ARRAY;
118
119 fn describe(&self, description: &mut TypeDescription) {
120 description.set_details("set").set_items(&self.0);
121 }
122
123 impl_serialization_for_repeated!(HashSet<T, S>);
124}
125
126impl<T, De> DeserializeParam<BTreeSet<T>> for Repeated<De>
127where
128 T: 'static + Eq + Ord,
129 De: DeserializeParam<T>,
130{
131 const EXPECTING: BasicTypes = BasicTypes::ARRAY;
132
133 fn describe(&self, description: &mut TypeDescription) {
134 description.set_details("set").set_items(&self.0);
135 }
136
137 impl_serialization_for_repeated!(BTreeSet<T>);
138}
139
140impl<T: 'static, De, const N: usize> DeserializeParam<[T; N]> for Repeated<De>
141where
142 De: DeserializeParam<T>,
143{
144 const EXPECTING: BasicTypes = BasicTypes::ARRAY;
145
146 fn describe(&self, description: &mut TypeDescription) {
147 description
148 .set_details(format!("{N}-element array"))
149 .set_items(&self.0);
150 }
151
152 fn deserialize_param(
153 &self,
154 ctx: DeserializeContext<'_>,
155 param: &'static ParamMetadata,
156 ) -> Result<[T; N], ErrorWithOrigin> {
157 let items: Vec<_> = self.deserialize_array(ctx, param, Some(N))?;
158 Ok(items.try_into().ok().unwrap())
160 }
161
162 fn serialize_param(&self, param: &[T; N]) -> serde_json::Value {
163 let array = param
164 .iter()
165 .map(|item| self.0.serialize_param(item))
166 .collect();
167 serde_json::Value::Array(array)
168 }
169}
170
171impl<T: WellKnown> WellKnown for Vec<T> {
172 type Deserializer = Repeated<T::Deserializer>;
173 const DE: Self::Deserializer = Repeated(T::DE);
174}
175
176impl<T: WellKnown> WellKnownOption for Vec<T> {}
177
178impl<T: WellKnown, const N: usize> WellKnown for [T; N] {
179 type Deserializer = Repeated<T::Deserializer>;
180 const DE: Self::Deserializer = Repeated(T::DE);
181}
182
183impl<T: WellKnown, const N: usize> WellKnownOption for [T; N] {}
184
185impl<T, S> WellKnown for HashSet<T, S>
189where
190 T: Eq + Hash + WellKnown,
191 S: 'static + Default + BuildHasher,
192{
193 type Deserializer = Repeated<T::Deserializer>;
194 const DE: Self::Deserializer = Repeated(T::DE);
195}
196
197impl<T, S> WellKnownOption for HashSet<T, S>
198where
199 T: Eq + Hash + WellKnown,
200 S: 'static + Default + BuildHasher,
201{
202}
203
204impl<T> WellKnown for BTreeSet<T>
205where
206 T: Eq + Ord + WellKnown,
207{
208 type Deserializer = Repeated<T::Deserializer>;
209 const DE: Self::Deserializer = Repeated(T::DE);
210}
211
212impl<T> WellKnownOption for BTreeSet<T> where T: Eq + Ord + WellKnown {}
213
214pub struct Entries<K, V, DeK = <K as WellKnown>::Deserializer, DeV = <V as WellKnown>::Deserializer>
218{
219 keys: DeK,
220 values: DeV,
221 _kv: PhantomData<fn(K, V)>,
222}
223
224impl<K, V, DeK: fmt::Debug, DeV: fmt::Debug> fmt::Debug for Entries<K, V, DeK, DeV> {
225 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
226 formatter
227 .debug_struct("Entries")
228 .field("keys", &self.keys)
229 .field("values", &self.values)
230 .finish()
231 }
232}
233
234impl<K: WellKnown, V: WellKnown> Entries<K, V, K::Deserializer, V::Deserializer> {
235 pub const WELL_KNOWN: Self = Self::new(K::DE, V::DE);
237}
238
239impl<K, V, DeK, DeV> Entries<K, V, DeK, DeV>
240where
241 DeK: DeserializeParam<K>,
242 DeV: DeserializeParam<V>,
243{
244 pub const fn new(keys: DeK, values: DeV) -> Self {
246 Self {
247 keys,
248 values,
249 _kv: PhantomData,
250 }
251 }
252
253 pub const fn named(
259 self,
260 keys_name: &'static str,
261 values_name: &'static str,
262 ) -> NamedEntries<K, V, DeK, DeV> {
263 assert!(!keys_name.is_empty());
264 assert!(!values_name.is_empty());
265 assert!(
266 !const_eq(keys_name.as_bytes(), values_name.as_bytes()),
267 "Keys and values fields must not coincide"
268 );
269
270 NamedEntries {
271 inner: self,
272 keys_name,
273 values_name,
274 }
275 }
276
277 pub const fn delimited<ESep: Split, KvSep: Split>(
283 self,
284 entry_sep: ESep,
285 key_value_sep: KvSep,
286 ) -> DelimitedEntries<K, V, DeK, DeV, ESep, KvSep> {
287 DelimitedEntries {
288 entry_sep,
289 key_value_sep,
290 inner: self,
291 }
292 }
293
294 fn deserialize_map<'s, C: FromIterator<(K, V)>>(
295 &self,
296 mut ctx: DeserializeContext<'_>,
297 param: &'static ParamMetadata,
298 map_entries: impl Iterator<Item = (&'s str, Cow<'s, WithOrigin>)>,
299 map_origin: &Arc<ValueOrigin>,
300 ) -> Result<C, ErrorWithOrigin> {
301 let mut has_errors = false;
302 let items = map_entries.filter_map(|(key, value)| {
303 let key_as_value = WithOrigin::new(
304 key.to_owned().into(),
305 Arc::new(ValueOrigin::Synthetic {
306 source: map_origin.clone(),
307 transform: "string key".into(),
308 }),
309 );
310 let parsed_key =
311 parse_key_or_value::<K, _>(&mut ctx, param, key, &self.keys, &key_as_value);
312 let parsed_value =
313 parse_key_or_value::<V, _>(&mut ctx, param, key, &self.values, &value);
314
315 has_errors |= parsed_key.is_none() || parsed_value.is_none();
316 Some((parsed_key?, parsed_value?)).filter(|_| !has_errors)
317 });
318 let items: C = items.collect();
319
320 if has_errors {
321 let origin = map_origin.clone();
322 Err(ErrorWithOrigin::new(LowLevelError::InvalidObject, origin))
323 } else {
324 Ok(items)
325 }
326 }
327}
328
329fn parse_key_or_value<T, De: DeserializeParam<T>>(
330 ctx: &mut DeserializeContext<'_>,
331 param: &'static ParamMetadata,
332 key_path: &str,
333 de: &De,
334 val: &WithOrigin,
335) -> Option<T> {
336 let coerced = val.coerce_value_type(De::EXPECTING);
337 let mut child_ctx = ctx.child(key_path, ctx.location_in_config);
338 let mut child_ctx = child_ctx.patched(coerced.as_ref().unwrap_or(val));
339 match de.deserialize_param(child_ctx.borrow(), param) {
340 Ok(val) => Some(val),
341 Err(err) => {
342 child_ctx.push_error(err);
343 None
344 }
345 }
346}
347
348pub trait ToEntry<'a, K, V>: Copy {
350 fn to_entry(self) -> (&'a K, &'a V);
352}
353
354impl<'a, K, V> ToEntry<'a, K, V> for &'a (K, V) {
355 fn to_entry(self) -> (&'a K, &'a V) {
356 (&self.0, &self.1)
357 }
358}
359
360impl<'a, K, V> ToEntry<'a, K, V> for (&'a K, &'a V) {
361 fn to_entry(self) -> (&'a K, &'a V) {
362 self
363 }
364}
365
366pub trait ToEntries<K: 'static, V: 'static> {
373 fn to_entries(&self) -> impl Iterator<Item = (&K, &V)>;
375}
376
377impl<K: 'static, V: 'static, C> ToEntries<K, V> for C
379where
380 for<'a> &'a C: IntoIterator<Item: ToEntry<'a, K, V>>,
381{
382 fn to_entries(&self) -> impl Iterator<Item = (&K, &V)> {
383 self.into_iter().map(ToEntry::to_entry)
384 }
385}
386
387impl<K, V, C, DeK, DeV> DeserializeParam<C> for Entries<K, V, DeK, DeV>
388where
389 K: 'static,
390 V: 'static,
391 DeK: DeserializeParam<K>,
392 DeV: DeserializeParam<V>,
393 C: FromIterator<(K, V)> + ToEntries<K, V>,
394{
395 const EXPECTING: BasicTypes = {
396 assert!(
397 DeK::EXPECTING.contains(BasicTypes::STRING)
398 || DeK::EXPECTING.contains(BasicTypes::INTEGER),
399 "map keys must be deserializable from strings or ints"
400 );
401 BasicTypes::OBJECT
402 };
403
404 fn describe(&self, description: &mut TypeDescription) {
405 description
406 .set_details("map")
407 .set_entries(&self.keys, &self.values);
408 }
409
410 fn deserialize_param(
411 &self,
412 ctx: DeserializeContext<'_>,
413 param: &'static ParamMetadata,
414 ) -> Result<C, ErrorWithOrigin> {
415 let deserializer = ctx.current_value_deserializer(param.name)?;
416 let Value::Object(map) = deserializer.value() else {
417 return Err(deserializer.invalid_type("object"));
418 };
419 let map_entries = map
420 .iter()
421 .map(|(key, value)| (key.as_str(), Cow::Borrowed(value)));
422 self.deserialize_map(ctx, param, map_entries, deserializer.origin())
423 }
424
425 fn serialize_param(&self, param: &C) -> serde_json::Value {
426 let object = param
427 .to_entries()
428 .map(|(key, value)| {
429 let key = match self.keys.serialize_param(key) {
430 serde_json::Value::String(s) => s,
431 serde_json::Value::Number(num) => num.to_string(),
432 _ => panic!("unsupported key value"),
433 };
434 let value = self.values.serialize_param(value);
435 (key, value)
436 })
437 .collect();
438 serde_json::Value::Object(object)
439 }
440}
441
442impl<K, V, S> WellKnown for HashMap<K, V, S>
443where
444 K: 'static + Eq + Hash + WellKnown,
445 V: 'static + WellKnown,
446 S: 'static + Default + BuildHasher,
447{
448 type Deserializer = Entries<K, V, K::Deserializer, V::Deserializer>;
449 const DE: Self::Deserializer = Entries::new(K::DE, V::DE);
450}
451
452impl<K, V, S> WellKnownOption for HashMap<K, V, S>
453where
454 K: 'static + Eq + Hash + WellKnown,
455 V: 'static + WellKnown,
456 S: 'static + Default + BuildHasher,
457{
458}
459
460impl<K, V> WellKnown for BTreeMap<K, V>
461where
462 K: 'static + Eq + Ord + WellKnown,
463 V: 'static + WellKnown,
464{
465 type Deserializer = Entries<K, V, K::Deserializer, V::Deserializer>;
466 const DE: Self::Deserializer = Entries::new(K::DE, V::DE);
467}
468
469impl<K, V> WellKnownOption for BTreeMap<K, V>
470where
471 K: 'static + Eq + Ord + WellKnown,
472 V: 'static + WellKnown,
473{
474}
475
476pub struct Delimited<De = (), S = &'static str>(pub De, pub S);
528
529impl<De: fmt::Debug, S: Split> fmt::Debug for Delimited<De, S> {
530 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
531 formatter
532 .debug_tuple("Delimited")
533 .field(&self.0)
534 .field(&self.1.display())
535 .finish()
536 }
537}
538
539impl<S: Split> Delimited<(), S> {
540 pub const fn new(sep: S) -> Self {
542 Self((), sep)
543 }
544}
545
546impl<De, S: Split> Delimited<Repeated<De>, S> {
547 pub const fn repeat(item_de: De, sep: S) -> Self {
549 Self(Repeated(item_de), sep)
550 }
551}
552
553impl<T, De, S> DeserializeParam<T> for Delimited<De, S>
554where
555 De: DeserializeParam<T>,
556 S: Split,
557{
558 const EXPECTING: BasicTypes = {
559 let base = <De as DeserializeParam<T>>::EXPECTING;
560 assert!(
561 base.contains(BasicTypes::ARRAY),
562 "can only apply `Delimited` to types that support deserialization from array"
563 );
564 base.or(BasicTypes::STRING)
565 };
566
567 fn describe(&self, description: &mut TypeDescription) {
568 self.0.describe(description);
569 description.set_items_sep(self.1.display());
570 }
571
572 fn deserialize_param(
573 &self,
574 mut ctx: DeserializeContext<'_>,
575 param: &'static ParamMetadata,
576 ) -> Result<T, ErrorWithOrigin> {
577 let Some(WithOrigin {
578 inner: Value::String(s),
579 origin,
580 }) = ctx.current_value()
581 else {
582 return self.0.deserialize_param(ctx, param);
583 };
584
585 let array_origin = Arc::new(ValueOrigin::Synthetic {
586 source: origin.clone(),
587 transform: format!("{}-delimited string", self.1.display()),
588 });
589
590 let array_items = self.1.split(s.expose()).enumerate().map(|(i, part)| {
591 let item_origin = ValueOrigin::Path {
592 source: array_origin.clone(),
593 path: i.to_string(),
594 };
595 let part = if s.is_secret() {
596 StrValue::Secret(part.into())
597 } else {
598 StrValue::Plain(part.into())
599 };
600 WithOrigin::new(Value::String(part), Arc::new(item_origin))
601 });
602 let array = WithOrigin::new(Value::Array(array_items.collect()), array_origin);
603 self.0.deserialize_param(ctx.patched(&array), param)
604 }
605
606 fn serialize_param(&self, param: &T) -> serde_json::Value {
607 self.0.serialize_param(param)
608 }
609}
610
611pub struct NamedEntries<
669 K,
670 V,
671 DeK = <K as WellKnown>::Deserializer,
672 DeV = <V as WellKnown>::Deserializer,
673> {
674 inner: Entries<K, V, DeK, DeV>,
675 keys_name: &'static str,
676 values_name: &'static str,
677}
678
679impl<K, V, DeK: fmt::Debug, DeV: fmt::Debug> fmt::Debug for NamedEntries<K, V, DeK, DeV> {
680 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
681 formatter
682 .debug_struct("NamedEntries")
683 .field("inner", &self.inner)
684 .field("keys_name", &self.keys_name)
685 .field("values_name", &self.values_name)
686 .finish()
687 }
688}
689
690impl<K, V, DeK, DeV> NamedEntries<K, V, DeK, DeV>
691where
692 DeK: DeserializeParam<K>,
693 DeV: DeserializeParam<V>,
694{
695 fn deserialize_entries<C: FromIterator<(K, V)>>(
696 &self,
697 mut ctx: DeserializeContext<'_>,
698 param: &'static ParamMetadata,
699 array: &[WithOrigin],
700 array_origin: &Arc<ValueOrigin>,
701 ) -> Result<C, ErrorWithOrigin> {
702 let mut has_errors = false;
703 let items = array.iter().enumerate().filter_map(|(i, entry)| {
704 let idx_str = i.to_string();
705 let (key, value) = match self.parse_entry(entry) {
706 Ok(entry) => entry,
707 Err(err) => {
708 ctx.child(&idx_str, ctx.location_in_config).push_error(err);
709 has_errors = true;
710 return None;
711 }
712 };
713
714 let parsed_key =
715 parse_key_or_value::<K, _>(&mut ctx, param, &idx_str, &self.inner.keys, key);
716 let null_value;
717 let value = if let Some(value) = value {
718 value
719 } else {
720 let null_origin = ValueOrigin::Synthetic {
721 source: entry.origin.clone(),
722 transform: "missing entry value".to_owned(),
723 };
724 null_value = WithOrigin::new(Value::Null, Arc::new(null_origin));
725 &null_value
726 };
727 let parsed_value =
728 parse_key_or_value::<V, _>(&mut ctx, param, &idx_str, &self.inner.values, value);
729 has_errors |= parsed_key.is_none() || parsed_value.is_none();
730 Some((parsed_key?, parsed_value?)).filter(|_| !has_errors)
731 });
732 let items: C = items.collect();
733
734 if has_errors {
735 let origin = array_origin.clone();
736 Err(ErrorWithOrigin::new(LowLevelError::InvalidArray, origin))
737 } else {
738 Ok(items)
739 }
740 }
741
742 fn parse_entry<'a>(
743 &self,
744 entry: &'a WithOrigin,
745 ) -> Result<(&'a WithOrigin, Option<&'a WithOrigin>), ErrorWithOrigin> {
746 let Value::Object(obj) = &entry.inner else {
747 let expected = format!(
748 "{{ {:?}: _, {:?}: _ }} tuple",
749 self.keys_name, self.values_name
750 );
751 return Err(entry.invalid_type(&expected));
752 };
753
754 let key = obj.get(self.keys_name).ok_or_else(|| {
755 let err = DeError::missing_field(self.keys_name);
756 ErrorWithOrigin::json(err, entry.origin.clone())
757 })?;
758 let value = obj.get(self.values_name);
759
760 if obj.len() > 2 {
761 let expected = format!(
762 "{{ {:?}: _, {:?}: _ }} tuple",
763 self.keys_name, self.values_name
764 );
765 return Err(entry.invalid_type(&expected));
766 }
767 Ok((key, value))
768 }
769}
770
771impl<K, V, DeK, DeV, C> DeserializeParam<C> for NamedEntries<K, V, DeK, DeV>
772where
773 K: 'static,
774 V: 'static,
775 DeK: DeserializeParam<K>,
776 DeV: DeserializeParam<V>,
777 C: FromIterator<(K, V)> + ToEntries<K, V>,
778{
779 const EXPECTING: BasicTypes = BasicTypes::OBJECT.or(BasicTypes::ARRAY);
780
781 fn describe(&self, description: &mut TypeDescription) {
782 let details = format!(
783 "map or array of {{ {:?}: _, {:?}: _ }} tuples",
784 self.keys_name, self.values_name
785 );
786 description
787 .set_details(details)
788 .set_entries(&self.inner.keys, &self.inner.values);
789 }
790
791 fn deserialize_param(
792 &self,
793 ctx: DeserializeContext<'_>,
794 param: &'static ParamMetadata,
795 ) -> Result<C, ErrorWithOrigin> {
796 let deserializer = ctx.current_value_deserializer(param.name)?;
797 match deserializer.value() {
798 Value::Object(map) => {
799 let map_entries = map
800 .iter()
801 .map(|(key, value)| (key.as_str(), Cow::Borrowed(value)));
802 self.inner
803 .deserialize_map(ctx, param, map_entries, deserializer.origin())
804 }
805 Value::Array(array) => {
806 self.deserialize_entries(ctx, param, array, deserializer.origin())
807 }
808 _ => Err(deserializer.invalid_type("object or array")),
809 }
810 }
811
812 fn serialize_param(&self, param: &C) -> serde_json::Value {
813 let entries = param.to_entries().map(|(key, value)| {
814 let key = self.inner.keys.serialize_param(key);
815 let value = self.inner.values.serialize_param(value);
816 serde_json::json!({
817 self.keys_name: key,
818 self.values_name: value,
819 })
820 });
821 serde_json::Value::Array(entries.collect())
822 }
823}
824
825pub struct DelimitedEntries<
883 K,
884 V,
885 DeK = <K as WellKnown>::Deserializer,
886 DeV = <V as WellKnown>::Deserializer,
887 ESep = &'static str,
888 KvSep = &'static str,
889> {
890 entry_sep: ESep,
891 key_value_sep: KvSep,
892 inner: Entries<K, V, DeK, DeV>,
893}
894
895impl<K, V, DeK, DeV, ESep, KvSep> fmt::Debug for DelimitedEntries<K, V, DeK, DeV, ESep, KvSep>
896where
897 DeK: fmt::Debug,
898 DeV: fmt::Debug,
899 ESep: Split,
900 KvSep: Split,
901{
902 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
903 formatter
904 .debug_struct("DelimitedEntries")
905 .field("item_sep", &self.entry_sep.display())
906 .field("key_value_sep", &self.key_value_sep.display())
907 .field("inner", &self.inner)
908 .finish()
909 }
910}
911
912impl<K, V, DeK, DeV, ESep, KvSep, C> DeserializeParam<C>
913 for DelimitedEntries<K, V, DeK, DeV, ESep, KvSep>
914where
915 DeK: DeserializeParam<K>,
916 DeV: DeserializeParam<V>,
917 ESep: Split,
918 KvSep: Split,
919 C: FromIterator<(K, V)>,
920 Entries<K, V, DeK, DeV>: DeserializeParam<C>,
921{
922 const EXPECTING: BasicTypes = Entries::<K, V, DeK, DeV>::EXPECTING.or(BasicTypes::STRING);
923
924 fn describe(&self, description: &mut TypeDescription) {
925 self.inner.describe(description);
926 description.set_entries_sep(self.entry_sep.display(), self.key_value_sep.display());
927 }
928
929 fn deserialize_param(
930 &self,
931 mut ctx: DeserializeContext<'_>,
932 param: &'static ParamMetadata,
933 ) -> Result<C, ErrorWithOrigin> {
934 let Some(WithOrigin {
935 inner: Value::String(s),
936 origin,
937 }) = ctx.current_value()
938 else {
939 return self.inner.deserialize_param(ctx, param);
940 };
941
942 let entry_sep = &self.entry_sep;
943 let key_value_sep = &self.key_value_sep;
944 let map_origin = Arc::new(ValueOrigin::Synthetic {
945 source: origin.clone(),
946 transform: format!(
947 "{}-delimited entries separated by {}",
948 entry_sep.display(),
949 key_value_sep.display()
950 ),
951 });
952 let mut errors = vec![];
953
954 let map_entries = entry_sep
955 .split(s.expose())
956 .enumerate()
957 .filter_map(|(i, part)| {
958 let Some((key_str, value_str)) = key_value_sep.split_once(part) else {
959 let key_origin = ValueOrigin::Path {
960 source: map_origin.clone(),
961 path: i.to_string(),
962 };
963 let err = DeError::custom(format!(
964 "{} separator is missing",
965 key_value_sep.display()
966 ));
967 let err = ErrorWithOrigin::json(err, Arc::new(key_origin));
968 errors.push(err);
969 return None;
970 };
971
972 let value_origin = ValueOrigin::Path {
973 source: map_origin.clone(),
974 path: format!("{i}.$value"),
975 };
976 let value_string = if s.is_secret() {
977 StrValue::Secret(value_str.into())
978 } else {
979 StrValue::Plain(value_str.into())
980 };
981 let value = WithOrigin::new(Value::String(value_string), Arc::new(value_origin));
982 Some((key_str, Cow::Owned(value)))
983 });
984
985 let mut output = self
986 .inner
987 .deserialize_map(ctx.borrow(), param, map_entries, &map_origin);
988 if output.is_ok() && !errors.is_empty() {
989 output = Err(ErrorWithOrigin::new(
990 LowLevelError::InvalidObject,
991 map_origin,
992 ));
993 }
994 for err in errors {
995 ctx.push_error(err);
996 }
997 output
998 }
999
1000 fn serialize_param(&self, param: &C) -> serde_json::Value {
1001 self.inner.serialize_param(param)
1002 }
1003}