use serde::{Deserialize, Serialize};
#[cfg(feature = "validation")]
use validator::Validate;
use super::{opt::{AnyText, NoUrl},
text,
Opt};
#[cfg(feature = "validation")]
use crate::val_helpr::ValidationResult;
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
#[cfg_attr(feature = "validation", derive(Validate))]
pub struct OptGroup<'a, T = AnyText, U = NoUrl> {
#[cfg_attr(feature = "validation", validate(custom = "validate::label"))]
label: text::Text,
#[cfg_attr(feature = "validation", validate(length(max = 100)))]
options: Vec<Opt<'a, T, U>>,
}
impl<'a> OptGroup<'a> {
pub fn builder() -> build::OptGroupBuilderInit<'a> {
build::OptGroupBuilderInit::new()
}
}
impl<'a, T, U> OptGroup<'a, T, U> {
#[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)]
mod method {
#[derive(Copy, Clone, Debug)]
pub struct label;
#[derive(Copy, Clone, Debug)]
pub struct options;
}
#[derive(Debug)]
pub struct OptGroupBuilder<'a, T, U, Options, Label> {
label: Option<text::Text>,
options: Option<Vec<Opt<'a, T, U>>>,
state: PhantomData<(Options, Label)>,
}
pub type OptGroupBuilderInit<'a> =
OptGroupBuilder<'a,
AnyText,
NoUrl,
RequiredMethodNotCalled<method::options>,
RequiredMethodNotCalled<method::label>>;
impl<'a, T, U, O, L> OptGroupBuilder<'a, T, U, O, L> {
pub fn new() -> Self {
Self { label: None,
options: None,
state: PhantomData::<_> }
}
fn cast_state<O2, L2>(self) -> OptGroupBuilder<'a, T, U, O2, L2> {
OptGroupBuilder { label: self.label,
options: self.options,
state: PhantomData::<_> }
}
pub fn options<T2, U2, I>(
self,
options: I)
-> OptGroupBuilder<'a, T2, U2, Set<method::options>, L>
where I: IntoIterator<Item = Opt<'a, T2, U2>>
{
OptGroupBuilder { label: self.label,
options: Some(options.into_iter().collect()),
state: PhantomData::<_> }
}
pub fn label<S>(mut self,
label: S)
-> OptGroupBuilder<'a, T, U, O, Set<method::label>>
where S: Into<text::Plain>
{
self.label = Some(label.into().into());
self.cast_state()
}
}
impl<'a, T, U, L>
OptGroupBuilder<'a, T, U, RequiredMethodNotCalled<method::options>, L>
{
pub fn option<T2, U2>(
self,
option: Opt<'a, T2, U2>)
-> OptGroupBuilder<'a, T2, U2, Set<method::options>, L> {
OptGroupBuilder { label: self.label,
options: Some(vec![option.into()]),
state: PhantomData::<_> }
}
#[cfg(feature = "blox")]
#[cfg_attr(docsrs, doc(cfg(feature = "blox")))]
pub fn child<T2, U2>(
self,
option: Opt<'a, T2, U2>)
-> OptGroupBuilder<'a, T2, U2, Set<method::options>, L> {
self.option::<T2, U2>(option)
}
}
impl<'a, T, U, L> OptGroupBuilder<'a, T, U, Set<method::options>, L> {
pub fn option(mut self, option: Opt<'a, T, U>) -> Self {
self.options.as_mut().unwrap().push(option);
self
}
#[cfg(feature = "blox")]
#[cfg_attr(docsrs, doc(cfg(feature = "blox")))]
pub fn child(self, option: Opt<'a, T, U>) -> Self {
self.option(option)
}
}
impl<'a, T, U>
OptGroupBuilder<'a, T, U, Set<method::options>, Set<method::label>>
{
pub fn build(self) -> OptGroup<'a, T, U> {
OptGroup { label: self.label.unwrap(),
options: self.options.unwrap() }
}
}
}
#[cfg(feature = "validation")]
mod validate {
use super::*;
use crate::val_helpr::{below_len, ValidatorResult};
pub(super) fn label(text: &text::Text) -> ValidatorResult {
below_len("Option Group Label", 75, text.as_ref())
}
}