Skip to main content

vstorage/
disco.rs

1//! Types related to collection discovery.
2//!
3//! Discovery is the process of automatically locating collections inside a storage.
4
5use std::collections::HashSet;
6
7use crate::CollectionId;
8
9/// Collection found during discovery.
10pub struct DiscoveredCollection {
11    // TODO: this does an eager calculation of the CollectionId.
12    //       ideally, we'd do this on-demand.
13    href: String,
14    id: CollectionId,
15}
16
17impl DiscoveredCollection {
18    /// Create a new instance.
19    ///
20    /// Should only be used when implementing discovery for storage implementations.
21    #[must_use]
22    pub fn new(href: String, id: CollectionId) -> DiscoveredCollection {
23        DiscoveredCollection { href, id }
24    }
25
26    /// Return the path for this collection.
27    #[must_use]
28    pub fn href(&self) -> &str {
29        &self.href
30    }
31
32    /// Return the collection id for this collection.
33    #[must_use]
34    pub fn id(&self) -> &CollectionId {
35        &self.id
36    }
37}
38
39/// Result of running discovery on a `Storage`.
40///
41/// See [`crate::base::Storage::discover_collections`].
42pub struct Discovery {
43    // INVARIANT: each collection has a unique id.
44    collections: Vec<DiscoveredCollection>,
45}
46
47impl Discovery {
48    /// All discovered collections.
49    #[must_use]
50    pub fn collections(&self) -> &[DiscoveredCollection] {
51        &self.collections
52    }
53
54    /// Total amount of discovered collections.
55    #[must_use]
56    pub fn collection_count(&self) -> usize {
57        self.collections.len()
58    }
59
60    /// Find a collection with a matching id.
61    pub(super) fn find_collection_by_id<'disco>(
62        self: &'disco Discovery,
63        id: &CollectionId,
64    ) -> Option<&'disco DiscoveredCollection> {
65        self.collections().iter().find(|c| c.id == *id)
66    }
67}
68
69#[derive(thiserror::Error, Debug)]
70#[error("Multiple collections share the same id.")]
71pub struct DuplicateIds;
72
73impl TryFrom<Vec<DiscoveredCollection>> for Discovery {
74    type Error = DuplicateIds;
75
76    fn try_from(collections: Vec<DiscoveredCollection>) -> Result<Self, DuplicateIds> {
77        let mut seen_ids = HashSet::new();
78        for collection in &collections {
79            if !seen_ids.insert(&collection.id) {
80                return Err(DuplicateIds);
81            }
82        }
83        Ok(Discovery { collections })
84    }
85}