use crate::driver::{
settings,
settings::{demands, errors},
};
#[derive(Clone, Copy, Default, PartialEq, Eq)]
pub struct Claim {
routes: settings::Routes,
files: demands::Files,
receive: demands::Receive,
resident_domains: settings::Domain,
schedule: demands::Schedule,
}
impl Claim {
pub const fn new(routes: settings::Routes) -> Self {
Self {
routes,
files: demands::Files::ZERO,
receive: demands::Receive::ZERO,
resident_domains: settings::Domain::ZERO,
schedule: demands::Schedule::ZERO,
}
}
#[must_use]
pub const fn files(mut self, files: demands::Files) -> Self {
self.files = files;
self
}
#[must_use]
pub const fn receive(mut self, receive: demands::Receive) -> Self {
self.receive = receive;
self
}
#[must_use]
pub const fn domains(mut self, domains: settings::Domain) -> Self {
self.resident_domains = domains;
self
}
#[must_use]
pub const fn schedule(mut self, schedule: demands::Schedule) -> Self {
self.schedule = schedule;
self
}
}
#[derive(Clone, Copy, Default, PartialEq, Eq)]
#[repr(transparent)]
pub struct Needs {
claim: Claim,
}
const _: () = {
assert!(std::mem::size_of::<Needs>() == std::mem::size_of::<Claim>());
assert!(std::mem::align_of::<Needs>() == std::mem::align_of::<Claim>());
assert!(!std::mem::needs_drop::<Needs>());
};
impl Needs {
pub const fn new() -> Self {
Self {
claim: Claim::new(settings::Routes::EMPTY),
}
}
pub fn include(mut self, next: Claim) -> Result<Self, errors::Claim> {
if let Some(route) = self.claim.routes.overlap(next.routes) {
return Err(errors::Claim::DuplicateRoute(route));
}
self.claim.routes = self.claim.routes.join(next.routes);
self.claim.files = self.claim.files.merge(next.files)?;
self.claim.receive = self.claim.receive.merge(next.receive)?;
self.claim.resident_domains = self.claim.resident_domains.combine(next.resident_domains)?;
self.claim.schedule = self.claim.schedule.merge(next.schedule)?;
Ok(self)
}
pub fn from_tree(tree: &impl settings::Resource) -> Result<Self, errors::Claim> {
tree.include_in(Self::new())
}
pub fn resolve<P: settings::Profile>(&self) -> Result<settings::Config, errors::Claim> {
self.apply_to(settings::Config::for_profile::<P>())
}
pub fn exact<P: settings::Profile>(&self) -> Result<settings::Config, errors::Claim> {
self.apply_exact(settings::Config::for_profile::<P>())
}
pub fn apply_to(&self, baseline: settings::Config) -> Result<settings::Config, errors::Claim> {
let receive = baseline.receive().resolve(self.claim.receive)?;
self.apply(baseline, receive)
}
pub fn apply_exact(
&self,
baseline: settings::Config,
) -> Result<settings::Config, errors::Claim> {
let receive = settings::Receive::exact(self.claim.receive)?;
self.apply(baseline, receive)
}
fn apply(
&self,
baseline: settings::Config,
receive: settings::Receive,
) -> Result<settings::Config, errors::Claim> {
let base = baseline.file_slots();
let files = base.resolve(self.claim.files)?;
let base = baseline.schedule();
let schedule = base.resolve(self.claim.schedule);
let domains = baseline.domains().resolve(self.claim.resident_domains);
Ok(baseline
.with_files(files)
.set_schedule(schedule)
.with_receive(receive)
.with_domains(domains))
}
}