1use super::{Multiset, Objects};
2use crate::{
3 DefaultBuildHasher,
4 Id,
5 IndexMap,
6 IndexedObject,
7 object::{InvalidExpandedJson, TryFromJson, TryFromJsonObject},
8};
9use derive_where::derive_where;
10use rdfx::vocabulary::VocabularyMut;
11use std::hash::{Hash, Hasher};
12
13pub type PropertyObjects<T, B> = Multiset<IndexedObject<T, B>>;
15
16#[derive(Debug, Clone)]
18#[derive_where(PartialEq; T: Eq + Hash, B: Eq + Hash)]
19pub struct Properties<T, B>(IndexMap<Id<T, B>, PropertyObjects<T, B>>);
20
21impl<T: Eq + Hash, B: Eq + Hash> Eq for Properties<T, B> {}
22
23impl<T, B> Default for Properties<T, B> {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl<T, B> Properties<T, B> {
30 #[must_use]
32 pub fn new() -> Self {
33 Self(IndexMap::with_hasher(DefaultBuildHasher::default()))
34 }
35
36 #[inline(always)]
38 #[must_use]
39 pub fn len(&self) -> usize {
40 self.0.len()
41 }
42
43 #[inline(always)]
45 #[must_use]
46 pub fn is_empty(&self) -> bool {
47 self.0.is_empty()
48 }
49
50 #[inline(always)]
52 #[must_use]
53 pub fn iter(&self) -> Iter<'_, T, B> {
54 Iter { inner: self.0.iter() }
55 }
56
57 #[inline(always)]
59 pub fn iter_mut(&mut self) -> IterMut<'_, T, B> {
60 self.0.iter_mut()
61 }
62
63 #[inline(always)]
65 pub fn clear(&mut self) {
66 self.0.clear();
67 }
68}
69
70impl<T: Eq + Hash, B: Eq + Hash> Properties<T, B> {
71 #[inline(always)]
73 pub fn contains<Q: ?Sized + Hash + indexmap::Equivalent<Id<T, B>>>(&self, prop: &Q) -> bool {
74 self.0.get(prop).is_some()
75 }
76
77 #[inline(always)]
79 pub fn get<Q: ?Sized + Hash + indexmap::Equivalent<Id<T, B>>>(&self, prop: &Q) -> Objects<'_, T, B> {
80 match self.0.get(prop) {
81 Some(values) => Objects::new(Some(values.iter())),
82 None => Objects::new(None),
83 }
84 }
85
86 #[inline(always)]
91 pub fn get_any<Q: ?Sized + Hash + indexmap::Equivalent<Id<T, B>>>(&self, prop: &Q) -> Option<&IndexedObject<T, B>> {
92 match self.0.get(prop) {
93 Some(values) => values.iter().next(),
94 None => None,
95 }
96 }
97
98 #[inline(always)]
100 pub fn insert(&mut self, prop: Id<T, B>, value: IndexedObject<T, B>) {
101 if let Some(node_values) = self.0.get_mut(&prop) {
102 node_values.insert(value);
103 } else {
104 self.0.insert(prop, Multiset::singleton(value));
105 }
106 }
107
108 #[inline(always)]
110 pub fn insert_unique(&mut self, prop: Id<T, B>, value: IndexedObject<T, B>) {
111 if let Some(node_values) = self.0.get_mut(&prop) {
112 if node_values.iter().all(|v| !v.equivalent(&value)) {
113 node_values.insert(value);
114 }
115 } else {
116 self.0.insert(prop, Multiset::singleton(value));
117 }
118 }
119
120 #[inline(always)]
122 pub fn insert_all<Objects: IntoIterator<Item = IndexedObject<T, B>>>(&mut self, prop: Id<T, B>, values: Objects) {
123 if let Some(node_values) = self.0.get_mut(&prop) {
124 node_values.extend(values);
125 } else {
126 let mut iter = values.into_iter();
129 match (iter.next(), iter.size_hint()) {
130 (Some(first), (0, Some(0))) => {
131 self.0.insert(prop, Multiset::singleton(first));
132 }
133 (Some(first), _) => {
134 let mut multiset: PropertyObjects<T, B> = Multiset::singleton(first);
135 multiset.extend(iter);
136 self.0.insert(prop, multiset);
137 }
138 (None, _) => {
139 self.0.insert(prop, Multiset::default());
140 }
141 }
142 }
143 }
144
145 #[inline(always)]
149 pub fn insert_all_unique<Objects: IntoIterator<Item = IndexedObject<T, B>>>(&mut self, prop: Id<T, B>, values: Objects) {
150 if let Some(node_values) = self.0.get_mut(&prop) {
151 for value in values {
152 if node_values.iter().all(|v| !v.equivalent(&value)) {
153 node_values.insert(value);
154 }
155 }
156 } else {
157 let values = values.into_iter();
158 let mut node_values: PropertyObjects<T, B> = Multiset::with_capacity(values.size_hint().0);
159 for value in values {
160 if node_values.iter().all(|v| !v.equivalent(&value)) {
161 node_values.insert(value);
162 }
163 }
164
165 self.0.insert(prop, node_values);
166 }
167 }
168
169 pub fn set(&mut self, prop: Id<T, B>, values: PropertyObjects<T, B>) {
171 self.0.insert(prop, values);
172 }
173
174 pub fn extend_unique<I, O>(&mut self, iter: I)
177 where
178 I: IntoIterator<Item = (Id<T, B>, O)>,
179 O: IntoIterator<Item = IndexedObject<T, B>>,
180 {
181 for (prop, values) in iter {
182 self.insert_all_unique(prop, values);
183 }
184 }
185
186 #[inline(always)]
188 pub fn remove<Q: ?Sized + Hash + indexmap::Equivalent<Id<T, B>>>(&mut self, prop: &Q) -> Option<PropertyObjects<T, B>> {
189 self.0.shift_remove(prop)
190 }
191}
192
193impl<T: Eq + Hash, B: Eq + Hash, O> FromIterator<(Id<T, B>, O)> for Properties<T, B>
194where
195 O: IntoIterator<Item = IndexedObject<T, B>>,
196{
197 fn from_iter<I: IntoIterator<Item = (Id<T, B>, O)>>(iter: I) -> Self {
198 let mut result = Self::default();
199 for (id, values) in iter {
200 result.insert_all(id, values);
201 }
202 result
203 }
204}
205
206impl<T: Eq + Hash, B: Eq + Hash> TryFromJson<T, B> for Properties<T, B> {
207 fn try_from_json_in(vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>, value: jstrict::Value) -> Result<Self, InvalidExpandedJson> {
208 match value {
209 jstrict::Value::Object(object) => Self::try_from_json_object_in(vocabulary, object),
210 _ => Err(InvalidExpandedJson::InvalidObject),
211 }
212 }
213}
214
215impl<T: Eq + Hash, B: Eq + Hash> TryFromJsonObject<T, B> for Properties<T, B> {
216 fn try_from_json_object_in(vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>, object: jstrict::Object) -> Result<Self, InvalidExpandedJson> {
217 let mut result = Self::new();
218
219 for entry in object {
220 let prop = Id::from_string_in(vocabulary, entry.key.to_string());
221 let objects: Vec<IndexedObject<T, B>> = Vec::try_from_json_in(vocabulary, entry.value)?;
222 result.insert_all(prop, objects);
223 }
224
225 Ok(result)
226 }
227}
228
229impl<T: Hash, B: Hash> Hash for Properties<T, B> {
230 #[inline(always)]
231 fn hash<H: Hasher>(&self, h: &mut H) {
232 crate::utils::hash_map(&self.0, h);
233 }
234}
235
236impl<T: Eq + Hash, B: Eq + Hash> Extend<(Id<T, B>, Vec<IndexedObject<T, B>>)> for Properties<T, B> {
237 fn extend<I>(&mut self, iter: I)
238 where
239 I: IntoIterator<Item = (Id<T, B>, Vec<IndexedObject<T, B>>)>,
240 {
241 for (prop, values) in iter {
242 self.insert_all(prop, values);
243 }
244 }
245}
246
247pub type Binding<T, B> = (Id<T, B>, PropertyObjects<T, B>);
250
251pub type BindingRef<'a, T, B> = (&'a Id<T, B>, &'a [IndexedObject<T, B>]);
254
255pub type BindingMut<'a, T, B> = (&'a Id<T, B>, &'a mut PropertyObjects<T, B>);
258
259impl<T, B> IntoIterator for Properties<T, B> {
260 type Item = Binding<T, B>;
261 type IntoIter = IntoIter<T, B>;
262
263 #[inline(always)]
264 fn into_iter(self) -> Self::IntoIter {
265 self.0.into_iter()
266 }
267}
268
269impl<'a, T, B> IntoIterator for &'a Properties<T, B> {
270 type Item = BindingRef<'a, T, B>;
271 type IntoIter = Iter<'a, T, B>;
272
273 #[inline(always)]
274 fn into_iter(self) -> Self::IntoIter {
275 self.iter()
276 }
277}
278
279impl<'a, T, B> IntoIterator for &'a mut Properties<T, B> {
280 type Item = BindingMut<'a, T, B>;
281 type IntoIter = IterMut<'a, T, B>;
282
283 #[inline(always)]
284 fn into_iter(self) -> Self::IntoIter {
285 self.iter_mut()
286 }
287}
288
289pub type IntoIter<T, B> = indexmap::map::IntoIter<Id<T, B>, PropertyObjects<T, B>>;
293
294#[derive_where(Clone)]
298pub struct Iter<'a, T, B> {
299 inner: indexmap::map::Iter<'a, Id<T, B>, PropertyObjects<T, B>>,
300}
301
302impl<'a, T, B> Iterator for Iter<'a, T, B> {
303 type Item = BindingRef<'a, T, B>;
304
305 #[inline(always)]
306 fn size_hint(&self) -> (usize, Option<usize>) {
307 self.inner.size_hint()
308 }
309
310 #[inline(always)]
311 fn next(&mut self) -> Option<Self::Item> {
312 self.inner.next().map(|(property, objects)| (property, objects.as_slice()))
313 }
314}
315
316impl<T, B> ExactSizeIterator for Iter<'_, T, B> {}
317
318impl<T, B> std::iter::FusedIterator for Iter<'_, T, B> {}
319
320pub type IterMut<'a, T, B> = indexmap::map::IterMut<'a, Id<T, B>, PropertyObjects<T, B>>;