wnfs_common/utils/
common.rs

1use super::Arc;
2use crate::HashOutput;
3use anyhow::Result;
4use bytes::Bytes;
5use cid::Cid;
6use futures::{AsyncRead, AsyncReadExt};
7use parking_lot::Mutex;
8use rand_core::CryptoRngCore;
9use serde::{Deserialize, Serialize, Serializer};
10use std::collections::HashMap;
11
12//--------------------------------------------------------------------------------------------------
13// Functions
14//--------------------------------------------------------------------------------------------------
15
16pub fn error<T>(err: impl std::error::Error + Send + Sync + 'static) -> Result<T> {
17    Err(err.into())
18}
19
20pub async fn read_fully(
21    stream: &mut (impl AsyncRead + Unpin),
22    buffer: &mut [u8],
23) -> Result<(usize, bool)> {
24    let mut bytes_read = 0;
25    let mut done = false;
26    loop {
27        let bytes_read_in_iteration = stream.read(&mut buffer[bytes_read..]).await?;
28
29        bytes_read += bytes_read_in_iteration;
30
31        if bytes_read_in_iteration == 0 {
32            done = true;
33            break;
34        }
35
36        if bytes_read == buffer.len() {
37            break;
38        }
39    }
40    Ok((bytes_read, done))
41}
42
43/// Generates a random byte array of the given length.
44///
45/// # Examples
46///
47/// ```
48/// use rand::thread_rng;
49/// use wnfs_common::utils;
50///
51/// let rng = &mut thread_rng();
52/// let bytes = utils::get_random_bytes::<32>(rng);
53///
54/// assert_eq!(bytes.len(), 32);
55/// ```
56pub fn get_random_bytes<const N: usize>(rng: &mut impl CryptoRngCore) -> [u8; N] {
57    let mut bytes = [0u8; N];
58    rng.fill_bytes(&mut bytes);
59    bytes
60}
61
62/// Creates a [`HashOutput`][HashOutput] ([u8; 32]) from a possibly incomplete slice.
63///
64/// If the slice is smaller than `HashOutput`, the remaining bytes are filled with zeros.
65///
66/// # Examples
67///
68/// ```
69/// use wnfs_common::utils;
70///
71/// let digest = utils::to_hash_output(&[0xff, 0x22]);
72///
73/// assert_eq!(digest.len(), 32);
74/// ```
75///
76/// [HashOutput]: crate::HashOutput
77pub fn to_hash_output(bytes: &[u8]) -> HashOutput {
78    let mut nibbles = [0u8; 32];
79    nibbles[..bytes.len()].copy_from_slice(bytes);
80    nibbles
81}
82
83pub(crate) fn serialize_cid_map<S>(
84    map: &Arc<Mutex<HashMap<Cid, Bytes>>>,
85    serializer: S,
86) -> Result<S::Ok, S::Error>
87where
88    S: Serializer,
89{
90    let map = map
91        .lock()
92        .iter()
93        .map(|(cid, bytes)| (cid.to_string(), bytes.to_vec()))
94        .collect::<HashMap<_, _>>();
95
96    map.serialize(serializer)
97}
98
99pub(crate) fn deserialize_cid_map<'de, D>(
100    deserializer: D,
101) -> Result<Arc<Mutex<HashMap<Cid, Bytes>>>, D::Error>
102where
103    D: serde::Deserializer<'de>,
104{
105    let map = HashMap::<String, Vec<u8>>::deserialize(deserializer)?;
106    let map = map
107        .into_iter()
108        .map(|(cid, bytes)| {
109            let cid = cid.parse::<Cid>().map_err(serde::de::Error::custom)?;
110            Ok((cid, bytes.into()))
111        })
112        .collect::<Result<_, _>>()?;
113
114    Ok(Arc::new(Mutex::new(map)))
115}