1mod async_io;
2mod dir_entry;
3mod file;
4mod metadata;
5
6pub use async_io::*;
7pub use dir_entry::DirEntry;
8pub use file::File;
9pub use metadata::Metadata;
10
11use std::{
12 io::{self, Read, Write},
13 ops::Sub,
14 time::Duration,
15};
16
17fn write_rec(io: &impl Io, p: &str, path: &str, data: &[u8]) -> io::Result<()> {
18 io.create_dir_recursively(p)?;
19 io.write(path, data)
20}
21
22pub trait Io: Sized {
23 type Args: Iterator<Item = String>;
24 type File: File;
25 type Stdout: Write;
26 type Metadata: Metadata;
27 type DirEntry: DirEntry;
28 type Instant: Sub<Output = Duration> + Clone;
29 fn args(&self) -> Self::Args;
30 fn stdout(&self) -> Self::Stdout;
31 fn metadata(&self, path: &str) -> io::Result<Self::Metadata>;
32 fn create_dir(&self, path: &str) -> io::Result<()>;
33 fn create(&self, path: &str) -> io::Result<Self::File>;
34 fn open(&self, path: &str) -> io::Result<Self::File>;
35 fn now(&self) -> Self::Instant;
36 fn read(&self, path: &str) -> io::Result<Vec<u8>> {
37 let mut result = Vec::default();
38 self.open(path)?.read_to_end(&mut result)?;
39 Ok(result)
40 }
41 fn read_dir(&self, path: &str) -> io::Result<Vec<Self::DirEntry>>;
42 fn read_to_string(&self, path: &str) -> io::Result<String> {
43 let mut result = String::default();
44 self.open(path)?.read_to_string(&mut result)?;
45 Ok(result)
46 }
47 fn write(&self, path: &str, data: &[u8]) -> io::Result<()> {
48 self.create(path)?.write_all(data)
49 }
50 fn create_dir_recursively(&self, path: &str) -> io::Result<()> {
51 let mut x = String::default();
52 let mut e = Ok(());
53 for i in path.split('/') {
54 x += i;
55 e = self.create_dir(&x);
56 x += "/";
57 }
58 e
59 }
60 fn write_recursively(&self, path: &str, data: &[u8]) -> io::Result<()> {
61 let e = self.write(path, data);
62 if let Err(er) = e {
63 if let Some((p, _)) = path.rsplit_once('/') {
64 write_rec(self, p, path, data)
65 } else {
66 Err(er)
67 }
68 } else {
69 Ok(())
70 }
71 }
72 fn read_dir_type(&self, path: &str, is_dir: bool) -> io::Result<Vec<Self::DirEntry>> {
73 let mut result = Vec::default();
74 for i in self.read_dir(path)? {
75 if i.metadata()?.is_dir() == is_dir {
76 result.push(i);
77 }
78 }
79 Ok(result)
80 }
81 fn current_dir(&self) -> io::Result<String>;
82 fn set_current_dir(&self, path: &str) -> io::Result<()>;
83}