stac_server/backend/
memory.rs1use 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#[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 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}