greentic_bundle/answers/
document.rs1use std::collections::BTreeMap;
2
3use anyhow::{Result, bail};
4use semver::Version;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct AnswerDocument {
10 pub wizard_id: String,
11 pub schema_id: String,
12 pub schema_version: Version,
13 pub locale: String,
14 #[serde(default)]
15 pub answers: BTreeMap<String, Value>,
16 #[serde(default)]
17 pub locks: BTreeMap<String, Value>,
18}
19
20impl AnswerDocument {
21 pub fn new(locale: &str) -> Self {
22 Self {
23 wizard_id: crate::wizard::WIZARD_ID.to_string(),
24 schema_id: crate::wizard::ANSWER_SCHEMA_ID.to_string(),
25 schema_version: Version::new(1, 0, 0),
26 locale: crate::i18n::normalize_locale(locale).unwrap_or_else(|| "en".to_string()),
27 answers: BTreeMap::new(),
28 locks: BTreeMap::new(),
29 }
30 }
31
32 pub fn from_json_str(raw: &str) -> Result<Self> {
33 let document: Self = serde_json::from_str(raw)?;
34 document.validate()?;
35 Ok(document)
36 }
37
38 pub fn validate(&self) -> Result<()> {
39 if self.wizard_id.trim().is_empty() {
40 bail!("{}", crate::i18n::tr("errors.answer_document.wizard_id"));
41 }
42 if self.schema_id.trim().is_empty() {
43 bail!("{}", crate::i18n::tr("errors.answer_document.schema_id"));
44 }
45 if self.locale.trim().is_empty() {
46 bail!("{}", crate::i18n::tr("errors.answer_document.locale"));
47 }
48 Ok(())
49 }
50
51 pub fn to_pretty_json_string(&self) -> Result<String> {
52 self.validate()?;
53 let mut rendered = serde_json::to_string_pretty(self)?;
54 rendered.push('\n');
55 Ok(rendered)
56 }
57}