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