use std::{collections::BTreeMap, future::Future};
use super::{NixDeserialize, NixRead};
#[allow(clippy::manual_async_fn)]
impl<T> NixDeserialize for Vec<T>
where
T: NixDeserialize + Send,
{
fn try_deserialize<R>(
reader: &mut R,
) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_
where
R: ?Sized + NixRead + Send,
{
async move {
if let Some(len) = reader.try_read_value::<usize>().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<K, V> NixDeserialize for BTreeMap<K, V>
where
K: NixDeserialize + Ord + Send,
V: NixDeserialize + Send,
{
fn try_deserialize<R>(
reader: &mut R,
) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_
where
R: ?Sized + NixRead + Send,
{
async move {
if let Some(len) = reader.try_read_value::<usize>().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<usize>, #[case] data: &[u8]) {
let mock = Builder::new().read(data).build();
let mut reader = NixReader::new(mock);
let actual: Vec<usize> = reader.read_value().await.unwrap();
assert_eq!(actual, expected);
}
fn empty_map() -> BTreeMap<usize, u64> {
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<E>(#[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);
}
}