pub mod caps;
pub mod extract;
pub mod replace;
pub mod set;
pub mod shorten;
pub mod trim;
pub use self::{
caps::Caps, extract::Extract, replace::Replace, set::Set, shorten::Shorten, trim::Trim,
};
#[cfg(feature = "action-html-decode")]
pub mod decode_html;
#[cfg(feature = "action-html-decode")]
pub use self::decode_html::DecodeHtml;
use std::{
convert::Infallible,
fmt::{self, Debug},
};
use super::{
Transform,
result::{OptionUnwrapTransformResultExt, TransformResult, TransformedEntry},
};
use crate::{
actions::transforms::error::TransformErrorKind,
entry::{Entry, EntryId},
maybe_send::{MaybeSend, MaybeSendSync},
};
pub trait TransformField: MaybeSendSync {
type Err: Into<TransformErrorKind>;
fn transform_field(
&mut self,
value: Option<&str>,
) -> impl Future<Output = Result<TransformResult<String>, Self::Err>> + MaybeSend;
}
#[derive(Clone, Copy, Debug)]
pub enum Field {
Title,
Body,
Link,
Id,
ReplyTo,
RawContents,
}
#[derive(Clone, Debug)]
pub struct TransformFieldAdapter<T>
where
T: TransformField,
{
pub field: Field,
pub transformator: T,
}
impl<T> Transform for TransformFieldAdapter<T>
where
T: TransformField,
{
type Err = TransformErrorKind;
async fn transform_entry(&mut self, entry: Entry) -> Result<Vec<TransformedEntry>, Self::Err> {
let mut new_entry = TransformedEntry::default();
match self.field {
Field::Title => {
new_entry.msg.title = self
.transformator
.transform_field(entry.msg.title.as_deref())
.await
.map_err(Into::into)?;
}
Field::Body => {
new_entry.msg.body = self
.transformator
.transform_field(entry.msg.body.as_deref())
.await
.map_err(Into::into)?;
}
Field::Link => {
new_entry.msg.link = self
.transformator
.transform_field(entry.msg.link.as_deref())
.await
.map_err(Into::into)?;
}
Field::Id => {
new_entry.id = self
.transformator
.transform_field(entry.id.as_deref())
.await
.map_err(Into::into)?
.and_then(|id| EntryId::new(id).unwrap_or_empty());
}
Field::ReplyTo => {
new_entry.reply_to = self
.transformator
.transform_field(entry.reply_to.as_deref())
.await
.map_err(Into::into)?
.and_then(|id| EntryId::new(id).unwrap_or_empty());
}
Field::RawContents => {
new_entry.raw_contents = self
.transformator
.transform_field(entry.msg.body.as_deref())
.await
.map_err(Into::into)?;
}
}
Ok(vec![new_entry])
}
}
impl TransformField for () {
type Err = Infallible;
async fn transform_field(
&mut self,
_value: Option<&str>,
) -> Result<TransformResult<String>, Self::Err> {
Ok(TransformResult::default())
}
}
impl TransformField for Infallible {
type Err = Infallible;
async fn transform_field(
&mut self,
_value: Option<&str>,
) -> Result<TransformResult<String>, Self::Err> {
match *self {}
}
}
#[cfg(feature = "nightly")]
impl TransformField for ! {
type Err = !;
async fn transform_field(
&mut self,
_value: Option<&str>,
) -> Result<TransformResult<String>, Self::Err> {
match *self {}
}
}
impl<T> TransformField for Option<T>
where
T: TransformField,
{
type Err = T::Err;
async fn transform_field(
&mut self,
value: Option<&str>,
) -> Result<TransformResult<String>, Self::Err> {
let Some(inner) = self else {
return Ok(TransformResult::default());
};
inner.transform_field(value).await
}
}
impl<T> TransformField for &mut T
where
T: TransformField,
{
type Err = T::Err;
async fn transform_field(
&mut self,
value: Option<&str>,
) -> Result<TransformResult<String>, Self::Err> {
(*self).transform_field(value).await
}
}
impl fmt::Display for Field {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match self {
Self::Title => "Message::title",
Self::Body => "Message::body",
Self::Link => "Message::link",
Self::Id => "Entry::id",
Self::ReplyTo => "Entry::reply_to",
Self::RawContents => "Entry::raw_contents",
};
f.write_str(name)
}
}