Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_asset/src/io/file/file_asset.rs
6601 views
1
use crate::io::{
2
get_meta_path, AssetReader, AssetReaderError, AssetWriter, AssetWriterError, AsyncSeekForward,
3
PathStream, Reader, Writer,
4
};
5
use async_fs::{read_dir, File};
6
use futures_io::AsyncSeek;
7
use futures_lite::StreamExt;
8
9
use alloc::{borrow::ToOwned, boxed::Box};
10
use core::{pin::Pin, task, task::Poll};
11
use std::path::Path;
12
13
use super::{FileAssetReader, FileAssetWriter};
14
15
impl AsyncSeekForward for File {
16
fn poll_seek_forward(
17
mut self: Pin<&mut Self>,
18
cx: &mut task::Context<'_>,
19
offset: u64,
20
) -> Poll<futures_io::Result<u64>> {
21
let offset: Result<i64, _> = offset.try_into();
22
23
if let Ok(offset) = offset {
24
Pin::new(&mut self).poll_seek(cx, futures_io::SeekFrom::Current(offset))
25
} else {
26
Poll::Ready(Err(std::io::Error::new(
27
std::io::ErrorKind::InvalidInput,
28
"seek position is out of range",
29
)))
30
}
31
}
32
}
33
34
impl Reader for File {}
35
36
impl AssetReader for FileAssetReader {
37
async fn read<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
38
let full_path = self.root_path.join(path);
39
File::open(&full_path).await.map_err(|e| {
40
if e.kind() == std::io::ErrorKind::NotFound {
41
AssetReaderError::NotFound(full_path)
42
} else {
43
e.into()
44
}
45
})
46
}
47
48
async fn read_meta<'a>(&'a self, path: &'a Path) -> Result<impl Reader + 'a, AssetReaderError> {
49
let meta_path = get_meta_path(path);
50
let full_path = self.root_path.join(meta_path);
51
File::open(&full_path).await.map_err(|e| {
52
if e.kind() == std::io::ErrorKind::NotFound {
53
AssetReaderError::NotFound(full_path)
54
} else {
55
e.into()
56
}
57
})
58
}
59
60
async fn read_directory<'a>(
61
&'a self,
62
path: &'a Path,
63
) -> Result<Box<PathStream>, AssetReaderError> {
64
let full_path = self.root_path.join(path);
65
match read_dir(&full_path).await {
66
Ok(read_dir) => {
67
let root_path = self.root_path.clone();
68
let mapped_stream = read_dir.filter_map(move |f| {
69
f.ok().and_then(|dir_entry| {
70
let path = dir_entry.path();
71
// filter out meta files as they are not considered assets
72
if let Some(ext) = path.extension().and_then(|e| e.to_str())
73
&& ext.eq_ignore_ascii_case("meta")
74
{
75
return None;
76
}
77
// filter out hidden files. they are not listed by default but are directly targetable
78
if path
79
.file_name()
80
.and_then(|file_name| file_name.to_str())
81
.map(|file_name| file_name.starts_with('.'))
82
.unwrap_or_default()
83
{
84
return None;
85
}
86
let relative_path = path.strip_prefix(&root_path).unwrap();
87
Some(relative_path.to_owned())
88
})
89
});
90
let read_dir: Box<PathStream> = Box::new(mapped_stream);
91
Ok(read_dir)
92
}
93
Err(e) => {
94
if e.kind() == std::io::ErrorKind::NotFound {
95
Err(AssetReaderError::NotFound(full_path))
96
} else {
97
Err(e.into())
98
}
99
}
100
}
101
}
102
103
async fn is_directory<'a>(&'a self, path: &'a Path) -> Result<bool, AssetReaderError> {
104
let full_path = self.root_path.join(path);
105
let metadata = full_path
106
.metadata()
107
.map_err(|_e| AssetReaderError::NotFound(path.to_owned()))?;
108
Ok(metadata.file_type().is_dir())
109
}
110
}
111
112
impl AssetWriter for FileAssetWriter {
113
async fn write<'a>(&'a self, path: &'a Path) -> Result<Box<Writer>, AssetWriterError> {
114
let full_path = self.root_path.join(path);
115
if let Some(parent) = full_path.parent() {
116
async_fs::create_dir_all(parent).await?;
117
}
118
let file = File::create(&full_path).await?;
119
let writer: Box<Writer> = Box::new(file);
120
Ok(writer)
121
}
122
123
async fn write_meta<'a>(&'a self, path: &'a Path) -> Result<Box<Writer>, AssetWriterError> {
124
let meta_path = get_meta_path(path);
125
let full_path = self.root_path.join(meta_path);
126
if let Some(parent) = full_path.parent() {
127
async_fs::create_dir_all(parent).await?;
128
}
129
let file = File::create(&full_path).await?;
130
let writer: Box<Writer> = Box::new(file);
131
Ok(writer)
132
}
133
134
async fn remove<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
135
let full_path = self.root_path.join(path);
136
async_fs::remove_file(full_path).await?;
137
Ok(())
138
}
139
140
async fn remove_meta<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
141
let meta_path = get_meta_path(path);
142
let full_path = self.root_path.join(meta_path);
143
async_fs::remove_file(full_path).await?;
144
Ok(())
145
}
146
147
async fn rename<'a>(
148
&'a self,
149
old_path: &'a Path,
150
new_path: &'a Path,
151
) -> Result<(), AssetWriterError> {
152
let full_old_path = self.root_path.join(old_path);
153
let full_new_path = self.root_path.join(new_path);
154
if let Some(parent) = full_new_path.parent() {
155
async_fs::create_dir_all(parent).await?;
156
}
157
async_fs::rename(full_old_path, full_new_path).await?;
158
Ok(())
159
}
160
161
async fn rename_meta<'a>(
162
&'a self,
163
old_path: &'a Path,
164
new_path: &'a Path,
165
) -> Result<(), AssetWriterError> {
166
let old_meta_path = get_meta_path(old_path);
167
let new_meta_path = get_meta_path(new_path);
168
let full_old_path = self.root_path.join(old_meta_path);
169
let full_new_path = self.root_path.join(new_meta_path);
170
if let Some(parent) = full_new_path.parent() {
171
async_fs::create_dir_all(parent).await?;
172
}
173
async_fs::rename(full_old_path, full_new_path).await?;
174
Ok(())
175
}
176
177
async fn create_directory<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
178
let full_path = self.root_path.join(path);
179
async_fs::create_dir_all(full_path).await?;
180
Ok(())
181
}
182
183
async fn remove_directory<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
184
let full_path = self.root_path.join(path);
185
async_fs::remove_dir_all(full_path).await?;
186
Ok(())
187
}
188
189
async fn remove_empty_directory<'a>(&'a self, path: &'a Path) -> Result<(), AssetWriterError> {
190
let full_path = self.root_path.join(path);
191
async_fs::remove_dir(full_path).await?;
192
Ok(())
193
}
194
195
async fn remove_assets_in_directory<'a>(
196
&'a self,
197
path: &'a Path,
198
) -> Result<(), AssetWriterError> {
199
let full_path = self.root_path.join(path);
200
async_fs::remove_dir_all(&full_path).await?;
201
async_fs::create_dir_all(&full_path).await?;
202
Ok(())
203
}
204
}
205
206