1use serde::Deserialize;
7
8#[derive(Deserialize, Debug, PartialEq, Eq)]
10#[serde(rename_all = "kebab-case")]
11pub enum AspaceType {
12 Total,
13 Mprotect,
14 Subheaps,
15 #[serde(other)]
16 Other,
17}
18
19#[derive(Deserialize, Debug, PartialEq, Eq)]
21#[serde(rename_all = "kebab-case")]
22pub struct Aspace {
23 #[serde(rename = "@type")]
24 pub r#type: AspaceType,
25 #[serde(rename = "@size")]
26 pub size: usize,
27}
28
29#[derive(Deserialize, Debug, PartialEq, Eq)]
31#[serde(rename_all = "kebab-case")]
32pub enum SystemType {
33 Current,
34 Max,
35 #[serde(other)]
36 Other,
37}
38
39#[derive(Deserialize, Debug, PartialEq, Eq)]
41#[serde(rename_all = "kebab-case")]
42pub struct System {
43 #[serde(rename = "@type")]
44 pub r#type: SystemType,
45 #[serde(rename = "@size")]
46 pub size: usize,
47}
48
49#[derive(Deserialize, Debug, PartialEq, Eq)]
51#[serde(rename_all = "kebab-case")]
52pub enum TotalType {
53 Fast,
54 Rest,
55 Mmap,
56 #[serde(other)]
57 Other,
58}
59
60#[derive(Deserialize, Debug, PartialEq, Eq)]
62#[serde(rename_all = "kebab-case")]
63pub struct Total {
64 #[serde(rename = "@type")]
65 pub r#type: TotalType,
66 #[serde(rename = "@count")]
67 pub count: usize,
68 #[serde(rename = "@size")]
69 pub size: usize,
70}
71
72#[derive(Deserialize, Debug, PartialEq, Eq)]
74#[serde(rename_all = "kebab-case")]
75pub enum Size {
76 Size {
77 #[serde(rename = "@from")]
78 from: usize,
79 #[serde(rename = "@to")]
80 to: usize,
81 #[serde(rename = "@total")]
82 total: usize,
83 #[serde(rename = "@count")]
84 count: usize,
85 },
86 Unsorted {
87 #[serde(rename = "@from")]
88 from: usize,
89 #[serde(rename = "@to")]
90 to: usize,
91 #[serde(rename = "@total")]
92 total: usize,
93 #[serde(rename = "@count")]
94 count: usize,
95 },
96}
97
98#[derive(Deserialize, Debug, PartialEq, Eq)]
100#[serde(rename_all = "kebab-case")]
101pub struct Sizes {
102 #[serde(rename = "$value")]
103 pub sizes: Option<Vec<Size>>,
104}
105
106#[derive(Deserialize, Debug, PartialEq, Eq)]
108#[serde(rename_all = "kebab-case")]
109pub struct Heap {
110 #[serde(rename = "@nr")]
112 pub nr: usize,
113
114 pub sizes: Option<Sizes>,
116}
117
118#[derive(Deserialize, Debug, PartialEq, Eq)]
120#[serde(rename_all = "kebab-case")]
121pub struct Malloc {
122 #[serde(rename = "@version")]
123 pub version: String,
124 #[serde(rename = "heap")]
125 pub heaps: Vec<Heap>,
126 pub total: Vec<Total>,
127 pub system: Vec<System>,
128 pub aspace: Vec<Aspace>,
129}
130
131#[cfg(test)]
132mod test {
133 use super::*;
134
135 #[test]
136 fn parse_simple() {
137 const XML: &str = r#"
139<malloc version="1">
140<heap nr="0">
141<sizes>
142</sizes>
143<total type="fast" count="0" size="0"/>
144<total type="rest" count="0" size="0"/>
145<system type="current" size="135168"/>
146<system type="max" size="135168"/>
147<aspace type="total" size="135168"/>
148<aspace type="mprotect" size="135168"/>
149</heap>
150<total type="fast" count="0" size="0"/>
151<total type="rest" count="0" size="0"/>
152<system type="current" size="135168"/>
153<system type="max" size="135168"/>
154<aspace type="total" size="135168"/>
155<aspace type="mprotect" size="135168"/>
156</malloc>
157"#;
158 let parsed: Malloc = quick_xml::de::from_str(XML).expect("parse XML");
159 assert_eq!(parsed.version, "1");
160 assert_eq!(parsed.heaps.len(), 1);
161 assert_eq!(parsed.total.len(), 2);
162 assert_eq!(parsed.system.len(), 2);
163 assert_eq!(parsed.aspace.len(), 2);
164 }
165
166 #[test]
167 fn parse_complex() {
168 const XML: &str = r#"
170<malloc version="1">
171<heap nr="0">
172<sizes>
173</sizes>
174<total type="fast" count="0" size="0"/>
175<total type="rest" count="0" size="0"/>
176<system type="current" size="1081344"/>
177<system type="max" size="1081344"/>
178<aspace type="total" size="1081344"/>
179<aspace type="mprotect" size="1081344"/>
180</heap>
181<heap nr="1">
182<sizes>
183</sizes>
184<total type="fast" count="0" size="0"/>
185<total type="rest" count="0" size="0"/>
186<system type="current" size="1032192"/>
187<system type="max" size="1032192"/>
188<aspace type="total" size="1032192"/>
189<aspace type="mprotect" size="1032192"/>
190</heap>
191<total type="fast" count="0" size="0"/>
192<total type="rest" count="0" size="0"/>
193<system type="current" size="2113536"/>
194<system type="max" size="2113536"/>
195<aspace type="total" size="2113536"/>
196<aspace type="mprotect" size="2113536"/>
197</malloc>
198"#;
199 let parsed: Malloc = quick_xml::de::from_str(XML).expect("parse XML");
200 assert_eq!(parsed.version, "1");
201 assert_eq!(parsed.heaps.len(), 2);
202 assert_eq!(parsed.total.len(), 2);
203 assert_eq!(parsed.system.len(), 2);
204 assert_eq!(parsed.aspace.len(), 2);
205 }
206
207 #[test]
208 #[should_panic]
209 fn parse_invalid() {
210 const XML: &str = r#"
211<malloc version="1">
212</malloc>
213"#;
214 let _ = quick_xml::de::from_str::<Malloc>(XML).expect("parse XML");
215 }
216}