redust-resp 0.3.0

A simple RESP parser for Rust.
Documentation
use itertools::Itertools;
use serde::{
	de::{
		self,
		value::{MapDeserializer, SeqDeserializer},
	},
	forward_to_deserialize_any, Deserialize,
};

use hipstr::HipStr;

use crate::{Bulk, Data, Error};

/// Deserialize [Data] into `T`.
pub fn from_data<'de, T>(data: Data<'de>) -> Result<T, Error<'de>>
where
	T: Deserialize<'de>,
{
	T::deserialize(data)
}

impl<'de> de::Deserialize<'de> for Data<'de> {
	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
	where
		D: serde::Deserializer<'de>,
	{
		struct Visitor;

		impl<'de> de::Visitor<'de> for Visitor {
			type Value = Data<'de>;

			fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
				write!(formatter, "valid RESP data")
			}

			fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				Ok(Data::Integer(v))
			}

			fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				Ok(Data::SimpleString(v.into()))
			}

			fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				Ok(Data::SimpleString(v.into()))
			}

			fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				Ok(Data::SimpleString(HipStr::borrowed(v)))
			}

			fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				Ok(Data::BulkString(v.into()))
			}

			fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				self.visit_byte_buf(v.to_owned())
			}

			fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				Ok(Data::BulkString(v.into()))
			}

			fn visit_none<E>(self) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				Ok(Data::Null)
			}

			fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
			where
				D: serde::Deserializer<'de>,
			{
				de::Deserialize::deserialize(deserializer)
			}

			fn visit_unit<E>(self) -> Result<Self::Value, E>
			where
				E: de::Error,
			{
				self.visit_none()
			}

			fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
			where
				D: serde::Deserializer<'de>,
			{
				de::Deserialize::deserialize(deserializer)
			}

			fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
			where
				A: de::SeqAccess<'de>,
			{
				let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0));
				while let Some(v) = seq.next_element()? {
					out.push(v);
				}

				Ok(Data::Array(out))
			}
		}

		deserializer.deserialize_any(Visitor)
	}
}

fn visit_array<'de, V>(
	array: impl Iterator<Item = Data<'de>>,
	visitor: V,
) -> Result<V::Value, Error<'de>>
where
	V: de::Visitor<'de>,
{
	let mut deserializer = SeqDeserializer::new(array);
	let seq = visitor.visit_seq(&mut deserializer)?;
	deserializer.end()?;
	Ok(seq)
}

fn visit_map<'de, V>(
	array: impl Iterator<Item = Data<'de>>,
	visitor: V,
) -> Result<V::Value, Error<'de>>
where
	V: de::Visitor<'de>,
{
	let mut deserializer = MapDeserializer::new(array.tuples::<(_, _)>());
	let seq = visitor.visit_map(&mut deserializer)?;
	deserializer.end()?;
	Ok(seq)
}

impl<'de> de::Deserializer<'de> for Data<'de> {
	type Error = Error<'de>;

	fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
	where
		V: de::Visitor<'de>,
	{
		match self {
			Data::Array(data) => visit_array(data.into_iter(), visitor),
			Data::BulkString(bytes) => match bytes {
				Bulk::Borrowed(b) => visitor.visit_borrowed_bytes(b),
				Bulk::Shared(b) => visitor.visit_bytes(&b),
			},
			Data::Integer(i) => visitor.visit_i64(i),
			Data::Null => visitor.visit_none(),
			Data::SimpleString(str) => match str.as_borrowed() {
				Some(s) => visitor.visit_borrowed_str(s),
				None => visitor.visit_str(&str),
			},
		}
	}

	fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
	where
		V: de::Visitor<'de>,
	{
		fn make_err<T, E>(unex: de::Unexpected) -> Result<T, E>
		where
			E: de::Error,
		{
			Err(de::Error::invalid_type(unex, &"sequence"))
		}

		match self {
			Data::Array(data) => visit_map(data.into_iter(), visitor),
			Data::BulkString(b) => make_err(de::Unexpected::Bytes(&b)),
			Data::Integer(i) => make_err(de::Unexpected::Signed(i)),
			Data::Null => make_err(de::Unexpected::Unit),
			Data::SimpleString(str) => make_err(de::Unexpected::Str(&str)),
		}
	}

	fn deserialize_struct<V>(
		self,
		_name: &'static str,
		_fields: &'static [&'static str],
		visitor: V,
	) -> Result<V::Value, Self::Error>
	where
		V: de::Visitor<'de>,
	{
		self.deserialize_map(visitor)
	}

	fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
	where
		V: de::Visitor<'de>,
	{
		match self {
			Self::Null => visitor.visit_none(),
			_ => visitor.visit_some(self),
		}
	}

	forward_to_deserialize_any! {
		bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
		bytes byte_buf unit unit_struct newtype_struct seq tuple
		tuple_struct enum identifier ignored_any
	}
}

impl<'de> de::IntoDeserializer<'de, Error<'de>> for Data<'de> {
	type Deserializer = Self;

	fn into_deserializer(self) -> Self::Deserializer {
		self
	}
}

#[cfg(test)]
mod test {
	use crate::{array, Data};

	use super::from_data;

	#[test]
	fn to_str() {
		let res = from_data::<&str>(Data::simple_string("foo")).unwrap();
		assert_eq!(res, "foo");
	}

	#[test]
	fn to_bytes() {
		let res = from_data::<&[u8]>(Data::bulk_string(b"foo")).unwrap();
		assert_eq!(res, b"foo");
	}

	#[test]
	fn to_arr() {
		let res = from_data::<Vec<&str>>(array!(Data::simple_string("foo"))).unwrap();
		assert_eq!(res, vec!["foo"]);
	}

	#[test]
	fn to_int() {
		let res = from_data::<isize>(Data::Integer(42)).unwrap();
		assert_eq!(res, 42);
	}
}