krabka_metadata/
kafka_record.rs1use bytes::Bytes;
14use krabka_protocol::records::Record;
15use serde_wincode::SerdeCompat;
16use wincode::{Deserialize as _, Serialize as _};
17
18use crate::records::MetadataRecord;
19
20#[derive(Debug, thiserror::Error)]
22pub enum KafkaRecordError {
23 #[error("metadata record has no value payload")]
24 MissingValue,
25 #[error("wincode decode failed: {0}")]
26 Decode(String),
27 #[error("wincode encode failed: {0}")]
28 Encode(String),
29}
30
31pub fn to_kafka_record(rec: &MetadataRecord) -> Result<Record, KafkaRecordError> {
37 let payload = <SerdeCompat<MetadataRecord>>::serialize(rec)
38 .map_err(|e| KafkaRecordError::Encode(e.to_string()))?;
39 Ok(Record {
40 value: Some(Bytes::from(payload)),
41 ..Default::default()
42 })
43}
44
45pub fn from_kafka_record(rec: &Record) -> Result<MetadataRecord, KafkaRecordError> {
52 let value = rec.value.as_ref().ok_or(KafkaRecordError::MissingValue)?;
53 <SerdeCompat<MetadataRecord>>::deserialize(value)
54 .map_err(|e| KafkaRecordError::Decode(e.to_string()))
55}
56
57#[cfg(test)]
58mod tests {
59
60 use uuid::Uuid;
61
62 use super::*;
63 use crate::records::{MetadataRecord, TopicRecord};
64
65 fn sample_topic() -> MetadataRecord {
66 MetadataRecord::V1Topic(TopicRecord {
67 name: "orders".into(),
68 topic_id: Uuid::from_u128(0x1234_5678_9abc_def0),
69 partitions: 6,
70 replication_factor: 3,
71 })
72 }
73
74 #[test]
75 fn round_trips_through_kafka_record() {
76 let rec = sample_topic();
77 let kafka = to_kafka_record(&rec).expect("encode");
78 let back = from_kafka_record(&kafka).expect("decode");
79 assert2::assert!(rec == back);
80 }
81
82 #[test]
83 fn key_is_none_and_value_is_present() {
84 let kafka = to_kafka_record(&sample_topic()).expect("encode");
85 assert2::assert!(kafka.key == None);
86 assert2::assert!(kafka.value.is_some());
87 }
88
89 #[test]
90 fn record_key_is_none_even_when_default_record_has_key() {
91 let kafka = to_kafka_record(&sample_topic()).expect("encode");
92 assert2::assert!(kafka.key == None);
93 }
94
95 #[test]
96 fn missing_value_is_an_error() {
97 let empty = Record::default();
98 assert2::assert!(matches!(
99 from_kafka_record(&empty),
100 Err(KafkaRecordError::MissingValue)
101 ));
102 }
103
104 #[test]
105 fn encoding_is_stable_across_calls() {
106 let rec = sample_topic();
109 let a = to_kafka_record(&rec).expect("encode");
110 let b = to_kafka_record(&rec).expect("encode");
111 assert2::assert!(a.value == b.value);
112 }
113}