nix_compat/wire/de/
collections.rs

1use std::{collections::BTreeMap, future::Future};
2
3use super::{NixDeserialize, NixRead};
4
5#[allow(clippy::manual_async_fn)]
6impl<T> NixDeserialize for Vec<T>
7where
8    T: NixDeserialize + Send,
9{
10    fn try_deserialize<R>(
11        reader: &mut R,
12    ) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_
13    where
14        R: ?Sized + NixRead + Send,
15    {
16        async move {
17            if let Some(len) = reader.try_read_value::<usize>().await? {
18                let mut ret = Vec::with_capacity(len);
19                for _ in 0..len {
20                    ret.push(reader.read_value().await?);
21                }
22                Ok(Some(ret))
23            } else {
24                Ok(None)
25            }
26        }
27    }
28}
29
30#[allow(clippy::manual_async_fn)]
31impl<K, V> NixDeserialize for BTreeMap<K, V>
32where
33    K: NixDeserialize + Ord + Send,
34    V: NixDeserialize + Send,
35{
36    fn try_deserialize<R>(
37        reader: &mut R,
38    ) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_
39    where
40        R: ?Sized + NixRead + Send,
41    {
42        async move {
43            if let Some(len) = reader.try_read_value::<usize>().await? {
44                let mut ret = BTreeMap::new();
45                for _ in 0..len {
46                    let key = reader.read_value().await?;
47                    let value = reader.read_value().await?;
48                    ret.insert(key, value);
49                }
50                Ok(Some(ret))
51            } else {
52                Ok(None)
53            }
54        }
55    }
56}
57
58#[cfg(test)]
59mod test {
60    use std::collections::BTreeMap;
61    use std::fmt;
62
63    use hex_literal::hex;
64    use rstest::rstest;
65    use tokio_test::io::Builder;
66
67    use crate::wire::de::{NixDeserialize, NixRead, NixReader};
68
69    #[rstest]
70    #[case::empty(vec![], &hex!("0000 0000 0000 0000"))]
71    #[case::one(vec![0x29], &hex!("0100 0000 0000 0000 2900 0000 0000 0000"))]
72    #[case::two(vec![0x7469, 10], &hex!("0200 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))]
73    #[tokio::test]
74    async fn test_read_small_vec(#[case] expected: Vec<usize>, #[case] data: &[u8]) {
75        let mock = Builder::new().read(data).build();
76        let mut reader = NixReader::new(mock);
77        let actual: Vec<usize> = reader.read_value().await.unwrap();
78        assert_eq!(actual, expected);
79    }
80
81    fn empty_map() -> BTreeMap<usize, u64> {
82        BTreeMap::new()
83    }
84    macro_rules! map {
85        ($($key:expr => $value:expr),*) => {{
86            let mut ret = BTreeMap::new();
87            $(ret.insert($key, $value);)*
88            ret
89        }};
90    }
91
92    #[rstest]
93    #[case::empty(empty_map(), &hex!("0000 0000 0000 0000"))]
94    #[case::one(map![0x7469usize => 10u64], &hex!("0100 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))]
95    #[tokio::test]
96    async fn test_read_small_btree_map<E>(#[case] expected: E, #[case] data: &[u8])
97    where
98        E: NixDeserialize + PartialEq + fmt::Debug,
99    {
100        let mock = Builder::new().read(data).build();
101        let mut reader = NixReader::new(mock);
102        let actual: E = reader.read_value().await.unwrap();
103        assert_eq!(actual, expected);
104    }
105}