betfair_xml_parser/
exception_type.rs1use serde::{Deserialize, Serialize};
4
5use crate::common::{Description, Parameter};
6
7#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
9#[serde(rename_all = "camelCase")]
10pub struct ExceptionType {
11 pub name: String,
13 pub prefix: String,
15 #[serde(rename = "$value")]
17 pub values: Vec<ExceptionTypeItems>,
18}
19
20#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
22#[serde(rename_all = "camelCase")]
23#[expect(clippy::module_name_repetitions)]
24pub enum ExceptionTypeItems {
25 Description(Description),
27 Parameter(Parameter),
29}
30
31#[cfg(test)]
32mod tests {
33 use rstest::rstest;
34 use serde_xml_rs::from_str;
35
36 use super::*;
37
38 #[rstest]
39 fn test_parse_aping_exception() {
40 let xml = r#"
41 <exceptionType name="APINGException" prefix="ANGX">
42 <description>This exception is thrown when an operation fails</description>
43 <parameter name="errorCode" type="string">
44 <description>the unique code for this error</description>
45 <validValues>
46 <value id="1" name="TOO_MUCH_DATA">
47 <description>The operation requested too much data</description>
48 </value>
49 <value id="2" name="INVALID_INPUT_DATA">
50 <description>Invalid input data</description>
51 </value>
52 <value id="3" name="INVALID_SESSION_INFORMATION">
53 <description>The session token passed is invalid</description>
54 </value>
55 <value id="4" name="NO_APP_KEY">
56 <description>An application key is required for this operation</description>
57 </value>
58 <value id="5" name="NO_SESSION">
59 <description>A session token is required for this operation</description>
60 </value>
61 <value id="6" name="UNEXPECTED_ERROR">
62 <description>An unexpected internal error occurred that prevented successful request processing.
63 </description>
64 </value>
65 <value id="7" name="INVALID_APP_KEY">
66 <description>The application key passed is invalid</description>
67 </value>
68 <value id="8" name="TOO_MANY_REQUESTS">
69 <description>There are too many pending requests</description>
70 </value>
71 <value id="9" name="SERVICE_BUSY">
72 <description>The service is currently too busy to service this request</description>
73 </value>
74 <value id="10" name="TIMEOUT_ERROR">
75 <description>Internal call to downstream service timed out</description>
76 </value>
77 <value id="11" name="APP_KEY_CREATION_FAILED">
78 <description>The application key creation has failed</description>
79 </value>
80 <value id="12" name="DUPLICATE_APP_NAME">
81 <description>The application name specified already exists</description>
82 </value>
83 <value id="13" name="APP_CREATION_FAILED">
84 <description>The application name specified is too long</description>
85 </value>
86 <value id="14" name="REQUEST_SIZE_EXCEEDS_LIMIT">
87 <description>The request has exceeded the maximum allowed size</description>
88 </value>
89 <value id="15" name="ACCESS_DENIED">
90 <description>The access to this functionality is not allowed</description>
91 </value>
92 <value id="16" name="INVALID_MARKET_GROUP">
93 <description>
94 Provided market group id does not identify a known market group
95 </description>
96 </value>
97 <value id="17" name="EXPOSURE_LIMIT_NOT_EXIST">
98 <description>
99 Unable to delete/update limit as it doesn't exist
100 </description>
101 </value>
102 <value id="18" name="MARKET_GROUP_NOT_BLOCKED">
103 <description>
104 Unable to unblock market group after exposure limit breach, market group is not blocked
105 </description>
106 </value>
107 </validValues>
108 </parameter>
109 <parameter name="errorDetails" type="string">
110 <description>the stack trace of the error</description>
111 </parameter>
112 <parameter name="requestUUID" type="string">
113 <description/>
114 </parameter>
115 </exceptionType>
116 "#;
117
118 let exception = from_str::<ExceptionType>(xml);
119
120 match exception {
121 Ok(exception) => {
122 assert_eq!(exception.name, "APINGException");
123 assert_eq!(exception.prefix, "ANGX");
124 assert_eq!(exception.values.len(), 4);
125 assert!(exception.values.first().map_or(false, |item| {
126 matches!(item, &ExceptionTypeItems::Description(Description {
127 value: Some(ref desc)
128 }) if desc == "This exception is thrown when an operation fails")
129 }));
130
131 assert!(exception.values.get(1).map_or(false, |item| {
132 matches!(item, &ExceptionTypeItems::Parameter(_))
133 }));
134 }
135 Err(err) => {
136 log::error!("Failed to parse XML: {err}");
137 }
138 }
139 }
140}