use std::borrow::Cow;
use serde::{Deserialize, Serialize};
#[cfg(feature = "validation")]
use validator::Validate;
#[cfg(feature = "validation")]
use crate::val_helpr::ValidationResult;
use crate::{compose::text, elems::BlockElement};
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
#[cfg_attr(feature = "validation", derive(Validate))]
pub struct Section<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation", validate(custom = "validate::fields"))]
fields: Option<Cow<'a, [text::Text]>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation", validate(custom = "validate::text"))]
text: Option<text::Text>,
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation", validate(custom = "validate::block_id"))]
block_id: Option<Cow<'a, str>>,
#[serde(skip_serializing_if = "Option::is_none")]
accessory: Option<BlockElement<'a>>,
}
impl<'a> Section<'a> {
pub fn builder() -> build::SectionBuilderInit<'a> {
build::SectionBuilderInit::new()
}
#[cfg(feature = "validation")]
#[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
pub fn validate(&self) -> ValidationResult {
Validate::validate(self)
}
}
pub mod build {
use std::marker::PhantomData;
use super::*;
use crate::build::*;
#[allow(non_camel_case_types)]
pub mod method {
#[derive(Clone, Copy, Debug)]
pub struct text;
}
pub type SectionBuilderInit<'a> =
SectionBuilder<'a, RequiredMethodNotCalled<method::text>>;
#[derive(Debug)]
pub struct SectionBuilder<'a, Text> {
accessory: Option<BlockElement<'a>>,
text: Option<text::Text>,
fields: Option<Vec<text::Text>>,
block_id: Option<Cow<'a, str>>,
state: PhantomData<Text>,
}
impl<'a, E> SectionBuilder<'a, E> {
pub fn new() -> Self {
Self { accessory: None,
text: None,
fields: None,
block_id: None,
state: PhantomData::<_> }
}
pub fn accessory<B>(mut self, acc: B) -> Self
where B: Into<BlockElement<'a>>
{
self.accessory = Some(acc.into());
self
}
pub fn text<T>(self, text: T) -> SectionBuilder<'a, Set<method::text>>
where T: Into<text::Text>
{
SectionBuilder { accessory: self.accessory,
text: Some(text.into()),
fields: self.fields,
block_id: self.block_id,
state: PhantomData::<_> }
}
pub fn fields<I>(self, fields: I) -> SectionBuilder<'a, Set<method::text>>
where I: IntoIterator<Item = text::Text>
{
SectionBuilder { accessory: self.accessory,
text: self.text,
fields: Some(fields.into_iter().collect()),
block_id: self.block_id,
state: PhantomData::<_> }
}
pub fn field<T>(mut self, text: T) -> SectionBuilder<'a, Set<method::text>>
where T: Into<text::Text>
{
let mut fields = self.fields.take().unwrap_or_default();
fields.push(text.into());
self.fields(fields)
}
#[cfg(feature = "blox")]
#[cfg_attr(docsrs, doc(cfg(feature = "blox")))]
pub fn child<T>(self, text: T) -> SectionBuilder<'a, Set<method::text>>
where T: Into<text::Text>
{
self.field(text)
}
pub fn block_id<S>(mut self, block_id: S) -> Self
where S: Into<Cow<'a, str>>
{
self.block_id = Some(block_id.into());
self
}
}
impl<'a> SectionBuilder<'a, Set<method::text>> {
pub fn build(self) -> Section<'a> {
Section { text: self.text,
fields: self.fields.map(|fs| fs.into()),
accessory: self.accessory,
block_id: self.block_id }
}
}
}
#[cfg(feature = "validation")]
mod validate {
use super::*;
use crate::{compose::text,
val_helpr::{below_len, ValidatorResult}};
pub(super) fn text(text: &text::Text) -> ValidatorResult {
below_len("Section.text", 3000, text.as_ref())
}
pub(super) fn block_id(text: &Cow<str>) -> ValidatorResult {
below_len("Section.block_id", 255, text.as_ref())
}
pub(super) fn fields(texts: &Cow<[text::Text]>) -> ValidatorResult {
below_len("Section.fields", 10, texts.as_ref()).and(
texts.iter()
.map(|text| {
below_len(
"Section.fields",
2000,
text.as_ref())
})
.collect(),
)
}
}