1use crate::object_store::{DirType, PosixAttributes, Timestamp};
6use anyhow::Error;
7use async_trait::async_trait;
8use std::future::Future;
9use std::ops::Range;
10use std::sync::Arc;
11use storage_device::buffer::{BufferFuture, BufferRef, MutableBufferRef};
12use storage_units::BlockSize;
13
14pub const INVALID_OBJECT_ID: u64 = 0;
17
18pub trait ObjectHandle: Send + Sync + 'static {
21 fn object_id(&self) -> u64;
24
25 fn block_size(&self) -> BlockSize;
28
29 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_>;
31
32 fn set_trace(&self, _v: bool) {}
34}
35
36#[derive(Clone, Debug, PartialEq)]
37pub struct ObjectProperties {
38 pub refs: u64,
40 pub allocated_size: u64,
42 pub data_attribute_size: u64,
45 pub creation_time: Timestamp,
47 pub modification_time: Timestamp,
49 pub access_time: Timestamp,
51 pub change_time: Timestamp,
53 pub sub_dirs: u64,
55 pub posix_attributes: Option<PosixAttributes>,
57 pub dir_type: DirType,
59}
60
61#[async_trait]
62pub trait ReadObjectHandle: ObjectHandle {
63 async fn read_aligned(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error>;
71
72 fn get_size(&self) -> u64;
74}
75
76pub trait WriteObjectHandle: ObjectHandle {
77 fn write_or_append(
82 &self,
83 offset: Option<u64>,
84 buf: BufferRef<'_>,
85 ) -> impl Future<Output = Result<u64, Error>> + Send;
86
87 fn truncate(&self, size: u64) -> impl Future<Output = Result<(), Error>> + Send;
91
92 fn flush(&self) -> impl Future<Output = Result<(), Error>> + Send;
94}
95
96pub trait WriteBytes: Sized {
98 fn block_size(&self) -> BlockSize;
99
100 fn write_bytes(&mut self, buf: &[u8]) -> impl Future<Output = Result<(), Error>> + Send;
103
104 fn complete(self) -> impl Future<Output = Result<u64, Error>> + Send;
106
107 fn skip(&mut self, amount: u64) -> impl Future<Output = Result<(), Error>> + Send;
110}
111
112impl LayerObject for dyn ReadObjectHandle + '_ {}
113
114#[async_trait]
116pub trait LayerObject: ReadObjectHandle {
117 fn as_slice(&self) -> Option<&[u8]> {
120 None
121 }
122
123 #[cfg(target_os = "fuchsia")]
125 fn get_vmo(&self) -> Option<&zx::Vmo> {
126 None
127 }
128
129 fn has_io_error(&self) -> bool {
131 false
132 }
133
134 fn purge_cached_data(&self) {}
136
137 fn prefetch(&self, _range: Range<u64>) {}
139
140 async fn close(&self) {}
143}
144
145impl<T: ObjectHandle + ?Sized> ObjectHandle for Arc<T> {
146 fn object_id(&self) -> u64 {
147 (**self).object_id()
148 }
149
150 fn block_size(&self) -> BlockSize {
151 (**self).block_size()
152 }
153
154 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
155 (**self).allocate_buffer(size)
156 }
157
158 fn set_trace(&self, v: bool) {
159 (**self).set_trace(v)
160 }
161}
162
163#[async_trait]
164impl<T: ReadObjectHandle + ?Sized> ReadObjectHandle for Arc<T> {
165 async fn read_aligned(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error> {
166 (**self).read_aligned(offset, buf).await
167 }
168
169 fn get_size(&self) -> u64 {
170 (**self).get_size()
171 }
172}
173
174#[async_trait]
175impl<T: LayerObject + ?Sized> LayerObject for Arc<T> {
176 fn as_slice(&self) -> Option<&[u8]> {
177 (**self).as_slice()
178 }
179
180 #[cfg(target_os = "fuchsia")]
181 fn get_vmo(&self) -> Option<&zx::Vmo> {
182 (**self).get_vmo()
183 }
184
185 fn has_io_error(&self) -> bool {
186 (**self).has_io_error()
187 }
188
189 fn purge_cached_data(&self) {
190 (**self).purge_cached_data()
191 }
192
193 fn prefetch(&self, range: Range<u64>) {
194 (**self).prefetch(range)
195 }
196
197 async fn close(&self) {
198 (**self).close().await
199 }
200}
201
202impl<T: ObjectHandle + ?Sized> ObjectHandle for Box<T> {
203 fn object_id(&self) -> u64 {
204 (**self).object_id()
205 }
206
207 fn block_size(&self) -> BlockSize {
208 (**self).block_size()
209 }
210
211 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
212 (**self).allocate_buffer(size)
213 }
214
215 fn set_trace(&self, v: bool) {
216 (**self).set_trace(v)
217 }
218}
219
220#[async_trait]
221impl<T: ReadObjectHandle + ?Sized> ReadObjectHandle for Box<T> {
222 async fn read_aligned(&self, offset: u64, buf: MutableBufferRef<'_>) -> Result<usize, Error> {
223 (**self).read_aligned(offset, buf).await
224 }
225
226 fn get_size(&self) -> u64 {
227 (**self).get_size()
228 }
229}
230
231#[async_trait]
232impl<T: LayerObject + ?Sized> LayerObject for Box<T> {
233 fn as_slice(&self) -> Option<&[u8]> {
234 (**self).as_slice()
235 }
236
237 #[cfg(target_os = "fuchsia")]
238 fn get_vmo(&self) -> Option<&zx::Vmo> {
239 (**self).get_vmo()
240 }
241
242 fn has_io_error(&self) -> bool {
243 (**self).has_io_error()
244 }
245
246 fn purge_cached_data(&self) {
247 (**self).purge_cached_data()
248 }
249
250 fn prefetch(&self, range: Range<u64>) {
251 (**self).prefetch(range)
252 }
253
254 async fn close(&self) {
255 (**self).close().await
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262 use crate::testing::fake_object::{FakeObject, FakeObjectHandle};
263
264 #[fuchsia::test]
265 async fn test_object_handle_and_layer_object_defaults() {
266 let object = Arc::new(FakeObject::new());
267 let handle = FakeObjectHandle::new(object);
268
269 handle.set_trace(true);
270 assert_eq!(handle.as_slice(), None);
271 assert!(!handle.has_io_error());
272 handle.purge_cached_data();
273 handle.close().await;
274
275 let dyn_read: &dyn ReadObjectHandle = &handle;
276 assert_eq!(dyn_read.as_slice(), None);
277 assert!(!dyn_read.has_io_error());
278 dyn_read.purge_cached_data();
279 dyn_read.close().await;
280 }
281
282 #[fuchsia::test]
283 async fn test_arc_forwarding_impls() {
284 let object = Arc::new(FakeObject::new());
285 let arc_handle: Arc<FakeObjectHandle> = Arc::new(FakeObjectHandle::new(object));
286
287 assert_eq!(arc_handle.object_id(), 0);
288 assert_eq!(arc_handle.block_size(), BlockSize::SIZE_512B);
289 arc_handle.set_trace(false);
290
291 let mut buf = arc_handle.allocate_buffer(512).await;
292 assert_eq!(arc_handle.get_size(), 0);
293 assert_eq!(arc_handle.read_aligned(0, buf.as_mut()).await.unwrap(), 0);
294
295 assert_eq!(arc_handle.as_slice(), None);
296 assert!(!arc_handle.has_io_error());
297 arc_handle.purge_cached_data();
298 arc_handle.close().await;
299 }
300
301 #[fuchsia::test]
302 async fn test_box_forwarding_impls() {
303 let object = Arc::new(FakeObject::new());
304 let box_handle: Box<FakeObjectHandle> = Box::new(FakeObjectHandle::new(object));
305
306 assert_eq!(box_handle.object_id(), 0);
307 assert_eq!(box_handle.block_size(), BlockSize::SIZE_512B);
308 box_handle.set_trace(true);
309
310 let mut buf = box_handle.allocate_buffer(512).await;
311 assert_eq!(box_handle.get_size(), 0);
312 assert_eq!(box_handle.read_aligned(0, buf.as_mut()).await.unwrap(), 0);
313
314 assert_eq!(box_handle.as_slice(), None);
315 assert!(!box_handle.has_io_error());
316 box_handle.purge_cached_data();
317 box_handle.close().await;
318 }
319}