Skip to main content

stam/
store.rs

1/*
2    STAM Library (Stand-off Text Annotation Model)
3        by Maarten van Gompel <proycon@anaproy.nl>
4        Digital Infrastucture, KNAW Humanities Cluster
5
6        Licensed under the GNU General Public License v3
7
8        https://github.com/annotation/stam-rust
9*/
10
11//! This module implements the low-level concept of a [`Store`], which is essentially a vector over certain
12//! items that are [`Storable`]. The items can be retrieved by a [`Handle`], which simply points
13//! at an index in the store vector. The [`StoreFor<T>`] trait is implemented on data types that act
14//! as a store for a particular storable item. An iterator to iterate over all items in a store is available as well: [`StoreIter`]
15//! Do not confuse this more abstract notion of [`Store`] with [`AnnotationStore`].
16//!
17//! This module also implements a structure [`IdMap`] to map public identifiers (strings) to these internal handles.
18//! Moreover, it implements relations maps ([`RelationMap`],[`TripleRelationMap`],[`SingleRelationMap`]) that are used to build the various
19//! reverse indices. These map one type of handle to another and effectively define the edges of the graph model.
20
21use sealed::sealed;
22use serde::Deserialize;
23use std::borrow::Cow;
24use std::cmp::Ordering;
25use std::collections::{BTreeMap, HashMap};
26use std::fmt::Debug;
27use std::hash::{Hash, Hasher};
28use std::marker::PhantomData;
29use std::ops::Deref;
30use std::slice::{Iter, IterMut};
31
32use datasize::{data_size, DataSize};
33use minicbor::{Decode, Encode};
34use nanoid::nanoid;
35
36use crate::annotationstore::AnnotationStore;
37use crate::config::Configurable;
38use crate::error::StamError;
39use crate::substore::AnnotationSubStoreHandle;
40use crate::types::*;
41
42/// Type for Store elements. The struct that owns a field of this type should implement the trait [`StoreFor<T>`]
43/// This is a low-level construct. Do not confuse with [`AnnotationStore`].
44pub type Store<T> = Vec<Option<T>>;
45
46const ID_LEN: usize = 21;
47const ID_ALPHABET: [char; 62] = [
48    '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
49    'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
50    'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
51    'V', 'W', 'X', 'Y', 'Z',
52];
53/// A map mapping public IDs to internal ids, implemented as a HashMap.
54/// Used to resolve public IDs to internal ones.
55#[derive(Debug, Clone, DataSize, Decode, Encode)]
56pub struct IdMap<HandleType> {
57    /// The actual map
58    #[n(0)] //these macros are field index numbers for cbor binary (de)serialisation
59    data: HashMap<String, HandleType>,
60
61    /// A prefix that automatically generated IDs will get when added to this map
62    #[n(1)]
63    autoprefix: String,
64
65    /// Resolve temp IDs
66    #[n(2)]
67    resolve_temp_ids: bool,
68}
69
70impl<HandleType> Default for IdMap<HandleType>
71where
72    HandleType: Handle,
73{
74    fn default() -> Self {
75        Self {
76            data: HashMap::new(),
77            autoprefix: "_".to_string(),
78            resolve_temp_ids: true,
79        }
80    }
81}
82
83impl<HandleType> IdMap<HandleType>
84where
85    HandleType: Handle,
86{
87    pub(crate) fn new(autoprefix: String) -> Self {
88        Self {
89            autoprefix,
90            ..Self::default()
91        }
92    }
93
94    pub(crate) fn with_resolve_temp_ids(mut self, value: bool) -> Self {
95        self.set_resolve_temp_ids(value);
96        self
97    }
98
99    pub(crate) fn set_resolve_temp_ids(&mut self, value: bool) {
100        self.resolve_temp_ids = value;
101    }
102
103    pub fn len(&self) -> usize {
104        self.data.len()
105    }
106
107    pub fn meminfo(&self) -> usize {
108        data_size(self)
109    }
110
111    pub fn shrink_to_fit(&mut self) {
112        self.data.shrink_to_fit();
113    }
114
115    pub(crate) fn reindex(&mut self, gaps: &[(HandleType, isize)]) {
116        for handle in self.data.values_mut() {
117            *handle = handle.reindex(gaps);
118        }
119    }
120}
121
122/// This models relations or 'edges' in graph terminology, between handles. It acts as a reverse index is used for various purposes.
123#[derive(Debug, Clone, DataSize, Decode, Encode)]
124pub(crate) struct RelationMap<A, B> {
125    /// The actual map
126    #[n(0)]
127    pub(crate) data: Vec<Vec<B>>,
128    //                   ^-- a Vec is sufficient, we don't need a BTreeSet; the way these maps are used as reverse indices, items are always inserted in sorted order
129    #[n(1)]
130    _marker: PhantomData<A>, //zero-size, only needed to bind generic A
131}
132
133impl<A, B> Default for RelationMap<A, B>
134where
135    A: Handle,
136    B: Handle,
137{
138    fn default() -> Self {
139        Self {
140            data: Vec::new(),
141            _marker: PhantomData,
142        }
143    }
144}
145
146impl<A, B> RelationMap<A, B>
147where
148    A: Handle,
149    B: Handle,
150{
151    pub fn new() -> Self {
152        Self::default()
153    }
154
155    /// Insert a relation into the map
156    pub fn insert(&mut self, x: A, y: B) {
157        if x.as_usize() >= self.data.len() {
158            //expand the map
159            self.data.resize_with(x.as_usize() + 1, Default::default);
160        }
161        self.data[x.as_usize()].push(y);
162    }
163
164    /// Remove a relation from the map
165    pub fn remove(&mut self, x: A, y: B) {
166        if let Some(values) = self.data.get_mut(x.as_usize()) {
167            if let Some(pos) = values.iter().position(|z| *z == y) {
168                values.remove(pos); //note: this shifts the array and may take O(n)
169            }
170        }
171    }
172
173    pub fn remove_all(&mut self, x: A) {
174        if x.as_usize() >= self.data.len() {
175            if let Some(values) = self.data.get_mut(x.as_usize()) {
176                values.clear();
177            }
178        }
179    }
180
181    pub fn get(&self, x: A) -> Option<&Vec<B>> {
182        self.data.get(x.as_usize())
183    }
184
185    pub fn totalcount(&self) -> usize {
186        let mut total = 0;
187        for v in self.data.iter() {
188            total += v.len();
189        }
190        total
191    }
192
193    /// Like countinfo(), but returns an extra value at the end of the tuple with the lower-bound estimated memory consumption in bytes.
194    pub fn meminfo(&self) -> usize {
195        data_size(self)
196    }
197
198    pub fn len(&self) -> usize {
199        self.data.len()
200    }
201
202    pub fn shrink_to_fit(&mut self, recursive: bool) {
203        if recursive {
204            for element in self.data.iter_mut() {
205                element.shrink_to_fit();
206            }
207        }
208        self.data.shrink_to_fit();
209    }
210
211    /// Returns a new reindexed map, copies all contents, not the most efficient
212    pub(crate) fn reindex(&self, gaps_a: &[(A, isize)], gaps_b: &[(B, isize)]) -> Self {
213        let mut newmap = Self::new();
214        for (handle_a, item) in self.data.iter().enumerate() {
215            let handle_a = A::new(handle_a).reindex(gaps_a);
216            for handle_b in item {
217                let handle_b = handle_b.reindex(gaps_b);
218                newmap.insert(handle_a, handle_b);
219            }
220        }
221        newmap
222    }
223}
224
225impl<A, B> Extend<(A, B)> for RelationMap<A, B>
226where
227    A: Handle,
228    B: Handle,
229{
230    fn extend<T>(&mut self, iter: T)
231    where
232        T: IntoIterator<Item = (A, B)>,
233    {
234        for (x, y) in iter {
235            self.insert(x, y);
236        }
237    }
238}
239
240/// This models relations or 'edges' in graph terminology, between handles. It acts as a reverse index is used for various purposes.
241#[derive(Debug, Clone, DataSize, Decode, Encode)]
242pub(crate) struct RelationBTreeMap<A, B>
243where
244    A: Handle,
245    B: Handle,
246{
247    /// The actual map
248    #[n(0)]
249    pub(crate) data: BTreeMap<A, Vec<B>>,
250    //                           ^-- a Vec is sufficient, we don't need a BTreeSet; the way these maps are used as reverse indices, items are always inserted in sorted order
251}
252
253impl<A, B> Default for RelationBTreeMap<A, B>
254where
255    A: Handle,
256    B: Handle,
257{
258    fn default() -> Self {
259        Self {
260            data: BTreeMap::new(),
261        }
262    }
263}
264
265impl<A, B> RelationBTreeMap<A, B>
266where
267    A: Handle,
268    B: Handle,
269{
270    pub fn new() -> Self {
271        Self::default()
272    }
273
274    /// Insert a relation into the map
275    pub fn insert(&mut self, x: A, y: B) {
276        if self.data.contains_key(&x) {
277            self.data.get_mut(&x).unwrap().push(y);
278        } else {
279            self.data.insert(x, vec![y]);
280        }
281    }
282
283    /// Remove a relation from the map
284    pub fn remove(&mut self, x: A, y: B) {
285        if let Some(values) = self.data.get_mut(&x) {
286            if let Some(pos) = values.iter().position(|z| *z == y) {
287                values.remove(pos); //note: this shifts the array and may take O(n)
288            }
289        }
290    }
291
292    /// Remove a relation from the map
293    pub fn remove_all(&mut self, x: A) {
294        self.data.remove(&x);
295    }
296
297    pub fn get(&self, x: A) -> Option<&Vec<B>> {
298        self.data.get(&x)
299    }
300
301    pub fn totalcount(&self) -> usize {
302        let mut total = 0;
303        for v in self.data.values() {
304            total += v.len();
305        }
306        total
307    }
308
309    /// Like countinfo(), but returns an extra value at the end of the tuple with the lower-bound estimated memory consumption in bytes.
310    pub fn meminfo(&self) -> usize {
311        data_size(self)
312    }
313
314    pub fn len(&self) -> usize {
315        self.data.len()
316    }
317
318    pub fn shrink_to_fit(&mut self, recursive: bool) {
319        if recursive {
320            for element in self.data.values_mut() {
321                element.shrink_to_fit();
322            }
323        }
324    }
325
326    /// Returns a new reindexed map, copies all contents, not the most efficient
327    pub(crate) fn reindex(&self, gaps_a: &[(A, isize)], gaps_b: &[(B, isize)]) -> Self {
328        let mut newmap = Self::new();
329        for (handle_a, item) in self.data.iter() {
330            let handle_a = handle_a.reindex(gaps_a);
331            for handle_b in item {
332                let handle_b = handle_b.reindex(gaps_b);
333                newmap.insert(handle_a, handle_b);
334            }
335        }
336        newmap
337    }
338}
339
340impl<A, B> Extend<(A, B)> for RelationBTreeMap<A, B>
341where
342    A: Handle,
343    B: Handle,
344{
345    fn extend<T>(&mut self, iter: T)
346    where
347        T: IntoIterator<Item = (A, B)>,
348    {
349        for (x, y) in iter {
350            self.insert(x, y);
351        }
352    }
353}
354
355#[derive(Debug, Clone, DataSize, Decode, Encode)]
356pub(crate) struct TripleRelationMap<A, B, C> {
357    /// The actual map
358    #[n(0)]
359    pub(crate) data: Vec<RelationMap<B, C>>,
360    #[n(1)]
361    _marker: PhantomData<A>,
362}
363
364impl<A, B, C> Default for TripleRelationMap<A, B, C> {
365    fn default() -> Self {
366        Self {
367            data: Vec::new(),
368            _marker: PhantomData,
369        }
370    }
371}
372
373impl<A, B, C> TripleRelationMap<A, B, C>
374where
375    A: Handle,
376    B: Handle,
377    C: Handle,
378{
379    pub fn new() -> Self {
380        Self::default()
381    }
382
383    pub fn insert(&mut self, x: A, y: B, z: C) {
384        if x.as_usize() >= self.data.len() {
385            //expand the map
386            self.data.resize_with(x.as_usize() + 1, Default::default);
387        }
388        self.data[x.as_usize()].insert(y, z);
389    }
390
391    pub fn get(&self, x: A, y: B) -> Option<&Vec<C>> {
392        if let Some(v) = self.data.get(x.as_usize()) {
393            v.get(y)
394        } else {
395            None
396        }
397    }
398
399    /// Remove a relation from the map
400    pub fn remove(&mut self, x: A, y: B, z: C) {
401        if let Some(map) = self.data.get_mut(x.as_usize()) {
402            map.remove(y, z);
403        }
404    }
405
406    /// Remove a relation from the map
407    pub fn remove_all(&mut self, x: A) {
408        if x.as_usize() >= self.data.len() {
409            self.data.remove(x.as_usize());
410        }
411    }
412
413    /// Remove a relation from the map
414    pub fn remove_second(&mut self, x: A, y: B) {
415        if let Some(v) = self.data.get_mut(x.as_usize()) {
416            v.remove_all(y)
417        }
418    }
419
420    pub fn totalcount(&self) -> usize {
421        let mut total = 0;
422        for v in self.data.iter() {
423            total += v.totalcount();
424        }
425        total
426    }
427
428    /// Returns partcial count, does not count the deepest layer
429    pub fn partialcount(&self) -> usize {
430        let mut total = 0;
431        for v in self.data.iter() {
432            total += v.len();
433        }
434        total
435    }
436
437    /// Like countinfo(), but returns an extra value at the end of the tuple with the lower-estimate  memory consumption in bytes.
438    pub fn meminfo(&self) -> usize {
439        data_size(self)
440    }
441
442    pub fn len(&self) -> usize {
443        self.data.len()
444    }
445
446    pub fn shrink_to_fit(&mut self, recursive: bool) {
447        if recursive {
448            for element in self.data.iter_mut() {
449                element.shrink_to_fit(recursive);
450            }
451        }
452        self.data.shrink_to_fit();
453    }
454
455    /// Returns a new reindexed map, copies all contents, not the most efficient
456    pub(crate) fn reindex(
457        &self,
458        gaps_a: &[(A, isize)],
459        gaps_b: &[(B, isize)],
460        gaps_c: &[(C, isize)],
461    ) -> Self {
462        let mut newmap = Self::new();
463        for (handle_a, inner) in self.data.iter().enumerate() {
464            let handle_a = A::new(handle_a).reindex(gaps_a);
465            for (handle_b, item) in inner.data.iter().enumerate() {
466                let handle_b = B::new(handle_b).reindex(gaps_b);
467                for handle_c in item {
468                    let handle_c = handle_c.reindex(gaps_c);
469                    newmap.insert(handle_a, handle_b, handle_c);
470                }
471            }
472        }
473        newmap
474    }
475}
476
477impl<A, B, C> Extend<(A, B, C)> for TripleRelationMap<A, B, C>
478where
479    A: Handle,
480    B: Handle,
481    C: Handle,
482{
483    fn extend<T>(&mut self, iter: T)
484    where
485        T: IntoIterator<Item = (A, B, C)>,
486    {
487        for (x, y, z) in iter {
488            self.insert(x, y, z);
489        }
490    }
491}
492
493#[derive(Clone, Debug, DataSize, Encode, Decode)]
494/// A simple wrapper around a key value map, storing exclusive one on one relations
495pub struct ExclusiveRelationMap<A, B>
496where
497    A: Handle,
498    B: Handle,
499{
500    #[n(0)]
501    data: BTreeMap<A, B>,
502}
503
504impl<A, B> Default for ExclusiveRelationMap<A, B>
505where
506    A: Handle,
507    B: Handle,
508{
509    fn default() -> Self {
510        Self::new()
511    }
512}
513
514impl<A, B> Extend<(A, B)> for ExclusiveRelationMap<A, B>
515where
516    A: Handle,
517    B: Handle,
518{
519    fn extend<T>(&mut self, iter: T)
520    where
521        T: IntoIterator<Item = (A, B)>,
522    {
523        for (x, y) in iter {
524            self.insert(x, y);
525        }
526    }
527}
528
529impl<A, B> ExclusiveRelationMap<A, B>
530where
531    A: Handle,
532    B: Handle,
533{
534    pub fn new() -> Self {
535        Self {
536            data: BTreeMap::new(),
537        }
538    }
539
540    /// Insert a relation into the map
541    pub fn insert(&mut self, x: A, y: B) {
542        if self.data.contains_key(&x) {
543            if let Some(entry) = self.data.get_mut(&x) {
544                *entry = y;
545            }
546        } else {
547            self.data.insert(x, y);
548        }
549    }
550
551    /// Remove a relation from the map
552    pub fn remove_all(&mut self, x: A) {
553        self.data.remove(&x);
554    }
555
556    pub fn get(&self, x: A) -> Option<B> {
557        self.data.get(&x).copied()
558    }
559
560    /// Like countinfo(), but returns an extra value at the end of the tuple with the lower-bound estimated memory consumption in bytes.
561    pub fn meminfo(&self) -> usize {
562        data_size(self)
563    }
564
565    pub fn len(&self) -> usize {
566        self.data.len()
567    }
568}
569
570#[sealed(pub(crate))] //<-- this ensures nobody outside this crate can implement the trait
571/// This is a low-level trait that is implemented on the various STAM data structures that
572/// are held in a store, such as [`Annotation`](crate::Annotation), [`AnnotationData`](crate::AnnotationData),[`TextResource`](crate::TextResource), etc..
573/// All storable elements have a [`Handle`], defined by the associated [`Self::HandleType`].
574/// It corresponds directly to their index in a vector, so this type is a simple wrapper around `usize`.
575/// This is a sealed trait, not implementable outside this crate.
576pub trait Storable: PartialEq + TypeInfo + Debug + Sized {
577    type HandleType: Handle;
578    type StoreHandleType: Copy + Ord + Debug;
579    type FullHandleType: Copy + Ord + Debug;
580    type StoreType: StoreFor<Self>;
581
582    fn fullhandle(parent: Self::StoreHandleType, handle: Self::HandleType) -> Self::FullHandleType;
583
584    /// Retrieve the internal (numeric) id. For any type T in `StoreFor<T>`, this may return `None` only in the initial
585    /// stage when it is still unbounded to a store, so this is almost always safe to unwrap when used in the public API.
586    fn handle(&self) -> Option<Self::HandleType> {
587        None
588    }
589
590    /// Like [`Self::handle()`] but returns a [`StamError::Unbound`] error if there is no internal id.
591    fn handle_or_err(&self) -> Result<Self::HandleType, StamError> {
592        self.handle().ok_or(StamError::Unbound(""))
593    }
594
595    /// Get the public identifier
596    fn id(&self) -> Option<&str> {
597        None
598    }
599
600    /// Generate a temporary public ID based on the internal handle.
601    fn temp_id(&self) -> Result<String, StamError> {
602        Ok(format!(
603            "{}{}",
604            Self::temp_id_prefix(),
605            self.handle_or_err()?.as_usize()
606        ))
607    }
608
609    /// Does this type support an ID?
610    fn carries_id() -> bool;
611
612    /// Returns the item of type `T` as a [`ResultItem<T>`], i.e. a wrapped reference that includes a reference to
613    /// both this item as well as the store that owns it. All high-level API functions are implemented
614    /// on such Result types. You should not need to invoke this yourself.
615    fn as_resultitem<'store>(
616        &'store self,
617        store: &'store Self::StoreType,
618        rootstore: &'store AnnotationStore,
619    ) -> ResultItem<'store, Self>
620    where
621        Self: Sized,
622    {
623        ResultItem::new(self, store, rootstore)
624    }
625
626    /// Set the internal ID for an item. May only be called once just after instantiation.
627    /// This is a low-level API method that can not be used publicly due to ownership restrictions.
628    fn with_handle(self, _handle: <Self as Storable>::HandleType) -> Self {
629        //no-op in default implementation
630        self
631    }
632
633    /// Generate a random ID in a given idmap (adds it to the map and assigns it to the item)
634    /// This is a low-level API method that can not be used publicly due to ownership restrictions.
635    fn generate_id(self, idmap: Option<&mut IdMap<Self::HandleType>>) -> Self
636    where
637        Self: Sized,
638    {
639        if let Some(intid) = self.handle() {
640            if let Some(idmap) = idmap {
641                loop {
642                    let id = generate_id(&idmap.autoprefix, "");
643                    let id_copy = id.clone();
644                    if idmap.data.insert(id, intid).is_none() {
645                        //checks for collisions (extremely unlikely)
646                        //returns none if the key did not exist yet
647                        return self.with_id(id_copy);
648                    }
649                }
650            }
651        }
652        // if the item is not bound or has no IDmap, we can't check collisions, but that's okay
653        self.with_id(generate_id("X", ""))
654    }
655
656    /// Builder pattern to set the public ID
657    #[allow(unused_variables)]
658    fn with_id(self, id: impl Into<String>) -> Self
659    where
660        Self: Sized,
661    {
662        if Self::carries_id() {
663            unimplemented!("with_id() not implemented");
664        }
665        //no-op
666        self
667    }
668
669    /// Merge another item into this one
670    /// This is a low-level API method, mostly for internal use.
671    fn merge(&mut self, other: Self) -> Result<(), StamError>;
672
673    /// Unbind an item
674    /// This is a low-level API method that can not be used publicly due to ownership restrictions.
675    fn unbind(self) -> Self;
676}
677
678/// This trait is implemented on types that provide storage for a certain other generic type (T)
679/// It belongs to the low-level API.
680/// It is a sealed trait, not implementable outside this crate.
681#[sealed(pub(crate))] //<-- this ensures nobody outside this crate can implement the trait
682pub trait StoreFor<T: Storable>: Configurable + private::StoreCallbacks<T> {
683    /// Get a reference to the entire store for the associated type
684    /// This is a low-level API method.
685    fn store(&self) -> &Store<T>;
686
687    /// Get a mutable reference to the entire store for the associated type
688    /// This is a low-level API method.
689    fn store_mut(&mut self) -> &mut Store<T>;
690
691    /// Get a reference to the id map for the associated type, mapping global ids to internal ids
692    /// This is a low-level API method.
693    fn idmap(&self) -> Option<&IdMap<T::HandleType>> {
694        None
695    }
696    /// Get a mutable reference to the id map for the associated type, mapping global ids to internal ids
697    /// This is a low-level API method.
698    fn idmap_mut(&mut self) -> Option<&mut IdMap<T::HandleType>> {
699        None
700    }
701
702    fn store_typeinfo() -> &'static str;
703
704    /// Adds an item to the store. Returns a handle to it upon success.
705    fn insert(&mut self, mut item: T) -> Result<T::HandleType, StamError> {
706        debug(self.config(), || {
707            format!("StoreFor<{}>.insert: new item", Self::store_typeinfo())
708        });
709        let handle = if let Some(intid) = item.handle() {
710            intid
711        } else {
712            // item has no internal id yet, i.e. it is unbound
713            // we generate an id and bind it now
714            let intid = self.next_handle();
715
716            // Bind an item to the store *PRIOR* to it being actually added:
717
718            //we already pass the internal id this item will get upon the next insert()
719            //so it knows its internal id immediate after construction
720            if item.handle().is_some() {
721                return Err(StamError::AlreadyBound("bind()"));
722            } else {
723                item = item.with_handle(self.next_handle());
724            }
725            intid
726        };
727
728        if T::carries_id() {
729            //insert a mapping from the public ID to the internal numeric ID in the idmap
730            if let Some(id) = item.id() {
731                //check if public ID does not already exist
732                if self.has(id) {
733                    //ok. the already ID exists, now is the existing item exactly the same as the item we're about to insert?
734                    //in that case we can discard this error and just return the existing handle without actually inserting a new one
735                    let existing_item = self.get(id).unwrap();
736                    if *existing_item == item {
737                        return Ok(existing_item.handle().unwrap());
738                    }
739
740                    if self.config().merge {
741                        // is the existing item different but we are in merge mode? Then merge
742                        // (note that merge is only supported for some Storables)
743                        let existing_item = self.get_mut(id).unwrap();
744                        existing_item.merge(item)?;
745                        return Ok(existing_item.handle().unwrap());
746                    } else {
747                        //in all other cases, we return an error
748                        return Err(StamError::DuplicateIdError(
749                            id.to_string(),
750                            Self::store_typeinfo(),
751                        ));
752                    }
753                }
754
755                self.idmap_mut().map(|idmap| {
756                    //                 v-- MAYBE TODO: optimise the id copy away
757                    idmap.data.insert(id.to_string(), item.handle().unwrap())
758                });
759
760                debug(self.config(), || {
761                    format!(
762                        "StoreFor<{}>.insert: ^--- id={:?}",
763                        Self::store_typeinfo(),
764                        id
765                    )
766                });
767            } else if self.config().generate_ids {
768                item = item.generate_id(self.idmap_mut());
769                debug(self.config(), || {
770                    format!(
771                        "StoreFor<{}>.insert: ^--- autogenerated id {}",
772                        Self::store_typeinfo(),
773                        item.id().unwrap(),
774                    )
775                });
776            }
777        }
778
779        self.preinsert(&mut item)?;
780
781        //add the resource
782        self.store_mut().push(Some(item));
783
784        self.inserted(handle)?;
785
786        debug(self.config(), || {
787            format!(
788                "StoreFor<{}>.insert: ^--- {:?} (insertion complete now)",
789                Self::store_typeinfo(),
790                handle
791            )
792        });
793
794        assert_eq!(handle, T::HandleType::new(self.store().len() - 1), "sanity check to ensure no item can determine its own internal id that does not correspond with what's allocated
795");
796
797        Ok(handle)
798    }
799
800    /// Inserts items into the store using a builder pattern.
801    fn with_item(mut self, item: T) -> Result<Self, StamError>
802    where
803        Self: Sized,
804    {
805        self.insert(item)?;
806        Ok(self)
807    }
808
809    /// Returns true if the store has the item
810    #[inline]
811    fn has(&self, item: impl Request<T>) -> bool {
812        if let Some(handle) = item.to_handle(self) {
813            self.store().get(handle.as_usize()).is_some()
814        } else {
815            false
816        }
817    }
818
819    /// Get a reference to an item from the store, by handle, without checking validity.
820    ///
821    /// ## Safety
822    /// Calling this method with an out-of-bounds index is [undefined behavior](https://doc.rust-lang.org/reference/behavior-considered-undefined.html)  │       
823    /// even if the resulting reference is not used.                                                                                                     │       
824    #[inline]
825    unsafe fn get_unchecked(&self, handle: T::HandleType) -> Option<&T> {
826        self.store().get_unchecked(handle.as_usize()).as_ref()
827    }
828
829    /// Get a reference to an item from the store
830    /// This is a low-level API method, you usually want to use dedicated high-level methods like [`AnnotationStore::annotation()`](crate::AnnotationStore::annotation()) instead.
831    #[inline]
832    fn get(&self, item: impl Request<T>) -> Result<&T, StamError> {
833        if let Some(handle) = item.to_handle(self) {
834            if let Some(Some(item)) = self.store().get(handle.as_usize()) {
835                return Ok(item);
836            }
837        }
838        Err(StamError::HandleError(Self::store_typeinfo()))
839    }
840
841    /// Get a mutable reference to an item from the store by internal ID
842    /// This is a low-level API method
843    fn get_mut(&mut self, item: impl Request<T>) -> Result<&mut T, StamError> {
844        if let Some(handle) = item.to_handle(self) {
845            if let Some(Some(item)) = self.store_mut().get_mut(handle.as_usize()) {
846                return Ok(item);
847            }
848        }
849        Err(StamError::HandleError(Self::store_typeinfo()))
850    }
851
852    /// Removes an item
853    fn remove(&mut self, item: impl Request<T>) -> Result<(), StamError> {
854        if let Some(handle) = item.to_handle(self) {
855            //callback to remove the item from relation maps and to remove all its dependencies
856            self.preremove(handle)?;
857
858            //remove item from idmap
859            if let Some(Some(item)) = self.store().get(handle.as_usize()) {
860                let id: Option<String> = item.id().map(|x| x.to_string());
861                if let Some(id) = id {
862                    if let Some(idmap) = self.idmap_mut() {
863                        idmap.data.remove(id.as_str());
864                    }
865                }
866            } else {
867                return Err(StamError::HandleError(
868                    "Unable to remove non-existing handle",
869                ));
870            }
871
872            //now remove the actual item, removing means just setting its previously occupied index to None
873            //(and the actual item is owned so will be deallocated)
874            let item = self.store_mut().get_mut(handle.as_usize()).unwrap();
875            *item = None;
876            Ok(())
877        } else {
878            Err(StamError::HandleError(Self::store_typeinfo()))
879        }
880    }
881
882    /// Resolves an ID to a handle.
883    /// Also works for temporary IDs if enabled.
884    /// This is a low-level API method. You usually don't want to call this directly.
885    fn resolve_id(&self, id: &str) -> Result<T::HandleType, StamError> {
886        if let Some(idmap) = self.idmap() {
887            if idmap.resolve_temp_ids {
888                if let Some(handle) = resolve_temp_id(id) {
889                    return Ok(T::HandleType::new(handle));
890                }
891            }
892            if let Some(handle) = idmap.data.get(id) {
893                Ok(*handle)
894            } else {
895                Err(StamError::IdNotFoundError(
896                    id.to_string(),
897                    Self::store_typeinfo(),
898                ))
899            }
900        } else {
901            Err(StamError::NoIdError(Self::store_typeinfo()))
902        }
903    }
904
905    /// Iterate over all items in the store
906    /// This is a low-level API method, use dedicated high-level iterators like `annotations()`, `resources()` instead.  
907    #[inline]
908    fn iter<'a>(&'a self) -> StoreIter<'a, T>
909    where
910        T: Storable<StoreType = Self>,
911    {
912        StoreIter {
913            iter: self.store().iter(),
914            count: 0,
915            len: self.store().len(),
916        }
917    }
918
919    /// Iterate over the store, mutably
920    /// This is a low-level API method.
921    fn iter_mut<'a>(&'a mut self) -> StoreIterMut<'a, T> {
922        let len = self.store().len();
923        StoreIterMut {
924            iter: self.store_mut().iter_mut(),
925            count: 0,
926            len,
927        }
928    }
929
930    /// Return the internal id that will be assigned for the next item to the store
931    /// This is a low-level API method.
932    fn next_handle(&self) -> T::HandleType {
933        T::HandleType::new(self.store().len()) //this is one of the very few places in the code where we create a handle from scratch
934    }
935
936    /// Return the internal id that was assigned to last inserted item
937    /// This is a low-level API method.
938    fn last_handle(&self) -> T::HandleType {
939        T::HandleType::new(self.store().len() - 1)
940    }
941}
942
943pub(crate) mod private {
944    //we need a public trait in a private mod as a trick to have a sealed traits (private supertraits to publicly exposed traits)
945    //None of these traits and methods within are exposed publicly
946
947    pub trait StoreCallbacks<T: crate::store::Storable> {
948        /// Called prior to inserting an item into to the store
949        /// If it returns an error, the insert will be cancelled.
950        /// Allows for bookkeeping such as inheriting configuration
951        /// parameters from parent to the item
952        #[allow(unused_variables)]
953        #[doc(hidden)]
954        fn preinsert(&self, item: &mut T) -> Result<(), crate::error::StamError> {
955            //default implementation does nothing
956            Ok(())
957        }
958
959        /// Called after an item was inserted to the store
960        /// Allows the store to do further bookkeeping
961        /// like updating relation maps
962        #[allow(unused_variables)]
963        #[doc(hidden)]
964        fn inserted(&mut self, handle: T::HandleType) -> Result<(), crate::error::StamError> {
965            //default implementation does nothing
966            Ok(())
967        }
968
969        /// Called before an item is removed from the store
970        /// Allows the store to do further bookkeeping
971        /// like updating relation maps
972        #[allow(unused_variables)]
973        #[doc(hidden)]
974        fn preremove(&mut self, handle: T::HandleType) -> Result<(), crate::error::StamError> {
975            //default implementation does nothing
976            Ok(())
977        }
978    }
979}
980
981pub(crate) trait WrappableStore<T: Storable>: StoreFor<T> {
982    /// Wraps the entire store along with a reference to self
983    /// Low-level method that you won't need
984    fn wrap_store<'a>(
985        &'a self,
986        substore: Option<AnnotationSubStoreHandle>,
987    ) -> WrappedStore<'a, T, Self>
988    where
989        Self: Sized,
990    {
991        WrappedStore {
992            store: self.store(),
993            parent: self,
994            substore,
995        }
996    }
997}
998
999pub(crate) trait ReindexStore<T>
1000where
1001    T: Storable,
1002{
1003    fn gaps(&self) -> Vec<(T::HandleType, isize)>;
1004    fn reindex(self, gaps: &[(T::HandleType, isize)]) -> Self;
1005}
1006
1007impl<T> ReindexStore<T> for Vec<Option<T>>
1008where
1009    T: Storable,
1010{
1011    /// Low-level method that returns gaps in the store
1012    /// The gaps can be resolved by calling `reindex()`.
1013    fn gaps(&self) -> Vec<(T::HandleType, isize)> {
1014        let mut gaps = Vec::new();
1015        let mut gapsize: isize = 0;
1016        for item in self.iter() {
1017            if item.is_none() {
1018                gapsize -= 1;
1019            } else if gapsize != 0 {
1020                let handle = item.as_ref().unwrap().handle().expect("must have handle");
1021                gaps.push((handle, gapsize));
1022                gapsize = 0;
1023            }
1024        }
1025        gaps
1026    }
1027
1028    fn reindex(self, gaps: &[(T::HandleType, isize)]) -> Self {
1029        if !gaps.is_empty() {
1030            let totaldelta: isize = gaps.iter().map(|x| x.1).sum();
1031            let newsize: usize = (self.len() as isize + totaldelta) as usize;
1032            if newsize == 0 {
1033                return Vec::new();
1034            }
1035            let mut newstore: Vec<Option<T>> = Vec::with_capacity(newsize);
1036            for item in self {
1037                if let Some(mut item) = item {
1038                    let handle = item.handle().expect("handle must exist");
1039                    let newhandle = handle.reindex(gaps); //this does iterate over all gaps every time, not very efficient if there are many
1040                    item = item.with_handle(newhandle);
1041                    newstore.push(Some(item));
1042                }
1043            }
1044            return newstore;
1045        }
1046        self
1047    }
1048}
1049
1050//  generic iterator implementations, these take care of skipping over deleted items (None)
1051
1052/// This is the iterator to iterate over a Store,  it is created by the iter() method from the [`StoreFor<T>`] trait
1053/// It produces a references to the item wrapped in a fat pointer ([`ResultItem<T>`]) that also contains reference to the store
1054/// and which is immediately implements various methods for working with the type.
1055pub struct StoreIter<'store, T>
1056where
1057    T: Storable,
1058{
1059    iter: Iter<'store, Option<T>>,
1060    count: usize,
1061    len: usize,
1062}
1063
1064impl<'store, T> Iterator for StoreIter<'store, T>
1065where
1066    T: Storable,
1067{
1068    type Item = &'store T;
1069
1070    fn next(&mut self) -> Option<Self::Item> {
1071        self.count += 1;
1072        loop {
1073            match self.iter.next() {
1074                Some(Some(item)) => return Some(item),
1075                Some(None) => continue,
1076                None => return None,
1077            }
1078        }
1079    }
1080
1081    fn size_hint(&self) -> (usize, Option<usize>) {
1082        let l = self.len - self.count;
1083        //the lower-bound may be an overestimate (if there are deleted items)
1084        (l, Some(l))
1085    }
1086}
1087
1088/// Mutable variant of [`StoreIter<T>`], but unlike that one this does not wrap results in a fat pointer but returns them directly, ready for mutation.
1089pub struct StoreIterMut<'a, T> {
1090    iter: IterMut<'a, Option<T>>,
1091    count: usize,
1092    len: usize,
1093}
1094
1095impl<'a, T> Iterator for StoreIterMut<'a, T> {
1096    type Item = &'a mut T;
1097
1098    fn next(&mut self) -> Option<Self::Item> {
1099        self.count += 1;
1100        loop {
1101            match self.iter.next() {
1102                Some(Some(item)) => return Some(item),
1103                Some(None) => continue,
1104                None => return None,
1105            }
1106        }
1107    }
1108
1109    fn size_hint(&self) -> (usize, Option<usize>) {
1110        let l = self.len - self.count;
1111        //the lower-bound may be an overestimate (if there are deleted items)
1112        (l, Some(l))
1113    }
1114}
1115
1116/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1117
1118/// This is a smart pointer that encapsulates both the item and the store that owns it.
1119/// It allows the item to have some more introspection as it knows who its immediate parent is.
1120/// It is heavily used as a return type all throughout the higher-level API. Most API traits
1121/// are implemented for a particular variant of this type.
1122///
1123/// For further documentation, look carefully for the implementation for T that you want information on:
1124/// * [Annotation](#impl-ResultItem<'store,+Annotation>)
1125/// * [AnnotationData](#impl-ResultItem<'store,+AnnotationData>)
1126/// * [AnnotationDataSet](#impl-ResultItem<'store,+AnnotationDataSet>)
1127/// * [DataKey](#impl-ResultItem<'store,+DataKey>)
1128/// * [TextResource](#impl-ResultItem<'store,+TextResource>)
1129/// * [TextSelection](#impl-ResultItem<'store,+TextSelection>)
1130pub struct ResultItem<'store, T>
1131where
1132    T: Storable,
1133{
1134    // a reference to the item
1135    item: &'store T,
1136
1137    // a reference the store that holds the item
1138    store: &'store T::StoreType,
1139
1140    // a reference to the root AnnotationStore, can lead to some duplication if it's the same as store
1141    rootstore: Option<&'store AnnotationStore>,
1142}
1143
1144#[sealed(pub(crate))] //<-- this ensures nobody outside this crate can implement the trait
1145impl<'store, T> TypeInfo for ResultItem<'store, T>
1146where
1147    T: Storable + TypeInfo,
1148{
1149    fn typeinfo() -> Type {
1150        T::typeinfo()
1151    }
1152}
1153
1154impl<'store, T> Debug for ResultItem<'store, T>
1155where
1156    T: Storable,
1157{
1158    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1159        f.debug_struct("ResultItem")
1160            .field("item", &self.item)
1161            .finish()
1162    }
1163}
1164
1165impl<'store, T> Clone for ResultItem<'store, T>
1166where
1167    T: Storable + Clone,
1168{
1169    fn clone(&self) -> Self {
1170        Self {
1171            item: self.item,
1172            store: self.store,
1173            rootstore: self.rootstore,
1174        }
1175    }
1176}
1177
1178impl<'store, T> PartialEq for ResultItem<'store, T>
1179where
1180    T: Storable,
1181{
1182    fn eq(&self, other: &Self) -> bool {
1183        self.handle() == other.handle()
1184    }
1185}
1186impl<'store, T> Eq for ResultItem<'store, T> where T: Storable {}
1187impl<'store, T> Hash for ResultItem<'store, T>
1188where
1189    T: Storable,
1190{
1191    fn hash<H: Hasher>(&self, state: &mut H) {
1192        self.handle().hash(state)
1193    }
1194}
1195impl<'store, T> PartialOrd for ResultItem<'store, T>
1196where
1197    T: Storable,
1198{
1199    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1200        Some(self.handle().cmp(&other.handle()))
1201    }
1202}
1203impl<'store, T> Ord for ResultItem<'store, T>
1204where
1205    T: Storable,
1206{
1207    fn cmp(&self, other: &Self) -> Ordering {
1208        self.handle().cmp(&other.handle())
1209    }
1210}
1211
1212pub trait FullHandle<T>
1213where
1214    T: Storable,
1215{
1216    /// Returns the full handle (which may be a combination of multiple handles) to find this item
1217    fn fullhandle(&self) -> T::FullHandleType;
1218}
1219
1220impl<'store, T> ResultItem<'store, T>
1221where
1222    T: Storable,
1223{
1224    /// Create a new result item. Not public, called by [`StoreFor<T>::as_resultitem()`].
1225    /// will panic if called on an unbound item!
1226    pub(crate) fn new(
1227        item: &'store T,
1228        store: &'store T::StoreType,
1229        rootstore: &'store AnnotationStore,
1230    ) -> Self {
1231        if item.handle().is_none() {
1232            panic!("can't wrap unbound items");
1233        }
1234        Self {
1235            item,
1236            store,
1237            rootstore: Some(rootstore),
1238        }
1239    }
1240
1241    /// Create a new result item. Not public.
1242    /// Partial result items are dangerous as they are not bound to a rootstore, and
1243    /// this may cause run-time panics elsewhere.
1244    /// Do not return them in the public API!
1245    pub(crate) fn new_partial(item: &'store T, store: &'store T::StoreType) -> Self {
1246        if item.handle().is_none() {
1247            panic!("can't wrap unbound items");
1248        }
1249        Self {
1250            item,
1251            store,
1252            rootstore: None,
1253        }
1254    }
1255
1256    /// Get the store this item is a direct member of
1257    pub fn store(&self) -> &'store T::StoreType {
1258        self.store
1259    }
1260
1261    /// Get the underlying AnnotationStore
1262    pub fn rootstore(&self) -> &'store AnnotationStore {
1263        // This will panic for partial result items!
1264        self.rootstore
1265            .expect("Got a partial ResultItem, unable to get root annotationstore! This should not happen in the public API.")
1266    }
1267
1268    /// Returns the contained reference with the original lifetime
1269    #[inline]
1270    pub fn as_ref(&self) -> &'store T {
1271        //MAYBE TODO: This conflicts with the AsRef trait that has &self -> &T as signature , renamed this method to inner()?
1272        self.item
1273    }
1274
1275    /// Get the handle (internal identifier) for the contained item
1276    #[inline]
1277    pub fn handle(&self) -> T::HandleType {
1278        self.item
1279            .handle()
1280            .expect("handle was already guaranteed for ResultItem, this should always work")
1281    }
1282
1283    /// Get the public identifier for the contained item
1284    #[inline]
1285    pub fn id(&self) -> Option<&'store str> {
1286        self.item.id()
1287    }
1288}
1289
1290/// This trait defines the [`Self::or_fail`] method that is used to turn an `Option<T>` into `Result<T,StamError>`.
1291pub trait StamResult<T>
1292where
1293    T: TypeInfo,
1294{
1295    fn or_fail(self) -> Result<T, StamError>;
1296    fn or_fail_for_id(self, id: &str) -> Result<T, StamError>;
1297    fn or_fail_with<'a>(self, msg: Cow<'a, str>) -> Result<T, StamError>;
1298}
1299
1300impl<'store, T> StamResult<T> for Option<T>
1301where
1302    T: TypeInfo,
1303{
1304    fn or_fail(self) -> Result<T, StamError> {
1305        match self {
1306            Some(item) => Ok(item),
1307            None => Err(StamError::NotFoundError(
1308                T::typeinfo(),
1309                "Expected a result, got nothing".into(),
1310            )),
1311        }
1312    }
1313    fn or_fail_for_id(self, id: &str) -> Result<T, StamError> {
1314        match self {
1315            Some(item) => Ok(item),
1316            None => Err(StamError::NotFoundError(T::typeinfo(), id.to_string())),
1317        }
1318    }
1319    fn or_fail_with<'a>(self, msg: Cow<'a, str>) -> Result<T, StamError> {
1320        match self {
1321            Some(item) => Ok(item),
1322            None => Err(StamError::NotFoundError(T::typeinfo(), msg.to_string())),
1323        }
1324    }
1325}
1326
1327#[sealed]
1328impl<T> TypeInfo for Option<ResultItem<'_, T>>
1329where
1330    T: Storable,
1331{
1332    fn typeinfo() -> Type {
1333        T::typeinfo()
1334    }
1335}
1336
1337/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1338
1339// the following structure may be a bit obscure but it required internally to
1340// make serialization via serde work on our stores
1341// (ideally it needn't be public)
1342
1343/// Helper structure that contains a store and a reference to self. Mostly for internal use.
1344pub(crate) struct WrappedStore<'a, T, S: StoreFor<T>>
1345where
1346    T: Storable,
1347    S: Sized,
1348{
1349    pub(crate) store: &'a Store<T>,
1350    pub(crate) parent: &'a S,
1351    pub(crate) substore: Option<AnnotationSubStoreHandle>,
1352}
1353
1354impl<'a, T, S> Deref for WrappedStore<'a, T, S>
1355where
1356    T: Storable,
1357    S: StoreFor<T>,
1358{
1359    type Target = Store<T>;
1360
1361    fn deref(&self) -> &Self::Target {
1362        self.store
1363    }
1364}
1365
1366///////////////////////////////// Any
1367
1368#[derive(Debug, Deserialize)]
1369#[serde(untagged)]
1370/// `BuildItem` offers various ways of referring to a data structure of type `T` in the core STAM model
1371/// It abstracts over public IDs (both owned an and borrowed), handles, and references.
1372pub enum BuildItem<'a, T>
1373where
1374    T: Storable,
1375{
1376    Id(String), //for deserialisation only this variant is available
1377
1378    #[serde(skip)]
1379    IdRef(&'a str),
1380
1381    #[serde(skip)]
1382    Ref(&'a T),
1383
1384    #[serde(skip)]
1385    Handle(T::HandleType),
1386
1387    #[serde(skip)]
1388    None,
1389}
1390
1391impl<'a, T> Clone for BuildItem<'a, T>
1392where
1393    T: Storable,
1394{
1395    fn clone(&self) -> Self {
1396        match self {
1397            Self::Id(s) => Self::Id(s.clone()),
1398            Self::IdRef(s) => Self::Id(s.to_string()),
1399            Self::Ref(r) => Self::Ref(*r),
1400            Self::Handle(h) => Self::Handle(*h),
1401            Self::None => Self::None,
1402        }
1403    }
1404}
1405
1406impl<'a, T> Default for BuildItem<'a, T>
1407where
1408    T: Storable,
1409{
1410    fn default() -> Self {
1411        Self::None
1412    }
1413}
1414
1415impl<'a, T> PartialEq for BuildItem<'a, T>
1416where
1417    T: Storable,
1418{
1419    fn eq(&self, other: &Self) -> bool {
1420        match (self, other) {
1421            (Self::Handle(x), Self::Handle(y)) => x == y,
1422            (Self::Id(x), Self::Id(y)) => x == y,
1423            (Self::IdRef(x), Self::IdRef(y)) => x == y,
1424            (Self::Id(x), Self::IdRef(y)) => x.as_str() == *y,
1425            (Self::IdRef(x), Self::Id(y)) => *x == y.as_str(),
1426            (Self::Ref(x), Self::Ref(y)) => x == y,
1427            (Self::Ref(x), Self::Id(y)) => x.id() == Some(y.as_str()),
1428            (Self::Ref(x), Self::IdRef(y)) => x.id() == Some(y),
1429            (Self::Id(x), Self::Ref(y)) => Some(x.as_str()) == y.id(),
1430            (Self::IdRef(x), Self::Ref(y)) => Some(*x) == y.id(),
1431            _ => false,
1432        }
1433    }
1434}
1435
1436impl<'a, T> BuildItem<'a, T>
1437where
1438    T: Storable,
1439{
1440    pub fn is_handle(&self) -> bool {
1441        matches!(self, Self::Handle(_))
1442    }
1443
1444    pub fn is_id(&self) -> bool {
1445        match self {
1446            Self::Id(_) => true,
1447            Self::IdRef(_) => true,
1448            _ => false,
1449        }
1450    }
1451
1452    pub fn is_none(&self) -> bool {
1453        matches!(self, Self::None)
1454    }
1455
1456    pub fn is_some(&self) -> bool {
1457        !matches!(self, Self::None)
1458    }
1459
1460    // raises an ID error
1461    pub(crate) fn error(&self, contextmsg: &'static str) -> StamError {
1462        match self {
1463            Self::Handle(_) => StamError::HandleError(contextmsg),
1464            Self::Id(id) => StamError::IdNotFoundError(id.to_string(), contextmsg),
1465            Self::IdRef(id) => StamError::IdNotFoundError(id.to_string(), contextmsg),
1466            Self::Ref(instance) => StamError::IdNotFoundError(
1467                instance.id().unwrap_or("(no id)").to_string(),
1468                contextmsg,
1469            ),
1470            Self::None => StamError::Unbound("Supplied AnyId is not bound to anything!"),
1471        }
1472    }
1473
1474    /// Returns the ID as a new string, returns None if only handle is contained
1475    pub fn to_string(self) -> Option<String> {
1476        if let Self::Id(s) = self {
1477            Some(s)
1478        } else if let Self::IdRef(s) = self {
1479            Some(s.to_string())
1480        } else {
1481            None
1482        }
1483    }
1484
1485    /// Returns the ID as str, returns None if only handle is contained
1486    pub fn as_str<'slf>(&'slf self) -> Option<&'slf str> {
1487        if let Self::Id(s) = self {
1488            Some(s.as_str())
1489        } else if let Self::IdRef(s) = self {
1490            Some(s)
1491        } else {
1492            None
1493        }
1494    }
1495
1496    /*
1497    pub fn to_id<'slf, 'store, S>(&'slf self, store: &'store S) -> Option<&'slf str>
1498    where
1499        S: StoreFor<T>,
1500        'store: 'slf,
1501    {
1502        match self {
1503            BuildItem::Id(id) => Some(id.as_str()),
1504            BuildItem::IdRef(id) => Some(id),
1505            BuildItem::Handle(_) => {
1506                if let Some(instance) = self.to_ref(store) {
1507                    instance.id()
1508                } else {
1509                    None
1510                }
1511            }
1512            BuildItem::Ref(instance) => instance.id(),
1513            BuildItem::None => None,
1514        }
1515    }
1516    */
1517}
1518
1519/// This trait is implemented for types that can serve as a request for a specific item of type `T` from the store.
1520/// It is typically implemented on strings (both owned and borrowed) in which case the request is for a particular public identifier,
1521/// or it is implemented on handles.
1522pub trait Request<T>
1523where
1524    T: Storable,
1525    Self: Sized,
1526{
1527    /// Returns the handle for this item, looking it up in the store
1528    fn to_handle<'store, S>(&self, store: &'store S) -> Option<T::HandleType>
1529    where
1530        S: StoreFor<T>;
1531
1532    /// If this type encapsulates an Id, this returns it (borrowed)
1533    fn requested_id(&self) -> Option<&str> {
1534        None
1535    }
1536    /// If this type encapsulates an Id, this returns it (oened)
1537    fn requested_id_owned(self) -> Option<String> {
1538        None
1539    }
1540    /// If this type encapsulates a handle, this returns it
1541    fn requested_handle(&self) -> Option<T::HandleType> {
1542        None
1543    }
1544
1545    /// Represents a request for any value in certain contexts
1546    fn any(&self) -> bool {
1547        false
1548    }
1549
1550    /*
1551    /// Resolves a requested item from a store, producing a ResultItem.
1552    fn resolve<'store, S>(self, store: &'store S) -> Option<ResultItem<'store, T>>
1553    where
1554        S: StoreFor<T>,
1555    {
1556        if let Ok(item) = store.get(self) {
1557            Some(ResultItem { store, item })
1558        } else {
1559            None
1560        }
1561    }
1562    */
1563}
1564
1565impl<'a, T> Request<T> for &'a str
1566where
1567    T: Storable,
1568{
1569    fn to_handle<'store, S>(&self, store: &'store S) -> Option<T::HandleType>
1570    where
1571        S: StoreFor<T>,
1572    {
1573        store.resolve_id(self).ok()
1574    }
1575    fn requested_id(&self) -> Option<&'a str> {
1576        Some(self)
1577    }
1578    fn requested_id_owned(self) -> Option<String> {
1579        Some(self.to_string())
1580    }
1581    fn any(&self) -> bool {
1582        self.is_empty()
1583    }
1584}
1585
1586impl<'a, T> Request<T> for bool
1587where
1588    T: Storable,
1589{
1590    fn to_handle<'store, S>(&self, _store: &'store S) -> Option<T::HandleType>
1591    where
1592        S: StoreFor<T>,
1593    {
1594        None
1595    }
1596    fn any(&self) -> bool {
1597        true
1598    }
1599}
1600
1601impl<'a, T> Request<T> for String
1602where
1603    T: Storable,
1604{
1605    fn to_handle<'store, S>(&self, store: &'store S) -> Option<T::HandleType>
1606    where
1607        S: StoreFor<T>,
1608    {
1609        store.resolve_id(self.as_str()).ok()
1610    }
1611    fn requested_id(&self) -> Option<&str> {
1612        Some(self.as_str())
1613    }
1614    fn requested_id_owned(self) -> Option<String> {
1615        Some(self)
1616    }
1617    fn any(&self) -> bool {
1618        self.is_empty()
1619    }
1620}
1621
1622impl<'a, T> Request<T> for ResultItem<'a, T>
1623where
1624    T: Storable,
1625{
1626    fn to_handle<'store, S>(&self, _store: &'store S) -> Option<T::HandleType>
1627    where
1628        S: StoreFor<T>,
1629    {
1630        Some(self.handle())
1631    }
1632}
1633
1634impl<'a, T> Request<T> for &ResultItem<'a, T>
1635where
1636    T: Storable,
1637{
1638    fn to_handle<'store, S>(&self, _store: &'store S) -> Option<T::HandleType>
1639    where
1640        S: StoreFor<T>,
1641    {
1642        Some(self.handle())
1643    }
1644}
1645
1646impl<'a, T> Request<T> for BuildItem<'a, T>
1647where
1648    T: Storable,
1649{
1650    fn to_handle<'store, S>(&self, store: &'store S) -> Option<T::HandleType>
1651    where
1652        S: StoreFor<T>,
1653    {
1654        match self {
1655            BuildItem::Id(id) => store.resolve_id(id.as_str()).ok(),
1656            BuildItem::IdRef(id) => store.resolve_id(id).ok(),
1657            BuildItem::Handle(handle) => Some(*handle),
1658            BuildItem::Ref(instance) => instance.handle(),
1659            BuildItem::None => None,
1660        }
1661    }
1662}
1663
1664impl<'a, T> Request<T> for &BuildItem<'a, T>
1665where
1666    T: Storable,
1667{
1668    fn to_handle<'store, S>(&self, store: &'store S) -> Option<T::HandleType>
1669    where
1670        S: StoreFor<T>,
1671    {
1672        match self {
1673            BuildItem::Id(id) => store.resolve_id(id.as_str()).ok(),
1674            BuildItem::IdRef(id) => store.resolve_id(id).ok(),
1675            BuildItem::Handle(handle) => Some(*handle),
1676            BuildItem::Ref(instance) => instance.handle(),
1677            BuildItem::None => None,
1678        }
1679    }
1680}
1681
1682impl<'a, T> From<&'a str> for BuildItem<'a, T>
1683where
1684    T: Storable,
1685{
1686    fn from(id: &'a str) -> Self {
1687        if id.is_empty() {
1688            Self::None
1689        } else {
1690            Self::IdRef(id)
1691        }
1692    }
1693}
1694impl<'a, T> From<Option<&'a str>> for BuildItem<'a, T>
1695where
1696    T: Storable,
1697{
1698    fn from(id: Option<&'a str>) -> Self {
1699        if let Some(id) = id {
1700            if id.is_empty() {
1701                Self::None
1702            } else {
1703                Self::IdRef(id)
1704            }
1705        } else {
1706            Self::None
1707        }
1708    }
1709}
1710
1711impl<'a, T> From<String> for BuildItem<'a, T>
1712where
1713    T: Storable,
1714{
1715    fn from(id: String) -> Self {
1716        if id.is_empty() {
1717            Self::None
1718        } else {
1719            Self::Id(id)
1720        }
1721    }
1722}
1723
1724impl<'a, T> From<&'a String> for BuildItem<'a, T>
1725where
1726    T: Storable,
1727{
1728    fn from(id: &'a String) -> Self {
1729        if id.is_empty() {
1730            Self::None
1731        } else {
1732            Self::IdRef(id.as_str())
1733        }
1734    }
1735}
1736
1737impl<'a, T> From<Option<String>> for BuildItem<'a, T>
1738where
1739    T: Storable,
1740{
1741    fn from(id: Option<String>) -> Self {
1742        if let Some(id) = id {
1743            if id.is_empty() {
1744                Self::None
1745            } else {
1746                Self::Id(id)
1747            }
1748        } else {
1749            Self::None
1750        }
1751    }
1752}
1753
1754impl<'a, T> From<&'a T> for BuildItem<'a, T>
1755where
1756    T: Storable,
1757{
1758    fn from(instance: &'a T) -> Self {
1759        Self::Ref(instance)
1760    }
1761}
1762
1763impl<'a, T> From<usize> for BuildItem<'a, T>
1764where
1765    T: Storable,
1766{
1767    fn from(handle: usize) -> Self {
1768        Self::Handle(T::HandleType::new(handle))
1769    }
1770}
1771
1772impl<'a, T> From<Option<usize>> for BuildItem<'a, T>
1773where
1774    T: Storable,
1775{
1776    fn from(handle: Option<usize>) -> Self {
1777        if let Some(handle) = handle {
1778            Self::Handle(T::HandleType::new(handle))
1779        } else {
1780            Self::None
1781        }
1782    }
1783}
1784
1785impl<'a, T> From<&ResultItem<'a, T>> for BuildItem<'a, T>
1786where
1787    T: Storable,
1788{
1789    fn from(result: &ResultItem<'a, T>) -> Self {
1790        Self::Ref(result.as_ref())
1791    }
1792}
1793
1794impl<'a, T> PartialEq<&str> for BuildItem<'a, T>
1795where
1796    T: Storable,
1797{
1798    fn eq(&self, other: &&str) -> bool {
1799        match self {
1800            Self::Id(v) => v.as_str() == *other,
1801            _ => false,
1802        }
1803    }
1804}
1805
1806impl<'a, T> PartialEq<str> for BuildItem<'a, T>
1807where
1808    T: Storable,
1809{
1810    fn eq(&self, other: &str) -> bool {
1811        match self {
1812            Self::Id(v) => v.as_str() == other,
1813            Self::IdRef(v) => *v == other,
1814            Self::Ref(r) => r.id() == Some(other),
1815            _ => false,
1816        }
1817    }
1818}
1819
1820impl<'a, T> PartialEq<String> for BuildItem<'a, T>
1821where
1822    T: Storable,
1823{
1824    fn eq(&self, other: &String) -> bool {
1825        match self {
1826            Self::Id(v) => v == other,
1827            Self::IdRef(v) => *v == other.as_str(),
1828            Self::Ref(r) => r.id() == Some(other),
1829            _ => false,
1830        }
1831    }
1832}
1833
1834/// Test if this is a temporary public identifier,
1835/// they have a form like `!A0` . They start with an exclamation mark,
1836/// a capital letter indicates the type (A for Annotation), and a number
1837/// corresponds to whatever was the internal handle.
1838pub(crate) fn resolve_temp_id(id: &str) -> Option<usize> {
1839    let mut iter = id.chars();
1840    if let Some('!') = iter.next() {
1841        if let Some(x) = iter.next() {
1842            if !x.is_uppercase() {
1843                return None;
1844            }
1845            return Some(id[2..].parse().ok()?);
1846        }
1847    }
1848    None
1849}
1850
1851/// Generate an ID with a random 21-byte and ID/URI-safe component
1852/// This does no collision check (but they will be *extremely* unlikely)
1853pub fn generate_id(prefix: &str, suffix: &str) -> String {
1854    format!("{}{}{}", prefix, nanoid!(ID_LEN, &ID_ALPHABET), suffix)
1855}
1856
1857#[derive(Clone, Debug)]
1858pub enum IdStrategy {
1859    /// The new ID is formed by adding a static suffix to the old ID
1860    AddSuffix(String),
1861    /// The new ID is formed by adding random suffix (nanoid) to the old ID
1862    AddRandomSuffix,
1863    /// The new ID is formed by adding a static prefix to the old ID
1864    AddPrefix(String),
1865    /// The new ID is formed by adding or incrementing a version suffix (v1,v2,v3,etc) to the old ID
1866    UpdateVersion,
1867    /// The new ID is formed by simply replacing the old ID with a static new one
1868    Replace(String),
1869    /// The new ID is formed by simply replacing the old ID with a prefix, a random component (nanoid), and a suffix
1870    ReplaceRandom { prefix: String, suffix: String },
1871}
1872
1873impl Default for IdStrategy {
1874    fn default() -> Self {
1875        Self::UpdateVersion
1876    }
1877}
1878
1879/// Take an existing ID an apply a update stategy to create a derived new ID
1880pub fn regenerate_id<'a>(id: &'a str, strategy: &'a IdStrategy) -> String {
1881    match strategy {
1882        IdStrategy::AddSuffix(s) => {
1883            format!("{}{}", id, s)
1884        }
1885        IdStrategy::AddRandomSuffix => {
1886            format!("{}{}", id, nanoid!(ID_LEN, &ID_ALPHABET))
1887        }
1888        IdStrategy::AddPrefix(s) => {
1889            format!("{}{}", s, id)
1890        }
1891        IdStrategy::Replace(s) => s.clone(),
1892        IdStrategy::ReplaceRandom { prefix, suffix } => generate_id(prefix, suffix),
1893        IdStrategy::UpdateVersion => {
1894            if let Some(pos) = id.rfind(|c: char| c.is_ascii_punctuation()) {
1895                let mut version = &id[pos + 1..];
1896                if version.chars().next() == Some('v') {
1897                    version = &id[pos + 2..];
1898                    if let Ok(mut version) = version.parse::<usize>() {
1899                        version += 1;
1900                        return format!("{}v{}", &id[..pos + 1], version);
1901                    }
1902                }
1903            }
1904            format!("{}/v2", &id)
1905        }
1906    }
1907}
1908
1909impl TryFrom<&str> for IdStrategy {
1910    type Error = StamError;
1911    fn try_from(value: &str) -> Result<Self, Self::Error> {
1912        if let Some(pos) = value.find("=") {
1913            let strategy = &value[0..pos];
1914            if pos + 1 >= value.len() {
1915                Err(StamError::DeserializationError(format!(
1916                    "IdStrategy expects value after = "
1917                )))
1918            } else {
1919                let value = &value[pos + 1..];
1920                match strategy {
1921                    "suffix" | "addsuffix" => Ok(Self::AddSuffix(value.to_string())),
1922                    "prefix" | "addprefix" => Ok(Self::AddPrefix(value.to_string())),
1923                    "replace" => Ok(Self::Replace(value.to_string())),
1924                    "replacerandom" => {
1925                        let (prefix, suffix) = if let Some(pos) = value.find(";") {
1926                            (value[0..pos].to_string(), value[pos + 1..].to_string())
1927                        } else {
1928                            (value.to_string(), String::new())
1929                        };
1930                        Ok(Self::ReplaceRandom { prefix, suffix })
1931                    }
1932                    _ => Err(StamError::DeserializationError(format!(
1933                        "Invalid IdStrategy: {}",
1934                        strategy
1935                    ))),
1936                }
1937            }
1938        } else {
1939            match value {
1940                "version" | "updateversion" => Ok(Self::UpdateVersion),
1941                "random" | "randomsuffix" => Ok(Self::AddRandomSuffix),
1942                _ => Err(StamError::DeserializationError(format!(
1943                    "Invalid IdStrategy: {}",
1944                    value
1945                ))),
1946            }
1947        }
1948    }
1949}