bnr_xfs/xfs/
xfs_struct.rs1use std::fmt;
4
5use crate::{Error, Result};
6
7use super::value::XfsValue;
8
9#[repr(C)]
11#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
12#[serde(rename = "struct")]
13pub struct XfsStruct {
14 #[serde(rename = "$value", default)]
15 members: Vec<ListMember>,
16}
17
18impl XfsStruct {
19 pub const fn new() -> Self {
21 Self {
22 members: Vec::new(),
23 }
24 }
25
26 pub fn create<M: IntoIterator<Item = XfsMember>>(members: M) -> Self {
28 Self {
29 members: members.into_iter().map(ListMember::from).collect(),
30 }
31 }
32
33 pub fn members(&self) -> &[ListMember] {
35 self.members.as_ref()
36 }
37
38 pub fn members_mut(&mut self) -> &mut [ListMember] {
40 self.members.as_mut()
41 }
42
43 pub fn set_members<M: IntoIterator<Item = XfsMember>>(&mut self, members: M) {
45 self.members = members.into_iter().map(ListMember::from).collect();
46 }
47
48 pub fn with_members<M: IntoIterator<Item = XfsMember>>(mut self, members: M) -> Self {
50 self.set_members(members);
51 self
52 }
53
54 pub fn find_member(&self, name: &str) -> Result<&XfsMember> {
56 self.members
57 .iter()
58 .map(|m| m.inner())
59 .find(|m| m.name() == name)
60 .ok_or(Error::Xfs(format!(r#"Missing member "{name}""#)))
61 }
62}
63
64impl fmt::Display for XfsStruct {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 write!(f, r#"{{"members": ["#)?;
67 for (i, member) in self.members.iter().enumerate() {
68 if i != 0 {
69 write!(f, ", ")?;
70 }
71 write!(f, "{member}")?;
72 }
73 write!(f, "]}}")
74 }
75}
76
77#[repr(C)]
79#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
80pub enum ListStruct {
81 #[serde(rename = "struct")]
82 Struct(XfsStruct),
83}
84
85impl ListStruct {
86 pub const fn new() -> Self {
88 Self::Struct(XfsStruct::new())
89 }
90
91 pub const fn create(xfs: XfsStruct) -> Self {
93 Self::Struct(xfs)
94 }
95
96 pub const fn inner(&self) -> &XfsStruct {
98 match self {
99 Self::Struct(s) => s,
100 }
101 }
102
103 pub fn inner_mut(&mut self) -> &mut XfsStruct {
105 match self {
106 Self::Struct(s) => s,
107 }
108 }
109
110 pub fn into_inner(self) -> XfsStruct {
112 match self {
113 Self::Struct(s) => s,
114 }
115 }
116}
117
118impl fmt::Display for ListStruct {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 match self {
121 Self::Struct(s) => write!(f, "{s}"),
122 }
123 }
124}
125
126#[repr(C)]
128#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
129#[serde(rename = "member")]
130pub struct XfsMember {
131 name: String,
132 value: XfsValue,
133}
134
135impl XfsMember {
136 pub const fn new() -> Self {
138 Self {
139 name: String::new(),
140 value: XfsValue::new(),
141 }
142 }
143
144 pub fn create<S: Into<String>>(name: S, value: XfsValue) -> Self {
146 Self {
147 name: name.into(),
148 value,
149 }
150 }
151
152 pub fn name(&self) -> &str {
154 self.name.as_str()
155 }
156
157 pub fn set_name<S: Into<String>>(&mut self, name: S) {
159 self.name = name.into();
160 }
161
162 pub fn with_name<S: Into<String>>(mut self, name: S) -> Self {
164 self.set_name(name);
165 self
166 }
167
168 pub const fn value(&self) -> &XfsValue {
170 &self.value
171 }
172
173 pub fn set_value(&mut self, value: XfsValue) {
175 self.value = value;
176 }
177
178 pub fn with_value(mut self, value: XfsValue) -> Self {
180 self.set_value(value);
181 self
182 }
183}
184
185impl fmt::Display for XfsMember {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 write!(f, "{{")?;
188 write!(f, r#""name": "{}", "#, self.name)?;
189 write!(f, r#""value": {}"#, self.value)?;
190 write!(f, "}}")
191 }
192}
193
194#[repr(C)]
196#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
197pub enum ListMember {
198 #[serde(rename = "member")]
199 Member(XfsMember),
200}
201
202impl ListMember {
203 pub const fn new() -> Self {
205 Self::Member(XfsMember::new())
206 }
207
208 pub const fn create(m: XfsMember) -> Self {
210 Self::Member(m)
211 }
212
213 pub const fn from_inner(m: XfsMember) -> Self {
215 Self::Member(m)
216 }
217
218 pub const fn inner(&self) -> &XfsMember {
220 match self {
221 Self::Member(m) => m,
222 }
223 }
224
225 pub fn inner_mut(&mut self) -> &mut XfsMember {
227 match self {
228 Self::Member(m) => m,
229 }
230 }
231
232 pub fn into_inner(self) -> XfsMember {
234 match self {
235 Self::Member(m) => m,
236 }
237 }
238}
239
240impl From<&XfsMember> for ListMember {
241 fn from(val: &XfsMember) -> Self {
242 val.clone().into()
243 }
244}
245
246impl From<XfsMember> for ListMember {
247 fn from(val: XfsMember) -> Self {
248 Self::from_inner(val)
249 }
250}
251
252impl From<&ListMember> for XfsMember {
253 fn from(val: &ListMember) -> Self {
254 val.clone().into()
255 }
256}
257
258impl From<ListMember> for XfsMember {
259 fn from(val: ListMember) -> Self {
260 val.into_inner()
261 }
262}
263
264impl fmt::Display for ListMember {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 match self {
267 Self::Member(s) => write!(f, "{s}"),
268 }
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use super::*;
275 use crate::{xfs, Result};
276
277 #[test]
278 fn test_xfs_value_struct_serde() -> Result<()> {
279 let exp_xml = r#"<?xml version="1.0" encoding="UTF-8"?><value><struct><member><name>test</name><value><i4>16</i4></value></member></struct></value>"#;
280
281 let exp_struct = XfsValue::new().with_xfs_struct(XfsStruct::create([XfsMember::create(
282 "test",
283 XfsValue::new().with_i4(16),
284 )]));
285
286 assert_eq!(xfs::to_string(&exp_struct)?.as_str(), exp_xml);
287 assert_eq!(xfs::from_str::<XfsValue>(exp_xml)?, exp_struct);
288
289 Ok(())
290 }
291}