1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
use std::{
fs::{create_dir, File, OpenOptions},
io::{self, Write},
path::Path,
};
pub static EMBEDDED_FILES: EmbeddedFiles = rustlings_macros::include_files!();
#[derive(Clone, Copy)]
pub enum WriteStrategy {
IfNotExists,
Overwrite,
}
impl WriteStrategy {
fn open<P: AsRef<Path>>(self, path: P) -> io::Result<File> {
match self {
Self::IfNotExists => OpenOptions::new().create_new(true).write(true).open(path),
Self::Overwrite => OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(path),
}
}
}
struct EmbeddedFile {
path: &'static str,
content: &'static [u8],
}
impl EmbeddedFile {
fn write_to_disk(&self, strategy: WriteStrategy) -> io::Result<()> {
strategy.open(self.path)?.write_all(self.content)
}
}
struct EmbeddedFlatDir {
path: &'static str,
readme: EmbeddedFile,
content: &'static [EmbeddedFile],
}
impl EmbeddedFlatDir {
fn init_on_disk(&self) -> io::Result<()> {
let path = Path::new(self.path);
if let Err(e) = create_dir(path) {
if !path.is_dir() {
return Err(e);
}
}
self.readme.write_to_disk(WriteStrategy::Overwrite)?;
Ok(())
}
}
struct ExercisesDir {
readme: EmbeddedFile,
files: &'static [EmbeddedFile],
dirs: &'static [EmbeddedFlatDir],
}
pub struct EmbeddedFiles {
pub info_toml_content: &'static str,
exercises_dir: ExercisesDir,
}
impl EmbeddedFiles {
pub fn init_exercises_dir(&self) -> io::Result<()> {
create_dir("exercises")?;
self.exercises_dir
.readme
.write_to_disk(WriteStrategy::IfNotExists)?;
for file in self.exercises_dir.files {
file.write_to_disk(WriteStrategy::IfNotExists)?;
}
for dir in self.exercises_dir.dirs {
dir.init_on_disk()?;
for file in dir.content {
file.write_to_disk(WriteStrategy::IfNotExists)?;
}
}
Ok(())
}
pub fn write_exercise_to_disk(&self, path: &Path, strategy: WriteStrategy) -> io::Result<()> {
if let Some(file) = self
.exercises_dir
.files
.iter()
.find(|file| file.path == path.as_os_str())
{
return file.write_to_disk(strategy);
}
for dir in self.exercises_dir.dirs {
if let Some(file) = dir
.content
.iter()
.find(|file| file.path == path.as_os_str())
{
dir.init_on_disk()?;
return file.write_to_disk(strategy);
}
}
Err(io::Error::from(io::ErrorKind::NotFound))
}
}
|