use ruststream::asyncapi::{Binding, Bindings};
use serde::Serialize;
use crate::envelope::SharedEnvelope;
const REDIS_EXTENSION: &str = "x-ruststream-redis";
#[derive(Debug, Clone, Copy, Serialize)]
#[serde(rename_all = "lowercase")]
pub(crate) enum Form {
Stream,
List,
PubSub,
}
#[derive(Debug, Clone, Copy, Serialize)]
#[serde(rename_all = "lowercase")]
pub(crate) enum ReadMode {
Fresh,
Reclaim,
Claiming,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct StreamSubscription<'a> {
form: Form,
#[serde(skip_serializing_if = "Option::is_none")]
group: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
consumer: Option<&'a str>,
read_mode: ReadMode,
#[serde(skip_serializing_if = "Option::is_none")]
min_idle_ms: Option<u64>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ListSubscription<'a> {
form: Form,
reliable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
processing: Option<&'a str>,
envelope: Envelope,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct PubSubSubscription {
form: Form,
mode: &'static str,
pattern: bool,
envelope: Envelope,
}
#[derive(Debug, Serialize)]
#[serde(untagged)]
pub(crate) enum Target<'a> {
Key { key: &'a str },
Channel { channel: &'a str },
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct Publish<'a> {
form: Form,
#[serde(flatten)]
target: Target<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
mode: Option<&'static str>,
#[serde(skip_serializing_if = "Option::is_none")]
ttl_ms: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
envelope: Option<Envelope>,
}
#[derive(Debug, Clone, Copy, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct Envelope {
content_type: &'static str,
}
impl Envelope {
pub(crate) fn of(codec: Option<&SharedEnvelope>) -> Self {
Self {
content_type: codec.map_or("application/octet-stream", |codec| codec.content_type()),
}
}
}
impl<'a> StreamSubscription<'a> {
pub(crate) const fn new(
group: Option<&'a str>,
consumer: Option<&'a str>,
read_mode: ReadMode,
min_idle_ms: Option<u64>,
) -> Self {
Self {
form: Form::Stream,
group,
consumer,
read_mode,
min_idle_ms,
}
}
}
impl<'a> ListSubscription<'a> {
pub(crate) const fn new(
reliable: bool,
processing: Option<&'a str>,
envelope: Envelope,
) -> Self {
Self {
form: Form::List,
reliable,
processing,
envelope,
}
}
}
impl PubSubSubscription {
pub(crate) const fn new(mode: &'static str, pattern: bool, envelope: Envelope) -> Self {
Self {
form: Form::PubSub,
mode,
pattern,
envelope,
}
}
}
impl<'a> Publish<'a> {
pub(crate) const fn stream(key: &'a str) -> Self {
Self {
form: Form::Stream,
target: Target::Key { key },
mode: None,
ttl_ms: None,
envelope: None,
}
}
pub(crate) const fn list(key: &'a str, ttl_ms: Option<u64>, envelope: Envelope) -> Self {
Self {
form: Form::List,
target: Target::Key { key },
mode: None,
ttl_ms,
envelope: Some(envelope),
}
}
pub(crate) const fn pubsub(channel: &'a str, mode: &'static str, envelope: Envelope) -> Self {
Self {
form: Form::PubSub,
target: Target::Channel { channel },
mode: Some(mode),
ttl_ms: None,
envelope: Some(envelope),
}
}
}
pub(crate) fn channel<T: Serialize>(body: &T) -> Bindings {
Binding::extension(REDIS_EXTENSION, body)
.map_or_else(|_| Bindings::new(), |binding| Bindings::new().with(binding))
}