1use crate::message::Tag;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum SessionRejectReason {
6 InvalidTagNumber,
7 RequiredTagMissing,
8 TagNotDefinedForThisMessageType,
9 UndefinedTag,
10 TagSpecifiedWithoutAValue,
11 ValueIsIncorrect,
12 IncorrectDataFormatForValue,
13 DecryptionProblem,
14 SignatureProblem,
15 CompIDProblem,
16 SendingTimeAccuracyProblem,
17 InvalidMsgType,
18 XMLValidationError,
19 TagAppearsMoreThanOnce,
20 TagSpecifiedOutOfRequiredOrder,
21 RepeatingGroupFieldsOutOfOrder,
22 IncorrectNumInGroupCountForRepeatingGroup,
23 NonDataValueIncludesFieldDelimiter,
24 Other,
25}
26
27impl SessionRejectReason {
28 pub fn code(&self) -> u32 {
29 match self {
30 Self::InvalidTagNumber => 0,
31 Self::RequiredTagMissing => 1,
32 Self::TagNotDefinedForThisMessageType => 2,
33 Self::UndefinedTag => 3,
34 Self::TagSpecifiedWithoutAValue => 4,
35 Self::ValueIsIncorrect => 5,
36 Self::IncorrectDataFormatForValue => 6,
37 Self::DecryptionProblem => 7,
38 Self::SignatureProblem => 8,
39 Self::CompIDProblem => 9,
40 Self::SendingTimeAccuracyProblem => 10,
41 Self::InvalidMsgType => 11,
42 Self::XMLValidationError => 12,
43 Self::TagAppearsMoreThanOnce => 13,
44 Self::TagSpecifiedOutOfRequiredOrder => 14,
45 Self::RepeatingGroupFieldsOutOfOrder => 15,
46 Self::IncorrectNumInGroupCountForRepeatingGroup => 16,
47 Self::NonDataValueIncludesFieldDelimiter => 17,
48 Self::Other => 99,
49 }
50 }
51
52 pub fn text(&self) -> &'static str {
53 match self {
54 Self::InvalidTagNumber => "Invalid tag number",
55 Self::RequiredTagMissing => "Required tag missing",
56 Self::TagNotDefinedForThisMessageType => "Tag not defined for this message type",
57 Self::UndefinedTag => "Undefined tag",
58 Self::TagSpecifiedWithoutAValue => "Tag specified without a value",
59 Self::ValueIsIncorrect => "Value is incorrect (out of range) for this tag",
60 Self::IncorrectDataFormatForValue => "Incorrect data format for value",
61 Self::DecryptionProblem => "Decryption problem",
62 Self::SignatureProblem => "Signature problem",
63 Self::CompIDProblem => "CompID problem",
64 Self::SendingTimeAccuracyProblem => "SendingTime accuracy problem",
65 Self::InvalidMsgType => "Invalid MsgType",
66 Self::XMLValidationError => "XML validation error",
67 Self::TagAppearsMoreThanOnce => "Tag appears more than once",
68 Self::TagSpecifiedOutOfRequiredOrder => "Tag specified out of required order",
69 Self::RepeatingGroupFieldsOutOfOrder => "Repeating group fields out of order",
70 Self::IncorrectNumInGroupCountForRepeatingGroup => {
71 "Incorrect NumInGroup count for repeating group"
72 }
73 Self::NonDataValueIncludesFieldDelimiter => {
74 "Non-data value includes field delimiter (SOH character)"
75 }
76 Self::Other => "Other",
77 }
78 }
79}
80
81#[derive(Debug, Clone, thiserror::Error)]
86#[error("{}", .text.as_deref().unwrap_or(self.reason.text()))]
87pub struct RejectError {
88 pub reason: SessionRejectReason,
89 pub ref_tag: Option<Tag>,
90 pub text: Option<String>,
92 pub is_garbled: bool,
95}
96
97impl RejectError {
98 pub fn new(reason: SessionRejectReason) -> Self {
99 Self { reason, ref_tag: None, text: None, is_garbled: false }
100 }
101 pub fn with_tag(reason: SessionRejectReason, tag: Tag) -> Self {
102 Self { reason, ref_tag: Some(tag), text: None, is_garbled: false }
103 }
104 pub fn other(text: impl Into<String>, ref_tag: Tag) -> Self {
106 Self {
107 reason: SessionRejectReason::Other,
108 ref_tag: Some(ref_tag),
109 text: Some(text.into()),
110 is_garbled: false,
111 }
112 }
113}
114
115#[derive(Debug, Clone, thiserror::Error)]
117pub enum ConversionError {
118 #[error("field {tag} not found")]
119 FieldNotFound { tag: Tag },
120 #[error("cannot convert value {value:?} for tag {tag}")]
121 InvalidValue { tag: Tag, value: String },
122}
123
124#[derive(Debug, thiserror::Error)]
125pub enum Error {
126 #[error("message parse error: {0}")]
127 Parse(String),
128 #[error(transparent)]
129 Conversion(#[from] ConversionError),
130 #[error(transparent)]
131 Reject(#[from] RejectError),
132 #[error("session {0} not found")]
133 UnknownSession(String),
134 #[error("session {0} is not logged on")]
135 NotLoggedOn(String),
136 #[error("configuration error: {0}")]
137 Config(String),
138 #[error("TLS error: {0}")]
139 Tls(String),
140 #[error("data dictionary error: {0}")]
141 Dictionary(String),
142 #[error("store error: {0}")]
143 Store(String),
144 #[error("do not send")]
145 DoNotSend,
146 #[error(transparent)]
147 Io(#[from] std::io::Error),
148}
149
150pub type Result<T> = std::result::Result<T, Error>;