first cut at adding 'contains_key' to `trait Store`
[hiphop-php.git] / hphp / hack / src / hackrs / datastore / datastore.rs
blob15aef7d1ae6081be0f15165a462afe136c2e2328
1 // Copyright (c) Meta Platforms, Inc. and affiliates.
2 //
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
6 mod changes_store;
7 mod delta_store;
8 mod empty;
9 mod non_evicting;
11 use std::fmt::Debug;
13 use anyhow::Result;
14 pub use changes_store::ChangesStore;
15 pub use delta_store::DeltaStore;
16 pub use empty::EmptyStore;
17 pub use non_evicting::NonEvictingLocalStore;
18 pub use non_evicting::NonEvictingStore;
20 /// A threadsafe datastore, intended for global decl storage. The key type is
21 /// intended to be a `Symbol` or tuple of `Symbol`s, and the value type is
22 /// intended to be a ref-counted pointer (like `Arc` or `Hc`).
23 pub trait Store<K: Copy, V>: Debug + Send + Sync {
24     fn get(&self, key: K) -> Result<Option<V>>;
25     fn insert(&self, key: K, val: V) -> Result<()>;
27     /// Return `true` if the store contains a value for the given key (i.e.,
28     /// `self.get(key)?.is_some()` would evaluate to `true`).
29     ///
30     /// A default implementation is provided which uses the store's
31     /// implementation of `Store::get`, but some implementors will be able to
32     /// implement `contains_key` more efficiently than `get`.
33     fn contains_key(&self, key: K) -> Result<bool> {
34         Ok(self.get(key)?.is_some())
35     }
37     /// Implementations should return an error if a key to be removed does not
38     /// exist.
39     fn remove_batch(&self, keys: &mut dyn Iterator<Item = K>) -> Result<()>;
41     /// Implementations should return an error if a key to be moved does not
42     /// exist and well defined behavior is not a requirement if a key occurs in
43     /// both an old and new position.
44     fn move_batch(&self, keys: &mut dyn Iterator<Item = (K, K)>) -> Result<()> {
45         for (old_key, new_key) in keys {
46             if let Some(val) = self.get(old_key)? {
47                 self.remove_batch(&mut std::iter::once(old_key))?;
48                 self.insert(new_key, val)?;
49             } else {
50                 anyhow::bail!("move_batch: Trying to remove a non-existent value");
51             }
52         }
53         Ok(())
54     }
57 /// A thread-local datastore, intended for decl caching in typechecker workers.
58 /// The key type is intended to be a `Symbol` or tuple of `Symbol`s, and the
59 /// value type is intended to be a ref-counted pointer (like `Rc`).
60 pub trait LocalStore<K: Copy, V>: Debug {
61     fn get(&self, key: K) -> Option<V>;
62     fn insert(&mut self, key: K, val: V);
63     fn remove_batch(&mut self, keys: &mut dyn Iterator<Item = K>);
66 /// A readonly threadsafe datastore, intended to model readonly data sources
67 /// (like the filesystem in file_provider, or the naming SQLite database in
68 /// naming_provider) in terms of `datastore` traits (for purposes like
69 /// `DeltaStore`).
70 pub trait ReadonlyStore<K: Copy, V>: Send + Sync {
71     fn get(&self, key: K) -> Result<Option<V>>;
72     fn contains_key(&self, key: K) -> Result<bool> {
73         Ok(self.get(key)?.is_some())
74     }
77 impl<T: Store<K, V>, K: Copy, V> ReadonlyStore<K, V> for T {
78     fn contains_key(&self, key: K) -> Result<bool> {
79         Store::contains_key(self, key)
80     }
82     fn get(&self, key: K) -> Result<Option<V>> {
83         Store::get(self, key)
84     }