dir_structure/traits/
sync.rs

1//! Synchronous reading / writing traits.
2
3use std::pin::Pin;
4
5use crate::error::VfsResult;
6use crate::traits::vfs;
7use crate::traits::vfs::VfsCore;
8use crate::vfs::fs_vfs;
9
10/// The main trait. This is implemented for
11/// all directory structures by the derive macro.
12///
13/// This trait doesn't have any methods, just a supertype:
14/// [`DirStructureItem`].
15pub trait DirStructure: DirStructureItem {}
16
17/// Helper trait, implemented for all types that have a [`ReadFrom`]
18/// and [`WriteTo`] implementation.
19pub trait DirStructureItem {
20    /// Uses the [`ReadFrom`] implementation to read the structure from
21    /// disk, from the specified path.
22    fn read(path: impl AsRef<<fs_vfs::FsVfs as VfsCore>::Path>) -> VfsResult<Self, fs_vfs::FsVfs>
23    where
24        Self: ReadFrom<'static, fs_vfs::FsVfs> + Sized,
25    {
26        Self::read_from(path.as_ref(), Pin::new(&fs_vfs::FsVfs))
27    }
28
29    /// Uses the [`WriteTo`] implementation to write the structure
30    /// to disk at the specified path.
31    fn write<'a, 'vfs: 'a>(
32        &'a self,
33        path: impl AsRef<<fs_vfs::FsVfs as VfsCore>::Path>,
34    ) -> VfsResult<(), fs_vfs::FsVfs>
35    where
36        Self: WriteTo<'vfs, fs_vfs::FsVfs>,
37    {
38        self.write_to(path.as_ref(), Pin::new(&fs_vfs::FsVfs))
39    }
40}
41
42// Blanket impl.
43impl<T> DirStructureItem for T {}
44
45/// Trait for types / structures that can be
46/// read from disk, either from a file or a directory.
47pub trait ReadFrom<'vfs, Vfs: vfs::Vfs<'vfs> + ?Sized>: Sized + 'vfs {
48    /// Reads the structure from the specified path, which
49    /// can be either a file or a directory.
50    fn read_from(path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<Self, Vfs>;
51}
52
53/// Trait for types / structures that can be
54/// written to disk. All types in the library that
55/// write to files first check that the parent
56/// directories exist, so implementations of
57/// this that create the whole directory are
58/// not necessary (unless used empty children
59/// directories, in which case no directories will
60/// really be created).
61pub trait WriteTo<'vfs, Vfs: vfs::WriteSupportingVfs<'vfs> + ?Sized> {
62    /// Writes the structure to the specified path.
63    fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<(), Vfs>;
64}
65
66/// Trait to use when using the `with_newtype` attribute.
67///
68/// This is used to convert a reference to a normal type
69/// (like `String`, `Vec<u8>` etc. into a type that is a
70/// reference to them, like `&str`, `&[u8]` etc.), so that
71/// the `WriteTo` implementation can be written only for the
72/// reference types, and all the other [`WriteTo`] impls will
73/// only cast what they have to write to those reference types
74/// (via the function below), and then call the [`WriteTo::write_to`]
75/// method on that reference.
76pub trait FromRefForWriter<'a, 'vfs: 'a, Vfs: vfs::WriteSupportingVfs<'vfs> + ?Sized + 'vfs>:
77    'a
78{
79    /// The inner type to cast.
80    type Inner: ?Sized;
81    /// The reference type to cast to.
82    type Wr: WriteTo<'vfs, Vfs> + 'a;
83
84    /// Casts the reference to the inner type to a [`WriteTo`]
85    /// reference type.
86    fn from_ref_for_writer(value: &'a Self::Inner) -> Self::Wr;
87}
88
89/// Trait to use when using the `with_newtype` attribute.
90///
91/// This is used to convert a newtype to its inner type.
92/// We are using this because we cannot make blanket impls with
93/// [`From`] due to the orphan rules.
94pub trait NewtypeToInner {
95    /// The inner type.
96    type Inner;
97
98    /// Converts the newtype to its inner type.
99    fn into_inner(self) -> Self::Inner;
100}
101
102impl<'a, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for () {
103    fn read_from(_path: &Vfs::Path, _vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs> {
104        Ok(())
105    }
106}
107
108impl<'vfs, Vfs: vfs::WriteSupportingVfs<'vfs>> WriteTo<'vfs, Vfs> for () {
109    fn write_to(&self, _path: &Vfs::Path, _vfs: Pin<&'vfs Vfs>) -> VfsResult<(), Vfs> {
110        Ok(())
111    }
112}