Skip to main content

virtual_file_system/
synchronous_directory.rs

1use core::mem::forget;
2use exported_file_system::{
3    AccessFlags, AttributeFlags, AttributeOperations, Attributes, StateFlags, Statistics,
4};
5use file_system::{Context, DirectoryOperations, Entry, Flags, Path, Size};
6use task::TaskIdentifier;
7use task::block_on;
8
9use crate::{Error, ItemStatic, Result, VirtualFileSystem, blocking_operation};
10
11pub struct SynchronousDirectory<'a> {
12    virtual_file_system: &'a VirtualFileSystem,
13    pub(crate) directory: &'static dyn file_system::FileSystemOperations,
14    pub(crate) flags: Flags,
15    pub(crate) context: Context,
16}
17
18impl<'a> SynchronousDirectory<'a> {
19    pub fn new(
20        virtual_file_system: &'a VirtualFileSystem,
21        directory: &'static dyn file_system::FileSystemOperations,
22        flags: Flags,
23        context: Context,
24    ) -> Self {
25        Self {
26            virtual_file_system,
27            directory,
28            flags,
29            context,
30        }
31    }
32
33    fn blocking_operation<O>(
34        &mut self,
35        mut operation: impl FnMut(&mut Self) -> Result<O>,
36    ) -> Result<O> {
37        blocking_operation(self.flags, || operation(self))
38    }
39
40    pub fn create(
41        virtual_file_system: &'a VirtualFileSystem,
42        task: TaskIdentifier,
43        path: impl AsRef<Path>,
44    ) -> Result<()> {
45        block_on(virtual_file_system.create_directory(task, &path))
46    }
47
48    pub fn open(
49        virtual_file_system: &'a VirtualFileSystem,
50        task: TaskIdentifier,
51        path: impl AsRef<Path>,
52    ) -> Result<Self> {
53        let mut directory =
54            block_on(virtual_file_system.open_directory(task, &path))?.into_synchronous_directory();
55
56        directory.flags = directory.flags.set_status(StateFlags::None);
57
58        Ok(directory)
59    }
60
61    pub fn read(&mut self) -> Result<Option<Entry>> {
62        let entry = self.blocking_operation(|directory| {
63            Ok(DirectoryOperations::read(
64                directory.directory,
65                &mut directory.context,
66            )?)
67        })?;
68
69        Ok(entry)
70    }
71
72    pub fn get_statistics(&mut self) -> Result<Statistics> {
73        self.blocking_operation(|directory| {
74            let mut attributes = Attributes::new().set_mask(AttributeFlags::All);
75
76            AttributeOperations::get_attributes(
77                directory.directory,
78                &mut directory.context,
79                &mut attributes,
80            )?;
81
82            Statistics::from_attributes(&attributes).ok_or(Error::MissingAttribute)
83        })
84    }
85
86    pub fn get_position(&mut self) -> Result<Size> {
87        self.blocking_operation(|directory| {
88            Ok(DirectoryOperations::get_position(
89                directory.directory,
90                &mut directory.context,
91            )?)
92        })
93    }
94
95    pub fn set_position(&mut self, position: Size) -> Result<()> {
96        self.blocking_operation(|directory| {
97            Ok(DirectoryOperations::set_position(
98                directory.directory,
99                &mut directory.context,
100                position,
101            )?)
102        })?;
103
104        Ok(())
105    }
106
107    pub fn rewind(&mut self) -> Result<()> {
108        self.blocking_operation(|directory| {
109            Ok(DirectoryOperations::rewind(
110                directory.directory,
111                &mut directory.context,
112            )?)
113        })
114    }
115
116    pub fn get_access(&self) -> Result<AccessFlags> {
117        Ok(self.flags.get_access())
118    }
119
120    pub fn get_state(&self) -> Result<StateFlags> {
121        Ok(self.flags.get_state())
122    }
123
124    pub fn close_internal(&mut self, virtual_file_system: &VirtualFileSystem) -> Result<()> {
125        block_on(
126            virtual_file_system.close(&ItemStatic::Directory(self.directory), &mut self.context),
127        )
128    }
129
130    pub fn close(mut self, virtual_file_system: &VirtualFileSystem) -> Result<()> {
131        let result = self.close_internal(virtual_file_system);
132        forget(self);
133
134        result
135    }
136}
137
138impl Drop for SynchronousDirectory<'_> {
139    fn drop(&mut self) {
140        let _ = self.close_internal(self.virtual_file_system).map_err(|e| {
141            log::error!("Error closing directory: {}", e);
142        });
143    }
144}
145
146impl Iterator for SynchronousDirectory<'_> {
147    type Item = Entry;
148
149    fn next(&mut self) -> Option<Self::Item> {
150        self.read().unwrap()
151    }
152}