aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/derived-path-map.hh
blob: 4d72b301e9636900ec44237536eb6ba5cda8fd01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#pragma once

#include "types.hh"
#include "derived-path.hh"

namespace nix {

/**
 * A simple Trie, of sorts. Conceptually a map of `SingleDerivedPath` to
 * values.
 *
 * Concretely, an n-ary tree, as described below. A
 * `SingleDerivedPath::Opaque` maps to the value of an immediate child
 * of the root node. A `SingleDerivedPath::Built` maps to a deeper child
 * node: the `SingleDerivedPath::Built::drvPath` is first mapped to a a
 * child node (inductively), and then the
 * `SingleDerivedPath::Built::output` is used to look up that child's
 * child via its map. In this manner, every `SingleDerivedPath` is
 * mapped to a child node.
 *
 * @param V A type to instantiate for each output. It should probably
 * should be an "optional" type so not every interior node has to have a
 * value. `* const Something` or `std::optional<Something>` would be
 * good choices for "optional" types.
 */
template<typename V>
struct DerivedPathMap {
    /**
     * A child node (non-root node).
     */
    struct ChildNode {
        /**
         * Value of this child node.
         *
         * @see DerivedPathMap for what `V` should be.
         */
        V value;

        /**
         * The map type for the root node.
         */
        using Map = std::map<OutputName, ChildNode>;

        /**
         * The map of the root node.
         */
        Map childMap;

        DECLARE_CMP(ChildNode);
    };

    /**
     * The map type for the root node.
     */
    using Map = std::map<StorePath, ChildNode>;

    /**
     * The map of root node.
     */
    Map map;

    DECLARE_CMP(DerivedPathMap);

    /**
     * Find the node for `k`, creating it if needed.
     *
     * The node is referred to as a "slot" on the assumption that `V` is
     * some sort of optional type, so the given key can be set or unset
     * by changing this node.
     */
    ChildNode & ensureSlot(const SingleDerivedPath & k);

    /**
     * Like `ensureSlot` but does not create the slot if it doesn't exist.
     *
     * Read the entire description of `ensureSlot` to understand an
     * important caveat here that "have slot" does *not* imply "key is
     * set in map". To ensure a key is set one would need to get the
     * child node (with `findSlot` or `ensureSlot`) *and* check the
     * `ChildNode::value`.
     */
    ChildNode * findSlot(const SingleDerivedPath & k);
};


DECLARE_CMP_EXT(
    template<>,
    DerivedPathMap<std::set<std::string>>::,
    DerivedPathMap<std::set<std::string>>);
DECLARE_CMP_EXT(
    template<>,
    DerivedPathMap<std::set<std::string>>::ChildNode::,
    DerivedPathMap<std::set<std::string>>::ChildNode);

}