use bytes::Bytes;
use rdkafka::message::{Header, OwnedHeaders};
use ruststream::{HeaderMap, Str};
use crate::eos::EOS_SOURCE_HEADER;
use crate::message::PARTITION_KEY_HEADER;
use crate::record::HeldRecord;
pub(crate) fn headers_from_message(record: &HeldRecord) -> HeaderMap {
let mut headers = HeaderMap::new();
if let Some(native) = record.headers() {
for header in native.iter() {
if header.key.eq_ignore_ascii_case(PARTITION_KEY_HEADER) {
continue;
}
let value = header.value.map_or_else(Bytes::new, Bytes::copy_from_slice);
headers.insert(header.key, value);
}
}
if let Some(key) = record.key() {
headers.insert(
Str::from_static(PARTITION_KEY_HEADER),
Bytes::copy_from_slice(key),
);
}
headers
}
#[inline]
pub(crate) fn rides_the_wire(name: &str) -> bool {
!name.eq_ignore_ascii_case(PARTITION_KEY_HEADER)
&& !name.eq_ignore_ascii_case(EOS_SOURCE_HEADER)
}
#[derive(Debug)]
pub(crate) struct PublishParts {
pub(crate) headers: Option<OwnedHeaders>,
pub(crate) key: Option<Bytes>,
}
pub(crate) fn headers_for_publish(headers: &HeaderMap) -> PublishParts {
let key = headers.get_shared(PARTITION_KEY_HEADER);
let mut native: Option<OwnedHeaders> = None;
for (name, value) in headers.iter() {
if !rides_the_wire(name) {
continue;
}
let list = native
.take()
.unwrap_or_else(|| OwnedHeaders::new_with_capacity(headers.len()));
native = Some(list.insert(Header {
key: name,
value: Some(value),
}));
}
PublishParts {
headers: native,
key,
}
}
#[cfg(test)]
mod tests {
use rdkafka::message::Headers as _;
use super::*;
#[test]
fn publish_split_maps_key_and_skips_its_header() {
let mut headers = HeaderMap::new();
headers.insert("content-type", "application/json");
headers.insert(PARTITION_KEY_HEADER, "order-1");
let parts = headers_for_publish(&headers);
assert_eq!(parts.key.as_deref(), Some(b"order-1".as_slice()));
let native = parts.headers.expect("one wire header expected");
assert_eq!(native.count(), 1);
assert_eq!(native.get(0).key, "content-type");
}
#[test]
fn publish_split_without_headers_is_empty() {
let parts = headers_for_publish(&HeaderMap::new());
assert!(parts.headers.is_none());
assert!(parts.key.is_none());
}
}