1#[cfg(feature = "async")]
6use std::future;
7#[cfg(feature = "async")]
8use std::future::poll_fn;
9use std::pin::Pin;
10#[cfg(feature = "async")]
11use std::task::Poll;
12#[cfg(feature = "async")]
13use std::task::ready;
14
15use crate::error::Error;
16use crate::error::VfsResult;
17use crate::prelude::*;
18#[cfg(feature = "async")]
19use crate::traits::async_vfs::VfsAsync;
20#[cfg(feature = "async")]
21use crate::traits::async_vfs::WriteSupportingVfsAsync;
22use crate::traits::vfs;
23use crate::traits::vfs::PathType;
24
25pub enum TryParse<T, P: PathType + ?Sized> {
29 Success(T),
31
32 Failure(Error<P::OwnedPath>),
34}
35
36impl<'vfs, Vfs, T, P> ReadFrom<'vfs, Vfs> for TryParse<T, P>
37where
38 Vfs: vfs::Vfs<'vfs, Path = P>,
39 P: PathType + ?Sized + 'vfs,
40 T: ReadFrom<'vfs, Vfs>,
41{
42 fn read_from(path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<Self, Vfs> {
43 match T::read_from(path, vfs) {
44 Ok(value) => Ok(TryParse::Success(value)),
45 Err(error) => Ok(TryParse::Failure(error)),
46 }
47 }
48}
49
50impl<'vfs, Vfs, T, P> WriteTo<'vfs, Vfs> for TryParse<T, P>
51where
52 P: PathType + ?Sized + 'vfs,
53 Vfs: vfs::WriteSupportingVfs<'vfs, Path = P>,
54 T: WriteTo<'vfs, Vfs>,
55{
56 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<(), Vfs> {
57 match self {
58 Self::Success(value) => value.write_to(path, vfs),
59 Self::Failure(_error) => Ok(()),
60 }
61 }
62}
63
64#[cfg(feature = "async")]
65#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
66impl<'vfs, Vfs, T, P> ReadFromAsync<'vfs, Vfs> for TryParse<T, P>
67where
68 P: PathType + 'vfs,
69 Vfs: VfsAsync<Path = P> + 'vfs,
70 T: ReadFromAsync<'vfs, Vfs> + Send + 'vfs,
71{
72 type Future = Pin<Box<dyn Future<Output = VfsResult<Self, Vfs>> + Send + 'vfs>>;
73
74 fn read_from_async(path: P::OwnedPath, vfs: Pin<&'vfs Vfs>) -> Self::Future {
75 let mut read_fut = Box::pin(T::read_from_async(path, vfs));
76 Box::pin(poll_fn(move |cx| {
77 let result = ready!(read_fut.as_mut().poll(cx));
78 match result {
79 Ok(value) => Poll::Ready(Ok(TryParse::Success(value))),
80 Err(error) => Poll::Ready(Ok(TryParse::Failure(error))),
81 }
82 }))
83 }
84}
85
86#[cfg(feature = "async")]
87#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
88impl<'vfs, Vfs, T, P> WriteToAsync<'vfs, Vfs> for TryParse<T, P>
89where
90 P: PathType + ?Sized + 'vfs,
91 Vfs: WriteSupportingVfsAsync<Path = P> + 'vfs,
92 T: WriteToAsync<'vfs, Vfs> + Send + 'vfs,
93 <T as WriteToAsync<'vfs, Vfs>>::Future: Future<Output = VfsResult<(), Vfs>> + Unpin,
94{
95 type Future = Pin<Box<dyn Future<Output = VfsResult<(), Vfs>> + Send + 'vfs>>;
96
97 fn write_to_async(self, path: P::OwnedPath, vfs: Pin<&'vfs Vfs>) -> Self::Future {
98 match self {
99 Self::Success(value) => Box::pin(value.write_to_async(path, vfs)),
100 Self::Failure(_error) => Box::pin(future::ready(Ok(()))),
101 }
102 }
103}
104
105#[cfg(feature = "async")]
106#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
107impl<'vfs, Vfs, T, P> WriteToAsyncRef<'vfs, Vfs> for TryParse<T, P>
108where
109 P: PathType + ?Sized + 'vfs,
110 Vfs: WriteSupportingVfsAsync<Path = P> + 'static,
111 T: WriteToAsyncRef<'vfs, Vfs> + Send + 'vfs,
112 for<'a> <T as WriteToAsyncRef<'vfs, Vfs>>::Future<'a>:
113 Future<Output = VfsResult<(), Vfs>> + Send + Sync + Unpin + 'a,
114{
115 type Future<'a>
116 = Pin<Box<dyn Future<Output = VfsResult<(), Vfs>> + Send + Sync + 'a>>
117 where
118 Self: 'a,
119 'vfs: 'a,
120 T: 'a,
121 Vfs: 'a;
122
123 fn write_to_async_ref<'a>(&'a self, path: P::OwnedPath, vfs: Pin<&'a Vfs>) -> Self::Future<'a>
124 where
125 'vfs: 'a,
126 {
127 use std::future::poll_fn;
128
129 let mut wr: Option<Pin<Box<<T as WriteToAsyncRef<'vfs, Vfs>>::Future<'a>>>> = match self {
130 Self::Success(value) => Some(Box::pin(value.write_to_async_ref(path, vfs))),
131 Self::Failure(_error) => None,
132 };
133
134 Box::pin(poll_fn(move |cx| match &mut wr {
135 Some(wr) => wr.as_mut().poll(cx),
136 None => Poll::Ready(Ok(())),
137 }))
138 }
139}