use super::super::{decide, explain};
use super::{
CrateBinding, Door, Producer, RUST_DECLARATION_PROFILE, Request, Selection, Statements,
};
use crate::closure::Closure;
use crate::diagnostic::{Diagnostic, Placement, Refused};
use crate::expansion::Expansion;
use crate::explanation::View;
use crate::identity::{
self, Contract, Identity, OwnerFact, OwnerIdentity, Profile, Role, ServiceEntry, Transcript,
};
use crate::kind::{Kind, Question};
use crate::plan::Plan;
use crate::render::{Output, RenderError};
use crate::token::CapturedInput;
impl CrateBinding {
#[must_use]
pub const fn declared(spelling: &'static str) -> Self {
Self { spelling }
}
#[must_use]
pub const fn spelling(self) -> &'static str {
self.spelling
}
}
impl Door {
#[must_use]
pub const fn declared(
prefix: &'static str,
grammar: &'static str,
entry: &'static str,
binding: CrateBinding,
producer: Producer,
) -> Self {
Self {
prefix,
grammar,
entry,
binding,
producer,
}
}
#[must_use]
pub const fn prefix(&self) -> &'static str {
self.prefix
}
#[must_use]
pub fn grammar(&self) -> Identity<Contract> {
Identity::derived(Transcript::rooted(
Role::DeclaredName,
self.grammar.as_bytes(),
0,
))
}
#[must_use]
pub fn entry(&self) -> Identity<ServiceEntry> {
Identity::derived(Transcript::rooted(
Role::DeclaredName,
self.entry.as_bytes(),
1,
))
}
#[must_use]
pub const fn binding(&self) -> CrateBinding {
self.binding
}
#[must_use]
pub const fn producer(&self) -> Producer {
self.producer
}
}
impl<'door, K: Kind> Request<'door, K> {
pub fn over(capture: CapturedInput, content: K::Content, door: &'door Door) -> Self {
Self {
capture,
content,
door,
dependencies: Vec::new(),
profile: RUST_DECLARATION_PROFILE,
assumptions: Vec::new(),
addresses: Vec::new(),
answers: Vec::new(),
selection: Selection::All,
}
}
pub fn selecting(mut self, first: K::Role, rest: Vec<K::Role>) -> Self {
self.selection = Selection::Declared { first, rest };
self
}
pub fn depending_on(
mut self,
dependencies: Vec<Identity<identity::CapturedDeclaration>>,
) -> Self {
self.dependencies = dependencies;
self
}
pub fn profile(mut self, profile: Profile) -> Self {
self.profile = profile;
self
}
pub fn assuming(mut self, assumptions: Vec<OwnerFact>) -> Self {
self.assumptions = assumptions;
self
}
pub fn publishing_at(mut self, role: K::Role, address: OwnerIdentity) -> Self {
self.addresses.retain(|(seat, _)| *seat != role);
self.addresses.push((role, address));
self
}
pub fn answering(mut self, answers: Vec<<K::Question as Question>::Answer>) -> Self {
self.answers = answers;
self
}
pub fn render(
self,
renderer: impl FnOnce(&Plan<K>, &mut Output<'_, K>) -> Result<(), RenderError>,
) -> Result<Expansion<K>, Diagnostic> {
let Self {
capture,
content,
door,
dependencies,
profile,
assumptions,
addresses,
answers,
selection,
} = self;
let statements = Statements::from_request(&assumptions, &addresses, &selection);
let plan =
decide::planned::<K>(&capture, content, door, dependencies, profile, &statements)
.map_err(|refusal| refused(&refusal, door))?;
let mut out = Output::over(&plan);
renderer(&plan, &mut out).map_err(|refusal| refused(&refusal, door))?;
let units = out.rendered().map_err(|refusal| refused(&refusal, door))?;
let closure = Closure::proved(&plan, units).map_err(|refusal| refused(&refusal, door))?;
let universal = explain::universal(door, &plan, &closure, &assumptions)
.map_err(|refusal| refused(&refusal, door))?;
let view = View::complete(&plan, &closure, universal, answers)
.map_err(|refusal| refused(&refusal, door))?;
Expansion::bound(plan, closure, view).map_err(|refusal| refused(&refusal, door))
}
}
fn refused<E: Refused>(refusal: &E, door: &Door) -> Diagnostic {
Diagnostic::refused(refusal, door, &Placement::WholeDeclaration)
}