1use camino::{Utf8Path, Utf8PathBuf};
2use nom::Err::Failure;
3use nom::error::Error as NomError;
4use nom::error::ErrorKind as NomErrorKind;
5use nom::error::FromExternalError;
6use nom::IResult;
7use nom::number::complete::be_u32;
8use nom::bytes::complete::take;
9use serde::ser::SerializeTuple;
10use serde::Serialize;
11use serde::Serializer;
12use uuid::Uuid;
13
14#[cfg(test)]
15use proptest::strategy::Strategy;
16
17pub fn vec_u8_as_slice<S: Serializer>(elements: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error> {
18 let mut tuple = serializer.serialize_tuple(elements.len())?;
19 for e in elements {
20 tuple.serialize_element(e)?;
21 }
22 tuple.end()
23}
24
25pub fn vec_with_u32_length<S: Serializer, T: Serialize>(elements: &Vec<T>, serializer: S) -> Result<S::Ok, S::Error> {
26 let mut seq = serializer.serialize_tuple(elements.len() + 1)?;
27 seq.serialize_element(&(elements.len() as u32))?;
28 for e in elements {
29 seq.serialize_element(e)?;
30 }
31 seq.end()
32}
33
34pub fn path_with_u32_length<S: Serializer>(s: &Utf8Path, serializer: S) -> Result<S::Ok, S::Error> {
35 str_with_u32_length(s.as_str(), serializer)
36}
37
38pub fn str_with_u32_length<S: Serializer>(s: &str, serializer: S) -> Result<S::Ok, S::Error> {
39 let slice = s.as_bytes();
40 let mut seq = serializer.serialize_tuple(slice.len() + 1)?;
41 seq.serialize_element(&(slice.len() as u32))?;
42 for c in slice {
43 seq.serialize_element(c)?;
44 }
45 seq.end()
46}
47
48pub fn serialize_uuid<S: Serializer>(uuid: &Uuid, serializer: S) -> Result<S::Ok, S::Error> {
49 str_with_u32_length(&uuid.to_string(), serializer)
50}
51
52#[inline]
53pub fn parse_u8_vec(i: &[u8]) -> IResult<&[u8], Vec<u8>> {
54 let (i, len) = be_u32(i)?;
55 if(i.len() < len as usize) {
56 return Ok((i, Vec::new()));
57 }
58 let (i, slice) = take(len)(i)?;
59 Ok((i, Vec::from(slice)))
60}
61
62#[inline]
63pub fn parse_vec<'a, T: nom_derive::Parse<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], Vec<T>> {
64 let (mut i, len) = be_u32(i)?;
65 let mut s;
66 let mut vec = Vec::with_capacity(len as usize);
67 for _ in 0..len {
68 (i, s) = T::parse(i)?;
69 vec.push(s)
70 }
71 Ok((i, vec))
72}
73
74pub fn parse_str(i: &[u8]) -> IResult<&[u8], &str> {
76 let (i, len) = be_u32(i)?;
77 let (i, string) = take(len)(i)?;
78 Ok((i, std::str::from_utf8(string).map_err(|e| Failure(NomError::from_external_error(i, NomErrorKind::Char, e)))?))
79}
80
81#[inline]
82pub fn parse_string(i: &[u8]) -> IResult<&[u8], String> {
83 let (i, string) = parse_str(i)?;
84 Ok((i, string.to_string()))
85}
86
87#[inline]
88pub fn parse_path(i: &[u8]) -> IResult<&[u8], Utf8PathBuf> {
89 let (i, string) = parse_str(i)?;
90 Ok((i, string.into()))
91}
92
93#[inline]
94pub fn parse_uuid(i: &[u8]) -> IResult<&[u8], Uuid> {
95 let (i, s) = parse_str(i)?;
96 Ok((i, Uuid::parse_str(s).map_err(|e| Failure(NomError::from_external_error(i, NomErrorKind::Char, e)))?))
97}
98
99#[cfg(test)]
100pub(crate) fn arbitrary_uuid() -> impl Strategy<Value = Uuid> {
101 proptest::prelude::any::<u128>().prop_map(Uuid::from_u128)
102}
103