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