use std::cmp::{Eq, PartialEq};
use std::hash::{Hash, Hasher};
use std::mem;
use doc::{Data, Document, Identifier, Link, PrimaryData, Relationship};
use error::Error;
use query::Query;
use sealed::Sealed;
use value::{Key, Map, Set, Value};
use view::Render;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Object {
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub attributes: Map,
pub id: String,
#[serde(rename = "type")]
pub kind: Key,
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub links: Map<Key, Link>,
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub meta: Map,
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub relationships: Map<Key, Relationship>,
#[serde(skip)]
_ext: (),
}
impl Object {
pub fn new(kind: Key, id: String) -> Self {
Object {
id,
kind,
attributes: Default::default(),
links: Default::default(),
meta: Default::default(),
relationships: Default::default(),
_ext: (),
}
}
}
impl Eq for Object {}
impl Hash for Object {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
self.kind.hash(state);
}
}
impl PartialEq for Object {
fn eq(&self, rhs: &Object) -> bool {
self.id == rhs.id && self.kind == rhs.kind
}
}
impl PartialEq<Identifier> for Object {
fn eq(&self, rhs: &Identifier) -> bool {
self.id == rhs.id && self.kind == rhs.kind
}
}
impl Render<Identifier> for Object {
fn render(self, query: Option<&Query>) -> Result<Document<Identifier>, Error> {
Identifier::from(self).render(query)
}
}
impl Render<Identifier> for Vec<Object> {
fn render(self, _: Option<&Query>) -> Result<Document<Identifier>, Error> {
let data = self.into_iter().map(Identifier::from).collect();
Ok(Document::Ok {
data,
included: Default::default(),
jsonapi: Default::default(),
links: Default::default(),
meta: Default::default(),
})
}
}
impl Render<Object> for Object {
fn render(mut self, _: Option<&Query>) -> Result<Document<Object>, Error> {
let links = mem::replace(&mut self.links, Default::default());
let meta = mem::replace(&mut self.meta, Default::default());
Ok(Document::Ok {
links,
meta,
data: Data::Member(Box::new(Some(self))),
included: Default::default(),
jsonapi: Default::default(),
})
}
}
impl Render<Object> for Vec<Object> {
fn render(self, _: Option<&Query>) -> Result<Document<Object>, Error> {
Ok(Document::Ok {
data: Data::Collection(self),
included: Default::default(),
jsonapi: Default::default(),
links: Default::default(),
meta: Default::default(),
})
}
}
impl PrimaryData for Object {
fn flatten(self, incl: &Set<Object>) -> Value {
#[cfg_attr(rustfmt, rustfmt_skip)]
let Object { id, attributes, relationships, .. } = self;
let mut map = {
let size = attributes.len() + relationships.len() + 1;
Map::with_capacity(size)
};
map.insert(Key::from_raw("id".to_owned()), Value::String(id));
map.extend(attributes);
for (key, value) in relationships {
let value = match value.data {
Data::Member(data) => match *data {
Some(item) => item.flatten(incl),
None => Value::Null,
},
Data::Collection(data) => {
let iter = data.into_iter().map(|item| item.flatten(incl));
Value::Array(iter.collect())
}
};
map.insert(key, value);
}
Value::Object(map)
}
}
impl Sealed for Object {}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NewObject {
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub attributes: Map,
pub id: Option<String>,
#[serde(rename = "type")]
pub kind: Key,
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub links: Map<Key, Link>,
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub meta: Map,
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub relationships: Map<Key, Relationship>,
#[serde(skip)]
_ext: (),
}
impl NewObject {
pub fn new(kind: Key) -> Self {
NewObject {
kind,
id: Default::default(),
attributes: Default::default(),
links: Default::default(),
meta: Default::default(),
relationships: Default::default(),
_ext: (),
}
}
}
impl PrimaryData for NewObject {
fn flatten(self, _: &Set<Object>) -> Value {
#[cfg_attr(rustfmt, rustfmt_skip)]
let NewObject { id, attributes, relationships, .. } = self;
let mut map = {
let size = attributes.len() + relationships.len() + 1;
Map::with_capacity(size)
};
if let Some(value) = id {
map.insert(Key::from_raw("id".to_owned()), Value::String(value));
}
map.extend(attributes);
for (key, value) in relationships {
let value = match value.data {
Data::Member(data) => match *data {
Some(Identifier { id, .. }) => Value::String(id),
None => Value::Null,
},
Data::Collection(data) => {
data.into_iter().map(|ident| ident.id).collect()
}
};
map.insert(key, value);
}
Value::Object(map)
}
}
impl Render<NewObject> for NewObject {
fn render(self, _: Option<&Query>) -> Result<Document<NewObject>, Error> {
Ok(Document::Ok {
data: Data::Member(Box::new(Some(self))),
included: Default::default(),
jsonapi: Default::default(),
links: Default::default(),
meta: Default::default(),
})
}
}
impl Sealed for NewObject {}