summaryrefslogtreecommitdiff
path: root/src/state_file.rs
diff options
context:
space:
mode:
authormo8it <mo8it@proton.me>2024-04-07 19:01:08 +0200
committermo8it <mo8it@proton.me>2024-04-07 19:01:08 +0200
commit3bd26c7a24a97f9b4b87c453fbdbb06fe9971920 (patch)
treeb8cd9d7d0f23d69f260d8ec48e721d0c4b858faa /src/state_file.rs
parent8c31d38fa17970d0d2dc696922eb8cb329a6fdb9 (diff)
State -> StateFile
Diffstat (limited to 'src/state_file.rs')
-rw-r--r--src/state_file.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/state_file.rs b/src/state_file.rs
new file mode 100644
index 0000000..ca7ed34
--- /dev/null
+++ b/src/state_file.rs
@@ -0,0 +1,59 @@
+use anyhow::{bail, Context, Result};
+use serde::{Deserialize, Serialize};
+use std::fs;
+
+use crate::exercise::Exercise;
+
+#[derive(Serialize, Deserialize)]
+pub struct StateFile {
+ next_exercise_ind: usize,
+ progress: Vec<bool>,
+}
+
+impl StateFile {
+ fn read(exercises: &[Exercise]) -> Option<Self> {
+ let file_content = fs::read(".rustlings.json").ok()?;
+
+ let slf: Self = serde_json::de::from_slice(&file_content).ok()?;
+
+ if slf.progress.len() != exercises.len() || slf.next_exercise_ind >= exercises.len() {
+ return None;
+ }
+
+ Some(slf)
+ }
+
+ pub fn read_or_default(exercises: &[Exercise]) -> Self {
+ Self::read(exercises).unwrap_or_else(|| Self {
+ next_exercise_ind: 0,
+ progress: vec![false; exercises.len()],
+ })
+ }
+
+ fn write(&self) -> Result<()> {
+ // TODO: Capacity
+ let mut buf = Vec::with_capacity(1024);
+ serde_json::ser::to_writer(&mut buf, self).context("Failed to serialize the state")?;
+
+ Ok(())
+ }
+
+ #[inline]
+ pub fn next_exercise_ind(&self) -> usize {
+ self.next_exercise_ind
+ }
+
+ pub fn set_next_exercise_ind(&mut self, ind: usize) -> Result<()> {
+ if ind >= self.progress.len() {
+ bail!("The next exercise index is higher than the number of exercises");
+ }
+
+ self.next_exercise_ind = ind;
+ self.write()
+ }
+
+ #[inline]
+ pub fn progress(&self) -> &[bool] {
+ &self.progress
+ }
+}