Skip to main content

greentic_bundle/answers/
document.rs

1use 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}