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