nix_compat/wire/ser/
collections.rs

1use std::collections::BTreeMap;
2use std::future::Future;
3
4use super::{NixSerialize, NixWrite};
5
6impl<T> NixSerialize for Vec<T>
7where
8    T: NixSerialize + Send + Sync,
9{
10    #[allow(clippy::manual_async_fn)]
11    fn serialize<W>(&self, writer: &mut W) -> impl Future<Output = Result<(), W::Error>> + Send
12    where
13        W: NixWrite,
14    {
15        async move {
16            writer.write_value(&self.len()).await?;
17            for value in self.iter() {
18                writer.write_value(value).await?;
19            }
20            Ok(())
21        }
22    }
23}
24
25impl<K, V> NixSerialize for BTreeMap<K, V>
26where
27    K: NixSerialize + Ord + Send + Sync,
28    V: NixSerialize + Send + Sync,
29{
30    #[allow(clippy::manual_async_fn)]
31    fn serialize<W>(&self, writer: &mut W) -> impl Future<Output = Result<(), W::Error>> + Send
32    where
33        W: NixWrite,
34    {
35        async move {
36            writer.write_value(&self.len()).await?;
37            for (key, value) in self.iter() {
38                writer.write_value(key).await?;
39                writer.write_value(value).await?;
40            }
41            Ok(())
42        }
43    }
44}
45
46#[cfg(test)]
47mod test {
48    use std::collections::BTreeMap;
49    use std::fmt;
50
51    use hex_literal::hex;
52    use rstest::rstest;
53    use tokio::io::AsyncWriteExt as _;
54    use tokio_test::io::Builder;
55
56    use crate::wire::ser::{NixSerialize, NixWrite, NixWriter};
57
58    #[rstest]
59    #[case::empty(vec![], &hex!("0000 0000 0000 0000"))]
60    #[case::one(vec![0x29], &hex!("0100 0000 0000 0000 2900 0000 0000 0000"))]
61    #[case::two(vec![0x7469, 10], &hex!("0200 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))]
62    #[tokio::test]
63    async fn test_write_small_vec(#[case] value: Vec<usize>, #[case] data: &[u8]) {
64        let mock = Builder::new().write(data).build();
65        let mut writer = NixWriter::new(mock);
66        writer.write_value(&value).await.unwrap();
67        writer.flush().await.unwrap();
68    }
69
70    fn empty_map() -> BTreeMap<usize, u64> {
71        BTreeMap::new()
72    }
73    macro_rules! map {
74        ($($key:expr => $value:expr),*) => {{
75            let mut ret = BTreeMap::new();
76            $(ret.insert($key, $value);)*
77            ret
78        }};
79    }
80
81    #[rstest]
82    #[case::empty(empty_map(), &hex!("0000 0000 0000 0000"))]
83    #[case::one(map![0x7469usize => 10u64], &hex!("0100 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))]
84    #[tokio::test]
85    async fn test_write_small_btree_map<E>(#[case] value: E, #[case] data: &[u8])
86    where
87        E: NixSerialize + Send + PartialEq + fmt::Debug,
88    {
89        let mock = Builder::new().write(data).build();
90        let mut writer = NixWriter::new(mock);
91        writer.write_value(&value).await.unwrap();
92        writer.flush().await.unwrap();
93    }
94}