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    /// Environment id the wizard ran under (C7). `None` for documents
15    /// constructed via [`AnswerDocument::new`] (no env binding yet) or read
16    /// from pre-C7 artifacts; set to `Some(env)` once the wizard's
17    /// `execute_request` materializes it.
18    #[serde(default, skip_serializing_if = "Option::is_none")]
19    pub env_id: Option<String>,
20    #[serde(default)]
21    pub answers: BTreeMap<String, Value>,
22    #[serde(default)]
23    pub locks: BTreeMap<String, Value>,
24}
25
26impl AnswerDocument {
27    pub fn new(locale: &str) -> Self {
28        Self {
29            wizard_id: crate::wizard::WIZARD_ID.to_string(),
30            schema_id: crate::wizard::ANSWER_SCHEMA_ID.to_string(),
31            schema_version: Version::new(1, 0, 0),
32            locale: crate::i18n::normalize_locale(locale).unwrap_or_else(|| "en".to_string()),
33            env_id: None,
34            answers: BTreeMap::new(),
35            locks: BTreeMap::new(),
36        }
37    }
38
39    pub fn from_json_str(raw: &str) -> Result<Self> {
40        let document: Self = serde_json::from_str(raw)?;
41        document.validate()?;
42        Ok(document)
43    }
44
45    pub fn validate(&self) -> Result<()> {
46        if self.wizard_id.trim().is_empty() {
47            bail!("{}", crate::i18n::tr("errors.answer_document.wizard_id"));
48        }
49        if self.schema_id.trim().is_empty() {
50            bail!("{}", crate::i18n::tr("errors.answer_document.schema_id"));
51        }
52        if self.locale.trim().is_empty() {
53            bail!("{}", crate::i18n::tr("errors.answer_document.locale"));
54        }
55        Ok(())
56    }
57
58    pub fn to_pretty_json_string(&self) -> Result<String> {
59        self.validate()?;
60        let mut rendered = serde_json::to_string_pretty(self)?;
61        rendered.push('\n');
62        Ok(rendered)
63    }
64}