ps_hkey/store/
combined.rs1use std::ops::{Deref, DerefMut};
2
3use ps_datachunk::{BorrowedDataChunk, DataChunk, OwnedDataChunk, PsDataChunkError};
4use ps_hash::Hash;
5
6use crate::{PsHkeyError, Store};
7
8pub trait DynStore: Send + Sync {
9 type Error: From<PsDataChunkError> + From<PsHkeyError> + Send + 'static;
10
11 fn get(&self, hash: &Hash) -> Result<OwnedDataChunk, Self::Error>;
12 fn put_encrypted(&self, chunk: BorrowedDataChunk<'_>) -> Result<(), Self::Error>;
13}
14
15impl<T> DynStore for T
16where
17 T: Store + Send + Sync + 'static,
18{
19 type Error = T::Error;
20
21 fn get(&self, hash: &Hash) -> Result<OwnedDataChunk, Self::Error> {
22 Ok(Store::get(self, hash)?.into_owned())
23 }
24
25 fn put_encrypted(&self, chunk: BorrowedDataChunk<'_>) -> Result<(), Self::Error> {
26 Store::put_encrypted(self, chunk)
27 }
28}
29
30#[derive(Default)]
31pub struct CombinedStore<E: CombinedStoreError, const WRITE_TO_ALL: bool> {
32 stores: Vec<Box<dyn DynStore<Error = E>>>,
33}
34
35impl<E: CombinedStoreError, const WRITE_TO_ALL: bool> CombinedStore<E, WRITE_TO_ALL> {
36 #[must_use]
38 pub fn new<S, I>(stores: I) -> Self
39 where
40 S: Store<Error = E> + Send + Sync + 'static,
41 I: IntoIterator<Item = S>,
42 {
43 Self {
44 stores: stores.into_iter().map(|s| Box::new(s) as _).collect(),
45 }
46 }
47
48 pub fn push<S>(&mut self, store: S)
49 where
50 S: Store<Error = E> + Send + Sync + 'static,
51 {
52 self.stores.push(Box::new(store));
53 }
54
55 pub fn extend<S, I>(&mut self, iter: I)
56 where
57 S: Store<Error = E> + Send + Sync + 'static,
58 I: IntoIterator<Item = S>,
59 {
60 self.stores
61 .extend(iter.into_iter().map(|s| Box::new(s) as _));
62 }
63
64 #[must_use]
65 pub fn write_to_all(self) -> CombinedStore<E, true> {
66 CombinedStore {
67 stores: self.stores,
68 }
69 }
70
71 #[must_use]
72 pub fn write_to_one(self) -> CombinedStore<E, false> {
73 CombinedStore {
74 stores: self.stores,
75 }
76 }
77
78 fn get(&self, hash: &Hash) -> Result<OwnedDataChunk, E> {
79 let mut last_err = None;
80
81 for s in self.iter() {
82 match s.get(hash) {
83 Ok(chunk) => return Ok(chunk),
84 Err(err) => last_err = Some(err),
85 }
86 }
87
88 Err(last_err.unwrap_or_else(E::no_stores))
89 }
90}
91
92impl<E: CombinedStoreError, const WRITE_TO_ALL: bool> Deref for CombinedStore<E, WRITE_TO_ALL> {
93 type Target = Vec<Box<dyn DynStore<Error = E>>>;
94
95 fn deref(&self) -> &Self::Target {
96 &self.stores
97 }
98}
99
100impl<E: CombinedStoreError, const WRITE_TO_ALL: bool> DerefMut for CombinedStore<E, WRITE_TO_ALL> {
101 fn deref_mut(&mut self) -> &mut Self::Target {
102 &mut self.stores
103 }
104}
105
106impl<E: CombinedStoreError> Store for CombinedStore<E, true> {
107 type Chunk<'c> = OwnedDataChunk;
108 type Error = E;
109
110 fn get<'a>(&'a self, hash: &Hash) -> Result<Self::Chunk<'a>, Self::Error> {
111 self.get(hash)
112 }
113
114 fn put_encrypted<C: DataChunk>(&self, chunk: C) -> Result<(), Self::Error> {
115 if self.is_empty() {
116 return Err(E::no_stores());
117 }
118
119 let mut result = Ok(());
120
121 for s in self.iter() {
122 result = result.and(s.put_encrypted(chunk.borrow()));
123 }
124
125 result
126 }
127}
128
129impl<E: CombinedStoreError> Store for CombinedStore<E, false> {
130 type Chunk<'c> = OwnedDataChunk;
131 type Error = E;
132
133 fn get<'a>(&'a self, hash: &Hash) -> Result<Self::Chunk<'a>, Self::Error> {
134 self.get(hash)
135 }
136
137 fn put_encrypted<C: DataChunk>(&self, chunk: C) -> Result<(), Self::Error> {
138 let mut last_err = None;
139
140 for store in self.iter() {
141 match store.put_encrypted(chunk.borrow()) {
142 Ok(()) => return Ok(()),
143 Err(err) => last_err = Some(err),
144 }
145 }
146
147 Err(last_err.unwrap_or_else(E::no_stores))
148 }
149}
150
151pub trait CombinedStoreError: From<PsDataChunkError> + From<PsHkeyError> + Send + 'static {
152 fn no_stores() -> Self;
153}