1#[cfg(feature = "async")]
4use std::future;
5use std::marker;
6use std::pin::Pin;
7#[cfg(feature = "async")]
8use std::task::Context;
9#[cfg(feature = "async")]
10use std::task::Poll;
11
12#[cfg(feature = "async")]
13use pin_project::pin_project;
14
15use crate::error::VfsResult;
16use crate::prelude::*;
17#[cfg(feature = "async")]
18use crate::traits::asy::FromRefForWriterAsync;
19#[cfg(feature = "async")]
20use crate::traits::async_vfs::VfsAsync;
21#[cfg(feature = "async")]
22use crate::traits::async_vfs::WriteSupportingVfsAsync;
23use crate::traits::sync::FromRefForWriter;
24use crate::traits::sync::NewtypeToInner;
25use crate::traits::vfs;
26#[cfg(feature = "async")]
27use crate::traits::vfs::PathType;
28
29#[derive(Debug, Clone, PartialEq, Eq, Hash)]
31#[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
32pub struct FileBytes(pub Vec<u8>);
33
34impl FileBytes {
35 pub fn new(v: impl Into<Vec<u8>>) -> Self {
37 Self(v.into())
38 }
39}
40
41impl<'a, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for FileBytes {
42 fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
43 where
44 Self: Sized,
45 {
46 vfs.read(path).map(Self)
47 }
48}
49
50#[cfg(feature = "async")]
51impl<'a, Vfs: VfsAsync + 'static> ReadFromAsync<'a, Vfs> for FileBytes {
52 type Future = Pin<Box<dyn Future<Output = VfsResult<Self, Vfs>> + Send + 'a>>;
53
54 fn read_from_async(
55 path: <Vfs::Path as PathType>::OwnedPath,
56 vfs: Pin<&'a Vfs>,
57 ) -> Self::Future {
58 Box::pin(async move { vfs.read(path).await.map(Self::new) })
59 }
60}
61
62impl<'a, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for FileBytes {
63 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
64 Self::from_ref_for_writer(&self.0).write_to(path, vfs)
65 }
66}
67
68impl From<FileBytes> for Vec<u8> {
69 fn from(value: FileBytes) -> Self {
70 value.0
71 }
72}
73
74impl From<Vec<u8>> for FileBytes {
75 fn from(value: Vec<u8>) -> Self {
76 Self(value)
77 }
78}
79
80impl NewtypeToInner for FileBytes {
81 type Inner = Vec<u8>;
82
83 fn into_inner(self) -> Self::Inner {
84 self.0
85 }
86}
87
88impl<'a, 'vfs, Vfs: vfs::WriteSupportingVfs<'vfs> + 'vfs> FromRefForWriter<'a, 'vfs, Vfs>
89 for FileBytes
90where
91 'vfs: 'a,
92{
93 type Inner = [u8];
94 type Wr = FileBytesRefWr<'a, 'vfs, Vfs>;
95
96 fn from_ref_for_writer(value: &'a Self::Inner) -> Self::Wr {
97 FileBytesRefWr(value, marker::PhantomData)
98 }
99}
100
101#[cfg(feature = "async")]
102#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
103impl<'a, Vfs: WriteSupportingVfsAsync + 'static> FromRefForWriterAsync<'a, Vfs> for FileBytes {
104 type Inner = [u8];
105 type Wr = FileBytesRefWr<'a, 'a, Vfs>;
106
107 fn from_ref_for_writer_async(value: &'a Self::Inner) -> Self::Wr {
108 FileBytesRefWr(value, marker::PhantomData)
109 }
110}
111
112pub struct FileBytesRefWr<'a, 'vfs, Vfs: 'vfs>(&'a [u8], marker::PhantomData<&'vfs Vfs>)
114where
115 'vfs: 'a;
116
117impl<'a, 'vfs, Vfs: vfs::WriteSupportingVfs<'vfs>> WriteTo<'vfs, Vfs>
118 for FileBytesRefWr<'a, 'vfs, Vfs>
119where
120 'vfs: 'a,
121{
122 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<(), Vfs> {
123 vfs.create_parent_dir(path)?;
124 vfs.write(path, self.0)?;
125 Ok(())
126 }
127}
128
129#[cfg(feature = "async")]
130#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
131impl<'a, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs>
132 for FileBytesRefWr<'a, 'a, Vfs>
133{
134 type Future = Pin<Box<dyn Future<Output = VfsResult<(), Vfs>> + Send + 'a>>;
135
136 fn write_to_async(
137 self,
138 path: <Vfs::Path as PathType>::OwnedPath,
139 vfs: Pin<&'a Vfs>,
140 ) -> Self::Future {
141 Box::pin(async move {
142 vfs.create_parent_dir(path.clone()).await?;
143 vfs.write(path, self.0).await?;
144 Ok(())
145 })
146 }
147}
148
149#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
151#[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
152pub struct FileString(pub String);
153
154impl FileString {
155 pub fn new(s: impl Into<String>) -> Self {
157 Self(s.into())
158 }
159}
160
161impl From<FileString> for String {
162 fn from(value: FileString) -> Self {
163 value.0
164 }
165}
166
167impl From<String> for FileString {
168 fn from(value: String) -> Self {
169 Self(value)
170 }
171}
172
173impl NewtypeToInner for FileString {
174 type Inner = String;
175
176 fn into_inner(self) -> Self::Inner {
177 self.0
178 }
179}
180
181impl<'a, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for FileString {
182 fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
183 where
184 Self: Sized,
185 {
186 vfs.read_string(path).map(Self)
187 }
188}
189
190#[cfg(feature = "async")]
191#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
192#[doc(hidden)]
193pub struct FileStringReadFuture<'a, Vfs: VfsAsync + 'static>(Vfs::ReadStringFuture<'a>);
194
195#[cfg(feature = "async")]
196#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
197impl<'a, Vfs: VfsAsync + 'static> Future for FileStringReadFuture<'a, Vfs> {
198 type Output = VfsResult<FileString, Vfs>;
199
200 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
201 match Pin::new(&mut self.0).poll(cx) {
202 Poll::Ready(res) => Poll::Ready(res.map(FileString)),
203 Poll::Pending => Poll::Pending,
204 }
205 }
206}
207
208#[cfg(feature = "async")]
209#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
210impl<'a, Vfs: VfsAsync + 'static> ReadFromAsync<'a, Vfs> for FileString {
211 type Future = FileStringReadFuture<'a, Vfs>;
212
213 fn read_from_async(
214 path: <Vfs::Path as PathType>::OwnedPath,
215 vfs: Pin<&'a Vfs>,
216 ) -> Self::Future {
217 FileStringReadFuture(vfs.read_string(path))
218 }
219}
220
221impl<'a, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for FileString {
222 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
223 Self::from_ref_for_writer(&self.0).write_to(path, vfs)
224 }
225}
226
227#[cfg(feature = "async")]
228#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
229impl<'a, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs> for FileString {
230 type Future = Pin<Box<dyn Future<Output = VfsResult<(), Vfs>> + Send + 'a>>;
231
232 fn write_to_async(
233 self,
234 path: <Vfs::Path as PathType>::OwnedPath,
235 vfs: Pin<&'a Vfs>,
236 ) -> Self::Future {
237 Box::pin(async move {
238 vfs.create_parent_dir(path.clone()).await?;
239 vfs.write(path, self.0.as_bytes()).await?;
240 Ok(())
241 })
242 }
243}
244
245impl<'a, 'vfs, Vfs: vfs::WriteSupportingVfs<'vfs> + 'vfs> FromRefForWriter<'a, 'vfs, Vfs>
246 for FileString
247where
248 'vfs: 'a,
249{
250 type Inner = str;
251 type Wr = FileStrWr<'a, 'vfs, Vfs>;
252
253 fn from_ref_for_writer(value: &'a Self::Inner) -> Self::Wr {
254 FileStrWr(value, marker::PhantomData)
255 }
256}
257
258#[cfg(feature = "async")]
259#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
260impl<'a, Vfs: WriteSupportingVfsAsync + 'static> FromRefForWriterAsync<'a, Vfs> for FileString {
261 type Inner = str;
262 type Wr = FileStrWr<'a, 'a, Vfs>;
263
264 fn from_ref_for_writer_async(value: &'a Self::Inner) -> Self::Wr {
265 FileStrWr(value, marker::PhantomData)
266 }
267}
268
269pub struct FileStrWr<'a, 'vfs, Vfs: 'vfs>(&'a str, marker::PhantomData<&'vfs Vfs>)
271where
272 'vfs: 'a;
273
274impl<'a, 'vfs, Vfs: vfs::WriteSupportingVfs<'vfs>> WriteTo<'vfs, Vfs> for FileStrWr<'a, 'vfs, Vfs>
275where
276 'vfs: 'a,
277{
278 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<(), Vfs> {
279 FileBytes::from_ref_for_writer(self.0.as_bytes()).write_to(path, vfs)
280 }
281}
282
283#[cfg(feature = "async")]
284#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
285impl<'a, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs> for FileStrWr<'a, 'a, Vfs> {
286 type Future = <FileBytesRefWr<'a, 'a, Vfs> as WriteToAsync<'a, Vfs>>::Future;
287
288 fn write_to_async(
289 self,
290 path: <Vfs::Path as PathType>::OwnedPath,
291 vfs: Pin<&'a Vfs>,
292 ) -> Self::Future {
293 FileBytes::from_ref_for_writer_async(self.0.as_bytes()).write_to_async(path, vfs)
294 }
295}
296
297impl<'a, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for String {
300 fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
301 where
302 Self: Sized,
303 {
304 vfs.read_string(path)
305 }
306}
307
308#[cfg(feature = "async")]
309#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
310impl<'a, Vfs: VfsAsync + 'static> ReadFromAsync<'a, Vfs> for String {
311 type Future = Vfs::ReadStringFuture<'a>;
312
313 fn read_from_async(
314 path: <Vfs::Path as PathType>::OwnedPath,
315 vfs: Pin<&'a Vfs>,
316 ) -> Self::Future {
317 vfs.read_string(path)
318 }
319}
320
321impl<'a, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for String {
322 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
323 FileString::from_ref_for_writer(self).write_to(path, vfs)
324 }
325}
326
327#[cfg(feature = "async")]
328#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
329impl<'a, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs> for String {
330 type Future = <FileString as WriteToAsync<'a, Vfs>>::Future;
331
332 fn write_to_async(
333 self,
334 path: <Vfs::Path as PathType>::OwnedPath,
335 vfs: Pin<&'a Vfs>,
336 ) -> Self::Future {
337 FileString::new(self).write_to_async(path, vfs)
338 }
339}
340
341#[cfg(feature = "async")]
342#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
343impl<'a, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsyncRef<'a, Vfs> for String {
344 type Future<'b>
345 = <FileString as WriteToAsync<'b, Vfs>>::Future
346 where
347 Self: 'b,
348 'a: 'b,
349 Vfs: 'b;
350
351 fn write_to_async_ref<'b>(
352 &'b self,
353 path: <Vfs::Path as PathType>::OwnedPath,
354 vfs: Pin<&'b Vfs>,
355 ) -> <Self as WriteToAsync<'b, Vfs>>::Future
356 where
357 'a: 'b,
358 {
359 FileString::new(self).write_to_async(path, vfs)
360 }
361}
362
363impl<'a, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for Vec<u8> {
364 fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
365 where
366 Self: Sized,
367 {
368 FileBytes::read_from(path, vfs).map(|v| v.0)
369 }
370}
371
372#[cfg(feature = "async")]
373#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
374#[pin_project]
375#[doc(hidden)]
376pub struct VecReadFuture<'a, Vfs: VfsAsync + 'static>(
377 #[pin] <FileBytes as ReadFromAsync<'a, Vfs>>::Future,
378);
379
380#[cfg(feature = "async")]
381#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
382impl<'a, Vfs: VfsAsync + 'static> Future for VecReadFuture<'a, Vfs> {
383 type Output = VfsResult<Vec<u8>, Vfs>;
384
385 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
386 let projection = self.project();
387 let res = <FileBytes as ReadFromAsync<'a, Vfs>>::Future::poll(projection.0, cx);
388 match res {
389 Poll::Ready(res) => Poll::Ready(res.map(|inner| inner.0)),
390 Poll::Pending => Poll::Pending,
391 }
392 }
393}
394
395#[cfg(feature = "async")]
396#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
397impl<'a, Vfs: VfsAsync + 'static> ReadFromAsync<'a, Vfs> for Vec<u8> {
398 type Future = VecReadFuture<'a, Vfs>;
399
400 fn read_from_async(
401 path: <Vfs::Path as PathType>::OwnedPath,
402 vfs: Pin<&'a Vfs>,
403 ) -> Self::Future {
404 VecReadFuture(FileBytes::read_from_async(path, vfs))
405 }
406}
407
408impl<'a, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for Vec<u8> {
409 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
410 FileBytes::from_ref_for_writer(self).write_to(path, vfs)
411 }
412}
413
414#[cfg(feature = "async")]
415#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
416impl<'a, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs> for Vec<u8> {
417 type Future = <FileBytesRefWr<'a, 'a, Vfs> as WriteToAsync<'a, Vfs>>::Future;
418
419 fn write_to_async(
420 self,
421 path: <Vfs::Path as PathType>::OwnedPath,
422 vfs: Pin<&'a Vfs>,
423 ) -> Self::Future {
424 Box::pin(async move {
425 vfs.create_parent_dir(path.clone()).await?;
426 vfs.write(path, &self).await
427 })
428 }
429}
430
431impl<'a, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for str {
432 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
433 FileStrWr(self, marker::PhantomData).write_to(path, vfs)
434 }
435}
436
437impl<'a, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for &str {
438 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
439 FileStrWr(self, marker::PhantomData).write_to(path, vfs)
440 }
441}
442
443#[cfg(feature = "async")]
444#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
445impl<'a, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs> for &'a str {
446 type Future = <Vfs as WriteSupportingVfsAsync>::WriteFuture<'a>;
447
448 fn write_to_async(
449 self,
450 path: <Vfs::Path as PathType>::OwnedPath,
451 vfs: Pin<&'a Vfs>,
452 ) -> Self::Future {
453 vfs.write(path, self.as_bytes())
454 }
455}
456
457impl<'a, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for [u8] {
458 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
459 FileBytesRefWr(self, marker::PhantomData).write_to(path, vfs)
460 }
461}
462
463impl<'a, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for &[u8] {
464 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
465 FileBytesRefWr(self, marker::PhantomData).write_to(path, vfs)
466 }
467}
468
469#[cfg(feature = "async")]
470#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
471impl<'a, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs> for &'a [u8] {
472 type Future = <Vfs as WriteSupportingVfsAsync>::WriteFuture<'a>;
473
474 fn write_to_async(
475 self,
476 path: <Vfs::Path as PathType>::OwnedPath,
477 vfs: Pin<&'a Vfs>,
478 ) -> Self::Future {
479 vfs.write(path, self)
480 }
481}
482
483impl<'a, T: 'a, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for marker::PhantomData<T> {
484 fn read_from(_path: &Vfs::Path, _vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
485 where
486 Self: Sized,
487 {
488 Ok(Self)
489 }
490}
491
492impl<'a, T, Vfs: vfs::WriteSupportingVfs<'a>> WriteTo<'a, Vfs> for marker::PhantomData<T> {
493 fn write_to(&self, _path: &Vfs::Path, _vfs: Pin<&'a Vfs>) -> VfsResult<(), Vfs> {
494 Ok(())
495 }
496}
497
498#[cfg(feature = "async")]
499#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
500impl<'a, T, Vfs: VfsAsync + 'a> ReadFromAsync<'a, Vfs> for marker::PhantomData<T>
501where
502 T: Send + Sync + 'static,
503{
504 type Future = future::Ready<VfsResult<Self, Vfs>>;
505
506 fn read_from_async(_path: <Vfs::Path as PathType>::OwnedPath, _vfs: Pin<&Vfs>) -> Self::Future {
507 future::ready(Ok(Self))
508 }
509}
510
511#[cfg(feature = "async")]
512#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
513impl<'a, T, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs> for marker::PhantomData<T>
514where
515 T: Send + Sync + 'static,
516{
517 type Future = future::Ready<VfsResult<(), Vfs>>;
518
519 fn write_to_async(
520 self,
521 _path: <Vfs::Path as PathType>::OwnedPath,
522 _vfs: Pin<&'a Vfs>,
523 ) -> Self::Future {
524 future::ready(Ok(()))
525 }
526}
527
528