json_ld/core/object/node/
properties.rs1use super::JsonLdObjects;
2use crate::{
3 JsonLdIndexedObject, JsonLdLenient, JsonLdVisit,
4 object::{JsonLdObjectMut, JsonLdObjectRef},
5};
6use btree_indexmap::{BTreeIndexMap, BTreeIndexMultiSet, Comparable};
7use educe::Educe;
8use rdf_syntax::Id;
9use std::hash::Hash;
10
11pub type PropertyObjects = BTreeIndexMultiSet<JsonLdIndexedObject>;
12
13#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16#[cfg_attr(feature = "serde", serde(transparent))]
17pub struct JsonLdProperties(BTreeIndexMap<JsonLdLenient<Id>, PropertyObjects>);
18
19impl Default for JsonLdProperties {
20 fn default() -> Self {
21 Self::new()
22 }
23}
24
25impl JsonLdProperties {
26 pub fn new() -> Self {
28 Self(BTreeIndexMap::new())
29 }
30
31 #[inline(always)]
33 pub fn len(&self) -> usize {
34 self.0.len()
35 }
36
37 #[inline(always)]
39 pub fn is_empty(&self) -> bool {
40 self.0.is_empty()
41 }
42
43 #[inline(always)]
45 pub fn iter(&self) -> JsonLdPropertiesIter<'_> {
46 JsonLdPropertiesIter {
47 inner: self.0.iter(),
48 }
49 }
50
51 #[inline(always)]
53 pub fn iter_mut(&mut self) -> JsonLdPropertiesIterMut<'_> {
54 self.0.iter_mut()
55 }
56
57 #[inline(always)]
59 pub fn clear(&mut self) {
60 self.0.clear()
61 }
62
63 #[inline(always)]
65 pub fn contains<Q: ?Sized + Hash + Comparable<JsonLdLenient<Id>>>(&self, prop: &Q) -> bool {
66 self.0.get(prop).is_some()
67 }
68
69 #[inline(always)]
71 pub fn count<Q: ?Sized + Hash + Comparable<JsonLdLenient<Id>>>(&self, prop: &Q) -> usize {
72 self.0
73 .get(prop)
74 .map(BTreeIndexMultiSet::len)
75 .unwrap_or_default()
76 }
77
78 #[inline(always)]
80 pub fn get<Q: ?Sized + Hash + Comparable<JsonLdLenient<Id>>>(
81 &self,
82 prop: &Q,
83 ) -> JsonLdObjects<'_> {
84 match self.0.get(prop) {
85 Some(values) => JsonLdObjects::new(Some(values.iter())),
86 None => JsonLdObjects::new(None),
87 }
88 }
89
90 #[inline(always)]
94 pub fn get_any<Q: ?Sized + Hash + Comparable<JsonLdLenient<Id>>>(
95 &self,
96 prop: &Q,
97 ) -> Option<&JsonLdIndexedObject> {
98 match self.0.get(prop) {
99 Some(values) => values.iter().next(),
100 None => None,
101 }
102 }
103
104 #[inline(always)]
106 pub fn insert(&mut self, prop: impl Into<JsonLdLenient<Id>>, value: JsonLdIndexedObject) {
107 let prop = prop.into();
108 if let Some(node_values) = self.0.get_mut(&prop) {
109 node_values.insert(value);
110 } else {
111 self.0.insert(prop, BTreeIndexMultiSet::singleton(value));
112 }
113 }
114
115 #[inline(always)]
117 pub fn insert_unique(
118 &mut self,
119 prop: impl Into<JsonLdLenient<Id>>,
120 value: JsonLdIndexedObject,
121 ) {
122 let prop = prop.into();
123 if let Some(node_values) = self.0.get_mut(&prop) {
124 if node_values.iter().all(|v| !v.equivalent(&value)) {
125 node_values.insert(value);
126 }
127 } else {
128 self.0.insert(prop, BTreeIndexMultiSet::singleton(value));
129 }
130 }
131
132 #[inline(always)]
134 pub fn insert_all<Objects: IntoIterator<Item = JsonLdIndexedObject>>(
135 &mut self,
136 prop: impl Into<JsonLdLenient<Id>>,
137 values: Objects,
138 ) {
139 let prop = prop.into();
140 if let Some(node_values) = self.0.get_mut(&prop) {
141 node_values.extend(values);
142 } else {
143 self.0.insert(prop, values.into_iter().collect());
144 }
145 }
146
147 #[inline(always)]
151 pub fn insert_all_unique<Objects: IntoIterator<Item = JsonLdIndexedObject>>(
152 &mut self,
153 prop: JsonLdLenient<Id>,
154 values: Objects,
155 ) {
156 if let Some(node_values) = self.0.get_mut(&prop) {
157 for value in values {
158 if node_values.iter().all(|v| !v.equivalent(&value)) {
159 node_values.insert(value);
160 }
161 }
162 } else {
163 let values = values.into_iter();
164 let mut node_values: PropertyObjects =
165 BTreeIndexMultiSet::with_capacity(values.size_hint().0);
166 for value in values {
167 if node_values.iter().all(|v| !v.equivalent(&value)) {
168 node_values.insert(value);
169 }
170 }
171
172 self.0.insert(prop, node_values);
173 }
174 }
175
176 pub fn set(&mut self, prop: impl Into<JsonLdLenient<Id>>, values: PropertyObjects) {
177 let prop = prop.into();
178 self.0.insert(prop, values);
179 }
180
181 pub fn extend_unique<I, O>(&mut self, iter: I)
182 where
183 I: IntoIterator<Item = (JsonLdLenient<Id>, O)>,
184 O: IntoIterator<Item = JsonLdIndexedObject>,
185 {
186 for (prop, values) in iter {
187 self.insert_all_unique(prop, values)
188 }
189 }
190
191 #[inline(always)]
193 pub fn remove<Q: ?Sized + Hash + Comparable<JsonLdLenient<Id>>>(
194 &mut self,
195 prop: &Q,
196 ) -> Option<PropertyObjects> {
197 self.0.swap_remove(prop)
198 }
199}
200
201impl JsonLdVisit for JsonLdProperties {
202 fn visit_with(&self, f: &mut impl FnMut(JsonLdObjectRef)) {
203 for (_, t) in self {
204 t.visit_with(&mut *f);
205 }
206 }
207
208 fn visit_mut_with(&mut self, f: &mut impl FnMut(JsonLdObjectMut)) {
209 for (_, values) in self {
210 values.visit_mut_with(f);
211 }
212 }
213}
214
215impl<O> FromIterator<(JsonLdLenient<Id>, O)> for JsonLdProperties
216where
217 O: IntoIterator<Item = JsonLdIndexedObject>,
218{
219 fn from_iter<I: IntoIterator<Item = (JsonLdLenient<Id>, O)>>(iter: I) -> Self {
220 let mut result = Self::default();
221 for (id, values) in iter {
222 result.insert_all(id, values);
223 }
224 result
225 }
226}
227
228impl Extend<(JsonLdLenient<Id>, Vec<JsonLdIndexedObject>)> for JsonLdProperties {
229 fn extend<I>(&mut self, iter: I)
230 where
231 I: IntoIterator<Item = (JsonLdLenient<Id>, Vec<JsonLdIndexedObject>)>,
232 {
233 for (prop, values) in iter {
234 self.insert_all(prop, values)
235 }
236 }
237}
238
239pub type JsonLdBinding = (JsonLdLenient<Id>, PropertyObjects);
242
243pub type JsonLdBindingRef<'a> = (&'a JsonLdLenient<Id>, &'a [JsonLdIndexedObject]);
246
247pub type JsonLdBindingMut<'a> = (&'a JsonLdLenient<Id>, &'a mut PropertyObjects);
250
251impl IntoIterator for JsonLdProperties {
252 type Item = JsonLdBinding;
253 type IntoIter = JsonLdPropertiesIntoIter;
254
255 #[inline(always)]
256 fn into_iter(self) -> Self::IntoIter {
257 self.0.into_iter()
258 }
259}
260
261impl<'a> IntoIterator for &'a JsonLdProperties {
262 type Item = JsonLdBindingRef<'a>;
263 type IntoIter = JsonLdPropertiesIter<'a>;
264
265 #[inline(always)]
266 fn into_iter(self) -> Self::IntoIter {
267 self.iter()
268 }
269}
270
271impl<'a> IntoIterator for &'a mut JsonLdProperties {
272 type Item = JsonLdBindingMut<'a>;
273 type IntoIter = JsonLdPropertiesIterMut<'a>;
274
275 #[inline(always)]
276 fn into_iter(self) -> Self::IntoIter {
277 self.iter_mut()
278 }
279}
280
281pub type JsonLdPropertiesIntoIter = std::vec::IntoIter<(JsonLdLenient<Id>, PropertyObjects)>;
285
286#[derive(Educe)]
290#[educe(Clone)]
291pub struct JsonLdPropertiesIter<'a> {
292 inner: btree_indexmap::map::Iter<'a, JsonLdLenient<Id>, PropertyObjects>,
293}
294
295impl<'a> Iterator for JsonLdPropertiesIter<'a> {
296 type Item = JsonLdBindingRef<'a>;
297
298 #[inline(always)]
299 fn size_hint(&self) -> (usize, Option<usize>) {
300 self.inner.size_hint()
301 }
302
303 #[inline(always)]
304 fn next(&mut self) -> Option<Self::Item> {
305 self.inner
306 .next()
307 .map(|(property, objects)| (property, objects.as_slice()))
308 }
309}
310
311impl<'a> ExactSizeIterator for JsonLdPropertiesIter<'a> {}
312
313impl<'a> std::iter::FusedIterator for JsonLdPropertiesIter<'a> {}
314
315pub type JsonLdPropertiesIterMut<'a> =
320 btree_indexmap::map::IterMut<'a, JsonLdLenient<Id>, PropertyObjects>;