use super::*;
use serde::de::Visitor;
use std::fmt::Formatter;
pub struct CibouletteQueryParametersFieldVisitor;
pub enum CibouletteQueryParametersField<'request> {
Include,
Sparse(Cow<'request, str>),
Sorting,
Page(CiboulettePageType<'request>),
Filter,
FilterTyped(Cow<'request, str>),
Meta(Cow<'request, str>),
}
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum CiboulettePageType<'request> {
Number,
Size,
Offset,
Limit,
Cursor,
Other(Cow<'request, str>),
}
impl CibouletteQueryParametersFieldVisitor {
#[inline]
fn parse_str(value: Cow<'_, str>) -> CibouletteQueryParametersField<'_> {
let preemptive_val = match value.as_ref() {
"include" => Some(CibouletteQueryParametersField::Include),
"sort" => Some(CibouletteQueryParametersField::Sorting),
"filter" => Some(CibouletteQueryParametersField::Filter),
_ => None,
};
if let Some(preemptive_val) = preemptive_val {
return preemptive_val;
}
let has_type = value.find('['); match has_type {
Some(type_end_index) => {
let type_ = &value[0..type_end_index];
match type_ {
"page" => {
let page_type =
typed_param::parse_typed_query_param(&value[type_end_index..]) .unwrap_or_default();
match page_type.as_ref() {
"limit" => {
CibouletteQueryParametersField::Page(CiboulettePageType::Limit)
}
"size" => {
CibouletteQueryParametersField::Page(CiboulettePageType::Size)
}
"offset" => {
CibouletteQueryParametersField::Page(CiboulettePageType::Offset)
}
"number" => {
CibouletteQueryParametersField::Page(CiboulettePageType::Number)
}
"cursor" => {
CibouletteQueryParametersField::Page(CiboulettePageType::Cursor)
}
_ => CibouletteQueryParametersField::Page(CiboulettePageType::Other(
Cow::Owned(page_type.into_owned()),
)),
}
}
"fields" => {
let type_ = typed_param::parse_typed_query_param(&value[type_end_index..])
.unwrap_or_default();
CibouletteQueryParametersField::Sparse(Cow::Owned(type_.into_owned()))
}
"filter" => {
let type_ = typed_param::parse_typed_query_param(&value[type_end_index..])
.unwrap_or_default();
CibouletteQueryParametersField::FilterTyped(Cow::Owned(type_.into_owned()))
}
_ => CibouletteQueryParametersField::Meta(value),
}
}
None => CibouletteQueryParametersField::Meta(value),
}
}
}
impl<'de> Visitor<'de> for CibouletteQueryParametersFieldVisitor {
type Value = CibouletteQueryParametersField<'de>;
#[inline]
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
Formatter::write_str(formatter, "field identifier")
}
#[inline]
fn visit_borrowed_str<E>(self, value: &'de str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Self::parse_str(Cow::Borrowed(value)))
}
#[inline]
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Self::parse_str(Cow::Owned(value.to_string())))
}
#[inline]
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Self::parse_str(Cow::Owned(value)))
}
#[inline]
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
self.visit_str(
std::str::from_utf8(value)
.map_err(|e| serde::de::Error::custom(format!("UTF8 error : {}", e)))?,
)
}
}
impl<'de> serde::Deserialize<'de> for CibouletteQueryParametersField<'de> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
serde::Deserializer::deserialize_identifier(
deserializer,
CibouletteQueryParametersFieldVisitor,
)
}
}