bnr_xfs/xfs/
method_response.rs1use std::fmt;
4
5use super::fault::XfsFault;
6use super::params::{XfsParam, XfsParams};
7use crate::{Error, Result};
8
9#[repr(C)]
14#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
15#[serde(rename = "methodResponse")]
16pub enum XfsMethodResponse {
17 #[serde(rename = "params")]
18 Params(XfsParams),
19 #[serde(rename = "fault")]
20 Fault(XfsFault),
21}
22
23impl XfsMethodResponse {
24 pub fn new_params<P: Into<Vec<XfsParam>>>(params: P) -> Self {
26 Self::Params(XfsParams::create(params.into()))
27 }
28
29 pub fn new_fault<S: Into<String>>(code: i32, string: S) -> Self {
31 Self::Fault(XfsFault::create(code, string))
32 }
33
34 pub fn call_id(&self) -> Result<i32> {
38 self.as_params()?
39 .params()
40 .iter()
41 .find(|&p| p.inner().value().i4().is_some())
42 .ok_or(Error::Xfs("missing response ID".into()))?
43 .inner()
44 .value()
45 .i4()
46 .cloned()
47 .ok_or(Error::Xfs("missing response ID".into()))
48 }
49}
50
51inner_enum!(XfsMethodResponse, Params, XfsParams);
52inner_enum!(XfsMethodResponse, Fault, XfsFault);
53
54impl fmt::Display for XfsMethodResponse {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 match self {
57 Self::Params(res) => write!(f, "{res}"),
58 Self::Fault(res) => write!(f, "{res}"),
59 }
60 }
61}
62
63#[repr(C)]
67#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
68#[serde(rename = "methodResponse")]
69pub struct XfsMethodResponseStruct {
70 #[serde(rename = "$value")]
71 response: XfsMethodResponse,
72}
73
74impl XfsMethodResponseStruct {
75 pub const fn new(response: XfsMethodResponse) -> Self {
77 Self { response }
78 }
79
80 pub const fn inner(&self) -> &XfsMethodResponse {
82 &self.response
83 }
84
85 pub fn inner_mut(&mut self) -> &mut XfsMethodResponse {
87 &mut self.response
88 }
89
90 pub fn into_inner(self) -> XfsMethodResponse {
92 self.response
93 }
94}
95
96impl From<XfsMethodResponse> for XfsMethodResponseStruct {
97 fn from(val: XfsMethodResponse) -> Self {
98 Self::new(val)
99 }
100}
101
102impl From<&XfsMethodResponse> for XfsMethodResponseStruct {
103 fn from(val: &XfsMethodResponse) -> Self {
104 Self::new(val.clone())
105 }
106}
107
108impl From<XfsMethodResponseStruct> for XfsMethodResponse {
109 fn from(val: XfsMethodResponseStruct) -> Self {
110 val.into_inner()
111 }
112}
113
114impl From<&XfsMethodResponseStruct> for XfsMethodResponse {
115 fn from(val: &XfsMethodResponseStruct) -> Self {
116 val.clone().into()
117 }
118}
119
120impl fmt::Display for XfsMethodResponseStruct {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 let s = self.inner();
123 write!(f, "{s}")
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use crate::{
131 xfs::{self, value::XfsValue},
132 Result,
133 };
134
135 #[test]
136 fn test_method_response_serde() -> Result<()> {
137 let exp_xml = r#"<?xml version="1.0" encoding="UTF-8"?><methodResponse><fault><value><struct><member><name>faultCode</name><value><i4>6072</i4></value></member><member><name>faultString</name><value><string></string></value></member></struct></value></fault></methodResponse>"#;
138 let res = XfsMethodResponseStruct::from(XfsMethodResponse::new_fault(6072, ""));
139
140 assert_eq!(xfs::to_string(&res)?.as_str(), exp_xml);
141 assert_eq!(xfs::from_str::<XfsMethodResponseStruct>(exp_xml)?, res);
142
143 let exp_xml = r#"<?xml version="1.0" encoding="UTF-8"?><methodResponse><params><param><value><i4>32</i4></value></param></params></methodResponse>"#;
144 let res = XfsMethodResponseStruct::from(XfsMethodResponse::new_params([XfsParam::create(
145 XfsValue::new().with_i4(32),
146 )]));
147
148 assert_eq!(xfs::to_string(&res)?.as_str(), exp_xml);
149 assert_eq!(xfs::from_str::<XfsMethodResponseStruct>(exp_xml)?, res);
150
151 Ok(())
152 }
153
154 #[test]
155 fn test_method_response_accessors() -> Result<()> {
156 let fault = XfsMethodResponse::new_fault(1010, "");
157 let exp_fault = XfsFault::create(1010, "");
158
159 assert!(fault.is_fault());
160 assert_eq!(fault.as_fault()?, &exp_fault);
161 assert_eq!(fault.into_fault()?, exp_fault);
162
163 let params = XfsMethodResponse::new_params([XfsParam::create(XfsValue::new().with_i4(32))]);
164 let exp_params = XfsParams::create([XfsParam::create(XfsValue::new().with_i4(32))]);
165
166 assert!(params.is_params());
167 assert_eq!(params.as_params()?, &exp_params);
168 assert_eq!(params.into_params()?, exp_params);
169
170 Ok(())
171 }
172
173 #[test]
174 fn test_nested_response() -> Result<()> {
175 let fuck_xml = r#"<?xml version="1.0"?>
176 <methodResponse>
177 <params>
178 <param>
179 <value>
180 <struct>
181 <member>
182 <name>
183 outerStruct
184 </name>
185 <value>
186 <array>
187 <data>
188 <value>
189 <struct>
190 <member>
191 <name>
192 innerStruct
193 </name>
194 <value>
195 <array>
196 <data>
197 <value>
198 <i4>0</i4>
199 </value>
200 <value>
201 <i4>1</i4>
202 </value>
203 </data>
204 </array>
205 </value>
206 </member>
207 </struct>
208 </value>
209 </data>
210 </array>
211 </value>
212 </member>
213 </struct>
214 </value>
215 </param>
216 </params>
217 </methodResponse>
218 "#;
219
220 xfs::from_str::<XfsMethodResponseStruct>(fuck_xml)?;
221
222 Ok(())
223 }
224
225 #[test]
226 fn test_null_param_value_serde() -> Result<()> {
227 let exp_xml = r#"<?xml version="1.0" encoding="UTF-8"?><methodResponse><params><param><value/></param></params></methodResponse>"#;
228 let exp_res =
229 XfsMethodResponseStruct::from(XfsMethodResponse::Params(XfsParams::create([
230 XfsParam::new(),
231 ])));
232
233 assert_eq!(xfs::to_string(&exp_res)?.as_str(), exp_xml);
234 assert_eq!(xfs::from_str::<XfsMethodResponseStruct>(exp_xml)?, exp_res);
235
236 Ok(())
237 }
238}