mod builder;
mod page;
mod sort;
use std::fmt::{self, Formatter};
use percent_encoding::percent_decode;
use serde::de::{Deserialize, Deserializer, MapAccess, Visitor};
use serde::ser::{Serialize, SerializeStruct, Serializer};
use serde_qs;
use error::Error;
use value::{Key, Map, Path, Set, Stringify, Value};
pub use self::builder::Builder;
pub use self::page::Page;
pub use self::sort::{Direction, Sort};
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Query {
pub fields: Map<Key, Set>,
pub filter: Map<Path, Value>,
pub include: Set<Path>,
pub page: Option<Page>,
pub sort: Set<Sort>,
_ext: (),
}
impl Query {
pub fn new() -> Self {
Default::default()
}
pub fn builder() -> Builder {
Default::default()
}
}
impl<'de> Deserialize<'de> for Query {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
const FIELDS: &[&str] = &["fields", "filter", "include", "page", "sort"];
#[derive(Debug, Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum Field {
Fields,
Filter,
Include,
Page,
Sort,
}
struct QueryVisitor;
impl<'de> Visitor<'de> for QueryVisitor {
type Value = Query;
fn expecting(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "an object containing query parameters")
}
fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
use serde::de::Error;
let mut fields = None;
let mut filter = None;
let mut include = None;
let mut page = None;
let mut sort = None;
while let Some(key) = access.next_key()? {
match key {
Field::Fields => {
let data = access.next_value::<Map<_, String>>()?;
let mut map = Map::with_capacity(data.len());
for (field, value) in data {
let value = value.parse().map_err(Error::custom)?;
map.insert(field, value);
}
fields = Some(map);
}
Field::Filter => {
filter = Some(access.next_value()?);
}
Field::Include => {
let data = access.next_value::<String>()?;
include = Some(data.parse().map_err(Error::custom)?);
}
Field::Page => {
page = Some(access.next_value()?);
}
Field::Sort => {
let data = access.next_value::<String>()?;
sort = Some(data.parse().map_err(Error::custom)?);
}
}
}
Ok(Query {
page,
fields: fields.unwrap_or_default(),
filter: filter.unwrap_or_default(),
include: include.unwrap_or_default(),
sort: sort.unwrap_or_default(),
_ext: (),
})
}
}
deserializer.deserialize_struct("Query", FIELDS, QueryVisitor)
}
}
impl Serialize for Query {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("Query", 5)?;
if !self.fields.is_empty() {
let mut fields = Map::with_capacity(self.fields.len());
for (key, value) in &self.fields {
fields.insert(key, value.stringify());
}
state.serialize_field("fields", &fields)?;
}
if !self.filter.is_empty() {
state.serialize_field("filter", &self.filter)?;
}
if !self.include.is_empty() {
state.serialize_field("include", &self.include.stringify())?;
}
if let Some(ref page) = self.page {
state.serialize_field("page", page)?;
}
if !self.sort.is_empty() {
state.serialize_field("sort", &self.sort.stringify())?;
}
state.end()
}
}
pub fn from_slice(data: &[u8]) -> Result<Query, Error> {
let value = percent_decode(data).decode_utf8()?;
Ok(serde_qs::from_bytes(value.as_bytes())?)
}
pub fn from_str(data: &str) -> Result<Query, Error> {
from_slice(data.as_bytes())
}
pub fn to_string(query: &Query) -> Result<String, Error> {
use percent_encoding::{percent_encode, QUERY_ENCODE_SET};
let value = serde_qs::to_string(query)?;
let data = value.as_bytes();
Ok(percent_encode(data, QUERY_ENCODE_SET).collect())
}
pub fn to_vec(query: &Query) -> Result<Vec<u8>, Error> {
to_string(query).map(Vec::from)
}