pub mod nouns_attempts_repo;
pub mod nouns_repo;
pub mod sentence_attempts_repo;
pub mod sentence_repo;
use std::path::PathBuf;
use miette::{miette, Context as _, IntoDiagnostic as _, Report, Result};
use serde::{Deserialize, Serialize};
use tracing::{info, instrument};
use crate::nouns::Article;
#[derive(Debug, Clone)]
pub struct Storage(pub PathBuf);
impl Storage {
fn nouns_attempts_path(&self) -> PathBuf {
self.0.join("nouns_attempts")
}
fn nouns_path(&self) -> PathBuf {
self.0.join("nouns")
}
fn sentence_path(&self) -> PathBuf {
self.0.join("sentences")
}
#[allow(unused)]
fn sentence_attempts_path(&self) -> PathBuf {
self.0.join("sentence_attempts")
}
}
impl TryFrom<PathBuf> for Storage {
type Error = Report;
#[instrument]
fn try_from(at: PathBuf) -> Result<Self> {
if !at
.try_exists()
.into_diagnostic()
.wrap_err_with(|| "somethig good!")?
{
info!(
directory = at.to_string_lossy().into_owned(),
"storage directory does not exist yet. creating it right now."
);
fs_extra::dir::create_all(&at, false).into_diagnostic()?;
};
if at.is_file() {
return Err(miette!(
help = "The address should be directory where I can store a load of data files.",
"The path at {} is not a directory.",
at.to_string_lossy()
));
};
let storage = Storage(at);
if !storage.nouns_path().try_exists().into_diagnostic()? {
info!(
directory = storage.nouns_path().to_string_lossy().into_owned(),
"storage nouns directory does not exist yet. creating it right now."
);
fs_extra::dir::create_all(storage.nouns_path(), false).into_diagnostic()?;
}
if !storage
.nouns_attempts_path()
.try_exists()
.into_diagnostic()?
{
info!(
directory = storage.nouns_attempts_path().to_string_lossy().into_owned(),
"storage nouns attempts directory does not exist yet. creating it right now."
);
fs_extra::dir::create_all(storage.nouns_attempts_path(), false).into_diagnostic()?;
}
Ok(storage)
}
}
#[derive(Debug, Clone, Copy, clap::ValueEnum, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum ArticleFileV1 {
Der,
Die,
Das,
}
impl From<ArticleFileV1> for Article {
fn from(value: ArticleFileV1) -> Self {
match value {
ArticleFileV1::Der => Article::Der,
ArticleFileV1::Die => Article::Die,
ArticleFileV1::Das => Article::Das,
}
}
}
impl From<Article> for ArticleFileV1 {
fn from(value: Article) -> Self {
match value {
Article::Der => ArticleFileV1::Der,
Article::Die => ArticleFileV1::Die,
Article::Das => ArticleFileV1::Das,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn is_normal<T: Sized + Send + Sync + Unpin>() {}
#[test]
fn normal_types() {
is_normal::<Storage>();
}
}