Skip to content

Commit 40ef391

Browse files
authored
chore: Improve en-/decode error messages (#536)
* feat: Make wrapped codec errors display their inner errors as well * feat: Simplify and harmonize error display for encode/decode errors
1 parent 4401ff9 commit 40ef391

2 files changed

Lines changed: 76 additions & 46 deletions

File tree

src/error/decode.rs

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ pub enum CodecDecodeError {
3030
Xer(XerDecodeErrorKind),
3131
}
3232

33+
impl core::fmt::Display for CodecDecodeError {
34+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35+
match self {
36+
CodecDecodeError::Ber(kind) => write!(f, "BER decoding error: {kind}"),
37+
CodecDecodeError::Cer(kind) => write!(f, "CER decoding error: {kind}"),
38+
CodecDecodeError::Der(kind) => write!(f, "DER decoding error: {kind}"),
39+
CodecDecodeError::Uper(kind) => write!(f, "UPER decoding error: {kind}"),
40+
CodecDecodeError::Aper(kind) => write!(f, "APER decoding error: {kind}"),
41+
CodecDecodeError::Jer(kind) => write!(f, "JER decoding error: {kind}"),
42+
CodecDecodeError::Oer(kind) => write!(f, "OER decoding error: {kind}"),
43+
CodecDecodeError::Coer(kind) => write!(f, "COER decoding error: {kind}"),
44+
CodecDecodeError::Xer(kind) => write!(f, "XER decoding error: {kind}"),
45+
}
46+
}
47+
}
48+
3349
macro_rules! impl_from {
3450
($variant:ident, $error_kind:ty) => {
3551
impl From<$error_kind> for DecodeError {
@@ -147,10 +163,9 @@ pub struct DecodeError {
147163

148164
impl core::fmt::Display for DecodeError {
149165
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
150-
writeln!(f, "Error Kind: {}", self.kind)?;
151-
writeln!(f, "Codec: {}", self.codec)?;
166+
write!(f, "{} (Codec: {})", self.kind, self.codec)?;
152167
#[cfg(feature = "backtraces")]
153-
write!(f, "\nBacktrace:\n{}", self.backtrace)?;
168+
write!(f, "\n\nBacktrace:\n{}", self.backtrace)?;
154169
Ok(())
155170
}
156171
}
@@ -485,15 +500,15 @@ pub enum DecodeErrorKind {
485500
},
486501

487502
/// Codec specific error.
488-
#[snafu(display("Wrapped codec-specific decode error"))]
503+
#[snafu(display("{inner}"))]
489504
CodecSpecific {
490505
/// The inner error type.
491506
inner: CodecDecodeError,
492507
},
493508

494509
/// Enumeration index didn't match any variant.
495510
#[snafu(display(
496-
"Enumeration index '{}' did not match any variant. Extended list: {}",
511+
"Enumeration index {} did not match any variant. Extended list checked: {}",
497512
index,
498513
extended_list
499514
))]
@@ -505,7 +520,7 @@ pub enum DecodeErrorKind {
505520
},
506521

507522
/// Choice index didn't match any variant.
508-
#[snafu(display("choice index '{index}' did not match any variant"))]
523+
#[snafu(display("Choice index {index} did not match any variant"))]
509524
ChoiceIndexNotFound {
510525
/// The found index of the choice variant.
511526
index: usize,
@@ -515,7 +530,7 @@ pub enum DecodeErrorKind {
515530

516531
/// Choice index exceeds maximum possible address width.
517532
#[snafu(display(
518-
"integer range larger than possible to address on this platform. needed: {needed} present: {present}"
533+
"Choice index exceeds platform index width. Needed {needed} bytes, present: {present}"
519534
))]
520535
ChoiceIndexExceedsPlatformWidth {
521536
/// Amount of bytes needed.
@@ -525,14 +540,14 @@ pub enum DecodeErrorKind {
525540
},
526541

527542
/// Uncategorised error.
528-
#[snafu(display("Custom: {}", msg))]
543+
#[snafu(display("Custom error: {}", msg))]
529544
Custom {
530545
/// The error's message.
531546
msg: alloc::string::String,
532547
},
533548

534549
/// Discriminant index didn't match any variant.
535-
#[snafu(display("Discriminant value '{}' did not match any variant", discriminant))]
550+
#[snafu(display("Discriminant value {} did not match any variant", discriminant))]
536551
DiscriminantValueNotFound {
537552
/// The found value of the discriminant
538553
discriminant: isize,
@@ -553,7 +568,7 @@ pub enum DecodeErrorKind {
553568
},
554569

555570
/// More than `usize::MAX` number of data requested.
556-
#[snafu(display("Length of the incoming data is either exceeds platform address width."))]
571+
#[snafu(display("Length of the data exceeds platform address width"))]
557572
LengthExceedsPlatformWidth {
558573
/// The specific message of the length error.
559574
msg: alloc::string::String,
@@ -571,19 +586,19 @@ pub enum DecodeErrorKind {
571586
/// Input is provided as BIT slice for nom in UPER/APER.
572587
/// On BER/CER/DER/OER/COER it is a BYTE slice.
573588
/// Hence, `needed` field can describe either bits or bytes depending on the codec.
574-
#[snafu(display("Need more data to continue: ({:?}).", needed))]
589+
#[snafu(display("Need more data to continue: {:?}", needed))]
575590
Incomplete {
576591
/// Amount of bits/bytes needed.
577592
needed: nom::Needed,
578593
},
579594
/// Encountered EOF when decoding.
580595
/// BER/CER/DER uses EOF as part of the decoding logic.
581-
#[snafu(display("EOF when decoding"))]
596+
#[snafu(display("Unexpected EOF when decoding"))]
582597
Eof,
583598

584599
/// Invalid item number in sequence.
585600
#[snafu(display(
586-
"Invalid item number in Sequence: expected {}, actual {}",
601+
"Invalid item number in Sequence: expected: {}; actual: {}",
587602
expected,
588603
actual
589604
))]
@@ -613,7 +628,7 @@ pub enum DecodeErrorKind {
613628
InvalidRealEncoding,
614629

615630
/// Decoder doesn't support REAL
616-
#[snafu(display("Decoder doesn't support REAL types"))]
631+
#[snafu(display("Decoder doesn't support `REAL` type"))]
617632
RealNotSupported,
618633

619634
/// `BitString` contains an invalid amount of unused bits.
@@ -637,7 +652,7 @@ pub enum DecodeErrorKind {
637652
#[snafu(display("Length of Length cannot be zero"))]
638653
ZeroLengthOfLength,
639654
/// The length does not match what was expected.
640-
#[snafu(display("Expected {:?} bytes, actual length: {:?}", expected, actual))]
655+
#[snafu(display("Expected {} bytes, actual length was {} bytes", expected, actual))]
641656
MismatchedLength {
642657
/// The expected length.
643658
expected: usize,
@@ -666,7 +681,7 @@ pub enum DecodeErrorKind {
666681

667682
/// The range of the integer exceeds the platform width.
668683
#[snafu(display(
669-
"integer range larger than possible to address on this platform. needed: {needed} present: {present}"
684+
"Integer range larger than possible to address on this platform. needed: {needed} present: {present}"
670685
))]
671686
RangeExceedsPlatformWidth {
672687
/// Amount of bytes needed.
@@ -752,10 +767,10 @@ pub enum DecodeErrorKind {
752767
#[non_exhaustive]
753768
pub enum BerDecodeErrorKind {
754769
/// An error when the length is not definite.
755-
#[snafu(display("Indefinite length encountered but not allowed."))]
770+
#[snafu(display("Indefinite length encountered but not allowed"))]
756771
IndefiniteLengthNotAllowed,
757772
/// An error if the value is not primitive when required.
758-
#[snafu(display("Invalid constructed identifier for ASN.1 value: not primitive."))]
773+
#[snafu(display("Invalid constructed identifier for ASN.1 value: not primitive"))]
759774
InvalidConstructedIdentifier,
760775
/// Invalid date.
761776
#[snafu(display("Invalid date string: {}", msg))]
@@ -764,7 +779,7 @@ pub enum BerDecodeErrorKind {
764779
msg: alloc::string::String,
765780
},
766781
/// An error when the object identifier is invalid.
767-
#[snafu(display("Invalid object identifier with missing or corrupt root nodes."))]
782+
#[snafu(display("Invalid object identifier with missing or corrupt root nodes"))]
768783
InvalidObjectIdentifier,
769784
/// The tag does not match what was expected.
770785
#[snafu(display("Expected {:?} tag, actual tag: {:?}", expected, actual))]
@@ -804,7 +819,7 @@ pub enum CerDecodeErrorKind {}
804819
#[non_exhaustive]
805820
pub enum DerDecodeErrorKind {
806821
/// An error when constructed encoding encountered but not allowed.
807-
#[snafu(display("Constructed encoding encountered but not allowed."))]
822+
#[snafu(display("Constructed encoding encountered but not allowed"))]
808823
ConstructedEncodingNotAllowed,
809824
}
810825

@@ -814,11 +829,11 @@ pub enum DerDecodeErrorKind {
814829
#[non_exhaustive]
815830
pub enum JerDecodeErrorKind {
816831
/// An error when the end of input is reached, but more data is needed.
817-
#[snafu(display("Unexpected end of input while decoding JER JSON."))]
832+
#[snafu(display("Unexpected end of input while decoding JER"))]
818833
EndOfInput {},
819834
/// An error when the JSON type is not the expected type.
820835
#[snafu(display(
821-
"Found mismatching JSON value. Expected type {}. Found value {}.",
836+
"Found mismatching JSON value. Expected type: {}. Found value: {}",
822837
needed,
823838
found
824839
))]
@@ -829,13 +844,13 @@ pub enum JerDecodeErrorKind {
829844
found: alloc::string::String,
830845
},
831846
/// An error when the JSON value is not a valid bit string.
832-
#[snafu(display("Found invalid byte in bit string. {parse_int_err}"))]
847+
#[snafu(display("Found invalid byte in bit string: {parse_int_err}"))]
833848
InvalidJerBitstring {
834849
/// The error that occurred when parsing the `BitString` byte.
835850
parse_int_err: ParseIntError,
836851
},
837852
/// An error when the JSON value is not a valid octet string.
838-
#[snafu(display("Found invalid character in octet string."))]
853+
#[snafu(display("Found invalid character in octet string"))]
839854
InvalidJerOctetString {},
840855
/// An error when the JSON value is not a valid OID string.
841856
#[snafu(display("Failed to construct OID from value {value}",))]
@@ -878,11 +893,11 @@ pub enum AperDecodeErrorKind {}
878893
#[snafu(visibility(pub))]
879894
#[non_exhaustive]
880895
pub enum XerDecodeErrorKind {
881-
#[snafu(display("Unexpected end of input while decoding XER XML."))]
896+
#[snafu(display("Unexpected end of input while decoding XER"))]
882897
/// An error that indicates that the XML input ended unexpectedly
883898
EndOfXmlInput {},
884899
#[snafu(display(
885-
"Found mismatching XML value. Expected type {}. Found value {}.",
900+
"Found mismatching XML value. Expected type: {}. Found value: {}.",
886901
needed,
887902
found
888903
))]
@@ -893,13 +908,13 @@ pub enum XerDecodeErrorKind {
893908
/// the encountered tag type or value
894909
found: alloc::string::String,
895910
},
896-
#[snafu(display("Found invalid character in octet string."))]
911+
#[snafu(display("Found invalid character in octet string"))]
897912
/// An error that indicates a character in an octet string that does not conform to the hex alphabet
898913
InvalidXerOctetstring {
899914
/// Inner error thrown by the `parse` method
900915
parse_int_err: ParseIntError,
901916
},
902-
#[snafu(display("Encountered invalid value. {details}"))]
917+
#[snafu(display("Encountered invalid value: {details}"))]
903918
/// An error that indicates invalid input XML
904919
InvalidInput {
905920
/// Error details from the underlying XML parser
@@ -945,7 +960,7 @@ pub enum OerDecodeErrorKind {
945960
class: u8,
946961
},
947962
/// The tag number was incorrect when decoding a Choice type.
948-
#[snafu(display("Invalid tag number when decoding Choice. Value: {value}"))]
963+
#[snafu(display("Invalid tag number when decoding Choice: {value}"))]
949964
InvalidTagNumberOnChoice {
950965
/// Invalid tag bytes at the time of decoding.
951966
value: u32,

src/error/encode.rs

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,22 @@ pub enum CodecEncodeError {
2121
Coer(CoerEncodeErrorKind),
2222
Xer(XerEncodeErrorKind),
2323
}
24+
25+
impl core::fmt::Display for CodecEncodeError {
26+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
27+
match self {
28+
CodecEncodeError::Ber(kind) => write!(f, "BER encoding error: {kind}"),
29+
CodecEncodeError::Cer(kind) => write!(f, "CER encoding error: {kind}"),
30+
CodecEncodeError::Der(kind) => write!(f, "DER encoding error: {kind}"),
31+
CodecEncodeError::Uper(kind) => write!(f, "UPER encoding error: {kind}"),
32+
CodecEncodeError::Aper(kind) => write!(f, "APER encoding error: {kind}"),
33+
CodecEncodeError::Jer(kind) => write!(f, "JER encoding error: {kind}"),
34+
CodecEncodeError::Coer(kind) => write!(f, "COER encoding error: {kind}"),
35+
CodecEncodeError::Xer(kind) => write!(f, "XER encoding error: {kind}"),
36+
}
37+
}
38+
}
39+
2440
macro_rules! impl_from {
2541
($variant:ident, $error_kind:ty) => {
2642
impl From<$error_kind> for EncodeError {
@@ -117,10 +133,9 @@ impl core::error::Error for EncodeError {}
117133

118134
impl core::fmt::Display for EncodeError {
119135
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
120-
writeln!(f, "Error Kind: {}", self.kind)?;
121-
writeln!(f, "Codec: {}", self.kind)?;
136+
write!(f, "{} (Codec: {})", self.kind, self.codec)?;
122137
#[cfg(feature = "backtraces")]
123-
write!(f, "\nBacktrace:\n{}", self.backtrace)?;
138+
write!(f, "\n\nBacktrace:\n{}", self.backtrace)?;
124139

125140
Ok(())
126141
}
@@ -268,19 +283,19 @@ pub enum EncodeErrorKind {
268283
err: core::num::TryFromIntError,
269284
},
270285
/// Error when the length of the data is not in the constraint size range.
271-
#[snafu(display("invalid length, expected: {expected}; actual: {length}"))]
286+
#[snafu(display("Invalid length, expected: {expected}; actual: {length}"))]
272287
InvalidLength {
273288
/// Actual length of the data
274289
length: usize,
275290
/// Expected length of the data
276291
expected: Bounded<usize>,
277292
},
278293
/// Error when the length of the data is more than we can technically handle.
279-
#[snafu(display("invalid length, exceeds platform maximum size usize::MAX"))]
294+
#[snafu(display("Invalid length, exceeds platform maximum size usize::MAX"))]
280295
LengthExceedsPlatformSize,
281296
/// Encode error when the
282297
#[snafu(display(
283-
"The provided value does not fit to the reserved octets {expected}; actual: {value}"
298+
"The provided value does not fit in the reserved octets {expected}; actual: {value}"
284299
))]
285300
MoreBytesThanExpected {
286301
/// The count of the provided bytes
@@ -289,13 +304,13 @@ pub enum EncodeErrorKind {
289304
expected: usize,
290305
},
291306
/// Error when the custom error is thrown.
292-
#[snafu(display("custom error:\n{}", msg))]
307+
#[snafu(display("Custom error: {}", msg))]
293308
Custom {
294309
/// The custom error message
295310
msg: alloc::string::String,
296311
},
297312
/// Wraps codec-specific errors as inner [`CodecEncodeError`].
298-
#[snafu(display("Wrapped codec-specific encode error"))]
313+
#[snafu(display("{inner}"))]
299314
CodecSpecific {
300315
/// Inner codec-specific error
301316
inner: CodecEncodeError,
@@ -323,19 +338,19 @@ pub enum EncodeErrorKind {
323338
expected: Bounded<i128>,
324339
},
325340
/// Error when the type conversion failed between different integer types.
326-
#[snafu(display("Failed to cast integer to another integer type: {msg} "))]
341+
#[snafu(display("Failed to cast integer to another integer type: {msg}"))]
327342
IntegerTypeConversionFailed {
328343
/// More precise error message
329344
msg: alloc::string::String,
330345
},
331346
/// Error mainly used as part of SMI standard which converts type to BER encoding and handles bytes as `Opaque`.
332-
#[snafu(display("Conversion to Opaque type failed: {msg}"))]
347+
#[snafu(display("Conversion to opaque type failed: {msg}"))]
333348
OpaqueConversionFailed {
334349
/// More precise error message
335350
msg: alloc::string::String,
336351
},
337352
/// Error when the selected variant is not found in the choice.
338-
#[snafu(display("Selected Variant not found from Choice"))]
353+
#[snafu(display("Selected Variant not found in Choice"))]
339354
VariantNotInChoice,
340355

341356
/// Error when we try to encode a `REAL` type with an unspported codec.
@@ -392,7 +407,7 @@ pub enum JerEncodeErrorKind {
392407
upstream: alloc::string::String,
393408
},
394409
/// Error to be thrown when the JER encoder contains no encoded root value
395-
#[snafu(display("No encoded JSON root value found!"))]
410+
#[snafu(display("No encoded JSON root value found"))]
396411
NoRootValueFound,
397412
/// Internal JSON encoder error
398413
#[snafu(display("Error in JSON encoder: {}", msg))]
@@ -401,7 +416,7 @@ pub enum JerEncodeErrorKind {
401416
msg: alloc::string::String,
402417
},
403418
/// Error to be thrown when encoding large integers than the supported range
404-
#[snafu(display("Exceeds supported integer range -2^63..2^63 ({:?}).", value))]
419+
#[snafu(display("Exceeds supported integer range -2^63..2^63 ({:?})", value))]
405420
ExceedsSupportedIntSize {
406421
/// value failed to encode
407422
value: BigInt,
@@ -439,10 +454,10 @@ pub enum XerEncodeErrorKind {
439454
/// Stringified error of the underlying XML writer
440455
upstream: alloc::string::String,
441456
},
442-
#[snafu(display("Failed to encode integer."))]
457+
#[snafu(display("Failed to encode integer"))]
443458
/// An error indicating an integer value outside of the supported bounds
444459
UnsupportedIntegerValue,
445-
#[snafu(display("Missing identifier for ASN.1 type."))]
460+
#[snafu(display("Missing identifier for ASN.1 type"))]
446461
/// An error indicating that the XML writer is missing information about the tag name of the item to encode
447462
MissingIdentifier,
448463
}
@@ -453,13 +468,13 @@ pub enum XerEncodeErrorKind {
453468
#[non_exhaustive]
454469
pub enum CoerEncodeErrorKind {
455470
/// Error type for a scenario when the provided data is too long to be encoded with COER.
456-
#[snafu(display("Provided data is too long to be encoded with COER."))]
471+
#[snafu(display("Provided data is too long to be encoded with COER"))]
457472
TooLongValue {
458473
/// The length of the provided data
459474
length: u128,
460475
},
461476
/// Error type for a secenario when the provided integer value exceeds the limits of the constrained word sizes.
462-
#[snafu(display("Provided integer exceeds limits of the constrained word sizes."))]
477+
#[snafu(display("Provided integer exceeds limits of the constrained word sizes"))]
463478
InvalidConstrainedIntegerOctetSize,
464479
}
465480

0 commit comments

Comments
 (0)