sqlite_diff_rs/wire/source.rs
1//! [`WireSource`]: sealed marker trait for CDC wire formats.
2
3use core::hash::Hash;
4
5use super::sealed::Sealed;
6
7/// Per-format marker naming a CDC wire source.
8///
9/// Implementors are unit structs owned by each format module
10/// (`PgWalstream`, `Wal2Json`, `Maxwell`). The associated types describe
11/// the format's per-column payload and its native type-identity key.
12///
13/// # Type keys
14///
15/// - `PgWalstream::TypeKey = pg_walstream::Oid` (u32 alias).
16/// - `Wal2Json::TypeKey = alloc::sync::Arc<str>` (Postgres type name).
17/// - `Maxwell::TypeKey = alloc::sync::Arc<str>` (MySQL type name; empty
18/// string when the Maxwell daemon runs without `--include_types`).
19pub trait WireSource: Sealed {
20 /// Per-column payload the format hands to a decoder.
21 ///
22 /// Every payload struct carries a `column_name: &'a str` so decoder
23 /// errors are self-describing without an outer wrapping layer.
24 type Payload<'a>;
25
26 /// Type identity as seen on this source's wire.
27 type TypeKey: Hash + Eq + Clone;
28
29 /// Extract the type key from a payload for dispatch.
30 fn type_key(payload: &Self::Payload<'_>) -> Self::TypeKey;
31
32 /// Extract the column name from a payload for diagnostic messages.
33 fn column_name<'a>(payload: &'a Self::Payload<'_>) -> &'a str;
34}
35
36/// Schema-side source-native type key for one column of one table.
37pub trait WireColumnTypes<Src: WireSource> {
38 /// Type key for the column at `column_index`.
39 fn column_type_key(&self, column_index: usize) -> Src::TypeKey;
40}
41
42/// Table-name lookup for the [`DiffSetBuilder::digest`](crate::DiffSetBuilder::digest) entry point.
43pub trait WireSchema<Src: WireSource> {
44 /// Concrete schema type for one table.
45 type Table: crate::schema::NamedColumns + WireColumnTypes<Src>;
46
47 /// Resolve a table name to its schema entry.
48 fn get(&self, table_name: &str) -> Option<&Self::Table>;
49}
50
51/// One CDC wire event digested via [`DiffSetBuilder::digest`](crate::DiffSetBuilder::digest).
52///
53/// Implemented in-crate for `pg_walstream::EventType`, `wal2json::MessageV2`,
54/// `wal2json::ChangeV1`, and `maxwell::Message` (each times both formats).
55pub trait Digestable<F, T, S, B>
56where
57 F: crate::builders::Format<S, B>,
58 T: crate::schema::NamedColumns + WireColumnTypes<Self::Src>,
59{
60 /// Wire source this event came from.
61 type Src: WireSource;
62
63 /// Failure mode raised on schema lookup or decode failure.
64 type Error;
65
66 /// Fold this event into `builder`, resolving affected tables via `schema`
67 /// and decoding column payloads via `adapter`.
68 ///
69 /// # Errors
70 ///
71 /// Any per-source `ConversionError`.
72 fn digest_into<Sch, A>(
73 &self,
74 builder: crate::builders::DiffSetBuilder<F, T, S, B>,
75 schema: &Sch,
76 adapter: &A,
77 ) -> Result<crate::builders::DiffSetBuilder<F, T, S, B>, Self::Error>
78 where
79 Sch: WireSchema<Self::Src, Table = T>,
80 A: super::WireAdapter<Self::Src, S, B>;
81}