Skip to main content

a2ui_types/v08/
data_model.rs

1use serde::{Deserialize, Serialize};
2
3/// A value that can be either a literal or bound to the data model.
4/// Used in v0.8 for component properties like `text`, `label`, etc.
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
6#[serde(deny_unknown_fields)]
7pub struct BoundValue {
8    /// A static string value.
9    #[serde(rename = "literalString", skip_serializing_if = "Option::is_none")]
10    pub literal_string: Option<String>,
11
12    /// A static number value.
13    #[serde(rename = "literalNumber", skip_serializing_if = "Option::is_none")]
14    pub literal_number: Option<f64>,
15
16    /// A static boolean value.
17    #[serde(rename = "literalBoolean", skip_serializing_if = "Option::is_none")]
18    pub literal_boolean: Option<bool>,
19
20    /// A static array value.
21    #[serde(rename = "literalArray", skip_serializing_if = "Option::is_none")]
22    pub literal_array: Option<Vec<serde_json::Value>>,
23
24    /// A JSON Pointer path to a value in the data model.
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub path: Option<String>,
27}
28
29impl BoundValue {
30    /// Create a BoundValue from a literal string.
31    pub fn from_literal_string(s: impl Into<String>) -> Self {
32        Self {
33            literal_string: Some(s.into()),
34            literal_number: None,
35            literal_boolean: None,
36            literal_array: None,
37            path: None,
38        }
39    }
40
41    /// Create a BoundValue from a data model path.
42    pub fn from_path(path: impl Into<String>) -> Self {
43        Self {
44            literal_string: None,
45            literal_number: None,
46            literal_boolean: None,
47            literal_array: None,
48            path: Some(path.into()),
49        }
50    }
51
52    /// Create a BoundValue with both a path and a literal string (initialization shorthand).
53    pub fn from_path_with_default(path: impl Into<String>, default: impl Into<String>) -> Self {
54        Self {
55            literal_string: Some(default.into()),
56            literal_number: None,
57            literal_boolean: None,
58            literal_array: None,
59            path: Some(path.into()),
60        }
61    }
62}
63
64/// Defines the children of a container component.
65/// Must contain exactly one of `explicit_list` or `template`.
66#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67#[serde(deny_unknown_fields)]
68pub struct Children {
69    /// An ordered list of component IDs that are direct children.
70    #[serde(rename = "explicitList", skip_serializing_if = "Option::is_none")]
71    pub explicit_list: Option<Vec<String>>,
72
73    /// A template for rendering dynamic lists of children.
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub template: Option<ChildTemplate>,
76}
77
78impl Children {
79    /// Create children from an explicit list of component IDs.
80    pub fn from_explicit_list(ids: Vec<String>) -> Self {
81        Self {
82            explicit_list: Some(ids),
83            template: None,
84        }
85    }
86
87    /// Create children from a template.
88    pub fn from_template(template: ChildTemplate) -> Self {
89        Self {
90            explicit_list: None,
91            template: Some(template),
92        }
93    }
94}
95
96/// A template for generating dynamic lists of children from a data-bound list.
97#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
98#[serde(deny_unknown_fields)]
99pub struct ChildTemplate {
100    /// The path to a list in the data model.
101    #[serde(rename = "dataBinding")]
102    pub data_binding: String,
103
104    /// The ID of the component to use as a template for each item.
105    #[serde(rename = "componentId")]
106    pub component_id: String,
107}
108
109/// A single data entry in a `dataModelUpdate` message.
110/// Each entry has a key and exactly one typed value.
111#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
112pub struct DataEntry {
113    /// The key for this data entry.
114    pub key: String,
115
116    /// A string value.
117    #[serde(rename = "valueString", skip_serializing_if = "Option::is_none")]
118    pub value_string: Option<String>,
119
120    /// A number value.
121    #[serde(rename = "valueNumber", skip_serializing_if = "Option::is_none")]
122    pub value_number: Option<f64>,
123
124    /// A boolean value.
125    #[serde(rename = "valueBoolean", skip_serializing_if = "Option::is_none")]
126    pub value_boolean: Option<bool>,
127
128    /// A map value, represented as a nested adjacency list.
129    #[serde(rename = "valueMap", skip_serializing_if = "Option::is_none")]
130    pub value_map: Option<Vec<DataEntry>>,
131}
132
133/// An action definition on an interactive component (e.g. Button).
134#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
135pub struct Action {
136    /// The name of the action to dispatch to the server.
137    pub name: String,
138
139    /// Key-value pairs for the action context. Values can be literals or data-bound.
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub context: Option<Vec<ActionContextEntry>>,
142}
143
144/// A single entry in an action's context array.
145#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
146pub struct ActionContextEntry {
147    /// The key name.
148    pub key: String,
149
150    /// The value, which can be literal or data-bound.
151    pub value: BoundValue,
152}