Skip to main content

bookyard_core/
model.rs

1use std::path::Path;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{BookyardError, Result, load_config, save_config};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct BookyardConfig {
9    pub workspace: WorkspaceConfig,
10    #[serde(default)]
11    pub build: BuildConfig,
12    #[serde(default)]
13    pub books: Vec<BookConfig>,
14}
15
16impl BookyardConfig {
17    pub fn new(title: impl Into<String>) -> Self {
18        Self {
19            workspace: WorkspaceConfig {
20                title: title.into(),
21                output: "bookyard".into(),
22            },
23            build: BuildConfig::default(),
24            books: Vec::new(),
25        }
26    }
27
28    pub fn load_from(path: impl AsRef<Path>) -> Result<Self> {
29        load_config(path.as_ref())
30    }
31
32    pub fn save_to(&self, path: impl AsRef<Path>) -> Result<()> {
33        save_config(path.as_ref(), self)
34    }
35
36    pub fn validate(&self) -> Result<()> {
37        for book in &self.books {
38            if book.engine != BookEngine::MdBook {
39                return Err(BookyardError::UnsupportedBookEngine(
40                    book.engine.to_string(),
41                ));
42            }
43        }
44        Ok(())
45    }
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
49pub struct WorkspaceConfig {
50    pub title: String,
51    #[serde(default = "default_output")]
52    pub output: String,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
56pub struct BuildConfig {
57    #[serde(default = "default_jobs")]
58    pub jobs: usize,
59    #[serde(default)]
60    pub fail_fast: bool,
61}
62
63impl Default for BuildConfig {
64    fn default() -> Self {
65        Self {
66            jobs: default_jobs(),
67            fail_fast: false,
68        }
69    }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
73pub struct BookConfig {
74    pub id: String,
75    pub title: String,
76    pub source: String,
77    #[serde(default)]
78    pub engine: BookEngine,
79    #[serde(default)]
80    pub folders: Vec<String>,
81    #[serde(default)]
82    pub tags: Vec<String>,
83    #[serde(default)]
84    pub order: i32,
85}
86
87impl BookConfig {
88    pub fn new_mdbook(
89        id: impl Into<String>,
90        title: impl Into<String>,
91        source: impl Into<String>,
92        folders: Vec<impl Into<String>>,
93    ) -> Self {
94        Self {
95            id: id.into(),
96            title: title.into(),
97            source: source.into(),
98            engine: BookEngine::MdBook,
99            folders: folders.into_iter().map(Into::into).collect(),
100            tags: Vec::new(),
101            order: 0,
102        }
103    }
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
107pub enum BookEngine {
108    #[serde(rename = "mdbook")]
109    MdBook,
110}
111
112impl Default for BookEngine {
113    fn default() -> Self {
114        Self::MdBook
115    }
116}
117
118impl std::fmt::Display for BookEngine {
119    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120        match self {
121            BookEngine::MdBook => f.write_str("mdbook"),
122        }
123    }
124}
125
126fn default_output() -> String {
127    "bookyard".into()
128}
129
130fn default_jobs() -> usize {
131    4
132}