use std::{collections::BTreeMap, future::Future}; use super::{NixDeserialize, NixRead}; #[allow(clippy::manual_async_fn)] impl NixDeserialize for Vec where T: NixDeserialize + Send, { fn try_deserialize( reader: &mut R, ) -> impl Future, R::Error>> + Send + '_ where R: ?Sized + NixRead + Send, { async move { if let Some(len) = reader.try_read_value::().await? { let mut ret = Vec::with_capacity(len); for _ in 0..len { ret.push(reader.read_value().await?); } Ok(Some(ret)) } else { Ok(None) } } } } #[allow(clippy::manual_async_fn)] impl NixDeserialize for BTreeMap where K: NixDeserialize + Ord + Send, V: NixDeserialize + Send, { fn try_deserialize( reader: &mut R, ) -> impl Future, R::Error>> + Send + '_ where R: ?Sized + NixRead + Send, { async move { if let Some(len) = reader.try_read_value::().await? { let mut ret = BTreeMap::new(); for _ in 0..len { let key = reader.read_value().await?; let value = reader.read_value().await?; ret.insert(key, value); } Ok(Some(ret)) } else { Ok(None) } } } } #[cfg(test)] mod test { use std::collections::BTreeMap; use std::fmt; use hex_literal::hex; use rstest::rstest; use tokio_test::io::Builder; use crate::nix_daemon::de::{NixDeserialize, NixRead, NixReader}; #[rstest] #[case::empty(vec![], &hex!("0000 0000 0000 0000"))] #[case::one(vec![0x29], &hex!("0100 0000 0000 0000 2900 0000 0000 0000"))] #[case::two(vec![0x7469, 10], &hex!("0200 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))] #[tokio::test] async fn test_read_small_vec(#[case] expected: Vec, #[case] data: &[u8]) { let mock = Builder::new().read(data).build(); let mut reader = NixReader::new(mock); let actual: Vec = reader.read_value().await.unwrap(); assert_eq!(actual, expected); } fn empty_map() -> BTreeMap { BTreeMap::new() } macro_rules! map { ($($key:expr => $value:expr),*) => {{ let mut ret = BTreeMap::new(); $(ret.insert($key, $value);)* ret }}; } #[rstest] #[case::empty(empty_map(), &hex!("0000 0000 0000 0000"))] #[case::one(map![0x7469usize => 10u64], &hex!("0100 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))] #[tokio::test] async fn test_read_small_btree_map(#[case] expected: E, #[case] data: &[u8]) where E: NixDeserialize + PartialEq + fmt::Debug, { let mock = Builder::new().read(data).build(); let mut reader = NixReader::new(mock); let actual: E = reader.read_value().await.unwrap(); assert_eq!(actual, expected); } }