1use serde::Deserialize;
2
3#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
4pub struct Question {
5 pub id: String,
7 pub text: String,
8 #[serde(default)]
11 pub slug: Option<String>,
12 #[serde(default = "default_addressee")]
13 pub addressee: String,
14 #[serde(default = "default_cadence")]
15 pub cadence: String, #[serde(default)]
17 pub slot: Option<String>, }
19
20fn default_addressee() -> String { "self".into() }
21fn default_cadence() -> String { "daily".into() }
22
23#[derive(Clone, Debug, Deserialize)]
24pub struct Pack {
25 pub name: String,
26 #[serde(default)]
27 pub description: String,
28 #[serde(rename = "questions", default)]
29 pub questions: Vec<Question>,
30}
31
32impl Pack {
33 pub fn from_toml(s: &str) -> Result<Pack, toml::de::Error> {
34 toml::from_str(s)
35 }
36
37 pub fn held_len(cadence: &str) -> Option<u32> {
39 cadence.strip_prefix("held:").and_then(|n| n.parse().ok())
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn loads_a_pack_with_defaults() {
49 let toml = r#"
50 name = "future-self"
51 description = "Talk to the you that's coming."
52 [[questions]]
53 id = "scared-of"
54 text = "Tell next-December you what you're scared of."
55 addressee = "future-self"
56 [[questions]]
57 id = "held-avoid"
58 text = "What am I avoiding?"
59 cadence = "held:7"
60 "#;
61 let pack = Pack::from_toml(toml).unwrap();
62 assert_eq!(pack.name, "future-self");
63 assert_eq!(pack.questions.len(), 2);
64 assert_eq!(pack.questions[0].addressee, "future-self");
65 assert_eq!(pack.questions[1].cadence, "held:7");
66 assert_eq!(pack.questions[0].cadence, "daily"); assert_eq!(Pack::held_len("held:7"), Some(7));
68 assert_eq!(Pack::held_len("daily"), None);
69 }
70}