1use std::cmp::{Eq, PartialEq};
2use std::hash::{Hash, Hasher};
3use std::mem;
4
5use doc::{Data, Document, Object, PrimaryData};
6use error::Error;
7use query::Query;
8use sealed::Sealed;
9use value::{Key, Map, Set, Value};
10use view::Render;
11
12#[derive(Clone, Debug, Deserialize, Serialize)]
23pub struct Identifier {
24 pub id: String,
30
31 #[serde(rename = "type")]
38 pub kind: Key,
39
40 #[serde(default, skip_serializing_if = "Map::is_empty")]
46 pub meta: Map,
47
48 #[serde(skip)]
50 _ext: (),
51}
52
53impl Identifier {
54 pub fn new(kind: Key, id: String) -> Self {
74 Identifier {
75 id,
76 kind,
77 meta: Default::default(),
78 _ext: (),
79 }
80 }
81}
82
83impl Eq for Identifier {}
84
85impl From<Object> for Identifier {
86 fn from(object: Object) -> Self {
87 let Object { id, kind, meta, .. } = object;
88 let mut ident = Identifier::new(kind, id);
89
90 ident.meta = meta;
91 ident
92 }
93}
94
95impl<'a> From<&'a Object> for Identifier {
96 fn from(object: &'a Object) -> Self {
97 object.clone().into()
98 }
99}
100
101impl Hash for Identifier {
102 fn hash<H: Hasher>(&self, state: &mut H) {
103 self.id.hash(state);
104 self.kind.hash(state);
105 }
106}
107
108impl PartialEq for Identifier {
109 fn eq(&self, rhs: &Identifier) -> bool {
110 self.id == rhs.id && self.kind == rhs.kind
111 }
112}
113
114impl PartialEq<Object> for Identifier {
115 fn eq(&self, rhs: &Object) -> bool {
116 self.id == rhs.id && self.kind == rhs.kind
117 }
118}
119
120impl Render<Identifier> for Identifier {
121 fn render(mut self, _: Option<&Query>) -> Result<Document<Identifier>, Error> {
122 let meta = mem::replace(&mut self.meta, Default::default());
123
124 Ok(Document::Ok {
125 meta,
126 data: Data::Member(Box::new(Some(self))),
127 included: Default::default(),
128 jsonapi: Default::default(),
129 links: Default::default(),
130 })
131 }
132}
133
134impl Render<Identifier> for Vec<Identifier> {
135 fn render(self, _: Option<&Query>) -> Result<Document<Identifier>, Error> {
136 Ok(Document::Ok {
137 data: Data::Collection(self),
138 included: Default::default(),
139 jsonapi: Default::default(),
140 links: Default::default(),
141 meta: Default::default(),
142 })
143 }
144}
145
146impl PrimaryData for Identifier {
147 fn flatten(self, incl: &Set<Object>) -> Value {
148 incl.into_iter()
149 .find(|item| self == **item)
150 .map(|item| item.clone().flatten(incl))
151 .unwrap_or_else(|| self.id.clone().into())
152 }
153}
154
155impl Sealed for Identifier {}