serde_partial/
alloc.rs

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}