use std::borrow::Cow;
use serde::{Deserialize, Serialize};
#[cfg(feature = "validation")]
use validator::Validate;
use crate::compose::text;
#[cfg(feature = "validation")]
use crate::val_helpr::ValidationResult;
#[derive(Clone, Debug, Default, Deserialize, Hash, PartialEq, Serialize)]
#[cfg_attr(feature = "validation", derive(Validate))]
pub struct Image<'a> {
#[cfg_attr(feature = "validation", validate(length(max = 3000)))]
image_url: Cow<'a, str>,
#[cfg_attr(feature = "validation", validate(length(max = 2000)))]
alt_text: Cow<'a, str>,
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation", validate(custom = "validate::title"))]
title: Option<text::Text>,
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation",
validate(custom = "super::validate_block_id"))]
block_id: Option<Cow<'a, str>>,
}
impl<'a> Image<'a> {
pub fn builder() -> build::ImageBuilderInit<'a> {
build::ImageBuilderInit::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 url;
#[derive(Clone, Copy, Debug)]
pub struct alt;
}
pub type ImageBuilderInit<'a> =
ImageBuilder<'a,
RequiredMethodNotCalled<method::url>,
RequiredMethodNotCalled<method::alt>>;
#[derive(Debug)]
pub struct ImageBuilder<'a, Url, Alt> {
image_url: Option<Cow<'a, str>>,
alt_text: Option<Cow<'a, str>>,
title: Option<text::Text>,
block_id: Option<Cow<'a, str>>,
state: PhantomData<(Url, Alt)>,
}
impl<'a, Url, Alt> ImageBuilder<'a, Url, Alt> {
pub fn new() -> Self {
Self { image_url: None,
alt_text: None,
title: None,
block_id: None,
state: PhantomData::<_> }
}
pub fn title<T>(mut self, text: T) -> Self
where T: Into<text::Plain>
{
self.title = Some(text.into().into());
self
}
pub fn src<S>(self, image_url: S) -> ImageBuilder<'a, Set<method::url>, Alt>
where S: Into<Cow<'a, str>>
{
self.image_url(image_url)
}
pub fn image_url<S>(self,
image_url: S)
-> ImageBuilder<'a, Set<method::url>, Alt>
where S: Into<Cow<'a, str>>
{
ImageBuilder { image_url: Some(image_url.into()),
alt_text: self.alt_text,
title: self.title,
block_id: self.block_id,
state: PhantomData::<_> }
}
pub fn alt_text<S>(self,
alt_text: S)
-> ImageBuilder<'a, Url, Set<method::alt>>
where S: Into<Cow<'a, str>>
{
ImageBuilder { alt_text: Some(alt_text.into()),
image_url: self.image_url,
title: self.title,
block_id: self.block_id,
state: PhantomData::<_> }
}
pub fn alt<S>(self, alt_text: S) -> ImageBuilder<'a, Url, Set<method::alt>>
where S: Into<Cow<'a, str>>
{
self.alt_text(alt_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> ImageBuilder<'a, Set<method::url>, Set<method::alt>> {
pub fn build(self) -> Image<'a> {
Image { image_url: self.image_url.unwrap(),
alt_text: self.alt_text.unwrap(),
title: self.title,
block_id: self.block_id }
}
}
}
#[cfg(feature = "validation")]
mod validate {
use crate::{compose::text,
val_helpr::{below_len, ValidatorResult}};
pub(super) fn title(text: &text::Text) -> ValidatorResult {
below_len("Image Title", 2000, text.as_ref())
}
}