Skip to main content

ratio_metadata/
store.rs

1//! # Main metadata store module
2//!
3//! This module contains the main data store containing the different field stores, as well as
4//! types and builders to perform transactions to the underlying store.
5//!
6//! ## License
7//!
8//! This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
9//! If a copy of the MPL was not distributed with this file,
10//! You can obtain one at <https://mozilla.org/MPL/2.0/>.
11//!
12//! **Code examples both in the docstrings and rendered documentation are free to use.**
13
14use std::borrow::Cow;
15use std::collections::{BTreeMap, BTreeSet};
16use std::fmt::Debug;
17
18use slotmap::{Key, new_key_type};
19use snafu::prelude::*;
20use uuid::Uuid;
21
22use crate::aggregate::Aggregate;
23use crate::category::Category;
24use crate::interner::{DenseSlottedBTreeInterner, Interner, ValueAlreadyExistsSnafu};
25use crate::metadata::{AnnotationValue, Field, Metadata, MetadataRef, WeightValue};
26use crate::transaction::{Transaction, TransactionMode};
27
28/// Metadata store error.
29#[derive(Clone, Debug, Snafu)]
30#[snafu(visibility(pub))]
31pub enum Error {
32    /// Field name interner error.
33    InternerError { source: crate::interner::Error },
34}
35
36new_key_type! {
37    /// Unique object key type.
38    pub struct ObjectKey;
39
40    /// Unique name key type.
41    pub struct NameKey;
42
43    /// Unique kind key type.
44    pub struct KindKey;
45
46    /// Unique label key type.
47    pub struct LabelKey;
48
49    /// Unique weight key type.
50    pub struct WeightKey;
51
52    /// Unique annotation key type.
53    pub struct AnnotationKey;
54}
55
56/// Store type for names.
57pub type NameStore<ObjKey, Name> = Category<ObjKey, NameKey, NameKey, Name>;
58
59/// Store type for kinds.
60pub type KindStore<ObjKey, Kind> = Category<ObjKey, KindKey, KindKey, Kind>;
61
62/// Store type for label sets.
63pub type LabelStore<ObjKey, Label> = Category<ObjKey, BTreeSet<LabelKey>, LabelKey, Label>;
64
65/// Store type for weight mappings.
66pub type WeightStore<ObjKey, Weight, Value> =
67    Category<ObjKey, BTreeMap<WeightKey, Value>, WeightKey, Weight>;
68
69/// Store type for annotation mappings.
70pub type AnnotationStore<ObjKey, Annotation, SubValue> =
71    Category<ObjKey, BTreeMap<AnnotationKey, SubValue>, AnnotationKey, Annotation>;
72
73/// Metadata store for simplified metadata.
74pub type SimpleStore =
75    MetadataStore<ObjectKey, String, String, String, String, f64, String, serde_json::Value>;
76
77/// Metadata store that holds metadata for externally defined objects.
78#[derive(Clone, Debug, bon::Builder)]
79#[cfg_attr(
80    feature = "serde",
81    derive(serde::Serialize, serde::Deserialize),
82    serde(default, rename_all = "camelCase")
83)]
84#[cfg_attr(feature = "reactive", derive(reactive_stores::Store))]
85pub struct MetadataStore<ObjKey, N, K, L, W, WV, A, AV>
86where
87    ObjKey: Key,
88    N: Field,
89    K: Field,
90    L: Field,
91    W: Field,
92    WV: WeightValue,
93    A: Field,
94    AV: AnnotationValue,
95{
96    /// ID mapping for external object identification.
97    ids: DenseSlottedBTreeInterner<ObjKey, Uuid>,
98
99    /// Name metadata store.
100    names: NameStore<ObjKey, N>,
101
102    /// Kind metadata store.
103    kinds: KindStore<ObjKey, K>,
104
105    /// Label metadata store.
106    labels: LabelStore<ObjKey, L>,
107
108    /// Weight metadata store.
109    weights: WeightStore<ObjKey, W, WV>,
110
111    /// Annotation metadata store.
112    annotations: AnnotationStore<ObjKey, A, AV>,
113}
114
115impl<ObjKey, N, K, L, W, WV, A, AV> Default for MetadataStore<ObjKey, N, K, L, W, WV, A, AV>
116where
117    ObjKey: Key,
118    N: Field,
119    K: Field,
120    L: Field,
121    W: Field,
122    WV: WeightValue,
123    A: Field,
124    AV: AnnotationValue,
125{
126    fn default() -> Self {
127        Self {
128            ids: Default::default(),
129            names: Default::default(),
130            kinds: Default::default(),
131            labels: Default::default(),
132            weights: Default::default(),
133            annotations: Default::default(),
134        }
135    }
136}
137
138impl<ObjKey, N, K, L, W, WV, A, AV> MetadataStore<ObjKey, N, K, L, W, WV, A, AV>
139where
140    ObjKey: Key,
141    N: Field,
142    K: Field,
143    L: Field,
144    W: Field,
145    WV: WeightValue,
146    A: Field,
147    AV: AnnotationValue,
148{
149    /// Create a new metadata store.
150    pub fn new() -> Self {
151        Self::default()
152    }
153
154    /// The number of objects in store.
155    pub fn len(&self) -> usize {
156        self.ids.len()
157    }
158
159    /// Whether this store is empty.
160    pub fn is_empty(&self) -> bool {
161        self.len() == 0
162    }
163
164    /// Add an object to the store by registering an ID for it.
165    /// Returns the internally used key as well as the ID itself.
166    pub fn add(&mut self) -> (ObjKey, Uuid) {
167        let id = Uuid::new_v4();
168        (self.intern_id(Cow::Borrowed(&id)), id)
169    }
170
171    /// Add a specific ID to the store.
172    pub fn intern_id(&mut self, id: Cow<'_, Uuid>) -> ObjKey {
173        self.ids.intern(id)
174    }
175
176    /// Try to insert a metadata object, returns an error if the ID already exists.
177    pub fn try_insert(&mut self, meta: Metadata<N, K, L, W, WV, A, AV>) -> Result<ObjKey, Error> {
178        let obj = self
179            .ids
180            .try_intern(Cow::Borrowed(&meta.id))
181            .context(InternerSnafu)?;
182
183        self.insert(meta);
184
185        Ok(obj)
186    }
187
188    /// Insert a metadata object. Overrides any existing metadata.
189    pub fn insert(&mut self, meta: Metadata<N, K, L, W, WV, A, AV>) -> ObjKey {
190        let id = self.ids.intern_borrowed(&meta.id);
191
192        let mut tx = meta.as_replace_transaction();
193        tx.strip_id();
194
195        self.apply(id, tx);
196
197        id
198    }
199
200    /// Apply a transaction to an object using named metadata fields.
201    /// Raises an error if the ID does not exist and when the new ID as supplied in the transaction
202    /// already exists for another object.
203    pub fn try_apply<Id: AsRef<Uuid>>(
204        &mut self,
205        id: Id,
206        tx: Transaction<N, K, L, W, WV, A, AV>,
207    ) -> Result<(), Error> {
208        let obj = self.ids.try_get_key(id.as_ref()).context(InternerSnafu)?;
209
210        if let Some(new_id) = tx.id.as_ref()
211            && self.ids.get_key(new_id).as_ref() != Some(&obj)
212        {
213            ValueAlreadyExistsSnafu.fail().context(InternerSnafu)?;
214        }
215
216        self.apply(obj, tx);
217
218        Ok(())
219    }
220
221    /// Apply a transaction to an object using named metadata fields.
222    /// Assumes any potential ID update is valid.
223    pub fn apply(&mut self, obj: ObjKey, tx: Transaction<N, K, L, W, WV, A, AV>) {
224        let Transaction {
225            mode,
226            id: new_id,
227            name,
228            kind,
229            labels,
230            weights,
231            annotations,
232        } = tx;
233
234        if let Some(new_id) = new_id
235            && self.ids.get_key(&new_id).as_ref() != Some(&obj)
236        {
237            self.ids.remove_key(obj);
238            self.ids.intern_owned(new_id);
239        }
240
241        // stored as option values internally
242        if name.is_some() {
243            self.names
244                .set_value_name_of_object(obj, name.map(Cow::Owned));
245        }
246
247        // stored as option values internally
248        if kind.is_some() {
249            self.kinds
250                .set_value_name_of_object(obj, kind.map(Cow::Owned));
251        }
252
253        if let Some(labels) = labels {
254            if matches!(mode, TransactionMode::Replace) {
255                self.labels.remove_object(obj);
256            }
257            labels.into_iter().for_each(|label| {
258                self.labels
259                    .insert_field_name_for_object(obj, Cow::Owned(label));
260            });
261        }
262
263        if let Some(weights) = weights {
264            if matches!(mode, TransactionMode::Replace) {
265                self.weights.remove_object(obj);
266            }
267            weights.into_iter().for_each(|(k, v)| {
268                self.weights
269                    .insert_field_name_value_for_object(obj, Cow::Owned(k), v);
270            });
271        }
272
273        if let Some(annotations) = annotations {
274            if matches!(mode, TransactionMode::Replace) {
275                self.annotations.remove_object(obj);
276            }
277            annotations.into_iter().for_each(|(k, v)| {
278                self.annotations
279                    .insert_field_name_value_for_object(obj, Cow::Owned(k), v);
280            });
281        };
282    }
283
284    /// Apply a transaction to an object based on internal keys representing metadata fields.
285    /// Raises an error if a potential new ID as supplied in the transaction already exists
286    /// for another object.
287    pub fn try_apply_keyed(
288        &mut self,
289        obj: ObjKey,
290        tx: Transaction<NameKey, KindKey, LabelKey, WeightKey, WV, AnnotationKey, AV>,
291    ) -> Result<(), Error> {
292        if let Some(new_id) = tx.id.as_ref()
293            && self.ids.get_key(new_id).as_ref() != Some(&obj)
294        {
295            ValueAlreadyExistsSnafu.fail().context(InternerSnafu)?;
296        }
297
298        self.apply_keyed(obj, tx);
299
300        Ok(())
301    }
302
303    /// Apply a transaction to an object based on internal keys representing metadata field.
304    /// Assumes any potential ID update is valid.
305    pub fn apply_keyed(
306        &mut self,
307        obj: ObjKey,
308        tx: Transaction<NameKey, KindKey, LabelKey, WeightKey, WV, AnnotationKey, AV>,
309    ) {
310        let Transaction {
311            mode,
312            id: new_id,
313            name,
314            kind,
315            labels,
316            weights,
317            annotations,
318        } = tx;
319
320        if let Some(new_id) = new_id
321            && self.ids.get_key(&new_id).as_ref() != Some(&obj)
322        {
323            self.ids.remove_key(obj);
324            self.ids.intern_owned(new_id);
325        }
326
327        // stored as option values internally
328        if let Some(name) = name {
329            self.set_object_name_key(obj, name);
330        }
331
332        // stored as option values internally
333        if let Some(kind) = kind {
334            self.set_object_kind_key(obj, kind);
335        }
336
337        if let Some(labels) = labels {
338            if matches!(mode, TransactionMode::Replace) {
339                self.labels.remove_object(obj);
340            }
341            labels.into_iter().for_each(|label| {
342                self.set_object_label_key(obj, label);
343            });
344        }
345
346        if let Some(weights) = weights {
347            if matches!(mode, TransactionMode::Replace) {
348                self.weights.remove_object(obj);
349            }
350            weights.into_iter().for_each(|(k, v)| {
351                self.set_object_weight_key(obj, k, v);
352            });
353        }
354
355        if let Some(annotations) = annotations {
356            if matches!(mode, TransactionMode::Replace) {
357                self.annotations.remove_object(obj);
358            }
359            annotations.into_iter().for_each(|(k, v)| {
360                self.set_object_annotation_key(obj, k, v);
361            });
362        };
363    }
364
365    /// Intern a name. Returns the internally used key for that name.
366    pub fn intern_name(&mut self, name: Cow<'_, N>) -> NameKey {
367        self.names.field_key(name)
368    }
369
370    /// Forget a name entirely. Removes it from any object it was attached to.
371    pub fn forget_name(&mut self, name: &N) -> Option<NameKey> {
372        self.names.remove_field_name(name)
373    }
374
375    /// Forget a name entirely (by key). Removes it from any object it was attached to.
376    pub fn forget_name_key(&mut self, name: NameKey) -> Option<N> {
377        self.names.remove_field(name)
378    }
379
380    /// Apply a name to an object.
381    pub fn set_object_name<Id: AsRef<Uuid>>(&mut self, id: Id, name: &N) {
382        let obj = self.intern_id(Cow::Borrowed(id.as_ref()));
383        let value = self.intern_name(Cow::Borrowed(name));
384        self.set_object_name_key(obj, value);
385    }
386
387    /// Apply a name to an object using internally used keys.
388    pub fn set_object_name_key(&mut self, obj: ObjKey, name: NameKey) {
389        self.names.insert_object_value(obj, name);
390    }
391
392    /// Strip an objects name value.
393    pub fn remove_object_name<Id: AsRef<Uuid>>(&mut self, id: Id) -> Option<&N> {
394        let obj = self.ids.get_key(id.as_ref())?;
395        self.remove_object_name_key(obj)
396            .and_then(|key| self.names.field_name(key))
397    }
398
399    /// Strip an objects name value by means of the internally used keys.
400    pub fn remove_object_name_key(&mut self, obj: ObjKey) -> Option<NameKey> {
401        self.names.remove_object(obj)
402    }
403
404    /// Intern a kind. Returns the internally used key for that kind.
405    pub fn intern_kind(&mut self, kind: Cow<K>) -> KindKey {
406        self.kinds.field_key(kind)
407    }
408
409    /// Forget a kind entirely. Removes it from any object it was attached to.
410    pub fn forget_kind(&mut self, kind: &K) -> Option<KindKey> {
411        self.kinds.remove_field_name(kind)
412    }
413
414    /// Forget a kind entirely (by key). Removes it from any object it was attached to.
415    pub fn forget_kind_key(&mut self, kind: KindKey) -> Option<K> {
416        self.kinds.remove_field(kind)
417    }
418
419    /// Apply a kind to an object.
420    pub fn set_object_kind<Id: AsRef<Uuid>>(&mut self, id: Id, kind: &K) {
421        let obj = self.intern_id(Cow::Borrowed(id.as_ref()));
422        let value = self.intern_kind(Cow::Borrowed(kind));
423        self.set_object_kind_key(obj, value);
424    }
425
426    /// Apply a kind to an object using internally used keys.
427    pub fn set_object_kind_key(&mut self, obj: ObjKey, kind: KindKey) {
428        self.kinds.insert_object_value(obj, kind);
429    }
430
431    /// Strip an object's kind value.
432    pub fn remove_object_kind<Id: AsRef<Uuid>>(&mut self, id: Id) -> Option<&K> {
433        let obj = self.ids.get_key(id.as_ref())?;
434        self.remove_object_kind_key(obj)
435            .and_then(|key| self.kinds.field_name(key))
436    }
437
438    /// Strip an object's kind value by means of the internally used keys.
439    pub fn remove_object_kind_key(&mut self, obj: ObjKey) -> Option<KindKey> {
440        self.kinds.remove_object(obj)
441    }
442
443    /// Intern a label. Returns the internally used key for that label.
444    pub fn intern_label(&mut self, label: Cow<L>) -> LabelKey {
445        self.labels.field_key(label)
446    }
447
448    /// Forget a label entirely. Removes it from any object it was attached to.
449    pub fn forget_label(&mut self, label: &L) -> Option<LabelKey> {
450        self.labels.remove_field_name(label)
451    }
452
453    /// Forget a label entirely (by key). Removes it from any object it was attached to.
454    pub fn forget_label_key(&mut self, label: LabelKey) -> Option<L> {
455        self.labels.remove_field(label)
456    }
457
458    /// Apply a label to an object.
459    pub fn set_object_label<Id: AsRef<Uuid>>(&mut self, id: Id, label: &L) {
460        let obj = self.intern_id(Cow::Borrowed(id.as_ref()));
461        self.labels
462            .insert_field_name_for_object(obj, Cow::Borrowed(label));
463    }
464
465    /// Apply a label to an object by using internally used keys.
466    pub fn set_object_label_key(&mut self, obj: ObjKey, label: LabelKey) {
467        self.labels.insert_field_for_object(obj, label);
468    }
469
470    /// Strip a label from an object.
471    pub fn remove_object_label<Id: AsRef<Uuid>>(&mut self, id: Id, label: &L) {
472        if let Some(obj) = self.ids.get_key(id.as_ref()) {
473            self.labels.remove_field_name_from_object(obj, label);
474        }
475    }
476
477    /// Strip a label from an object by using internally used keys.
478    pub fn strip_label_key(&mut self, obj: ObjKey, label: LabelKey) {
479        self.labels.remove_field_from_object(obj, label);
480    }
481
482    /// Intern a weight. Returns the internally used key.
483    pub fn intern_weight(&mut self, weight: Cow<W>) -> WeightKey {
484        self.weights.field_key(weight)
485    }
486
487    /// Forget a weight field entirely. Removes it from any object it was attached to.
488    /// Returns forgotten object-value pairs.
489    pub fn forget_weight(&mut self, weight: &W) -> Option<WeightKey> {
490        self.weights.remove_field_name_values(weight)
491    }
492
493    /// Forget a weight field entirely (by key). Removes it from any object it was attached to.
494    /// Returns forgotten object-value pairs.
495    pub fn forget_weight_key(&mut self, weight: WeightKey) -> Option<W> {
496        self.weights.remove_field_values(weight)
497    }
498
499    /// Apply a weight value to an object.
500    /// Returns the previous value if any.
501    pub fn set_object_weight<Id: AsRef<Uuid>>(
502        &mut self,
503        id: Id,
504        weight: &W,
505        value: WV,
506    ) -> Option<WV> {
507        let obj = self.intern_id(Cow::Borrowed(id.as_ref()));
508        self.weights
509            .insert_field_name_value_for_object(obj, Cow::Borrowed(weight), value)
510    }
511
512    /// Apply a weight value to an object using internally used keys.
513    /// Returns the previous value if any.
514    pub fn set_object_weight_key(&mut self, obj: ObjKey, key: WeightKey, value: WV) -> Option<WV> {
515        self.weights.insert_field_value_for_object(obj, key, value)
516    }
517
518    /// Strip a weight value from an object.
519    pub fn remove_object_weight<Id: AsRef<Uuid>>(&mut self, id: Id, weight: &W) -> Option<WV> {
520        self.ids.get_key(id.as_ref()).and_then(|obj| {
521            self.weights
522                .remove_field_name_value_from_object(obj, weight)
523        })
524    }
525
526    /// Strip a weight value from an object using internally used keys.
527    pub fn remove_object_weight_key(&mut self, obj: ObjKey, weight: WeightKey) -> Option<WV> {
528        self.weights.remove_field_value_from_object(obj, weight)
529    }
530
531    /// Intern an annotation. Returns the internally used key.
532    pub fn intern_annotation(&mut self, annotation: Cow<A>) -> AnnotationKey {
533        self.annotations.field_key(annotation)
534    }
535
536    /// Forget an annotation field entirely. Removes it from any object it was attached to.
537    /// Returns forgotten object-value pairs.
538    pub fn forget_annotation(&mut self, annotation: &A) -> Option<AnnotationKey> {
539        self.annotations.remove_field_name_values(annotation)
540    }
541
542    /// Forget an annotation field entirely. Removes it from any object it was attached to.
543    /// Returns forgotten object-value pairs.
544    pub fn forget_annotation_key(&mut self, key: AnnotationKey) -> Option<A> {
545        self.annotations.remove_field_values(key)
546    }
547
548    /// Apply an annotation value to an object.
549    /// Returns the previous value if any.
550    pub fn set_object_annotation<Id: AsRef<Uuid>>(
551        &mut self,
552        id: Id,
553        annotation: &A,
554        value: AV,
555    ) -> Option<AV> {
556        let obj = self.intern_id(Cow::Borrowed(id.as_ref()));
557        self.annotations
558            .insert_field_name_value_for_object(obj, Cow::Borrowed(annotation), value)
559    }
560
561    /// Apply a annotation value to an object using internally used keys.
562    /// Returns the previous value if any.
563    pub fn set_object_annotation_key(
564        &mut self,
565        obj: ObjKey,
566        key: AnnotationKey,
567        value: AV,
568    ) -> Option<AV> {
569        self.annotations
570            .insert_field_value_for_object(obj, key, value)
571    }
572
573    /// Strip an annotation value from an object.
574    pub fn remove_object_annotation<Id: AsRef<Uuid>>(
575        &mut self,
576        id: Id,
577        annotation: &A,
578    ) -> Option<AV> {
579        self.ids.get_key(id.as_ref()).and_then(|obj| {
580            self.annotations
581                .remove_field_name_value_from_object(obj, annotation)
582        })
583    }
584
585    /// Strip an annotation value from an object using internally used keys.
586    pub fn remove_object_annotation_key(
587        &mut self,
588        obj: ObjKey,
589        annotation: AnnotationKey,
590    ) -> Option<AV> {
591        self.annotations
592            .remove_field_value_from_object(obj, annotation)
593    }
594
595    /// Remove an object from the store by its ID.
596    /// Returns if any metadata was held apart from its ID.
597    pub fn remove_object<Id: AsRef<Uuid>>(&mut self, id: Id) -> bool {
598        match self.ids.remove_value(id.as_ref()) {
599            Some(obj) => self.remove_object_key(obj),
600            None => false,
601        }
602    }
603
604    /// Remove an object from the store by its key.  Returns if it was removed.
605    pub fn remove_object_key(&mut self, obj: ObjKey) -> bool {
606        self.ids.remove_key(obj);
607        let did_name = self.names.remove_object(obj).is_some();
608        let did_kind = self.kinds.remove_object(obj).is_some();
609        let did_labels = self.labels.remove_object(obj).is_some();
610        let did_weights = self.weights.remove_object(obj).is_some();
611        let did_annotations = self.annotations.remove_object(obj).is_some();
612        did_name | did_kind | did_labels | did_weights | did_annotations
613    }
614
615    /// Clean-up all interned field names that are no longer in use.
616    pub fn clean(&mut self) {
617        self.names.clean();
618        self.kinds.clean();
619        self.labels.clean();
620        self.weights.clean();
621        self.annotations.clean();
622    }
623
624    /// Get a metadata object with references to the field names.
625    pub fn object_meta_named<'a, Id: AsRef<Uuid>>(
626        &'a self,
627        id: Id,
628    ) -> Option<MetadataRef<'a, N, K, L, W, WV, A, AV>> {
629        let id = *id.as_ref();
630        self.ids.get_key(&id).map(|obj| {
631            MetadataRef::builder()
632                .id(id)
633                .maybe_name(self.names.value_name_of_object(obj))
634                .maybe_kind(self.kinds.value_name_of_object(obj))
635                .labels(self.labels.named_value_of_object(obj))
636                .weights(self.weights.named_value_of_object(obj))
637                .annotations(self.annotations.named_value_of_object(obj))
638                .build()
639        })
640    }
641
642    /// Get a metadata object expressed as internal field keys.
643    pub fn object_meta_keyed(
644        &self,
645        obj: ObjKey,
646    ) -> Option<Metadata<NameKey, KindKey, LabelKey, WeightKey, WV, AnnotationKey, AV>> {
647        self.object_id(obj).map(|id| {
648            Metadata::builder()
649                .id(id)
650                .maybe_name(self.object_name_key(obj))
651                .maybe_kind(self.object_kind_key(obj))
652                .maybe_labels(self.object_label_keys(obj).cloned())
653                .maybe_weights(self.object_weights_keyed(obj).cloned())
654                .maybe_annotations(self.object_annotations_keyed(obj).cloned())
655                .build()
656        })
657    }
658
659    /// All object keys in store.
660    pub fn object_keys(&self) -> impl Iterator<Item = ObjKey> {
661        self.ids.keys()
662    }
663
664    /// All object IDs in store.
665    pub fn object_ids(&self) -> impl Iterator<Item = &Uuid> {
666        self.ids.values()
667    }
668
669    /// Iterator over all object key-ID pairs.
670    pub fn object_key_id_pairs(&self) -> impl Iterator<Item = (ObjKey, &Uuid)> {
671        self.ids.items()
672    }
673
674    /// Get the ID of an object.
675    pub fn object_id(&self, obj: ObjKey) -> Option<Uuid> {
676        self.ids.get_value(obj).copied()
677    }
678
679    /// Get the key of an object from its ID.
680    pub fn object_key<Id: AsRef<Uuid>>(&self, id: Id) -> Option<ObjKey> {
681        self.ids.get_key(id.as_ref())
682    }
683
684    /// Read-only access to the name interner.
685    pub fn name_store(&self) -> &NameStore<ObjKey, N> {
686        &self.names
687    }
688
689    /// Get all interned name field values.
690    pub fn name_field_names(&self) -> impl Iterator<Item = &N> {
691        self.names.field_names()
692    }
693
694    /// Get all interned name field keys.
695    pub fn name_field_keys(&self) -> impl Iterator<Item = NameKey> {
696        self.names.field_keys()
697    }
698
699    /// Get all interned name field key-name pairs.
700    pub fn name_field_items(&self) -> impl Iterator<Item = (NameKey, &N)> {
701        self.names.field_items()
702    }
703
704    /// Get all objects with the given name and return their ID.
705    pub fn objects_with_name(&self, name: &N) -> impl Iterator<Item = Uuid> {
706        self.names
707            .objects_with_field_name(name)
708            .into_iter()
709            .flatten()
710            .flat_map(|&obj| self.object_id(obj))
711    }
712
713    /// Get all objects with the given internal name key and return their internal key.
714    pub fn objects_with_name_key(&self, name: NameKey) -> impl Iterator<Item = ObjKey> {
715        self.names
716            .objects_with_field(name)
717            .into_iter()
718            .flatten()
719            .copied()
720    }
721
722    /// Get the name of an object by ID.
723    pub fn object_name<Id: AsRef<Uuid>>(&self, id: Id) -> Option<&N> {
724        self.object_key(id)
725            .and_then(|obj| self.names.value_name_of_object(obj))
726    }
727
728    /// Get the interned name key of an object by internal key.
729    pub fn object_name_key(&self, obj: ObjKey) -> Option<NameKey> {
730        self.names.object_value(obj).copied()
731    }
732
733    /// Read-only access to the kind store.
734    pub fn kind_store(&self) -> &KindStore<ObjKey, K> {
735        &self.kinds
736    }
737
738    /// Get all interned kind field names.
739    pub fn kind_field_names(&self) -> impl Iterator<Item = &K> {
740        self.kinds.field_names()
741    }
742
743    /// Get all interned kind field keys.
744    pub fn kind_field_keys(&self) -> impl Iterator<Item = KindKey> {
745        self.kinds.field_keys()
746    }
747
748    /// Get all interned kind field key-name pairs.
749    pub fn kind_field_items(&self) -> impl Iterator<Item = (KindKey, &K)> {
750        self.kinds.field_items()
751    }
752
753    /// Get the kind of an object by ID.
754    pub fn object_kind<Id: AsRef<Uuid>>(&self, id: Id) -> Option<&K> {
755        self.object_key(id)
756            .and_then(|obj| self.kinds.value_name_of_object(obj))
757    }
758
759    /// Get the interned kind key of an object by internal key.
760    pub fn object_kind_key(&self, obj: ObjKey) -> Option<KindKey> {
761        self.kinds.object_value(obj).copied()
762    }
763
764    /// Read-only access to the label store.
765    pub fn label_store(&self) -> &LabelStore<ObjKey, L> {
766        &self.labels
767    }
768
769    /// Get all interned label field names.
770    pub fn label_field_names(&self) -> impl Iterator<Item = &L> {
771        self.labels.field_names()
772    }
773
774    /// Get all interned label field keys.
775    pub fn label_field_keys(&self) -> impl Iterator<Item = LabelKey> {
776        self.labels.field_keys()
777    }
778
779    /// Get all interned label field key-name pairs.
780    pub fn label_field_items(&self) -> impl Iterator<Item = (LabelKey, &L)> {
781        self.labels.field_items()
782    }
783
784    /// Get the labels of an object.
785    pub fn object_labels<Id: AsRef<Uuid>>(&self, id: Id) -> impl Iterator<Item = &L> {
786        self.object_key(id)
787            .into_iter()
788            .flat_map(|obj| self.labels.object_field_names(obj))
789    }
790
791    /// Get the set of interned label keys for an object.
792    pub fn object_label_keys(&self, obj: ObjKey) -> Option<&BTreeSet<LabelKey>> {
793        self.labels.object_value(obj)
794    }
795
796    /// Read-only access to the weight store.
797    pub fn weight_store(&self) -> &WeightStore<ObjKey, W, WV> {
798        &self.weights
799    }
800
801    /// Get all interned weight field names.
802    pub fn weight_field_names(&self) -> impl Iterator<Item = &W> {
803        self.weights.field_names()
804    }
805
806    /// Get all interned weight field keys.
807    pub fn weight_field_keys(&self) -> impl Iterator<Item = WeightKey> {
808        self.weights.field_keys()
809    }
810
811    /// Get all interned weight field key-name pairs.
812    pub fn weight_field_items(&self) -> impl Iterator<Item = (WeightKey, &W)> {
813        self.weights.field_items()
814    }
815
816    /// Get all weight values of an object.
817    pub fn object_weights<Id: AsRef<Uuid>>(&self, id: Id) -> BTreeMap<&W, &WV> {
818        self.object_key(id)
819            .map(|obj| self.weights.named_value_of_object(obj))
820            .unwrap_or_default()
821    }
822
823    /// Get the mapping of weights by internal field keys for an object.
824    pub fn object_weights_keyed(&self, obj: ObjKey) -> Option<&BTreeMap<WeightKey, WV>> {
825        self.weights.object_value(obj)
826    }
827
828    /// Get a specific weight of an object via its name.
829    pub fn object_weight<Id: AsRef<Uuid>>(&self, id: Id, weight: &W) -> Option<&WV> {
830        self.object_key(id)
831            .and_then(|obj| self.weights.field_name_value_for_object(obj, weight))
832    }
833
834    /// Get a specific weight of an object via its internal key.
835    pub fn object_weight_by_key(&self, obj: ObjKey, weight: WeightKey) -> Option<&WV> {
836        self.weights.field_value_for_object(obj, weight)
837    }
838
839    /// Read-only access to the annotation store.
840    pub fn annotation_store(&self) -> &AnnotationStore<ObjKey, A, AV> {
841        &self.annotations
842    }
843
844    /// Get all interned annotation field names.
845    pub fn annotation_field_names(&self) -> impl Iterator<Item = &A> {
846        self.annotations.field_names()
847    }
848
849    /// Get all interned annotation field keys.
850    pub fn annotation_field_keys(&self) -> impl Iterator<Item = AnnotationKey> {
851        self.annotations.field_keys()
852    }
853
854    /// Get all interned annotation field key-name pairs.
855    pub fn annotation_field_items(&self) -> impl Iterator<Item = (AnnotationKey, &A)> {
856        self.annotations.field_items()
857    }
858
859    /// Get all annotation values of an object.
860    pub fn object_annotations<Id: AsRef<Uuid>>(&self, id: Id) -> BTreeMap<&A, &AV> {
861        self.object_key(id)
862            .map(|obj| self.annotations.named_value_of_object(obj))
863            .unwrap_or_default()
864    }
865
866    /// Get the annotations mapping by internal field keys for an object.
867    pub fn object_annotations_keyed(&self, obj: ObjKey) -> Option<&BTreeMap<AnnotationKey, AV>> {
868        self.annotations.object_value(obj)
869    }
870
871    /// Get a specific annotation of an object via its name.
872    pub fn object_annotation<Id: AsRef<Uuid>>(&self, id: Id, annotation: &A) -> Option<&AV> {
873        self.object_key(id).and_then(|obj| {
874            self.annotations
875                .field_name_value_for_object(obj, annotation)
876        })
877    }
878
879    /// Get a specific annotation of an object via its internal key.
880    pub fn object_annotation_by_key(&self, obj: ObjKey, annotation: AnnotationKey) -> Option<&AV> {
881        self.annotations.field_value_for_object(obj, annotation)
882    }
883
884    /// Iterate over the interned metadata in terms of field names
885    pub fn iter_meta_named<'a>(
886        &'a self,
887    ) -> impl Iterator<Item = MetadataRef<'a, N, K, L, W, WV, A, AV>> {
888        self.object_ids().map(|id| {
889            self.object_meta_named(id).expect(
890                "Object key and UUID pairs should always result in a metadata ref instance.",
891            )
892        })
893    }
894
895    /// Iterate over all interned metadata items in terms of internal keys.
896    pub fn iter_meta_keyed(
897        &self,
898    ) -> impl Iterator<Item = Metadata<NameKey, KindKey, LabelKey, WeightKey, WV, AnnotationKey, AV>>
899    {
900        self.object_keys().map(|key| {
901            self.object_meta_keyed(key).expect(
902                "Object key and UUID pairs should always result in a metadata ref instance.",
903            )
904        })
905    }
906
907    /// Calculate the aggregate for this store.
908    pub fn aggregate(&self) -> Aggregate<N, K, L, W, WV, A> {
909        self.iter_meta_named()
910            .fold(Aggregate::new(), |mut agg, meta| {
911                agg.add(&meta);
912                agg
913            })
914    }
915}
916
917#[cfg(test)]
918pub mod tests {
919    #[allow(unused_imports)]
920    use pretty_assertions::{assert_eq, assert_ne, assert_str_eq};
921
922    #[allow(unused_imports)]
923    use super::*;
924    pub use crate::metadata::tests::*;
925
926    pub type TestStore = MetadataStore<ObjectKey, N, K, L, W, f64, A, serde_json::Value>;
927
928    impl TestStore {
929        pub fn foobarbazquux() -> Self {
930            let mut store = Self::new();
931
932            TestMeta::foobarbazquux().into_iter().for_each(|meta| {
933                store.insert(meta);
934            });
935
936            store
937        }
938    }
939
940    #[test]
941    fn test_helper_store_empty() {
942        let mut store = TestStore::new();
943
944        assert_eq!(store.len(), 0);
945        assert!(store.is_empty());
946
947        let (key, id) = store.add();
948        assert_eq!(store.object_key(id), Some(key));
949        assert_eq!(store.object_id(key), Some(id));
950        assert_eq!(store.len(), 1);
951        assert!(!store.is_empty());
952    }
953
954    #[test]
955    fn test_helper_store_reads() {
956        let store = TestStore::foobarbazquux();
957
958        assert_eq!(store.len(), 4);
959        assert_eq!(store.object_keys().collect::<BTreeSet<_>>().len(), 4);
960        assert_eq!(store.object_ids().collect::<BTreeSet<_>>().len(), 4);
961        assert_eq!(store.object_key_id_pairs().collect::<Vec<_>>().len(), 4);
962
963        let foo_id = store.objects_with_name(&N::Foo).next().expect("foo id");
964        let foo_key = store.object_key(foo_id).expect("foo key");
965
966        let meta_named = store.object_meta_named(foo_id).expect("metadata ref");
967        assert_eq!(meta_named.name, Some(&N::Foo));
968        assert_eq!(meta_named.kind, Some(&K::A));
969        assert_eq!(meta_named.labels, bon::set![&L::A, &L::B]);
970        assert_eq!(meta_named.weights, bon::map! { &W::A: &1.0 });
971        assert_eq!(
972            meta_named.annotations,
973            bon::map! {&A::A: &serde_json::Value::String("FOO".to_string())}
974        );
975
976        let meta_keyed = store.object_meta_keyed(foo_key).expect("metadata keyed");
977        assert_eq!(
978            meta_keyed.name,
979            store.name_store().field_key_interned(&N::Foo)
980        );
981    }
982
983    #[test]
984    fn test_aggregate() {
985        let store = TestStore::foobarbazquux();
986        let aggregate = store.aggregate();
987
988        assert_eq!(
989            aggregate.names,
990            bon::map! { N::Foo: 1usize, N::Bar: 1usize, N::Baz: 1usize, N::Quux: 1usize },
991            "names"
992        );
993        assert_eq!(
994            aggregate.kinds,
995            bon::map! { K::A: 1usize, K::B: 1usize, K::C: 1usize },
996            "kinds"
997        );
998        assert_eq!(
999            aggregate.labels,
1000            bon::map! { L::A: 1usize, L::B: 2usize, L::C: 2usize },
1001            "labels"
1002        );
1003        assert_eq!(
1004            aggregate.weights,
1005            bon::map! { W::A: 1.0, W::B: 4.0},
1006            "weights"
1007        );
1008        assert_eq!(
1009            aggregate.annotations,
1010            bon::map! { A::A: 4usize, A::B: 2usize },
1011            "annotations"
1012        );
1013    }
1014}