Skip to main content

crabka_schema_serde/
subject.rs

1//! Subject naming. Confluent's default `TopicNameStrategy` maps a topic +
2//! key/value role to `<topic>-key` / `<topic>-value`.
3
4/// Whether a serde handles the record key or value.
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum Role {
7    Key,
8    Value,
9}
10
11/// The schema format, used to set the registry `schemaType` field.
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum SchemaKind {
14    Avro,
15    Protobuf,
16    Json,
17}
18
19impl SchemaKind {
20    /// Registry `schemaType` wire value (`None` ⇒ omitted ⇒ AVRO default).
21    #[must_use]
22    pub fn wire_name(self) -> Option<&'static str> {
23        match self {
24            Self::Avro => None,
25            Self::Protobuf => Some("PROTOBUF"),
26            Self::Json => Some("JSON"),
27        }
28    }
29}
30
31/// Maps `(topic, role)` to a registry subject. The seam exists so
32/// Record/TopicRecord strategies can be added later; only `TopicNameStrategy`
33/// ships now.
34pub trait SubjectStrategy: Send + Sync + 'static {
35    fn subject(&self, topic: &str, role: Role) -> String;
36}
37
38/// Confluent default: `<topic>-key` / `<topic>-value`.
39#[derive(Debug, Clone, Copy, Default)]
40pub struct TopicNameStrategy;
41
42impl SubjectStrategy for TopicNameStrategy {
43    fn subject(&self, topic: &str, role: Role) -> String {
44        match role {
45            Role::Key => format!("{topic}-key"),
46            Role::Value => format!("{topic}-value"),
47        }
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54    use assert2::check;
55
56    #[test]
57    fn topic_name_strategy() {
58        let s = TopicNameStrategy;
59        check!(s.subject("orders", Role::Value) == "orders-value");
60        check!(s.subject("orders", Role::Key) == "orders-key");
61    }
62
63    #[test]
64    fn schema_kind_wire_names() {
65        check!(SchemaKind::Avro.wire_name().is_none());
66        check!(SchemaKind::Protobuf.wire_name() == Some("PROTOBUF"));
67        check!(SchemaKind::Json.wire_name() == Some("JSON"));
68    }
69}