Skip to main content

greentic_component/cmd/info/
report.rs

1use serde::{Deserialize, Serialize};
2
3/// Structured info about a compiled component `.wasm` artifact.
4///
5/// Serialized as JSON when the `info --json` flag is set. The
6/// `info_schema_version` field lets downstream consumers detect
7/// breaking changes to this shape.
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct InfoReport {
10    pub info_schema_version: u32,
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub component_id: Option<String>,
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub name: Option<String>,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub version: Option<String>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub description: Option<String>,
19    pub artifact_type: String,
20    pub size_bytes: u64,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub wit_world: Option<String>,
23    pub exports: Vec<String>,
24    pub imports: Vec<String>,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub capabilities: Option<Capabilities>,
27    pub manifest_source: ManifestSource,
28}
29
30/// Non-empty capability surfaces extracted from the manifest.
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct Capabilities {
33    pub host: Vec<String>,
34    pub wasi: Vec<String>,
35}
36
37/// Where the manifest-derived fields on [`InfoReport`] came from.
38#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
39#[serde(rename_all = "lowercase")]
40pub enum ManifestSource {
41    /// Manifest read from the `greentic.component.manifest.v1` custom section
42    /// inside the `.wasm`.
43    Embedded,
44    /// Manifest read from a `component.manifest.json` sibling next to the `.wasm`.
45    Sibling,
46    /// No manifest was found; info fields are binary-derived only.
47    None,
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn json_has_schema_version_one() {
56        let r = InfoReport {
57            info_schema_version: 1,
58            component_id: None,
59            name: None,
60            version: None,
61            description: None,
62            artifact_type: "component/wasm".into(),
63            size_bytes: 0,
64            wit_world: None,
65            exports: vec![],
66            imports: vec![],
67            capabilities: None,
68            manifest_source: ManifestSource::None,
69        };
70        let v: serde_json::Value = serde_json::to_value(&r).unwrap();
71        assert_eq!(v["info_schema_version"], 1);
72        assert_eq!(v["manifest_source"], "none");
73    }
74
75    #[test]
76    fn manifest_source_serializes_lowercase() {
77        let v = serde_json::to_value(ManifestSource::Embedded).unwrap();
78        assert_eq!(v, serde_json::Value::String("embedded".into()));
79        let v = serde_json::to_value(ManifestSource::Sibling).unwrap();
80        assert_eq!(v, serde_json::Value::String("sibling".into()));
81    }
82}