use alloc::string::String;
use core::fmt::{Display, Formatter, Result};
use core::ops::Deref;
use crate::stmt::{Stmt, StmtRef};
use crate::util::{AddOnlyVec, Indented, RefCounted};
use crate::{Rule, RuleVariables, ToArg, Variable, Variables};
#[derive(Debug)]
pub struct Build {
pub rule: RefCounted<String>,
pub outputs: AddOnlyVec<String>,
pub implicit_outputs: AddOnlyVec<String>,
pub dependencies: AddOnlyVec<String>,
pub implicit_dependencies: AddOnlyVec<String>,
pub order_only_dependencies: AddOnlyVec<String>,
pub validations: AddOnlyVec<String>,
pub variables: AddOnlyVec<Variable>,
}
pub trait BuildVariables: Variables {
fn as_build(&self) -> &Build;
#[inline]
fn dyndep(self, dyndep: impl ToArg) -> Self {
self.variable("dyndep", dyndep)
}
fn with(self, inputs: impl IntoIterator<Item = impl ToArg>) -> Self {
self.as_build()
.dependencies
.extend(inputs.into_iter().map(|s| s.to_arg()));
self
}
fn with_implicit(self, inputs: impl IntoIterator<Item = impl ToArg>) -> Self {
self.as_build()
.implicit_dependencies
.extend(inputs.into_iter().map(|s| s.to_arg()));
self
}
fn with_order_only(self, inputs: impl IntoIterator<Item = impl ToArg>) -> Self {
self.as_build()
.order_only_dependencies
.extend(inputs.into_iter().map(|s| s.to_arg()));
self
}
fn validations(self, validations: impl IntoIterator<Item = impl ToArg>) -> Self {
self.as_build()
.validations
.extend(validations.into_iter().map(|s| s.to_arg()));
self
}
fn output_implicit(self, outputs: impl IntoIterator<Item = impl ToArg>) -> Self {
self.as_build()
.implicit_outputs
.extend(outputs.into_iter().map(|s| s.to_arg()));
self
}
}
#[derive(Debug, Clone)]
pub struct BuildRef(pub(crate) StmtRef);
impl Deref for BuildRef {
type Target = Build;
fn deref(&self) -> &Self::Target {
match self.0.deref().deref() {
Stmt::Build(b) => b,
_ => unreachable!(),
}
}
}
impl AsRef<Build> for BuildRef {
#[inline]
fn as_ref(&self) -> &Build {
self.deref()
}
}
impl Build {
pub fn new(rule: &Rule, outputs: impl IntoIterator<Item = impl ToArg>) -> Self {
let self_outputs = AddOnlyVec::new();
self_outputs.extend(outputs.into_iter().map(|s| s.to_arg()));
Self {
rule: RefCounted::clone(&rule.name),
outputs: self_outputs,
implicit_outputs: AddOnlyVec::new(),
dependencies: AddOnlyVec::new(),
implicit_dependencies: AddOnlyVec::new(),
order_only_dependencies: AddOnlyVec::new(),
validations: AddOnlyVec::new(),
variables: AddOnlyVec::new(),
}
}
}
impl Variables for Build {
#[inline]
fn add_variable_internal(&self, v: Variable) {
self.variables.add(v);
}
}
impl BuildVariables for Build {
fn as_build(&self) -> &Build {
self
}
}
impl RuleVariables for Build {}
impl Variables for BuildRef {
#[inline]
fn add_variable_internal(&self, v: Variable) {
self.deref().variables.add(v);
}
}
impl BuildVariables for BuildRef {
fn as_build(&self) -> &Build {
self.deref()
}
}
impl RuleVariables for BuildRef {}
impl Display for Build {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "build")?;
for output in self.outputs.inner().iter() {
write!(f, " {}", output)?;
}
{
let implicit_outputs = self.implicit_outputs.inner();
if !implicit_outputs.is_empty() {
write!(f, " |")?;
for output in implicit_outputs.iter() {
write!(f, " {}", output)?;
}
}
}
write!(f, ": {}", self.rule)?;
for input in self.dependencies.inner().iter() {
write!(f, " {}", input)?;
}
{
let implicit_dependencies = self.implicit_dependencies.inner();
if !implicit_dependencies.is_empty() {
write!(f, " |")?;
for input in implicit_dependencies.iter() {
write!(f, " {}", input)?;
}
}
}
{
let order_only_dependencies = self.order_only_dependencies.inner();
if !order_only_dependencies.is_empty() {
write!(f, " ||")?;
for input in order_only_dependencies.iter() {
write!(f, " {}", input)?;
}
}
}
{
let validations = self.validations.inner();
if !validations.is_empty() {
write!(f, " |@")?;
for input in validations.iter() {
write!(f, " {}", input)?;
}
}
}
writeln!(f)?;
for variable in self.variables.inner().iter() {
Indented(variable).fmt(f)?;
writeln!(f)?;
}
Ok(())
}
}