use serde::{Deserialize, Serialize};
use crate::convert;
pub mod mrkdwn;
pub mod plain;
#[doc(inline)]
pub use mrkdwn::Contents as Mrkdwn;
#[doc(inline)]
pub use plain::Contents as Plain;
pub trait ToSlackPlaintext: Sized + Into<Plain> {
fn plaintext(self) -> Plain {
self.into()
}
}
impl<T: Into<Plain>> ToSlackPlaintext for T {}
pub trait ToSlackMarkdown: Sized + Into<Mrkdwn> {
fn markdown(self) -> Mrkdwn {
self.into()
}
}
impl<T: Into<Mrkdwn>> ToSlackMarkdown for T {}
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Text {
Mrkdwn(mrkdwn::Contents),
#[serde(rename = "plain_text")]
Plain(plain::Contents),
}
impl Text {
pub fn builder() -> build::TextBuilderInit {
build::TextBuilderInit::new()
}
pub fn copy_from<T: Into<Self> + Clone>(contents: &T) -> Self {
contents.clone().into()
}
}
convert!(impl From<mrkdwn::Contents> for Text => |contents| Text::Mrkdwn(contents));
convert!(impl From<plain::Contents> for Text => |contents| Text::Plain(contents));
pub mod build {
use std::marker::PhantomData;
use super::*;
use crate::build::*;
#[allow(non_camel_case_types)]
pub mod method {
#[derive(Copy, Clone, Debug)]
pub struct text;
#[derive(Copy, Clone, Debug)]
pub struct plain_or_mrkdwn;
}
#[allow(non_camel_case_types)]
#[cfg(feature = "blox")]
#[cfg_attr(docsrs, doc(cfg(feature = "blox")))]
pub mod kind {
use super::*;
pub trait TextKind<T> {
fn set_kind<M>(self, builder: TextBuilder<Text, M>) -> TextBuilder<T, M>;
}
#[derive(Copy, Clone, Debug)]
pub struct mrkdwn;
#[derive(Copy, Clone, Debug)]
pub struct plain;
impl TextKind<Mrkdwn> for mrkdwn {
fn set_kind<M>(self,
builder: TextBuilder<Text, M>)
-> TextBuilder<Mrkdwn, M> {
builder.mrkdwn()
}
}
impl TextKind<Plain> for plain {
fn set_kind<M>(self,
builder: TextBuilder<Text, M>)
-> TextBuilder<Plain, M> {
builder.plain()
}
}
}
pub type TextBuilderInit =
TextBuilder<Text, RequiredMethodNotCalled<method::text>>;
#[derive(Debug)]
pub struct TextBuilder<T, TMarker> {
text: Option<Text>,
text_value: Option<String>,
state: PhantomData<(T, TMarker)>,
}
impl<T> TextBuilder<T, RequiredMethodNotCalled<method::text>> {
pub fn new() -> Self {
Self { text: None,
text_value: None,
state: PhantomData::<_> }
}
pub fn text(mut self,
t: impl AsRef<str>)
-> TextBuilder<T, Set<method::text>> {
let text = t.as_ref().to_string();
match self.text {
| Some(Text::Mrkdwn(ref mut t)) => {
t.text = text;
},
| Some(Text::Plain(ref mut t)) => {
t.text = text;
},
| None => self.text_value = Some(text),
};
TextBuilder { text: self.text,
text_value: self.text_value,
state: PhantomData::<_> }
}
#[cfg(feature = "blox")]
#[cfg_attr(docsrs, doc(cfg(feature = "blox")))]
pub fn child(self,
t: impl AsRef<str>)
-> TextBuilder<T, Set<method::text>> {
self.text(t)
}
}
impl<M> TextBuilder<Text, M> {
#[cfg(feature = "blox")]
#[cfg_attr(docsrs, doc(cfg(feature = "blox")))]
pub fn kind<T, K>(self, kind: K) -> TextBuilder<T, M>
where T: Into<Text>,
K: kind::TextKind<T>
{
kind.set_kind(self)
}
pub fn plain(self) -> TextBuilder<Plain, M> {
let text = Some(Plain::from(self.text_value.unwrap_or_default()).into());
TextBuilder { text,
text_value: None,
state: PhantomData::<_> }
}
pub fn mrkdwn(self) -> TextBuilder<Mrkdwn, M> {
let text = Some(Mrkdwn::from(self.text_value.unwrap_or_default()).into());
TextBuilder { text,
text_value: None,
state: PhantomData::<_> }
}
}
impl<M> TextBuilder<Mrkdwn, M> {
pub fn verbatim(mut self, verbatim: bool) -> Self {
if let Some(Text::Mrkdwn(ref mut m)) = self.text {
m.verbatim = Some(verbatim);
}
self
}
}
impl<M> TextBuilder<Plain, M> {
pub fn emoji(mut self, emoji: bool) -> Self {
if let Some(Text::Plain(ref mut p)) = self.text {
p.emoji = Some(emoji);
}
self
}
}
impl TextBuilder<Plain, Set<method::text>> {
pub fn build(self) -> Plain {
match self.text.unwrap() {
| Text::Plain(p) => p,
| _ => unreachable!("type marker says this should be plain."),
}
}
}
impl TextBuilder<Mrkdwn, Set<method::text>> {
pub fn build(self) -> Mrkdwn {
match self.text.unwrap() {
| Text::Mrkdwn(p) => p,
| _ => unreachable!("type marker says this should be markdown."),
}
}
}
}
impl AsRef<str> for Text {
fn as_ref(&self) -> &str {
match self {
| Self::Mrkdwn(cts) => cts.as_ref(),
| Self::Plain(cts) => cts.as_ref(),
}
}
}