Skip to main content

danube_client/
schema_types.rs

1use std::fmt;
2use std::str::FromStr;
3
4/// Schema compatibility modes for schema evolution
5///
6/// Defines how strictly new schema versions must be compatible with existing versions.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum CompatibilityMode {
9    /// No compatibility checking - any schema change is allowed
10    None,
11    /// New schema can read data written with old schema (most common)
12    /// - Allows: adding optional fields, removing fields from reader
13    /// - Use case: Consumers upgrade before producers
14    Backward,
15    /// Old schema can read data written with new schema
16    /// - Allows: adding required fields, removing optional fields
17    /// - Use case: Producers upgrade before consumers
18    Forward,
19    /// Both backward and forward compatible (strictest)
20    /// - Use case: Critical schemas that need both directions
21    Full,
22}
23
24impl CompatibilityMode {
25    /// Convert to string representation for API calls
26    pub fn as_str(&self) -> &'static str {
27        match self {
28            CompatibilityMode::None => "none",
29            CompatibilityMode::Backward => "backward",
30            CompatibilityMode::Forward => "forward",
31            CompatibilityMode::Full => "full",
32        }
33    }
34}
35
36impl Default for CompatibilityMode {
37    fn default() -> Self {
38        CompatibilityMode::Backward
39    }
40}
41
42impl fmt::Display for CompatibilityMode {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        f.write_str(self.as_str())
45    }
46}
47
48impl FromStr for CompatibilityMode {
49    type Err = String;
50
51    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
52        match s.to_lowercase().as_str() {
53            "none" => Ok(CompatibilityMode::None),
54            "backward" => Ok(CompatibilityMode::Backward),
55            "forward" => Ok(CompatibilityMode::Forward),
56            "full" => Ok(CompatibilityMode::Full),
57            other => Err(format!("unknown compatibility mode: '{}'", other)),
58        }
59    }
60}
61
62/// Schema types supported by the registry
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum SchemaType {
65    /// Raw bytes - no schema validation
66    /// Use for binary data or custom serialization
67    Bytes,
68
69    /// UTF-8 string - validates string encoding
70    /// Use for plain text messages
71    String,
72
73    /// Numeric types (int, long, float, double)
74    /// Validates numeric data
75    Number,
76
77    /// Apache Avro schema format
78    /// Structured binary format with schema evolution support
79    Avro,
80
81    /// JSON Schema format
82    /// JSON-based schema validation
83    JsonSchema,
84
85    /// Protocol Buffers schema format
86    /// Google's language-neutral serialization format
87    Protobuf,
88}
89
90impl SchemaType {
91    /// Convert to string representation for API calls
92    pub fn as_str(&self) -> &'static str {
93        match self {
94            SchemaType::Bytes => "bytes",
95            SchemaType::String => "string",
96            SchemaType::Number => "number",
97            SchemaType::Avro => "avro",
98            SchemaType::JsonSchema => "json_schema",
99            SchemaType::Protobuf => "protobuf",
100        }
101    }
102}
103
104impl fmt::Display for SchemaType {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        f.write_str(self.as_str())
107    }
108}
109
110impl FromStr for SchemaType {
111    type Err = String;
112
113    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
114        match s.to_lowercase().as_str() {
115            "bytes" => Ok(SchemaType::Bytes),
116            "string" => Ok(SchemaType::String),
117            "number" => Ok(SchemaType::Number),
118            "avro" => Ok(SchemaType::Avro),
119            "json_schema" | "jsonschema" => Ok(SchemaType::JsonSchema),
120            "protobuf" | "proto" => Ok(SchemaType::Protobuf),
121            other => Err(format!("unknown schema type: '{}'", other)),
122        }
123    }
124}
125
126use danube_core::proto::danube_schema::GetSchemaResponse as ProtoGetSchemaResponse;
127
128/// Information about a schema retrieved from the registry
129///
130/// This is a user-friendly wrapper around the proto GetSchemaResponse.
131/// Consumers can use this to fetch and validate schemas.
132#[derive(Debug, Clone)]
133pub struct SchemaInfo {
134    /// Schema ID (identifies the subject)
135    pub schema_id: u64,
136    /// Subject name
137    pub subject: String,
138    /// Schema version number
139    pub version: u32,
140    /// Schema type (avro, json, protobuf, etc.)
141    pub schema_type: String,
142    /// Schema definition as bytes (e.g., Avro schema JSON, Protobuf descriptor)
143    pub schema_definition: Vec<u8>,
144    /// Fingerprint for deduplication
145    pub fingerprint: String,
146}
147
148impl SchemaInfo {
149    /// Get schema definition as a UTF-8 string (for JSON-based schemas)
150    ///
151    /// Returns None if the schema definition is not valid UTF-8
152    pub fn schema_definition_as_string(&self) -> Option<String> {
153        std::str::from_utf8(&self.schema_definition)
154            .ok()
155            .map(|s| s.to_string())
156    }
157}
158
159impl From<ProtoGetSchemaResponse> for SchemaInfo {
160    fn from(proto: ProtoGetSchemaResponse) -> Self {
161        SchemaInfo {
162            schema_id: proto.schema_id,
163            subject: proto.subject,
164            version: proto.version,
165            schema_type: proto.schema_type,
166            schema_definition: proto.schema_definition,
167            fingerprint: proto.fingerprint,
168        }
169    }
170}