1use crate::object_store::{DirType, PosixAttributes, Timestamp};
6use anyhow::Error;
7use async_trait::async_trait;
8use std::future::Future;
9use std::sync::Arc;
10use storage_device::buffer::{BufferFuture, BufferRef, MutableBufferRef};
11use storage_units::BlockSize;
12
13pub const INVALID_OBJECT_ID: u64 = 0;
16
17pub trait ObjectHandle: Send + Sync + 'static {
20 fn object_id(&self) -> u64;
23
24 fn block_size(&self) -> BlockSize;
27
28 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_>;
30
31 fn set_trace(&self, _v: bool) {}
33}
34
35#[derive(Clone, Debug, PartialEq)]
36pub struct ObjectProperties {
37 pub refs: u64,
39 pub allocated_size: u64,
41 pub data_attribute_size: u64,
44 pub creation_time: Timestamp,
46 pub modification_time: Timestamp,
48 pub access_time: Timestamp,
50 pub change_time: Timestamp,
52 pub sub_dirs: u64,
54 pub posix_attributes: Option<PosixAttributes>,
56 pub dir_type: DirType,
58}
59
60#[async_trait]
61pub trait ReadObjectHandle: ObjectHandle {
62 async fn read_aligned(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error>;
70
71 fn get_size(&self) -> u64;
73}
74
75pub trait WriteObjectHandle: ObjectHandle {
76 fn write_or_append(
81 &self,
82 offset: Option<u64>,
83 buf: BufferRef<'_>,
84 ) -> impl Future<Output = Result<u64, Error>> + Send;
85
86 fn truncate(&self, size: u64) -> impl Future<Output = Result<(), Error>> + Send;
90
91 fn flush(&self) -> impl Future<Output = Result<(), Error>> + Send;
93}
94
95pub trait WriteBytes: Sized {
97 fn block_size(&self) -> BlockSize;
98
99 fn write_bytes(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Error>> + Send;
102
103 fn complete(self) -> impl Future<Output = Result<u64, Error>> + Send;
105
106 fn skip(&mut self, amount: u64) -> impl Future<Output = Result<(), Error>> + Send;
109}
110
111impl LayerObject for dyn ReadObjectHandle + '_ {}
112
113#[async_trait]
115pub trait LayerObject: ReadObjectHandle {
116 fn as_slice(&self) -> Option<&[u8]> {
119 None
120 }
121
122 fn has_io_error(&self) -> bool {
124 false
125 }
126
127 fn purge_cached_data(&self) {}
129
130 async fn close(&self) {}
133}
134
135impl<T: ObjectHandle + ?Sized> ObjectHandle for Arc<T> {
136 fn object_id(&self) -> u64 {
137 (**self).object_id()
138 }
139
140 fn block_size(&self) -> BlockSize {
141 (**self).block_size()
142 }
143
144 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
145 (**self).allocate_buffer(size)
146 }
147
148 fn set_trace(&self, v: bool) {
149 (**self).set_trace(v)
150 }
151}
152
153#[async_trait]
154impl<T: ReadObjectHandle + ?Sized> ReadObjectHandle for Arc<T> {
155 async fn read_aligned(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error> {
156 (**self).read_aligned(offset, buf).await
157 }
158
159 fn get_size(&self) -> u64 {
160 (**self).get_size()
161 }
162}
163
164#[async_trait]
165impl<T: LayerObject + ?Sized> LayerObject for Arc<T> {
166 fn as_slice(&self) -> Option<&[u8]> {
167 (**self).as_slice()
168 }
169
170 fn has_io_error(&self) -> bool {
171 (**self).has_io_error()
172 }
173
174 fn purge_cached_data(&self) {
175 (**self).purge_cached_data()
176 }
177
178 async fn close(&self) {
179 (**self).close().await
180 }
181}
182
183impl<T: ObjectHandle + ?Sized> ObjectHandle for Box<T> {
184 fn object_id(&self) -> u64 {
185 (**self).object_id()
186 }
187
188 fn block_size(&self) -> BlockSize {
189 (**self).block_size()
190 }
191
192 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
193 (**self).allocate_buffer(size)
194 }
195
196 fn set_trace(&self, v: bool) {
197 (**self).set_trace(v)
198 }
199}
200
201#[async_trait]
202impl<T: ReadObjectHandle + ?Sized> ReadObjectHandle for Box<T> {
203 async fn read_aligned(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error> {
204 (**self).read_aligned(offset, buf).await
205 }
206
207 fn get_size(&self) -> u64 {
208 (**self).get_size()
209 }
210}
211
212#[async_trait]
213impl<T: LayerObject + ?Sized> LayerObject for Box<T> {
214 fn as_slice(&self) -> Option<&[u8]> {
215 (**self).as_slice()
216 }
217
218 fn has_io_error(&self) -> bool {
219 (**self).has_io_error()
220 }
221
222 fn purge_cached_data(&self) {
223 (**self).purge_cached_data()
224 }
225
226 async fn close(&self) {
227 (**self).close().await
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234 use crate::testing::fake_object::{FakeObject, FakeObjectHandle};
235
236 #[fuchsia::test]
237 async fn test_object_handle_and_layer_object_defaults() {
238 let object = Arc::new(FakeObject::new());
239 let handle = FakeObjectHandle::new(object);
240
241 handle.set_trace(true);
242 assert_eq!(handle.as_slice(), None);
243 assert!(!handle.has_io_error());
244 handle.purge_cached_data();
245 handle.close().await;
246
247 let dyn_read: &dyn ReadObjectHandle = &handle;
248 assert_eq!(dyn_read.as_slice(), None);
249 assert!(!dyn_read.has_io_error());
250 dyn_read.purge_cached_data();
251 dyn_read.close().await;
252 }
253
254 #[fuchsia::test]
255 async fn test_arc_forwarding_impls() {
256 let object = Arc::new(FakeObject::new());
257 let arc_handle: Arc<FakeObjectHandle> = Arc::new(FakeObjectHandle::new(object));
258
259 assert_eq!(arc_handle.object_id(), 0);
260 assert_eq!(arc_handle.block_size(), BlockSize::SIZE_512B);
261 arc_handle.set_trace(false);
262
263 let mut buf = arc_handle.allocate_buffer(512).await;
264 assert_eq!(arc_handle.get_size(), 0);
265 assert_eq!(arc_handle.read_aligned(0, buf.as_mut()).await.unwrap(), 0);
266
267 assert_eq!(arc_handle.as_slice(), None);
268 assert!(!arc_handle.has_io_error());
269 arc_handle.purge_cached_data();
270 arc_handle.close().await;
271 }
272
273 #[fuchsia::test]
274 async fn test_box_forwarding_impls() {
275 let object = Arc::new(FakeObject::new());
276 let box_handle: Box<FakeObjectHandle> = Box::new(FakeObjectHandle::new(object));
277
278 assert_eq!(box_handle.object_id(), 0);
279 assert_eq!(box_handle.block_size(), BlockSize::SIZE_512B);
280 box_handle.set_trace(true);
281
282 let mut buf = box_handle.allocate_buffer(512).await;
283 assert_eq!(box_handle.get_size(), 0);
284 assert_eq!(box_handle.read_aligned(0, buf.as_mut()).await.unwrap(), 0);
285
286 assert_eq!(box_handle.as_slice(), None);
287 assert!(!box_handle.has_io_error());
288 box_handle.purge_cached_data();
289 box_handle.close().await;
290 }
291}