use std::convert::Infallible;
use std::future::{Future, ready};
use futures::{Stream, StreamExt};
use ruststream::memory::{
ConnectedMemoryBroker, LogMode, MemoryError, MemoryMessage, MemorySubscriber,
};
use ruststream::runtime::{Input, IntoSource, SoloCarried};
use ruststream::{
AckError, AddressedCopies, Carries, HeaderMap, IncomingMessage, RedeliveryAddress,
RedeliveryAddressed, Subscribe, Subscriber, SubscriptionSource,
};
#[derive(Debug, Clone, PartialEq, Eq, schemars::JsonSchema)]
pub(crate) struct Row {
pub(crate) id: u64,
pub(crate) name: String,
}
impl Row {
#[must_use]
pub(crate) fn new(id: u64, name: &str) -> Self {
Self {
id,
name: name.to_owned(),
}
}
fn read(payload: &[u8]) -> Option<Self> {
let (id, name) = std::str::from_utf8(payload).ok()?.split_once(':')?;
Some(Self::new(id.parse().ok()?, name))
}
}
impl Input for Row {
type Axis = SoloCarried<Self>;
}
#[derive(Debug, Clone)]
pub(crate) struct Rows {
name: String,
}
impl Rows {
#[must_use]
pub(crate) fn new(name: impl Into<String>) -> Self {
Self { name: name.into() }
}
}
impl IntoSource for Rows {
type Source = Self;
fn into_source(self) -> Self {
self
}
}
impl<Log: LogMode> SubscriptionSource<ConnectedMemoryBroker<Log>> for Rows {
type Subscriber = RowSubscriber<Log>;
type Copies = AddressedCopies;
fn name(&self) -> &str {
&self.name
}
async fn subscribe(
self,
connected: &ConnectedMemoryBroker<Log>,
) -> Result<RowSubscriber<Log>, MemoryError> {
Ok(RowSubscriber(
Subscribe::subscribe(connected, &self.name).await?,
))
}
}
impl<Log: LogMode> RedeliveryAddressed<ConnectedMemoryBroker<Log>> for Rows {
fn redelivery_address(
&self,
_connected: &ConnectedMemoryBroker<Log>,
) -> impl Future<Output = Result<RedeliveryAddress, MemoryError>> + Send {
ready(Ok(RedeliveryAddress::new(self.name.clone())))
}
}
pub(crate) struct RowSubscriber<Log>(MemorySubscriber<Log>);
impl<Log: LogMode> Subscriber for RowSubscriber<Log> {
type Message = RowDelivery<Log>;
type Error = Infallible;
fn stream(&mut self) -> impl Stream<Item = Result<RowDelivery<Log>, Infallible>> + Send + '_ {
self.0.stream().map(|delivery| {
delivery.map(|inner| RowDelivery {
row: Row::read(inner.payload()),
inner,
})
})
}
}
pub(crate) struct RowDelivery<Log> {
inner: MemoryMessage<Log>,
row: Option<Row>,
}
impl<Log> Carries<Row> for RowDelivery<Log> {
fn carried(&self) -> Option<&Row> {
self.row.as_ref()
}
}
impl<Log: LogMode> IncomingMessage for RowDelivery<Log> {
fn payload(&self) -> &[u8] {
self.inner.payload()
}
fn headers(&self) -> &HeaderMap {
self.inner.headers()
}
fn redelivery_count(&self) -> Option<u64> {
self.inner.redelivery_count()
}
fn ack(self) -> impl Future<Output = Result<(), AckError>> + Send {
self.inner.ack()
}
fn nack(self, requeue: bool) -> impl Future<Output = Result<(), AckError>> + Send {
self.inner.nack(requeue)
}
}