mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-09 19:13:26 +03:00

The new implementation of `mapAttrsToList` is simpler than the previous one, avoiding an extra string conversion. Benchmarking shows a slight performance improvement. See the discussion here: https://discourse.nixos.org/t/another-implementation-of-mapattrstolist Additionally, I searched nixpkgs for expressions equivalent to the old `mapAttrsToList` and replaced them with direct calls to the new implementation.
97 lines
2.6 KiB
Nix
97 lines
2.6 KiB
Nix
lib:
|
|
|
|
with lib;
|
|
|
|
rec {
|
|
paramsToConf = cfg: ps: mkConf 0 (paramsToRenderedStrings cfg ps);
|
|
|
|
# mkConf takes an indentation level (which usually starts at 0) and a nested
|
|
# attribute set of strings and will render that set to a strongswan.conf style
|
|
# configuration format. For example:
|
|
#
|
|
# mkConf 0 {a = "1"; b = { c = { "foo" = "2"; "bar" = "3"; }; d = "4";};} => ''
|
|
# a = 1
|
|
# b {
|
|
# c {
|
|
# foo = 2
|
|
# bar = 3
|
|
# }
|
|
# d = 4
|
|
# }''
|
|
mkConf =
|
|
indent: ps:
|
|
concatMapStringsSep "\n" (
|
|
name:
|
|
let
|
|
value = ps.${name};
|
|
indentation = replicate indent " ";
|
|
in
|
|
indentation
|
|
+ (
|
|
if isAttrs value then
|
|
"${name} {\n" + mkConf (indent + 2) value + "\n" + indentation + "}"
|
|
else
|
|
"${name} = ${value}"
|
|
)
|
|
) (attrNames ps);
|
|
|
|
replicate = n: c: concatStrings (builtins.genList (_x: c) n);
|
|
|
|
# `paramsToRenderedStrings cfg ps` converts the NixOS configuration `cfg`
|
|
# (typically the "config" argument of a NixOS module) and the set of
|
|
# parameters `ps` (an attribute set where the values are constructed using the
|
|
# parameter constructors in ./param-constructors.nix) to a nested attribute
|
|
# set of strings (rendered parameters).
|
|
paramsToRenderedStrings =
|
|
cfg: ps:
|
|
filterEmptySets (
|
|
(mapParamsRecursive (
|
|
path: name: param:
|
|
let
|
|
value = attrByPath path null cfg;
|
|
in
|
|
optionalAttrs (value != null) (param.render name value)
|
|
) ps)
|
|
);
|
|
|
|
filterEmptySets =
|
|
set:
|
|
filterAttrs (n: v: (v != null)) (
|
|
mapAttrs (
|
|
name: value:
|
|
if isAttrs value then
|
|
let
|
|
value' = filterEmptySets value;
|
|
in
|
|
if value' == { } then null else value'
|
|
else
|
|
value
|
|
) set
|
|
);
|
|
|
|
# Recursively map over every parameter in the given attribute set.
|
|
mapParamsRecursive = mapAttrsRecursiveCond' (as: (!(as ? _type && as._type == "param")));
|
|
|
|
mapAttrsRecursiveCond' =
|
|
cond: f: set:
|
|
let
|
|
recurse =
|
|
path: set:
|
|
let
|
|
g =
|
|
name: value:
|
|
if isAttrs value && cond value then
|
|
{ ${name} = recurse (path ++ [ name ]) value; }
|
|
else
|
|
f (path ++ [ name ]) name value;
|
|
in
|
|
mapAttrs'' g set;
|
|
in
|
|
recurse [ ] set;
|
|
|
|
mapAttrs'' = f: set: foldl' (a: b: a // b) { } (mapAttrsToList f set);
|
|
|
|
# Extract the options from the given set of parameters.
|
|
paramsToOptions = ps: mapParamsRecursive (_path: name: param: { ${name} = param.option; }) ps;
|
|
|
|
}
|