1use std::fmt;
6use std::hash;
7use std::pin::Pin;
8#[cfg(feature = "async")]
9use std::task::Context;
10#[cfg(feature = "async")]
11use std::task::Poll;
12
13#[cfg(feature = "async")]
14use pin_project::pin_project;
15
16use crate::deferred_read::DeferredRead;
17use crate::error::Result;
18use crate::error::VfsResult;
19use crate::prelude::*;
20#[cfg(feature = "async")]
21use crate::traits::async_vfs::VfsAsync;
22#[cfg(feature = "async")]
23use crate::traits::async_vfs::WriteSupportingVfsAsync;
24#[cfg(feature = "resolve-path")]
25use crate::traits::resolve::DynamicHasField;
26#[cfg(feature = "resolve-path")]
27use crate::traits::resolve::HAS_FIELD_MAX_LEN;
28#[cfg(feature = "resolve-path")]
29use crate::traits::resolve::HasField;
30use crate::traits::vfs;
31#[cfg(feature = "resolve-path")]
32use crate::traits::vfs::OwnedPathType;
33use crate::traits::vfs::PathType;
34#[cfg(feature = "async")]
35use crate::traits::vfs::VfsCore;
36use crate::vfs::fs_vfs;
37
38#[derive(Clone)]
60pub enum DeferredReadOrOwn<'a, T, Vfs: VfsCore = fs_vfs::FsVfs, const CHECK_ON_READ: bool = false> {
61 Own(T),
63 Deferred(DeferredRead<'a, T, Vfs, CHECK_ON_READ>),
65}
66
67impl<'a, T, Vfs: VfsCore, const CHECK_ON_READ: bool> hash::Hash
68 for DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
69where
70 T: hash::Hash,
71 <Vfs::Path as PathType>::OwnedPath: hash::Hash,
72{
73 fn hash<H: hash::Hasher>(&self, state: &mut H) {
74 match self {
75 DeferredReadOrOwn::Own(own) => {
76 state.write_u8(0);
77 own.hash(state);
78 }
79 DeferredReadOrOwn::Deferred(d) => {
80 state.write_u8(1);
81 d.hash(state);
82 }
83 }
84 }
85}
86
87#[cfg(feature = "assert_eq")]
88impl<'a, T, Vfs: VfsCore<Path = P>, P, const CHECK_ON_READ: bool> assert_eq::AssertEq
89 for DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
90where
91 T: assert_eq::AssertEq,
92 P: PathType + ?Sized,
93 P::OwnedPath: assert_eq::AssertEq + fmt::Debug,
94{
95 fn assert_eq(
96 &self,
97 other: &Self,
98 path: &mut assert_eq::AssertPath,
99 init_left: &impl fmt::Display,
100 init_right: &impl fmt::Display,
101 ) {
102 match (self, other) {
103 (Self::Own(l), Self::Own(r)) => {
104 T::assert_eq(l, r, &mut *path.__guard("[Own]"), init_left, init_right);
105 }
106 (Self::Deferred(l), Self::Deferred(r)) => {
107 DeferredRead::<T, Vfs, CHECK_ON_READ>::assert_eq(
108 l,
109 r,
110 &mut *path.__guard("[Deferred]"),
111 init_left,
112 init_right,
113 );
114 }
115 (Self::Own(_), Self::Deferred(_)) => {
116 panic!("Left is Own, right is Deferred: at: {:?}", path);
117 }
118 (Self::Deferred(_), Self::Own(_)) => {
119 panic!("Left is Deferred, right is Own: at: {:?}", path);
120 }
121 }
122 }
123}
124
125impl<'a, const CHECK_ON_READ: bool, T, Vfs: VfsCore<Path = P>, P> fmt::Debug
126 for DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
127where
128 T: fmt::Debug,
129 P: PathType + ?Sized,
130 P::OwnedPath: fmt::Debug,
131{
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 match self {
134 DeferredReadOrOwn::Own(own) => f.debug_tuple("Own").field(own).finish(),
135 DeferredReadOrOwn::Deferred(d) => f.debug_tuple("Deferred").field(d).finish(),
136 }
137 }
138}
139
140impl<'a, const CHECK_ON_READ: bool, T, Vfs: vfs::Vfs<'a, Path = P>, P: PathType + ?Sized + 'a>
141 DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
142where
143 T: ReadFrom<'a, Vfs>,
144{
145 pub fn get(&self) -> VfsResult<T, Vfs>
181 where
182 T: Clone,
183 {
184 match self {
185 DeferredReadOrOwn::Own(own) => Ok(own.clone()),
186 DeferredReadOrOwn::Deferred(d) => Ok(d.perform_read()?),
187 }
188 }
189
190 pub fn perform_and_store_read(&mut self) -> VfsResult<&mut T, Vfs> {
222 match self {
223 DeferredReadOrOwn::Own(own) => Ok(own),
224 DeferredReadOrOwn::Deferred(d) => {
225 let value = d.perform_read()?;
226 *self = DeferredReadOrOwn::Own(value);
227 let DeferredReadOrOwn::Own(own) = self else {
228 unreachable!()
229 };
230 Ok(own)
231 }
232 }
233 }
234
235 pub fn flush_to<'t, TargetVfs: vfs::WriteSupportingVfs<'t, Path = P>>(
237 &self,
238 path: &P,
239 vfs: Pin<&'t TargetVfs>,
240 ) -> VfsResult<(), Vfs>
241 where
242 T: WriteTo<'t, TargetVfs>,
243 {
244 match self {
245 DeferredReadOrOwn::Own(own) => own.write_to(path, vfs),
246 DeferredReadOrOwn::Deferred(d) => d.write_to(path, vfs),
247 }
248 }
249}
250
251impl<'a, const CHECK_ON_READ: bool, T, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs>
252 for DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
253where
254 T: ReadFrom<'a, Vfs>,
255{
256 fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
257 where
258 Self: Sized,
259 {
260 ReadFrom::read_from(path, vfs).map(Self::Deferred)
261 }
262}
263
264#[cfg(feature = "async")]
265#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
266impl<'a, const CHECK_ON_READ: bool, T, Vfs: VfsAsync<Path = P> + 'a, P: PathType + ?Sized + 'a>
267 DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
268where
269 T: ReadFromAsync<'a, Vfs> + Send + 'static,
270{
271 pub async fn get_async(&'a self) -> VfsResult<T, Vfs>
273 where
274 T: Clone,
275 {
276 match self {
277 DeferredReadOrOwn::Own(own) => Ok(own.clone()),
278 DeferredReadOrOwn::Deferred(d) => d.perform_read_async().await,
279 }
280 }
281
282 pub async fn perform_and_store_read_async(&'a mut self) -> VfsResult<&'a mut T, Vfs> {
289 match self {
290 DeferredReadOrOwn::Own(own) => Ok(own),
291 DeferredReadOrOwn::Deferred(d) => {
292 let value = d.perform_read_async().await?;
293 *self = DeferredReadOrOwn::Own(value);
294 let DeferredReadOrOwn::Own(own) = self else {
295 unreachable!()
296 };
297 Ok(own)
298 }
299 }
300 }
301}
302
303#[cfg(feature = "async")]
304#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
305impl<'a, const CHECK_ON_READ: bool, T, Vfs: VfsAsync<Path = P> + 'a, P: PathType + ?Sized + 'a>
306 DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
307where
308 P::OwnedPath: 'a,
309{
310 pub async fn flush_to_async<TargetVfs: WriteSupportingVfsAsync<Path = P> + 'a, ReadFutTy>(
312 &'a self,
313 path: P::OwnedPath,
314 vfs: Pin<&'a TargetVfs>,
315 ) -> VfsResult<(), Vfs>
316 where
317 for<'b> T: ReadFromAsync<'b, Vfs, Future = ReadFutTy>
318 + WriteToAsync<'b, TargetVfs>
319 + WriteToAsyncRef<'b, TargetVfs>
320 + Send
321 + 'b,
322 ReadFutTy: Future<Output = VfsResult<T, Vfs>> + Unpin + 'static,
323 {
324 match self {
325 DeferredReadOrOwn::Own(own) => own.write_to_async_ref(path, vfs).await,
326 DeferredReadOrOwn::Deferred(d) => d.write_to_async_ref(path, vfs).await,
327 }
328 }
329}
330
331#[cfg(feature = "async")]
332#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
333impl<'a, const CHECK_ON_READ: bool, T, Vfs: VfsAsync<Path = P> + 'static, P: PathType + ?Sized + 'a>
334 ReadFromAsync<'a, Vfs> for DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
335where
336 T: ReadFromAsync<'a, Vfs> + Send + 'static,
337 P::OwnedPath: Send + Sync,
338{
339 type Future = Pin<Box<dyn Future<Output = VfsResult<Self, Vfs>> + Send + 'a>>;
340
341 fn read_from_async(path: P::OwnedPath, vfs: Pin<&'a Vfs>) -> Self::Future {
342 use std::future::poll_fn;
343
344 let mut fut = DeferredRead::<T, Vfs, CHECK_ON_READ>::read_from_async(path, vfs);
345
346 Box::pin(poll_fn(move |cx| {
347 fut.as_mut().poll(cx).map_ok(Self::Deferred)
348 }))
349 }
350}
351
352impl<
353 'a,
354 't,
355 const CHECK_ON_READ: bool,
356 T,
357 P: PathType + ?Sized + 'a,
358 SelfVfs: vfs::Vfs<'a, Path = P>,
359 TargetVfs: vfs::WriteSupportingVfs<'t, Path = P>,
360> WriteTo<'t, TargetVfs> for DeferredReadOrOwn<'a, T, SelfVfs, CHECK_ON_READ>
361where
362 T: ReadFrom<'a, SelfVfs> + WriteTo<'t, TargetVfs>,
363{
364 fn write_to(&self, path: &P, vfs: Pin<&'t TargetVfs>) -> Result<(), P::OwnedPath> {
365 match self {
366 DeferredReadOrOwn::Own(own) => own.write_to(path, vfs),
367 DeferredReadOrOwn::Deferred(d) => d.write_to(path, vfs),
368 }
369 }
370}
371
372#[cfg(feature = "async")]
373#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
374#[pin_project(project_replace = DeferredReadOrOwnWriteFutureProj)]
375#[doc(hidden)]
376pub enum DeferredReadOrOwnWriteFuture<
377 'a,
378 T,
379 Vfs: WriteSupportingVfsAsync + 'static,
380 const CHECK_ON_READ: bool,
381> where
382 T: for<'b> ReadFromAsync<'b, Vfs> + for<'b> WriteToAsync<'b, Vfs> + Send + 'static,
383 for<'b> <T as ReadFromAsync<'b, Vfs>>::Future: Future<Output = VfsResult<T, Vfs>> + Unpin + 'b,
384 for<'b> <T as WriteToAsync<'b, Vfs>>::Future: Future<Output = VfsResult<(), Vfs>> + Unpin + 'b,
385{
386 Poisson,
387 Own {
388 inner: <T as WriteToAsync<'a, Vfs>>::Future,
389 },
390 Deferred {
391 inner: <DeferredRead<'a, T, Vfs, CHECK_ON_READ> as WriteToAsync<'a, Vfs>>::Future,
392 },
393}
394
395#[cfg(all(feature = "async", doc))]
397impl<T, Vfs, const CHECK_ON_READ: bool> core::marker::Unpin
398 for DeferredReadOrOwnWriteFutureProj<'_, T, Vfs, CHECK_ON_READ>
399where
400 T: for<'b> ReadFromAsync<'b, Vfs> + for<'b> WriteToAsync<'b, Vfs> + Send + 'static,
401 for<'b> <T as ReadFromAsync<'b, Vfs>>::Future: Future<Output = VfsResult<T, Vfs>> + Unpin + 'b,
402 for<'b> <T as WriteToAsync<'b, Vfs>>::Future: Future<Output = VfsResult<(), Vfs>> + Unpin + 'b,
403 Vfs: WriteSupportingVfsAsync + 'static,
404{
405}
406
407#[cfg(feature = "async")]
408#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
409impl<
410 'a,
411 const CHECK_ON_READ: bool,
412 T,
413 P: PathType + ?Sized + 'a,
414 Vfs: WriteSupportingVfsAsync<Path = P> + 'a,
415> Future for DeferredReadOrOwnWriteFuture<'a, T, Vfs, CHECK_ON_READ>
416where
417 T: for<'b> ReadFromAsync<'b, Vfs> + for<'b> WriteToAsync<'b, Vfs> + Send + 'static,
418 for<'b> <T as ReadFromAsync<'b, Vfs>>::Future: Future<Output = VfsResult<T, Vfs>> + Unpin + 'b,
419 for<'b> <T as WriteToAsync<'b, Vfs>>::Future: Future<Output = VfsResult<(), Vfs>> + Unpin + 'b,
420{
421 type Output = VfsResult<(), Vfs>;
422
423 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
424 let this = self.as_mut().project_replace(Self::Poisson);
425 match this {
426 DeferredReadOrOwnWriteFutureProj::Own { mut inner } => {
427 match Pin::new(&mut inner).poll(cx) {
428 Poll::Ready(v) => Poll::Ready(v),
429 Poll::Pending => {
430 self.project_replace(Self::Own { inner });
431 Poll::Pending
432 }
433 }
434 }
435 DeferredReadOrOwnWriteFutureProj::Deferred { mut inner } => {
436 match Pin::new(&mut inner).poll(cx) {
437 Poll::Ready(v) => Poll::Ready(v),
438 Poll::Pending => {
439 self.project_replace(Self::Deferred { inner });
440 Poll::Pending
441 }
442 }
443 }
444 DeferredReadOrOwnWriteFutureProj::Poisson => {
445 panic!(
446 "DeferredReadOrOwnWriteFuture is in an invalid state. This is a bug in the code."
447 );
448 }
449 }
450 }
451}
452
453#[cfg(feature = "async")]
454#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
455impl<'a, const CHECK_ON_READ: bool, T, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs>
456 for DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
457where
458 T: for<'b> ReadFromAsync<'b, Vfs> + for<'b> WriteToAsync<'b, Vfs> + Send + 'static,
459 for<'b> <T as ReadFromAsync<'b, Vfs>>::Future: Future<Output = VfsResult<T, Vfs>> + Unpin + 'b,
460 for<'b> <T as WriteToAsync<'b, Vfs>>::Future: Future<Output = VfsResult<(), Vfs>> + Unpin + 'b,
461{
462 type Future = DeferredReadOrOwnWriteFuture<'a, T, Vfs, CHECK_ON_READ>;
463
464 fn write_to_async(
465 self,
466 path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
467 vfs: Pin<&'a Vfs>,
468 ) -> Self::Future {
469 match self {
470 DeferredReadOrOwn::Own(own) => DeferredReadOrOwnWriteFuture::Own {
471 inner: own.write_to_async(path, vfs),
472 },
473 DeferredReadOrOwn::Deferred(d) => DeferredReadOrOwnWriteFuture::Deferred {
474 inner: d.write_to_async(path, vfs),
475 },
476 }
477 }
478}
479
480#[cfg(feature = "resolve-path")]
481#[cfg_attr(docsrs, doc(cfg(feature = "resolve-path")))]
482impl<'a, const CHECK_ON_READ: bool, const NAME: [char; HAS_FIELD_MAX_LEN], T, Vfs> HasField<NAME>
483 for DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
484where
485 T: HasField<NAME>,
486 Vfs: VfsCore,
487{
488 type Inner = <T as HasField<NAME>>::Inner;
489
490 fn resolve_path<P: OwnedPathType>(p: P) -> P {
491 T::resolve_path(p)
492 }
493}
494
495#[cfg(feature = "resolve-path")]
496#[cfg_attr(docsrs, doc(cfg(feature = "resolve-path")))]
497impl<'a, const CHECK_ON_READ: bool, T, Vfs> DynamicHasField
498 for DeferredReadOrOwn<'a, T, Vfs, CHECK_ON_READ>
499where
500 T: DynamicHasField,
501 Vfs: VfsCore,
502{
503 type Inner = <T as DynamicHasField>::Inner;
504
505 fn resolve_path<P: OwnedPathType>(p: P, name: &str) -> P {
506 T::resolve_path(p, name)
507 }
508}