1use alloc::collections::{
2 btree_map::{BTreeMap, Keys},
3 BTreeSet,
4};
5use core::iter::Map;
6
7use serde::Serialize;
8
9use crate::{Field, Partial, SerializeFilter, SerializePartial};
10
11impl<'a, K, V> SerializePartial<'a> for BTreeMap<K, V>
12where
13 K: Ord + AsRef<str> + Serialize + 'a,
14 V: Serialize + 'a,
15{
16 #[allow(clippy::type_complexity)]
17 type Fields = Map<Keys<'a, K, V>, fn(&'a K) -> Field<'a, Self>>;
18 type Filter = BTreeSet<Field<'a, Self>>;
19
20 fn with_fields<F, I>(&'a self, select: F) -> Partial<'a, Self>
21 where
22 F: FnOnce(Self::Fields) -> I,
23 I: IntoIterator<Item = Field<'a, Self>>,
24 {
25 let fields: Self::Fields = self.keys().map(|k| Field::new(k.as_ref()));
26 let filter = select(fields).into_iter().collect();
27 Partial {
28 value: self,
29 filter,
30 }
31 }
32}
33
34impl<'a, K, V> SerializeFilter<BTreeMap<K, V>> for BTreeSet<Field<'a, BTreeMap<K, V>>> {
35 fn skip(&self, field: Field<'_, BTreeMap<K, V>>) -> bool {
36 !self.contains(&field)
37 }
38
39 fn filtered_len(&self, _len: Option<usize>) -> Option<usize> {
40 Some(self.len())
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use crate::{Field, SerializePartial};
47
48 use alloc::collections::BTreeMap;
49
50 #[test]
51 fn b_tree_map() {
52 let map = BTreeMap::from([("a", "b"), ("c", "d")]);
53 let filtered = map.with_fields(|_| [Field::new("a")]);
54 assert_eq!(
55 serde_json::to_value(&filtered).unwrap(),
56 serde_json::json!({ "a": "b" })
57 )
58 }
59}