Skip to main content

sqlite_diff_rs/wire/
error.rs

1//! [`DecodeError`]: shared failure mode for every decoder in the
2//! [`wire`](super) module.
3//!
4//! Per-format `ConversionError` types (in `pg_walstream::ConversionError`,
5//! `wal2json::ConversionError`, `maxwell::ConversionError`) wrap this
6//! via a `Decode(DecodeError)` variant so users can pattern-match on
7//! the outer error and route to a common inner arm.
8
9use alloc::string::String;
10
11/// Failure modes shared across every `wire::Decoder` implementation.
12#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
13#[non_exhaustive]
14pub enum DecodeError {
15    /// The [`TypeMap`](super::TypeMap) contains no decoder for the
16    /// wire type carried by this column.
17    #[error("no decoder registered for column {column:?}")]
18    NoDecoderForType {
19        /// Column whose type was unrecognized.
20        column: String,
21    },
22
23    /// The decoder skeleton exists but its implementation is not yet populated.
24    #[error("decoder {decoder} is not yet implemented")]
25    NotYetImplemented {
26        /// The unpopulated decoder's type name.
27        decoder: &'static str,
28    },
29
30    /// Column payload was expected to be valid UTF-8 and was not.
31    #[error("column {column:?} carried non-UTF-8 bytes")]
32    InvalidUtf8 {
33        /// Offending column name.
34        column: String,
35    },
36
37    /// Column payload did not parse as a UUID (36-char hyphenated or
38    /// braced form).
39    #[error("column {column:?} carried a malformed UUID (source length {source_len})")]
40    InvalidUuid {
41        /// Offending column name.
42        column: String,
43        /// Length of the string the decoder tried to parse.
44        source_len: usize,
45    },
46
47    /// Column payload was expected to be a `\xHEX` PG BYTEA escape and
48    /// contained an invalid character at the reported byte offset.
49    #[error("column {column:?} carried a malformed \\x hex escape at offset {at}")]
50    InvalidHexEscape {
51        /// Offending column name.
52        column: String,
53        /// Zero-based byte offset of the first invalid character.
54        at: usize,
55    },
56
57    /// Integer payload exceeded `i64` range and its shape (MySQL
58    /// `bigint unsigned`, PG `numeric` cast, ...) did not permit a
59    /// silent fallback to `Text`.
60    #[error("column {column:?} integer digits overflowed i64: {digits}")]
61    IntegerOverflow {
62        /// Offending column name.
63        column: String,
64        /// The raw digit string as received on the wire.
65        digits: String,
66    },
67
68    /// Column carried a decimal that was delivered as a JSON number,
69    /// which cannot preserve precision above ~15 significant digits.
70    #[error("column {column:?} carried a decimal as a lossy JSON number")]
71    DecimalPrecisionLoss {
72        /// Offending column name.
73        column: String,
74    },
75
76    /// JSON payload failed to serialize into the target text form.
77    /// Only observable when a JSON decoder receives a value that
78    /// `serde_json` cannot round-trip through `to_string`.
79    #[error("column {column:?} JSON value did not serialize: {error}")]
80    JsonNotSerializable {
81        /// Offending column name.
82        column: String,
83        /// `serde_json` error message.
84        error: String,
85    },
86
87    /// Payload kind was not what this decoder expected. Emitted when a
88    /// decoder registered for one shape (e.g. JSON string) receives a
89    /// different one (e.g. JSON object).
90    #[error("column {column:?} payload kind mismatch: expected {expected}, got {actual}")]
91    WrongPayloadKind {
92        /// Offending column name.
93        column: String,
94        /// Expected payload kind name.
95        expected: &'static str,
96        /// Actual payload kind name.
97        actual: &'static str,
98    },
99
100    /// Free-form failure emitted by user-supplied decoders.
101    #[error("column {column:?}: {message}")]
102    Custom {
103        /// Offending column name.
104        column: String,
105        /// Failure message from the decoder.
106        message: String,
107    },
108}