1use crate::directory::directory_layer::DirectoryLayer;
12use crate::directory::error::DirectoryError;
13use crate::directory::{Directory, DirectoryOutput};
14use crate::tuple::{PackResult, Subspace, TuplePack, TupleUnpack};
15use crate::Transaction;
16use async_trait::async_trait;
17
18#[derive(Debug, Clone)]
23pub struct DirectorySubspace {
24 pub(crate) directory_layer: DirectoryLayer,
25 subspace: Subspace,
26 path: Vec<String>,
27 layer: Vec<u8>,
28}
29
30impl DirectorySubspace {
31 pub fn new(
32 path: &[String],
33 prefix: Vec<u8>,
34 directory_layer: &DirectoryLayer,
35 layer: Vec<u8>,
36 ) -> Self {
37 DirectorySubspace {
38 directory_layer: directory_layer.clone(),
39 subspace: Subspace::from_bytes(prefix),
40 path: Vec::from(path),
41 layer,
42 }
43 }
44
45 fn get_partition_subpath(
47 &self,
48 path: &[String],
49 directory_layer: Option<DirectoryLayer>,
50 ) -> Result<Vec<String>, DirectoryError> {
51 let directory = match directory_layer {
52 None => self.directory_layer.clone(),
53 Some(d) => d,
54 };
55
56 if directory.path.len() > self.path.len() {
57 return Err(DirectoryError::CannotCreateSubpath);
58 }
59
60 let mut new_path = vec![];
61
62 new_path.extend_from_slice(&self.path[directory.path.len()..]);
63 new_path.extend_from_slice(path);
64
65 Ok(new_path)
66 }
67}
68
69impl DirectorySubspace {
70 pub fn subspace<T: TuplePack>(&self, t: &T) -> Subspace {
71 self.subspace.subspace(t)
72 }
73
74 pub fn bytes(&self) -> &[u8] {
75 self.subspace.bytes()
76 }
77
78 pub fn pack<T: TuplePack>(&self, t: &T) -> Vec<u8> {
79 self.subspace.pack(t)
80 }
81
82 pub fn unpack<'de, T: TupleUnpack<'de>>(&self, key: &'de [u8]) -> PackResult<T> {
83 self.subspace.unpack(key)
84 }
85
86 pub fn range(&self) -> (Vec<u8>, Vec<u8>) {
87 self.subspace.range()
88 }
89
90 pub fn get_path(&self) -> &[String] {
91 self.path.as_slice()
92 }
93
94 pub fn set_path(&mut self, path: Vec<String>) {
95 self.path = path;
96 }
97
98 pub fn get_layer(&self) -> &[u8] {
99 self.layer.as_slice()
100 }
101
102 pub fn is_start_of(&self, key: &[u8]) -> bool {
103 self.subspace.is_start_of(key)
104 }
105
106 fn get_directory_layer_for_path(&self, _: &[String]) -> DirectoryLayer {
107 self.directory_layer.clone()
108 }
109}
110
111#[async_trait]
112impl Directory for DirectorySubspace {
113 async fn create_or_open(
114 &self,
115 txn: &Transaction,
116 path: &[String],
117 prefix: Option<&[u8]>,
118 layer: Option<&[u8]>,
119 ) -> Result<DirectoryOutput, DirectoryError> {
120 self.directory_layer
121 .create_or_open(txn, &self.get_partition_subpath(path, None)?, prefix, layer)
122 .await
123 }
124
125 async fn create(
126 &self,
127 txn: &Transaction,
128 path: &[String],
129 prefix: Option<&[u8]>,
130 layer: Option<&[u8]>,
131 ) -> Result<DirectoryOutput, DirectoryError> {
132 self.directory_layer
133 .create(txn, &self.get_partition_subpath(path, None)?, prefix, layer)
134 .await
135 }
136
137 async fn open(
138 &self,
139 txn: &Transaction,
140 path: &[String],
141 layer: Option<&[u8]>,
142 ) -> Result<DirectoryOutput, DirectoryError> {
143 self.directory_layer
144 .open(txn, &self.get_partition_subpath(path, None)?, layer)
145 .await
146 }
147
148 async fn exists(&self, trx: &Transaction, path: &[String]) -> Result<bool, DirectoryError> {
149 let directory_layer = self.get_directory_layer_for_path(path);
150
151 directory_layer
152 .exists(
153 trx,
154 &self.get_partition_subpath(path, Some(directory_layer.clone()))?,
155 )
156 .await
157 }
158
159 async fn move_directory(
160 &self,
161 trx: &Transaction,
162 new_path: &[String],
163 ) -> Result<DirectoryOutput, DirectoryError> {
164 let directory_layer = self.get_directory_layer_for_path(&[]);
165 let directory_layer_path = &directory_layer.path;
166
167 if directory_layer_path.len() > new_path.len() {
168 return Err(DirectoryError::CannotMoveBetweenPartition);
169 }
170
171 for (i, path) in directory_layer_path.iter().enumerate() {
172 match new_path.get(i) {
173 None => return Err(DirectoryError::CannotMoveBetweenPartition),
174 Some(new_path_item) => {
175 if !new_path_item.eq(path) {
176 return Err(DirectoryError::CannotMoveBetweenPartition);
177 }
178 }
179 }
180 }
181
182 let mut new_relative_path = vec![];
183 new_relative_path.extend_from_slice(&new_path[directory_layer_path.len()..]);
184
185 directory_layer
186 .move_to(
187 trx,
188 &self.get_partition_subpath(&[], Some(directory_layer.clone()))?,
189 &new_relative_path,
190 )
191 .await
192 }
193
194 async fn move_to(
195 &self,
196 trx: &Transaction,
197 old_path: &[String],
198 new_path: &[String],
199 ) -> Result<DirectoryOutput, DirectoryError> {
200 self.directory_layer
201 .move_to(
202 trx,
203 &self.get_partition_subpath(old_path, None)?,
204 &self.get_partition_subpath(new_path, None)?,
205 )
206 .await
207 }
208
209 async fn remove(&self, trx: &Transaction, path: &[String]) -> Result<bool, DirectoryError> {
210 let directory_layer = self.get_directory_layer_for_path(path);
211 directory_layer
212 .remove(
213 trx,
214 &self.get_partition_subpath(path, Some(directory_layer.clone()))?,
215 )
216 .await
217 }
218
219 async fn remove_if_exists(
220 &self,
221 trx: &Transaction,
222 path: &[String],
223 ) -> Result<bool, DirectoryError> {
224 let directory_layer = self.get_directory_layer_for_path(path);
225 directory_layer
226 .remove_if_exists(
227 trx,
228 &self.get_partition_subpath(path, Some(directory_layer.clone()))?,
229 )
230 .await
231 }
232
233 async fn list(
234 &self,
235 trx: &Transaction,
236 path: &[String],
237 ) -> Result<Vec<String>, DirectoryError> {
238 self.directory_layer
239 .list(trx, &self.get_partition_subpath(path, None)?)
240 .await
241 }
242}