virtual_file_system/
synchronous_directory.rs1use 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}