use super::tree::{DomainDirectives, Script};
use crate::SubDomainHierarchy;
use vsmtp_common::Domain;
#[derive(Debug)]
pub struct Builder<'a> {
engine: &'a rhai::Engine,
inner: SubDomainHierarchy,
}
impl<'a> Builder<'a> {
#[must_use]
pub fn new(engine: &'a rhai::Engine) -> Self {
Self {
engine,
inner: SubDomainHierarchy::new_empty(engine),
}
}
pub fn add_root_filter_rules(mut self, script: &str) -> anyhow::Result<Self> {
self.inner.root_filter = Script::compile_source(self.engine, script)?;
Ok(self)
}
#[must_use]
pub const fn add_domain_rules(
self,
domain: Domain,
) -> DomainDirectivesBuilder<'a, WantsIncoming> {
DomainDirectivesBuilder {
inner: self,
domain,
state: WantsIncoming {},
}
}
#[allow(clippy::missing_const_for_fn)] #[must_use]
pub fn build(self) -> SubDomainHierarchy {
self.inner
}
}
#[derive(Debug)]
#[allow(clippy::module_name_repetitions)]
pub struct DomainDirectivesBuilder<'a, State: std::fmt::Debug> {
inner: Builder<'a>,
domain: Domain,
state: State,
}
#[derive(Debug)]
pub struct WantsIncoming;
impl<'a> DomainDirectivesBuilder<'a, WantsIncoming> {
pub fn with_incoming(
self,
incoming: &str,
) -> anyhow::Result<DomainDirectivesBuilder<'a, WantsOutgoing>> {
Ok(DomainDirectivesBuilder::<'a, WantsOutgoing> {
state: WantsOutgoing {
incoming: Some(Script::compile_source(self.inner.engine, incoming)?),
},
inner: self.inner,
domain: self.domain,
})
}
#[allow(clippy::missing_const_for_fn)] pub fn with_default(self) -> DomainDirectivesBuilder<'a, WantsOutgoing> {
DomainDirectivesBuilder::<'a, WantsOutgoing> {
state: WantsOutgoing { incoming: None },
inner: self.inner,
domain: self.domain,
}
}
}
#[derive(Debug)]
pub struct WantsOutgoing {
incoming: Option<Script>,
}
impl<'a> DomainDirectivesBuilder<'a, WantsOutgoing> {
pub fn with_outgoing(
self,
outgoing: &str,
) -> anyhow::Result<DomainDirectivesBuilder<'a, WantsInternal>> {
Ok(DomainDirectivesBuilder::<'a, WantsInternal> {
state: WantsInternal {
parent: self.state,
outgoing: Some(Script::compile_source(self.inner.engine, outgoing)?),
},
inner: self.inner,
domain: self.domain,
})
}
#[allow(clippy::missing_const_for_fn)] pub fn with_default(self) -> DomainDirectivesBuilder<'a, WantsInternal> {
DomainDirectivesBuilder::<'a, WantsInternal> {
state: WantsInternal {
parent: self.state,
outgoing: None,
},
inner: self.inner,
domain: self.domain,
}
}
}
#[derive(Debug)]
pub struct WantsInternal {
parent: WantsOutgoing,
outgoing: Option<Script>,
}
impl<'a> DomainDirectivesBuilder<'a, WantsInternal> {
pub fn with_internal(
self,
internal: &str,
) -> anyhow::Result<DomainDirectivesBuilder<'a, WantsBuild>> {
Ok(DomainDirectivesBuilder::<'a, WantsBuild> {
state: WantsBuild {
parent: self.state,
internal: Some(Script::compile_source(self.inner.engine, internal)?),
},
inner: self.inner,
domain: self.domain,
})
}
#[allow(clippy::missing_const_for_fn)] pub fn with_default(self) -> DomainDirectivesBuilder<'a, WantsBuild> {
DomainDirectivesBuilder::<'a, WantsBuild> {
state: WantsBuild {
parent: self.state,
internal: None,
},
inner: self.inner,
domain: self.domain,
}
}
}
#[derive(Debug)]
pub struct WantsBuild {
parent: WantsInternal,
internal: Option<Script>,
}
impl<'a> DomainDirectivesBuilder<'a, WantsBuild> {
#[allow(clippy::missing_const_for_fn)] #[must_use]
pub fn build(mut self) -> Builder<'a> {
self.inner.inner.domains.insert(
self.domain,
DomainDirectives {
incoming: self.state.parent.parent.incoming,
outgoing: self.state.parent.outgoing,
internal: self.state.internal,
},
);
self.inner
}
}