1lib:
2
3with lib;
4
5rec {
6 paramsToConf = cfg: ps: mkConf 0 (paramsToRenderedStrings cfg ps);
7
8 # mkConf takes an indentation level (which usually starts at 0) and a nested
9 # attribute set of strings and will render that set to a strongswan.conf style
10 # configuration format. For example:
11 #
12 # mkConf 0 {a = "1"; b = { c = { "foo" = "2"; "bar" = "3"; }; d = "4";};} => ''
13 # a = 1
14 # b {
15 # c {
16 # foo = 2
17 # bar = 3
18 # }
19 # d = 4
20 # }''
21 mkConf =
22 indent: ps:
23 concatMapStringsSep "\n" (
24 name:
25 let
26 value = ps.${name};
27 indentation = replicate indent " ";
28 in
29 indentation
30 + (
31 if isAttrs value then
32 "${name} {\n" + mkConf (indent + 2) value + "\n" + indentation + "}"
33 else
34 "${name} = ${value}"
35 )
36 ) (attrNames ps);
37
38 replicate = n: c: concatStrings (builtins.genList (_x: c) n);
39
40 # `paramsToRenderedStrings cfg ps` converts the NixOS configuration `cfg`
41 # (typically the "config" argument of a NixOS module) and the set of
42 # parameters `ps` (an attribute set where the values are constructed using the
43 # parameter constructors in ./param-constructors.nix) to a nested attribute
44 # set of strings (rendered parameters).
45 paramsToRenderedStrings =
46 cfg: ps:
47 filterEmptySets (
48 (mapParamsRecursive (
49 path: name: param:
50 let
51 value = attrByPath path null cfg;
52 in
53 optionalAttrs (value != null) (param.render name value)
54 ) ps)
55 );
56
57 filterEmptySets =
58 set:
59 filterAttrs (n: v: (v != null)) (
60 mapAttrs (
61 name: value:
62 if isAttrs value then
63 let
64 value' = filterEmptySets value;
65 in
66 if value' == { } then null else value'
67 else
68 value
69 ) set
70 );
71
72 # Recursively map over every parameter in the given attribute set.
73 mapParamsRecursive = mapAttrsRecursiveCond' (as: (!(as ? _type && as._type == "param")));
74
75 mapAttrsRecursiveCond' =
76 cond: f: set:
77 let
78 recurse =
79 path: set:
80 let
81 g =
82 name: value:
83 if isAttrs value && cond value then
84 { ${name} = recurse (path ++ [ name ]) value; }
85 else
86 f (path ++ [ name ]) name value;
87 in
88 mapAttrs'' g set;
89 in
90 recurse [ ] set;
91
92 mapAttrs'' = f: set: foldl' (a: b: a // b) { } (mapAttrsToList f set);
93
94 # Extract the options from the given set of parameters.
95 paramsToOptions = ps: mapParamsRecursive (_path: name: param: { ${name} = param.option; }) ps;
96
97}