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 {
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}