tuwunel_core/utils/
bytes.rs1#[cfg(test)]
7mod tests;
8
9use bytesize::ByteSize;
10use serde::{Deserialize, Deserializer, de};
11
12use crate::{Result, at, err};
13
14pub fn deserialize_bytesize_usize<'de, D>(de: D) -> Result<usize, D::Error>
17where
18 D: Deserializer<'de>,
19{
20 ByteSize::deserialize(de)
21 .map(at!(0))
22 .map(usize::try_from)?
23 .map_err(de::Error::custom)
24}
25
26pub fn deserialize_bytesize_u64<'de, D>(de: D) -> Result<u64, D::Error>
29where
30 D: Deserializer<'de>,
31{
32 ByteSize::deserialize(de).map(at!(0))
33}
34
35#[inline]
37pub fn from_str(str: &str) -> Result<usize> {
38 let bytes: ByteSize = str
39 .parse()
40 .map_err(|e| err!(Arithmetic("Failed to parse byte size: {e}")))?;
41
42 let bytes: usize = bytes
43 .as_u64()
44 .try_into()
45 .map_err(|e| err!(Arithmetic("Failed to convert u64 to usize: {e}")))?;
46
47 Ok(bytes)
48}
49
50#[inline]
52#[must_use]
53pub fn pretty(bytes: usize) -> String {
54 let bytes: u64 = bytes
55 .try_into()
56 .expect("failed to convert usize to u64");
57
58 ByteSize::b(bytes).display().iec().to_string()
59}
60
61#[inline]
66#[must_use]
67pub fn increment(old: Option<&[u8]>) -> [u8; 8] {
68 old.map_or(0_u64, |bytes| u64_from_bytes(bytes).unwrap_or(0))
69 .wrapping_add(1)
70 .to_be_bytes()
71}
72
73#[inline]
75#[must_use]
76pub fn u64_from_u8(bytes: &[u8]) -> u64 {
77 u64_from_bytes(bytes).expect("must slice at least 8 bytes")
78}
79
80#[inline]
82pub fn u64_from_bytes(bytes: &[u8]) -> Result<u64> { Ok(u64::from_be_bytes(bytes.try_into()?)) }
83
84#[must_use]
89pub fn prefix_successor(mut prefix: Vec<u8>) -> Option<Vec<u8>> {
90 let index = prefix.iter().rposition(|byte| *byte != u8::MAX)?;
91
92 prefix.truncate(index.saturating_add(1));
93 prefix[index] = prefix[index].saturating_add(1);
94 Some(prefix)
95}