dir_structure/
std_types.rs

1//! Implementations for standard library types.
2
3#[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/// A newtype around a `Vec<u8>`.
30#[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    /// Creates a new [`FileBytes`] from the specified `Vec<u8>`.
36    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
112/// The [`WriteTo`] wrapper around a reference to a `[u8]`.
113pub 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/// A newtype around a [`String`].
150#[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    /// Creates a new [`FileString`] from the specified [`String`].
156    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
269/// The [`WriteTo`] wrapper around a reference to a [`str`].
270pub 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
297// Impls for std types.
298
299impl<'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// #[cfg(test)]
529// mod tests {
530//     use super::*;
531//     use crate::TokioFsVfs;
532
533//     fn assert_unpin<T: Unpin>() {}
534
535//     #[test]
536//     fn test_file_string_read_future() {
537//         assert_unpin::<FileStringReadFuture<TokioFsVfs>>();
538//     }
539// }