1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
use std::fmt;
use std::fmt::Display;
use std::io;
/// Any error that is detected solely by examining a template definition, thus
/// even before receiving any data stream. Counterparties MUST signal static
/// errors and the template where the original error occurred must be discarded.
#[derive(Copy, Clone, Debug)]
pub enum StaticError {
/// It is a static error if templates encoded in the concrete XML syntax are
/// in fact not well-formed, do not follow the rules of XML namespaces or are
/// invalid with respect to the schema in Appendix 1.
S1 = 1,
/// It is a static error if an operator is specified for a field of a type to
/// which the operator is not applicable.
S2 = 2,
/// It is a static error if an initial value specified by the value attribute
/// in the concrete syntax cannot be converted to a value of the type of the
/// field.
S3 = 3,
/// It is a static error if no initial value is specified for a constant
/// operator.
S4 = 4,
/// It is a static error if no initial value is specified for a default
/// operator on a mandatory field.
S5 = 5,
}
/// Any error detected when encoding or decoding a FAST stream. Counterparties
/// MUST signal dynamic errors.
#[derive(Copy, Clone, Debug)]
pub enum DynamicError {
/// It is a dynamic error if type of a field in a template cannot be
/// converted to or from the type of the corresponding application field.
D1 = 1,
/// It is a dynamic error if an integer in the stream does not fall within
/// the bounds of the specific integer type specified on the corresponding
/// field.
D2 = 2,
/// It is a dynamic error if a decimal value cannot be encoded due to
/// limitations introduced by using individual operators on exponent and
/// mantissa.
D3 = 3,
/// It is a dynamic error if the type of the previous value is not the same
/// as the type of the field of the current operator.
D4 = 4,
/// It is a dynamic error if a mandatory field is not present in the stream,
/// has an undefined previous value and there is no initial value in the
/// instruction context.
D5 = 5,
/// It is a dynamic error if a mandatory field is not present in the stream
/// and has an empty previous value.
D6 = 6,
/// It is a dynamic error if the subtraction length exceeds the length of the
/// base value or if it does not fall in the value rang of an int32.
D7 = 7,
/// It is a dynamic error if the name specified on a static template
/// reference does not point to a template known by the encoder or decoder.
D8 = 8,
/// It is a dynamic error if a decoder cannot find a template associated with
/// a template identifier appearing in the stream.
D9 = 9,
/// It is a dynamic error if the syntax of a string does not follow the rules
/// for the type converted to.
D10 = 10,
/// It is a dynamic error if the syntax of a string does not follow the rules
/// for the type converted to
D11 = 11,
/// It is a dynamic error if a block length preamble is zero.
D12 = 12,
}
/// Any error detected when encoding or decoding a FAST stream. Contrary to
/// dynamic errors, counterparties are not obligated to signal dynamic errors an
/// may choose not to do so, e.g. to improve performance.
#[derive(Copy, Clone, Debug)]
pub enum ReportableError {
/// It is a reportable error if a decimal cannot be represented by an
/// exponent in the range [-63 … 63] or if the mantissa does not fit in an
/// int64.
R1 = 1,
/// It is a reportable error if the combined value after applying a tail or
/// delta operator to a Unicode string is not a valid UTF-8 sequence.
R2 = 2,
/// It is a reportable error if a Unicode string that is being converted to
/// an ASCII string contains characters that are outside the ASCII character
/// set.
R3 = 3,
/// It is a reportable error if a value of an integer type cannot be
/// represented in the target integer type in a conversion.
R4 = 4,
/// It is a reportable error if a decimal being converted to an integer has a
/// negative exponent or if the resulting integer does not fit the target
/// integer type.
R5 = 5,
/// It is a reportable error if an integer appears in an overlong encoding.
R6 = 6,
/// It is a reportable error if a presence map is overlong.
R7 = 7,
/// It is a reportable error if a presence map contains more bits than required.
R8 = 8,
/// It is a reportable error if a string appears in an overlong encoding.
R9 = 9,
}
#[derive(Debug)]
pub enum Error {
Static(StaticError),
Dynamic(DynamicError),
Reportable(ReportableError),
}
impl From<io::Error> for Error {
fn from(_err: io::Error) -> Self {
Error::Dynamic(DynamicError::D1)
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Dynamic(e) => {
write!(f, "Dynamic Error (D{}): ", *e as u8)?;
(*e).fmt(f)
}
Error::Reportable(e) => {
write!(f, "Reportable Error (R{}): ", *e as u8)?;
(*e).fmt(f)
}
Error::Static(e) => {
write!(f, "Dynamic Error (D{}): ", *e as u8)?;
(*e).fmt(f)
}
}
}
}
impl Display for StaticError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let message = match self {
Self::S1 => "The template is not encoded correctly according to the XML spec.",
Self::S2 => "An operator is specified for a field of a type to which the operator is not applicable.",
Self::S3 => "No initial value is specified for a default operator on a mandatory field.",
Self::S4 => "No initial value is specified for a constant operator.",
Self::S5 => "No initial value is specified for a default operator on a mandatory field.",
};
write!(f, "{}", message)
}
}
impl Display for DynamicError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let message = match self {
Self::D1 => "A field in a template cannot be converted to or from the type of the corresponding application field",
Self::D2 => "An integer in the stream does not fall within the bounds of the specific integer type specified on the corresponding field.",
Self::D3 => "A decimal value cannot be encoded due to limitations introduced by using individual operators on exponent and mantissa.",
Self::D4 => "The type of the previous value is not the same as the type of the field of the current operator.",
Self::D5 => "A mandatory field is not present in the stream, has an undefined previous value and there is no initial value in the instruction context.",
Self::D6 => "A mandatory field is not present in the stream and has an empty previous value.",
Self::D7 => "The subtraction length exceeds the length of the base value or if it does not fall in the value rang of an int32.",
Self::D8 => "The name specified on a static template reference does not point to a template known by the encoder or decoder.",
Self::D9 => "A decoder cannot find a template associated with a template identifier appearing in the stream.",
Self::D10 => "The syntax of a string does not follow the rules for the type converted to.",
Self::D11 => "The syntax of a string does not follow the rules for the type converted to.",
Self::D12 => "A block length preamble is zero.",
};
write!(f, "{}", message)
}
}
impl Display for ReportableError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let message = match self {
Self::R1 => "A decimal cannot be represented by an exponent in the range [-63 … 63] or if the mantissa does not fit in an int64.",
Self::R2 => "The combined value after applying a tail or delta operator to a Unicode string is not a valid UTF-8 sequence.",
Self::R3 => "A Unicode string that is being converted to an ASCII string contains characters that are outside the ASCII character set.",
Self::R4 => "A value of an integer type cannot be represented in the target integer type in a conversion.",
Self::R5 => "A decimal being converted to an integer has a negative exponent or if the resulting integer does not fit the target integer type.",
Self::R6 => "An integer appears in an overlong encoding.",
Self::R7 => "A presence map is overlong.",
Self::R8 => "A presence map contains more bits than required.",
Self::R9 => "A string appears in an overlong encoding.",
};
write!(f, "{}", message)
}
}