Skip to main content

config_disassembler/xml/
types.rs

1//! Type definitions for XML element representation.
2//!
3//! Uses serde_json::Value for flexible representation matching the TypeScript structure:
4//! - Object with keys: element names, @attr for attributes, #text for text content, ?xml for declaration
5//! - Values: string, nested object, or array of objects/strings
6
7use serde_json::Value as JsonValue;
8
9/// XmlElement is a flexible representation of XML - equivalent to TypeScript's XmlElement type.
10/// Uses serde_json::Value for compatibility with quickxml_to_serde output.
11pub type XmlElement = JsonValue;
12
13/// Parameters for parsing an element during disassembly.
14#[derive(Debug, Clone)]
15pub struct XmlElementParams<'a> {
16    pub element: XmlElement,
17    pub disassembled_path: &'a str,
18    pub unique_id_elements: Option<&'a str>,
19    pub root_element_name: &'a str,
20    pub root_attributes: XmlElement,
21    pub key: &'a str,
22    pub leaf_content: XmlElement,
23    pub leaf_count: usize,
24    pub has_nested_elements: bool,
25    pub format: &'a str,
26    pub xml_declaration: Option<XmlElement>,
27    pub strategy: &'a str,
28    /// Pre-resolved unique-ID for this element. When `Some`, the file
29    /// writer uses this verbatim and skips its own `parse_unique_id_element`
30    /// derivation. Set by the caller when collision detection across a
31    /// sibling group has determined this element must use a hash fallback
32    /// instead of its derived id (see `resolve_collision_safe_ids`).
33    pub precomputed_unique_id: Option<&'a str>,
34}
35
36/// Options for building a single disassembled file.
37#[derive(Debug, Clone)]
38pub struct BuildDisassembledFileOptions<'a> {
39    pub content: XmlElement,
40    pub disassembled_path: &'a str,
41    pub output_file_name: Option<&'a str>,
42    pub subdirectory: Option<&'a str>,
43    pub wrap_key: Option<&'a str>,
44    pub is_grouped_array: bool,
45    pub root_element_name: &'a str,
46    pub root_attributes: XmlElement,
47    pub format: &'a str,
48    pub xml_declaration: Option<XmlElement>,
49    pub unique_id_elements: Option<&'a str>,
50    /// Pre-resolved unique-ID for this element. When `Some`, takes
51    /// precedence over `unique_id_elements` derivation. See the matching
52    /// field on [`XmlElementParams`] for details.
53    pub precomputed_unique_id: Option<&'a str>,
54}
55
56/// Result from unified element parsing.
57#[derive(Debug, Clone, Default)]
58pub struct UnifiedParseResult {
59    pub leaf_content: XmlElement,
60    pub leaf_count: usize,
61    pub has_nested_elements: bool,
62    pub nested_groups: Option<XmlElementArrayMap>,
63}
64
65/// Map of tag name to array of elements.
66pub type XmlElementArrayMap = std::collections::HashMap<String, Vec<XmlElement>>;
67
68/// Rule for decomposing a nested tag when using grouped-by-tag strategy.
69/// E.g. write each &lt;objectPermissions&gt; to its own file, or group &lt;fieldPermissions&gt; by object.
70#[derive(Debug, Clone)]
71pub struct DecomposeRule {
72    /// Element tag to decompose (e.g. "objectPermissions", "fieldPermissions").
73    pub tag: String,
74    /// Subdirectory under disassembled path (defaults to tag if empty).
75    pub path_segment: String,
76    /// "split" = one file per array item (filename from field); "group" = group by field, one file per group.
77    pub mode: String,
78    /// Field name: for split, used for filename; for group, used to group items.
79    pub field: String,
80}
81
82/// Options for building disassembled files from a source file.
83#[derive(Debug, Clone)]
84pub struct BuildDisassembledFilesOptions<'a> {
85    pub file_path: &'a str,
86    pub disassembled_path: &'a str,
87    pub base_name: &'a str,
88    pub post_purge: bool,
89    pub format: &'a str,
90    pub unique_id_elements: Option<&'a str>,
91    pub strategy: &'a str,
92    /// When strategy is grouped-by-tag, optionally decompose specific tags (split or group by field).
93    pub decompose_rules: Option<&'a [DecomposeRule]>,
94}
95
96/// Parameters for writing leaf content.
97#[derive(Debug, Clone)]
98pub struct LeafWriteParams<'a> {
99    pub leaf_count: usize,
100    pub leaf_content: XmlElement,
101    pub strategy: &'a str,
102    pub key_order: Vec<String>,
103    pub options: LeafWriteOptions<'a>,
104}
105
106#[derive(Debug, Clone)]
107pub struct LeafWriteOptions<'a> {
108    pub disassembled_path: &'a str,
109    pub output_file_name: &'a str,
110    pub root_element_name: &'a str,
111    pub root_attributes: XmlElement,
112    pub xml_declaration: Option<XmlElement>,
113    pub format: &'a str,
114}
115
116/// Rule for multi-level disassembly: which files to further disassemble and how.
117#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
118pub struct MultiLevelRule {
119    /// File name pattern (e.g. "programProcesses-meta"); any XML file whose name contains this is processed.
120    pub file_pattern: String,
121    /// Root element to strip (e.g. "LoyaltyProgramSetup"); its inner content becomes the new document.
122    pub root_to_strip: String,
123    /// Comma-separated unique-id elements for the second-level disassembly (e.g. "parameterName,ruleName").
124    pub unique_id_elements: String,
125    /// Path segment under the disassembly root for reassembly (e.g. "programProcesses").
126    #[serde(default)]
127    pub path_segment: String,
128    /// Root element name to wrap reassembled files with (defaults to root_to_strip).
129    #[serde(default)]
130    pub wrap_root_element: String,
131    /// xmlns value for the wrap root (optional; captured from original when stripping).
132    #[serde(default)]
133    pub wrap_xmlns: String,
134}
135
136/// Persisted config for multi-level reassembly (stored as .multi_level.json in the disassembly root).
137#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
138pub struct MultiLevelConfig {
139    pub rules: Vec<MultiLevelRule>,
140}