ninja_writer/
pool.rs

1//! Implementation of the `pool` keyword
2
3use alloc::string::String;
4use core::fmt::{Display, Formatter, Result};
5use core::ops::Deref;
6
7use crate::stmt::{Stmt, StmtRef};
8use crate::util::{AddOnlyVec, Indented};
9use crate::{Ninja, ToArg, Variable, Variables};
10
11/// A pool, as defined by the `pool` keyword
12///
13/// See <https://ninja-build.org/manual.html#ref_pool>
14///
15/// # Example
16/// ```rust
17/// use ninja_writer::*;
18///
19/// let ninja = Ninja::new();
20/// let expensive = ninja.pool("expensive", 4)
21///     .variable("foo", "bar");
22///
23/// let compile = ninja.rule("compile", "gcc $cflags -c $in -o $out").pool(&expensive);
24///
25/// assert_eq!(ninja.to_string(), r###"
26/// pool expensive
27///   depth = 4
28///   foo = bar
29///
30/// rule compile
31///   command = gcc $cflags -c $in -o $out
32///   pool = expensive
33/// "###);
34/// ```
35#[derive(Debug)]
36pub struct Pool {
37    /// Name of the pool
38    pub name: String,
39    /// The list of variables, as an indented block
40    ///
41    /// Currently the only useful variable is `depth`
42    pub variables: AddOnlyVec<Variable>,
43}
44
45/// Reference to a pool statement
46#[derive(Debug, Clone)]
47pub struct PoolRef(pub(crate) StmtRef);
48
49impl Deref for PoolRef {
50    type Target = Pool;
51    fn deref(&self) -> &Self::Target {
52        match self.0.deref().deref() {
53            Stmt::Pool(p) => p,
54            // safety: PoolRef is only constructable within this crate
55            _ => unreachable!(),
56        }
57    }
58}
59
60impl AsRef<Pool> for PoolRef {
61    fn as_ref(&self) -> &Pool {
62        self.deref()
63    }
64}
65
66impl Pool {
67    /// Create a pool with a given name and depth
68    pub fn new(name: impl ToArg, depth: usize) -> Self {
69        let x = Self {
70            name: name.to_arg(),
71            variables: AddOnlyVec::new(),
72        };
73        x.variable("depth", depth)
74    }
75
76    /// Add the pool to a ninja file
77    #[inline]
78    pub fn add_to(self, ninja: &Ninja) -> PoolRef {
79        PoolRef(ninja.add_stmt(Stmt::Pool(self)))
80    }
81}
82
83impl Variables for Pool {
84    fn add_variable_internal(&self, v: Variable) {
85        self.variables.add(v);
86    }
87}
88
89impl Variables for PoolRef {
90    fn add_variable_internal(&self, v: Variable) {
91        self.deref().add_variable_internal(v);
92    }
93}
94
95impl Display for Pool {
96    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
97        writeln!(f, "pool {}", self.name)?;
98        for variable in self.variables.inner().iter() {
99            Indented(variable).fmt(f)?;
100            writeln!(f)?;
101        }
102        Ok(())
103    }
104}
105
106#[cfg(test)]
107mod test {
108    use super::*;
109    use alloc::string::ToString;
110
111    #[test]
112    fn test_default() {
113        let pool = Pool::new("foo", 1);
114        assert_eq!(pool.to_string(), "pool foo\n  depth = 1\n");
115    }
116
117    #[test]
118    fn test_variable() {
119        let pool = Pool::new("foo", 42).variable("foov", "z");
120        assert_eq!(pool.to_string(), "pool foo\n  depth = 42\n  foov = z\n");
121    }
122}