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
//! [`DecodeError`]: shared failure mode for every decoder in the
//! [`wire`](super) module.
//!
//! Per-format `ConversionError` types (in `pg_walstream::ConversionError`,
//! `wal2json::ConversionError`, `maxwell::ConversionError`) wrap this
//! via a `Decode(DecodeError)` variant so users can pattern-match on
//! the outer error and route to a common inner arm.
use alloc::string::String;
/// Failure modes shared across every `wire::Decoder` implementation.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[non_exhaustive]
pub enum DecodeError {
/// The [`TypeMap`](super::TypeMap) contains no decoder for the
/// wire type carried by this column.
#[error("no decoder registered for column {column:?}")]
NoDecoderForType {
/// Column whose type was unrecognized.
column: String,
},
/// The decoder skeleton exists but its implementation is not yet populated.
#[error("decoder {decoder} is not yet implemented")]
NotYetImplemented {
/// The unpopulated decoder's type name.
decoder: &'static str,
},
/// Column payload was expected to be valid UTF-8 and was not.
#[error("column {column:?} carried non-UTF-8 bytes")]
InvalidUtf8 {
/// Offending column name.
column: String,
},
/// Column payload did not parse as a UUID (36-char hyphenated or
/// braced form).
#[error("column {column:?} carried a malformed UUID (source length {source_len})")]
InvalidUuid {
/// Offending column name.
column: String,
/// Length of the string the decoder tried to parse.
source_len: usize,
},
/// Column payload was expected to be a `\xHEX` PG BYTEA escape and
/// contained an invalid character at the reported byte offset.
#[error("column {column:?} carried a malformed \\x hex escape at offset {at}")]
InvalidHexEscape {
/// Offending column name.
column: String,
/// Zero-based byte offset of the first invalid character.
at: usize,
},
/// Integer payload exceeded `i64` range and its shape (MySQL
/// `bigint unsigned`, PG `numeric` cast, ...) did not permit a
/// silent fallback to `Text`.
#[error("column {column:?} integer digits overflowed i64: {digits}")]
IntegerOverflow {
/// Offending column name.
column: String,
/// The raw digit string as received on the wire.
digits: String,
},
/// Column carried a decimal that was delivered as a JSON number,
/// which cannot preserve precision above ~15 significant digits.
#[error("column {column:?} carried a decimal as a lossy JSON number")]
DecimalPrecisionLoss {
/// Offending column name.
column: String,
},
/// JSON payload failed to serialize into the target text form.
/// Only observable when a JSON decoder receives a value that
/// `serde_json` cannot round-trip through `to_string`.
#[error("column {column:?} JSON value did not serialize: {error}")]
JsonNotSerializable {
/// Offending column name.
column: String,
/// `serde_json` error message.
error: String,
},
/// Payload kind was not what this decoder expected. Emitted when a
/// decoder registered for one shape (e.g. JSON string) receives a
/// different one (e.g. JSON object).
#[error("column {column:?} payload kind mismatch: expected {expected}, got {actual}")]
WrongPayloadKind {
/// Offending column name.
column: String,
/// Expected payload kind name.
expected: &'static str,
/// Actual payload kind name.
actual: &'static str,
},
/// Free-form failure emitted by user-supplied decoders.
#[error("column {column:?}: {message}")]
Custom {
/// Offending column name.
column: String,
/// Failure message from the decoder.
message: String,
},
}