use non_non_full::NonEmptyVec;
use crate::{
entry::{Entry, EntryId},
sinks::message::{Media, Message},
};
#[expect(
missing_docs,
reason = "a mirror of Entry struct, refer to Entry for docs"
)]
#[derive(Default, Debug)]
pub struct TransformedEntry {
pub id: TransformResult<EntryId>,
pub reply_to: TransformResult<EntryId>,
pub raw_contents: TransformResult<String>,
pub msg: TransformedMessage,
}
#[expect(
missing_docs,
reason = "a mirror of Message struct, refer to Message for docs"
)]
#[derive(Default, Debug)]
pub struct TransformedMessage {
pub title: TransformResult<String>,
pub body: TransformResult<String>,
pub link: TransformResult<String>,
pub media: TransformResult<NonEmptyVec<Media>>,
}
#[derive(Default, Debug)]
pub enum TransformResult<T> {
#[default]
Previous,
Empty,
New(T),
}
pub trait OptionUnwrapTransformResultExt<T> {
fn unwrap_or_prev(self) -> TransformResult<T>;
fn unwrap_or_empty(self) -> TransformResult<T>;
}
impl TransformedEntry {
#[must_use]
pub fn into_entry(self, old_entry: &Entry) -> Entry {
Entry {
id: self.id.get(|| old_entry.id.clone()),
reply_to: self.reply_to.get(|| old_entry.reply_to.clone()),
raw_contents: self.raw_contents.get(|| old_entry.raw_contents.clone()),
msg: self.msg.into_message(&old_entry.msg),
}
}
}
impl TransformedMessage {
#[must_use]
pub fn into_message(self, old_msg: &Message) -> Message {
Message {
title: self.title.get(|| old_msg.title.clone()),
body: self.body.get(|| old_msg.body.clone()),
link: self.link.get(|| old_msg.link.clone()),
media: self.media.get(|| old_msg.media.clone()),
}
}
}
impl<T> TransformResult<T> {
pub fn get<F>(self, prev_value: F) -> Option<T>
where
F: FnOnce() -> Option<T>,
{
match self {
Self::Previous => prev_value(),
Self::Empty => None,
Self::New(val) => Some(val),
}
}
pub fn and_then<F, U>(self, f: F) -> TransformResult<U>
where
F: FnOnce(T) -> TransformResult<U>,
{
match self {
TransformResult::Previous => TransformResult::Previous,
TransformResult::Empty => TransformResult::Empty,
TransformResult::New(t) => f(t),
}
}
pub fn map<F, U>(self, f: F) -> TransformResult<U>
where
F: FnOnce(T) -> U,
{
match self {
TransformResult::Previous => TransformResult::Previous,
TransformResult::Empty => TransformResult::Empty,
TransformResult::New(t) => TransformResult::New(f(t)),
}
}
pub fn try_map<F, U, E>(self, f: F) -> Result<TransformResult<U>, E>
where
F: FnOnce(T) -> Result<U, E>,
{
Ok(match self {
TransformResult::Previous => TransformResult::Previous,
TransformResult::Empty => TransformResult::Empty,
TransformResult::New(t) => TransformResult::New(f(t)?),
})
}
}
impl<T> OptionUnwrapTransformResultExt<T> for Option<T> {
fn unwrap_or_prev(self) -> TransformResult<T> {
self.map_or_else(|| TransformResult::Previous, TransformResult::New)
}
fn unwrap_or_empty(self) -> TransformResult<T> {
self.map_or_else(|| TransformResult::Empty, TransformResult::New)
}
}