stac_server/backend/
memory.rs

1use crate::{Backend, Error, Result, DEFAULT_LIMIT};
2use serde_json::Map;
3use stac::{Collection, Item};
4use stac_api::{ItemCollection, Items, Search};
5use std::{
6    collections::{BTreeMap, HashMap},
7    sync::{Arc, RwLock},
8};
9
10/// A naive backend that stores collections and items in memory.
11///
12/// This backend is meant to be used for testing and toy servers, not for production.
13#[derive(Clone, Debug)]
14pub struct MemoryBackend {
15    collections: Arc<RwLock<BTreeMap<String, Collection>>>,
16    items: Arc<RwLock<HashMap<String, Vec<Item>>>>,
17}
18
19impl MemoryBackend {
20    /// Creates a new memory backend.
21    ///
22    /// # Examples
23    ///
24    /// ```
25    /// use stac_server::MemoryBackend;
26    /// let backend = MemoryBackend::new();
27    /// ```
28    pub fn new() -> MemoryBackend {
29        MemoryBackend {
30            collections: Arc::new(RwLock::new(BTreeMap::new())),
31            items: Arc::new(RwLock::new(HashMap::new())),
32        }
33    }
34}
35
36impl Backend for MemoryBackend {
37    fn has_item_search(&self) -> bool {
38        true
39    }
40
41    fn has_filter(&self) -> bool {
42        false
43    }
44
45    async fn collections(&self) -> Result<Vec<Collection>> {
46        let collections = self.collections.read().unwrap();
47        Ok(collections.values().cloned().collect())
48    }
49
50    async fn collection(&self, id: &str) -> Result<Option<Collection>> {
51        let collections = self.collections.read().unwrap();
52        Ok(collections.get(id).cloned())
53    }
54
55    async fn add_collection(&mut self, collection: Collection) -> Result<()> {
56        let mut collections = self.collections.write().unwrap();
57        let _ = collections.insert(collection.id.clone(), collection);
58        Ok(())
59    }
60
61    async fn add_item(&mut self, item: Item) -> Result<()> {
62        if let Some(collection_id) = item.collection.clone() {
63            if self.collection(&collection_id).await?.is_none() {
64                Err(Error::MemoryBackend(format!(
65                    "no collection with id='{}'",
66                    collection_id
67                )))
68            } else {
69                let mut items = self.items.write().unwrap();
70                items.entry(collection_id).or_default().push(item);
71                Ok(())
72            }
73        } else {
74            Err(Error::MemoryBackend(format!(
75                "collection not set on item: {}",
76                item.id
77            )))
78        }
79    }
80
81    async fn items(&self, collection_id: &str, items: Items) -> Result<Option<ItemCollection>> {
82        {
83            let collections = self.collections.read().unwrap();
84            if !collections.contains_key(collection_id) {
85                return Ok(None);
86            }
87        };
88        let search = items.search_collection(collection_id);
89        self.search(search).await.map(Some)
90    }
91
92    async fn item(&self, collection_id: &str, item_id: &str) -> Result<Option<Item>> {
93        let items = self.items.read().unwrap();
94        Ok(items
95            .get(collection_id)
96            .and_then(|items| items.iter().find(|item| item.id == item_id).cloned()))
97    }
98
99    async fn search(&self, mut search: Search) -> Result<ItemCollection> {
100        let items = self.items.read().unwrap();
101        if search.collections.is_empty() {
102            search.collections = items.keys().cloned().collect();
103        }
104        let mut item_references = Vec::new();
105        for collection in &search.collections {
106            if let Some(items) = items.get(collection) {
107                item_references.extend(
108                    items
109                        .iter()
110                        .filter(|item| search.matches(item).unwrap_or_default()),
111                );
112            }
113        }
114        let limit = search.limit.unwrap_or(DEFAULT_LIMIT).try_into()?;
115        let skip = search
116            .additional_fields
117            .get("skip")
118            .and_then(|skip| skip.as_str())
119            .and_then(|skip| skip.parse::<u64>().ok())
120            .unwrap_or_default()
121            .try_into()?;
122        let len = item_references.len();
123        let items = item_references
124            .into_iter()
125            .skip(skip)
126            .take(limit)
127            .map(|item| stac_api::Item::try_from(item.clone()).map_err(Error::from))
128            .collect::<Result<Vec<_>>>()?;
129        let mut item_collection = ItemCollection::new(items)?;
130        if len > item_collection.items.len() + skip {
131            let mut next = Map::new();
132            let _ = next.insert("skip".to_string(), (skip + limit).into());
133            item_collection.next = Some(next);
134        }
135        if skip > 0 {
136            let mut prev = Map::new();
137            let skip = skip.saturating_sub(limit);
138            let _ = prev.insert("skip".to_string(), skip.into());
139            item_collection.prev = Some(prev);
140        }
141        Ok(item_collection)
142    }
143}
144
145impl Default for MemoryBackend {
146    fn default() -> Self {
147        Self::new()
148    }
149}