mod frame_outbox;
use bytes::Bytes;
use serde::{Deserialize, Serialize};
use tower::BoxError;
pub use frame_outbox::FrameOutbox;
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct MessageFrame {
pub uri: String,
pub data: Bytes,
pub meta: Bytes,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub enum Frame {
#[default]
Unit,
Error(Bytes),
Anonymous(Bytes),
Message(MessageFrame),
}
impl Frame {
pub fn new(bytes: impl Into<Bytes>) -> Self {
let bytes = bytes.into();
if bytes.is_empty() {
Frame::Unit
} else {
Frame::Anonymous(bytes)
}
}
pub fn message(uri: impl AsRef<str>, data: impl Into<Frame>, meta: impl Into<Frame>) -> Self {
Frame::Message(MessageFrame {
uri: uri.as_ref().into(),
data: data.into().into_bytes(),
meta: meta.into().into_bytes(),
})
}
pub fn len(&self) -> usize {
match self {
Frame::Unit => 0,
Frame::Error(data)
| Frame::Anonymous(data)
| Frame::Message(MessageFrame { data, .. }) => data.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn as_bytes(&self) -> &[u8] {
match self {
Frame::Unit => &[],
Frame::Error(data)
| Frame::Anonymous(data)
| Frame::Message(MessageFrame { data, .. }) => data.as_ref(),
}
}
pub fn into_bytes(self) -> Bytes {
match self {
Frame::Unit => Bytes::new(),
Frame::Error(data)
| Frame::Anonymous(data)
| Frame::Message(MessageFrame { data, .. }) => data,
}
}
}
impl AsRef<[u8]> for Frame {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl From<Vec<u8>> for Frame {
fn from(value: Vec<u8>) -> Self {
Bytes::from(value).into()
}
}
impl<T> From<Vec<T>> for Frame
where
T: Into<Frame>,
{
fn from(value: Vec<T>) -> Self {
let mut bytes: Vec<u8> = vec![];
for value in value {
bytes.extend_from_slice(value.into().as_ref());
}
Bytes::from(bytes).into()
}
}
impl From<()> for Frame {
fn from(_: ()) -> Self {
Frame::default()
}
}
impl From<Bytes> for Frame {
fn from(bytes: Bytes) -> Self {
Frame::new(bytes)
}
}
impl From<Frame> for Bytes {
fn from(frame: Frame) -> Bytes {
frame.into_bytes()
}
}
impl From<Frame> for String {
fn from(value: Frame) -> Self {
String::from_utf8_lossy(value.as_ref()).into_owned()
}
}
impl From<String> for Frame {
fn from(value: String) -> Self {
Frame::new(value)
}
}
impl<T> From<Option<T>> for Frame
where
T: Into<Frame>,
{
fn from(option: Option<T>) -> Self {
match option {
Some(value) => value.into(),
None => Frame::default(),
}
}
}
impl<T, E> From<Result<T, E>> for Frame
where
T: Into<Frame>,
E: Into<Frame>,
{
fn from(result: Result<T, E>) -> Self {
match result {
Ok(value) => value.into(),
Err(error) => error.into(),
}
}
}
impl From<BoxError> for Frame {
fn from(error: BoxError) -> Self {
error.to_string().into()
}
}