bevy_asset/io/file/
file_asset.rs1use crate::io::{
2 get_meta_path, AssetReader, AssetReaderError, AssetWriter, AssetWriterError, PathStream,
3 Reader, ReaderNotSeekableError, SeekableReader, Writer,
4};
5use async_fs::{read_dir, File};
6use futures_lite::StreamExt;
7
8use alloc::{borrow::ToOwned, boxed::Box};
9use std::path::Path;
10
11use super::{FileAssetReader, FileAssetWriter};
12
13impl Reader for File {
14 fn seekable(&mut self) -> Result<&mut dyn SeekableReader, ReaderNotSeekableError> {
15 Ok(self)
16 }
17}
18
19impl AssetReader for FileAssetReader {
20 async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
21 let full_path = self.root_path.join(path);
22 File::open(&full_path).await.map_err(|e| {
23 if e.kind() == std::io::ErrorKind::NotFound {
24 AssetReaderError::NotFound(full_path)
25 } else {
26 e.into()
27 }
28 })
29 }
30
31 async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
32 let meta_path = get_meta_path(path);
33 let full_path = self.root_path.join(meta_path);
34 File::open(&full_path).await.map_err(|e| {
35 if e.kind() == std::io::ErrorKind::NotFound {
36 AssetReaderError::NotFound(full_path)
37 } else {
38 e.into()
39 }
40 })
41 }
42
43 async fn read_directory<'a>(
44 &'a self,
45 path: &'a Path,
46 ) -> Result<Box<PathStream>, AssetReaderError> {
47 let full_path = self.root_path.join(path);
48 match read_dir(&full_path).await {
49 Ok(read_dir) => {
50 let root_path = self.root_path.clone();
51 let mapped_stream = read_dir.filter_map(move |f| {
52 f.ok().and_then(|dir_entry| {
53 let path = dir_entry.path();
54 if let Some(ext) = path.extension().and_then(|e| e.to_str())
56 && ext.eq_ignore_ascii_case("meta")
57 {
58 return None;
59 }
60 if path
62 .file_name()
63 .and_then(|file_name| file_name.to_str())
64 .map(|file_name| file_name.starts_with('.'))
65 .unwrap_or_default()
66 {
67 return None;
68 }
69 let relative_path = path.strip_prefix(&root_path).unwrap();
70 Some(relative_path.to_owned())
71 })
72 });
73 let read_dir: Box<PathStream> = Box::new(mapped_stream);
74 Ok(read_dir)
75 }
76 Err(e) => {
77 if e.kind() == std::io::ErrorKind::NotFound {
78 Err(AssetReaderError::NotFound(full_path))
79 } else {
80 Err(e.into())
81 }
82 }
83 }
84 }
85
86 async fn is_directory<'a>(&'a self, path: &'a Path) -> Result<bool, AssetReaderError> {
87 let full_path = self.root_path.join(path);
88 let metadata = full_path
89 .metadata()
90 .map_err(|_e| AssetReaderError::NotFound(path.to_owned()))?;
91 Ok(metadata.file_type().is_dir())
92 }
93}
94
95impl AssetWriter for FileAssetWriter {
96 async fn write<'a>(&'a self, path: &'a Path) -> Result<Box<Writer>, AssetWriterError> {
97 let full_path = self.root_path.join(path);
98 if let Some(parent) = full_path.parent() {
99 async_fs::create_dir_all(parent).await?;
100 }
101 let file = File::create(&full_path).await?;
102 let writer: Box<Writer> = Box::new(file);
103 Ok(writer)
104 }
105
106 async fn write_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Writer>, AssetWriterError> {
107 let meta_path = get_meta_path(path);
108 let full_path = self.root_path.join(meta_path);
109 if let Some(parent) = full_path.parent() {
110 async_fs::create_dir_all(parent).await?;
111 }
112 let file = File::create(&full_path).await?;
113 let writer: Box<Writer> = Box::new(file);
114 Ok(writer)
115 }
116
117 async fn remove<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
118 let full_path = self.root_path.join(path);
119 async_fs::remove_file(full_path).await?;
120 Ok(())
121 }
122
123 async fn remove_meta<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
124 let meta_path = get_meta_path(path);
125 let full_path = self.root_path.join(meta_path);
126 async_fs::remove_file(full_path).await?;
127 Ok(())
128 }
129
130 async fn rename<'a>(
131 &'a self,
132 old_path: &'a Path,
133 new_path: &'a Path,
134 ) -> Result<(), AssetWriterError> {
135 let full_old_path = self.root_path.join(old_path);
136 let full_new_path = self.root_path.join(new_path);
137 if let Some(parent) = full_new_path.parent() {
138 async_fs::create_dir_all(parent).await?;
139 }
140 async_fs::rename(full_old_path, full_new_path).await?;
141 Ok(())
142 }
143
144 async fn rename_meta<'a>(
145 &'a self,
146 old_path: &'a Path,
147 new_path: &'a Path,
148 ) -> Result<(), AssetWriterError> {
149 let old_meta_path = get_meta_path(old_path);
150 let new_meta_path = get_meta_path(new_path);
151 let full_old_path = self.root_path.join(old_meta_path);
152 let full_new_path = self.root_path.join(new_meta_path);
153 if let Some(parent) = full_new_path.parent() {
154 async_fs::create_dir_all(parent).await?;
155 }
156 async_fs::rename(full_old_path, full_new_path).await?;
157 Ok(())
158 }
159
160 async fn create_directory<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
161 let full_path = self.root_path.join(path);
162 async_fs::create_dir_all(full_path).await?;
163 Ok(())
164 }
165
166 async fn remove_directory<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
167 let full_path = self.root_path.join(path);
168 async_fs::remove_dir_all(full_path).await?;
169 Ok(())
170 }
171
172 async fn remove_empty_directory<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
173 let full_path = self.root_path.join(path);
174 async_fs::remove_dir(full_path).await?;
175 Ok(())
176 }
177
178 async fn remove_assets_in_directory<'a>(
179 &'a self,
180 path: &'a Path,
181 ) -> Result<(), AssetWriterError> {
182 let full_path = self.root_path.join(path);
183 async_fs::remove_dir_all(&full_path).await?;
184 async_fs::create_dir_all(&full_path).await?;
185 Ok(())
186 }
187}