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 <objectPermissions> to its own file, or group <fieldPermissions> 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}