1use std::{
4 collections::{BTreeMap, BTreeSet, HashMap, HashSet},
5 fmt,
6 hash::{BuildHasher, Hash},
7 marker::PhantomData,
8 sync::Arc,
9};
10
11use serde::de::{DeserializeOwned, Error as DeError};
12
13use crate::{
14 de::{DeserializeContext, DeserializeParam, WellKnown, WellKnownOption},
15 error::{ErrorWithOrigin, LowLevelError},
16 metadata::{BasicTypes, ParamMetadata, TypeDescription},
17 utils::const_eq,
18 value::{Map, StrValue, Value, ValueOrigin, WithOrigin},
19};
20
21#[derive(Debug)]
25pub struct Repeated<De>(pub De);
26
27impl<De> Repeated<De> {
28 fn deserialize_array<T, C>(
29 &self,
30 mut ctx: DeserializeContext<'_>,
31 param: &'static ParamMetadata,
32 expected_len: Option<usize>,
33 ) -> Result<C, ErrorWithOrigin>
34 where
35 De: DeserializeParam<T>,
36 C: FromIterator<T>,
37 {
38 let deserializer = ctx.current_value_deserializer(param.name)?;
39 let Value::Array(items) = deserializer.value() else {
40 return Err(deserializer.invalid_type("array"));
41 };
42
43 if let Some(expected_len) = expected_len {
44 if items.len() != expected_len {
45 let err = DeError::invalid_length(items.len(), &expected_len.to_string().as_str());
46 return Err(deserializer.enrich_err(err));
47 }
48 }
49
50 let mut has_errors = false;
51 let items = items.iter().enumerate().filter_map(|(i, item)| {
52 let coerced = item.coerce_value_type(De::EXPECTING);
53 let mut child_ctx = ctx.child(&i.to_string(), ctx.location_in_config);
54 let mut child_ctx = child_ctx.patched(coerced.as_ref().unwrap_or(item));
55 match self.0.deserialize_param(child_ctx.borrow(), param) {
56 Ok(val) if !has_errors => Some(val),
57 Ok(_) => None, Err(err) => {
59 has_errors = true;
60 child_ctx.push_error(err);
61 None
62 }
63 }
64 });
65 let items: C = items.collect();
66
67 if has_errors {
68 let origin = deserializer.origin().clone();
69 Err(ErrorWithOrigin::new(LowLevelError::InvalidArray, origin))
70 } else {
71 Ok(items)
72 }
73 }
74}
75
76macro_rules! impl_serialization_for_repeated {
77 ($param:ty) => {
78 fn deserialize_param(
79 &self,
80 ctx: DeserializeContext<'_>,
81 param: &'static ParamMetadata,
82 ) -> Result<$param, ErrorWithOrigin> {
83 self.deserialize_array(ctx, param, None)
84 }
85
86 fn serialize_param(&self, param: &$param) -> serde_json::Value {
87 let array = param
88 .iter()
89 .map(|item| self.0.serialize_param(item))
90 .collect();
91 serde_json::Value::Array(array)
92 }
93 };
94}
95
96impl<T: 'static, De> DeserializeParam<Vec<T>> for Repeated<De>
97where
98 De: DeserializeParam<T>,
99{
100 const EXPECTING: BasicTypes = BasicTypes::ARRAY;
101
102 fn describe(&self, description: &mut TypeDescription) {
103 description.set_items(&self.0);
104 }
105
106 impl_serialization_for_repeated!(Vec<T>);
107}
108
109impl<T, S, De> DeserializeParam<HashSet<T, S>> for Repeated<De>
110where
111 T: 'static + Eq + Hash,
112 S: 'static + Default + BuildHasher,
113 De: DeserializeParam<T>,
114{
115 const EXPECTING: BasicTypes = BasicTypes::ARRAY;
116
117 fn describe(&self, description: &mut TypeDescription) {
118 description.set_details("set").set_items(&self.0);
119 }
120
121 impl_serialization_for_repeated!(HashSet<T, S>);
122}
123
124impl<T, De> DeserializeParam<BTreeSet<T>> for Repeated<De>
125where
126 T: 'static + Eq + Ord,
127 De: DeserializeParam<T>,
128{
129 const EXPECTING: BasicTypes = BasicTypes::ARRAY;
130
131 fn describe(&self, description: &mut TypeDescription) {
132 description.set_details("set").set_items(&self.0);
133 }
134
135 impl_serialization_for_repeated!(BTreeSet<T>);
136}
137
138impl<T: 'static, De, const N: usize> DeserializeParam<[T; N]> for Repeated<De>
139where
140 De: DeserializeParam<T>,
141{
142 const EXPECTING: BasicTypes = BasicTypes::ARRAY;
143
144 fn describe(&self, description: &mut TypeDescription) {
145 description
146 .set_details(format!("{N}-element array"))
147 .set_items(&self.0);
148 }
149
150 fn deserialize_param(
151 &self,
152 ctx: DeserializeContext<'_>,
153 param: &'static ParamMetadata,
154 ) -> Result<[T; N], ErrorWithOrigin> {
155 let items: Vec<_> = self.deserialize_array(ctx, param, Some(N))?;
156 Ok(items.try_into().ok().unwrap())
158 }
159
160 fn serialize_param(&self, param: &[T; N]) -> serde_json::Value {
161 let array = param
162 .iter()
163 .map(|item| self.0.serialize_param(item))
164 .collect();
165 serde_json::Value::Array(array)
166 }
167}
168
169impl<T: WellKnown> WellKnown for Vec<T> {
170 type Deserializer = Repeated<T::Deserializer>;
171 const DE: Self::Deserializer = Repeated(T::DE);
172}
173
174impl<T: WellKnown> WellKnownOption for Vec<T> {}
175
176impl<T: WellKnown, const N: usize> WellKnown for [T; N] {
177 type Deserializer = Repeated<T::Deserializer>;
178 const DE: Self::Deserializer = Repeated(T::DE);
179}
180
181impl<T: WellKnown, const N: usize> WellKnownOption for [T; N] {}
182
183impl<T, S> WellKnown for HashSet<T, S>
187where
188 T: Eq + Hash + WellKnown,
189 S: 'static + Default + BuildHasher,
190{
191 type Deserializer = Repeated<T::Deserializer>;
192 const DE: Self::Deserializer = Repeated(T::DE);
193}
194
195impl<T, S> WellKnownOption for HashSet<T, S>
196where
197 T: Eq + Hash + WellKnown,
198 S: 'static + Default + BuildHasher,
199{
200}
201
202impl<T> WellKnown for BTreeSet<T>
203where
204 T: Eq + Ord + WellKnown,
205{
206 type Deserializer = Repeated<T::Deserializer>;
207 const DE: Self::Deserializer = Repeated(T::DE);
208}
209
210impl<T> WellKnownOption for BTreeSet<T> where T: Eq + Ord + WellKnown {}
211
212pub struct Entries<K, V, DeK = <K as WellKnown>::Deserializer, DeV = <V as WellKnown>::Deserializer>
216{
217 keys: DeK,
218 values: DeV,
219 _kv: PhantomData<fn(K, V)>,
220}
221
222impl<K, V, DeK: fmt::Debug, DeV: fmt::Debug> fmt::Debug for Entries<K, V, DeK, DeV> {
223 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
224 formatter
225 .debug_struct("Entries")
226 .field("keys", &self.keys)
227 .field("values", &self.values)
228 .finish()
229 }
230}
231
232impl<K: WellKnown, V: WellKnown> Entries<K, V, K::Deserializer, V::Deserializer> {
233 pub const WELL_KNOWN: Self = Self::new(K::DE, V::DE);
235}
236
237impl<K, V, DeK, DeV> Entries<K, V, DeK, DeV>
238where
239 DeK: DeserializeParam<K>,
240 DeV: DeserializeParam<V>,
241{
242 pub const fn new(keys: DeK, values: DeV) -> Self {
244 Self {
245 keys,
246 values,
247 _kv: PhantomData,
248 }
249 }
250
251 pub const fn named(
257 self,
258 keys_name: &'static str,
259 values_name: &'static str,
260 ) -> NamedEntries<K, V, DeK, DeV> {
261 assert!(!keys_name.is_empty());
262 assert!(!values_name.is_empty());
263 assert!(
264 !const_eq(keys_name.as_bytes(), values_name.as_bytes()),
265 "Keys and values fields must not coincide"
266 );
267
268 NamedEntries {
269 inner: self,
270 keys_name,
271 values_name,
272 }
273 }
274
275 fn deserialize_map<C: FromIterator<(K, V)>>(
276 &self,
277 mut ctx: DeserializeContext<'_>,
278 param: &'static ParamMetadata,
279 map: &Map,
280 map_origin: &Arc<ValueOrigin>,
281 ) -> Result<C, ErrorWithOrigin> {
282 let mut has_errors = false;
283 let items = map.iter().filter_map(|(key, value)| {
284 let key_as_value = WithOrigin::new(
285 key.clone().into(),
286 Arc::new(ValueOrigin::Synthetic {
287 source: map_origin.clone(),
288 transform: "string key".into(),
289 }),
290 );
291 let parsed_key =
292 parse_key_or_value::<K, _>(&mut ctx, param, key, &self.keys, &key_as_value);
293 let parsed_value =
294 parse_key_or_value::<V, _>(&mut ctx, param, key, &self.values, value);
295
296 has_errors |= parsed_key.is_none() || parsed_value.is_none();
297 Some((parsed_key?, parsed_value?)).filter(|_| !has_errors)
298 });
299 let items: C = items.collect();
300
301 if has_errors {
302 let origin = map_origin.clone();
303 Err(ErrorWithOrigin::new(LowLevelError::InvalidObject, origin))
304 } else {
305 Ok(items)
306 }
307 }
308}
309
310fn parse_key_or_value<T, De: DeserializeParam<T>>(
311 ctx: &mut DeserializeContext<'_>,
312 param: &'static ParamMetadata,
313 key_path: &str,
314 de: &De,
315 val: &WithOrigin,
316) -> Option<T> {
317 let coerced = val.coerce_value_type(De::EXPECTING);
318 let mut child_ctx = ctx.child(key_path, ctx.location_in_config);
319 let mut child_ctx = child_ctx.patched(coerced.as_ref().unwrap_or(val));
320 match de.deserialize_param(child_ctx.borrow(), param) {
321 Ok(val) => Some(val),
322 Err(err) => {
323 child_ctx.push_error(err);
324 None
325 }
326 }
327}
328
329pub trait ToEntry<'a, K, V>: Copy {
331 fn to_entry(self) -> (&'a K, &'a V);
333}
334
335impl<'a, K, V> ToEntry<'a, K, V> for &'a (K, V) {
336 fn to_entry(self) -> (&'a K, &'a V) {
337 (&self.0, &self.1)
338 }
339}
340
341impl<'a, K, V> ToEntry<'a, K, V> for (&'a K, &'a V) {
342 fn to_entry(self) -> (&'a K, &'a V) {
343 self
344 }
345}
346
347pub trait ToEntries<K: 'static, V: 'static> {
354 fn to_entries(&self) -> impl Iterator<Item = (&K, &V)>;
356}
357
358impl<K: 'static, V: 'static, C> ToEntries<K, V> for C
360where
361 for<'a> &'a C: IntoIterator<Item: ToEntry<'a, K, V>>,
362{
363 fn to_entries(&self) -> impl Iterator<Item = (&K, &V)> {
364 self.into_iter().map(ToEntry::to_entry)
365 }
366}
367
368impl<K, V, C, DeK, DeV> DeserializeParam<C> for Entries<K, V, DeK, DeV>
369where
370 K: 'static,
371 V: 'static,
372 DeK: DeserializeParam<K>,
373 DeV: DeserializeParam<V>,
374 C: FromIterator<(K, V)> + ToEntries<K, V>,
375{
376 const EXPECTING: BasicTypes = {
377 assert!(
378 DeK::EXPECTING.contains(BasicTypes::STRING)
379 || DeK::EXPECTING.contains(BasicTypes::INTEGER),
380 "map keys must be deserializable from strings or ints"
381 );
382 BasicTypes::OBJECT
383 };
384
385 fn describe(&self, description: &mut TypeDescription) {
386 description
387 .set_details("map")
388 .set_entries(&self.keys, &self.values);
389 }
390
391 fn deserialize_param(
392 &self,
393 ctx: DeserializeContext<'_>,
394 param: &'static ParamMetadata,
395 ) -> Result<C, ErrorWithOrigin> {
396 let deserializer = ctx.current_value_deserializer(param.name)?;
397 let Value::Object(map) = deserializer.value() else {
398 return Err(deserializer.invalid_type("object"));
399 };
400 self.deserialize_map(ctx, param, map, deserializer.origin())
401 }
402
403 fn serialize_param(&self, param: &C) -> serde_json::Value {
404 let object = param
405 .to_entries()
406 .map(|(key, value)| {
407 let key = match self.keys.serialize_param(key) {
408 serde_json::Value::String(s) => s,
409 serde_json::Value::Number(num) => num.to_string(),
410 _ => panic!("unsupported key value"),
411 };
412 let value = self.values.serialize_param(value);
413 (key, value)
414 })
415 .collect();
416 serde_json::Value::Object(object)
417 }
418}
419
420impl<K, V, S> WellKnown for HashMap<K, V, S>
421where
422 K: 'static + Eq + Hash + WellKnown,
423 V: 'static + WellKnown,
424 S: 'static + Default + BuildHasher,
425{
426 type Deserializer = Entries<K, V, K::Deserializer, V::Deserializer>;
427 const DE: Self::Deserializer = Entries::new(K::DE, V::DE);
428}
429
430impl<K, V, S> WellKnownOption for HashMap<K, V, S>
431where
432 K: 'static + Eq + Hash + WellKnown,
433 V: 'static + WellKnown,
434 S: 'static + Default + BuildHasher,
435{
436}
437
438impl<K, V> WellKnown for BTreeMap<K, V>
439where
440 K: 'static + Eq + Ord + WellKnown,
441 V: 'static + WellKnown,
442{
443 type Deserializer = Entries<K, V, K::Deserializer, V::Deserializer>;
444 const DE: Self::Deserializer = Entries::new(K::DE, V::DE);
445}
446
447impl<K, V> WellKnownOption for BTreeMap<K, V>
448where
449 K: 'static + Eq + Ord + WellKnown,
450 V: 'static + WellKnown,
451{
452}
453
454#[derive(Debug)]
503pub struct Delimited(pub &'static str);
504
505impl<T: DeserializeOwned + WellKnown> DeserializeParam<T> for Delimited {
506 const EXPECTING: BasicTypes = {
507 let base = <T::Deserializer as DeserializeParam<T>>::EXPECTING;
508 assert!(
509 base.contains(BasicTypes::ARRAY),
510 "can only apply `Delimited` to types that support deserialization from array"
511 );
512 base.or(BasicTypes::STRING)
513 };
514
515 fn describe(&self, description: &mut TypeDescription) {
516 T::DE.describe(description);
517 let details = if let Some(details) = description.details() {
518 format!("{details}; using {:?} delimiter", self.0)
519 } else {
520 format!("using {:?} delimiter", self.0)
521 };
522 description.set_details(details);
523 }
524
525 fn deserialize_param(
526 &self,
527 mut ctx: DeserializeContext<'_>,
528 param: &'static ParamMetadata,
529 ) -> Result<T, ErrorWithOrigin> {
530 let Some(WithOrigin {
531 inner: Value::String(s),
532 origin,
533 }) = ctx.current_value()
534 else {
535 return T::DE.deserialize_param(ctx, param);
536 };
537
538 let array_origin = Arc::new(ValueOrigin::Synthetic {
539 source: origin.clone(),
540 transform: format!("{:?}-delimited string", self.0),
541 });
542 let array_items = s.expose().split(self.0).enumerate().map(|(i, part)| {
543 let item_origin = ValueOrigin::Path {
544 source: array_origin.clone(),
545 path: i.to_string(),
546 };
547 let part = if s.is_secret() {
548 StrValue::Secret(part.into())
549 } else {
550 StrValue::Plain(part.into())
551 };
552 WithOrigin::new(Value::String(part), Arc::new(item_origin))
553 });
554 let array = WithOrigin::new(Value::Array(array_items.collect()), array_origin);
555 T::DE.deserialize_param(ctx.patched(&array), param)
556 }
557
558 fn serialize_param(&self, param: &T) -> serde_json::Value {
559 T::DE.serialize_param(param)
560 }
561}
562
563pub struct NamedEntries<
621 K,
622 V,
623 DeK = <K as WellKnown>::Deserializer,
624 DeV = <V as WellKnown>::Deserializer,
625> {
626 inner: Entries<K, V, DeK, DeV>,
627 keys_name: &'static str,
628 values_name: &'static str,
629}
630
631impl<K, V, DeK: fmt::Debug, DeV: fmt::Debug> fmt::Debug for NamedEntries<K, V, DeK, DeV> {
632 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
633 formatter
634 .debug_struct("NamedEntries")
635 .field("inner", &self.inner)
636 .field("keys_name", &self.keys_name)
637 .field("values_name", &self.values_name)
638 .finish()
639 }
640}
641
642impl<K, V, DeK, DeV> NamedEntries<K, V, DeK, DeV>
643where
644 DeK: DeserializeParam<K>,
645 DeV: DeserializeParam<V>,
646{
647 fn deserialize_entries<C: FromIterator<(K, V)>>(
648 &self,
649 mut ctx: DeserializeContext<'_>,
650 param: &'static ParamMetadata,
651 array: &[WithOrigin],
652 array_origin: &Arc<ValueOrigin>,
653 ) -> Result<C, ErrorWithOrigin> {
654 let mut has_errors = false;
655 let items = array.iter().enumerate().filter_map(|(i, entry)| {
656 let idx_str = i.to_string();
657 let (key, value) = match self.parse_entry(entry) {
658 Ok(entry) => entry,
659 Err(err) => {
660 ctx.child(&idx_str, ctx.location_in_config).push_error(err);
661 has_errors = true;
662 return None;
663 }
664 };
665
666 let parsed_key =
667 parse_key_or_value::<K, _>(&mut ctx, param, &idx_str, &self.inner.keys, key);
668 let null_value;
669 let value = if let Some(value) = value {
670 value
671 } else {
672 let null_origin = ValueOrigin::Synthetic {
673 source: entry.origin.clone(),
674 transform: "missing entry value".to_owned(),
675 };
676 null_value = WithOrigin::new(Value::Null, Arc::new(null_origin));
677 &null_value
678 };
679 let parsed_value =
680 parse_key_or_value::<V, _>(&mut ctx, param, &idx_str, &self.inner.values, value);
681 has_errors |= parsed_key.is_none() || parsed_value.is_none();
682 Some((parsed_key?, parsed_value?)).filter(|_| !has_errors)
683 });
684 let items: C = items.collect();
685
686 if has_errors {
687 let origin = array_origin.clone();
688 Err(ErrorWithOrigin::new(LowLevelError::InvalidArray, origin))
689 } else {
690 Ok(items)
691 }
692 }
693
694 fn parse_entry<'a>(
695 &self,
696 entry: &'a WithOrigin,
697 ) -> Result<(&'a WithOrigin, Option<&'a WithOrigin>), ErrorWithOrigin> {
698 let Value::Object(obj) = &entry.inner else {
699 let expected = format!(
700 "{{ {:?}: _, {:?}: _ }} tuple",
701 self.keys_name, self.values_name
702 );
703 return Err(entry.invalid_type(&expected));
704 };
705
706 let key = obj.get(self.keys_name).ok_or_else(|| {
707 let err = DeError::missing_field(self.keys_name);
708 ErrorWithOrigin::json(err, entry.origin.clone())
709 })?;
710 let value = obj.get(self.values_name);
711
712 if obj.len() > 2 {
713 let expected = format!(
714 "{{ {:?}: _, {:?}: _ }} tuple",
715 self.keys_name, self.values_name
716 );
717 return Err(entry.invalid_type(&expected));
718 }
719 Ok((key, value))
720 }
721}
722
723impl<K, V, DeK, DeV, C> DeserializeParam<C> for NamedEntries<K, V, DeK, DeV>
724where
725 K: 'static,
726 V: 'static,
727 DeK: DeserializeParam<K>,
728 DeV: DeserializeParam<V>,
729 C: FromIterator<(K, V)> + ToEntries<K, V>,
730{
731 const EXPECTING: BasicTypes = BasicTypes::OBJECT.or(BasicTypes::ARRAY);
732
733 fn describe(&self, description: &mut TypeDescription) {
734 let details = format!(
735 "map or array of {{ {:?}: _, {:?}: _ }} tuples",
736 self.keys_name, self.values_name
737 );
738 description
739 .set_details(details)
740 .set_entries(&self.inner.keys, &self.inner.values);
741 }
742
743 fn deserialize_param(
744 &self,
745 ctx: DeserializeContext<'_>,
746 param: &'static ParamMetadata,
747 ) -> Result<C, ErrorWithOrigin> {
748 let deserializer = ctx.current_value_deserializer(param.name)?;
749 match deserializer.value() {
750 Value::Object(map) => {
751 self.inner
752 .deserialize_map(ctx, param, map, deserializer.origin())
753 }
754 Value::Array(array) => {
755 self.deserialize_entries(ctx, param, array, deserializer.origin())
756 }
757 _ => Err(deserializer.invalid_type("object or array")),
758 }
759 }
760
761 fn serialize_param(&self, param: &C) -> serde_json::Value {
762 let entries = param.to_entries().map(|(key, value)| {
763 let key = self.inner.keys.serialize_param(key);
764 let value = self.inner.values.serialize_param(value);
765 serde_json::json!({
766 self.keys_name: key,
767 self.values_name: value,
768 })
769 });
770 serde_json::Value::Array(entries.collect())
771 }
772}