add standard attrs parsing interface
This commit is contained in:
parent
a3afe330c4
commit
3d9e9740d2
2 changed files with 95 additions and 0 deletions
13
nib/parse/default.nix
Normal file
13
nib/parse/default.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
attrs,
|
||||||
|
result,
|
||||||
|
}: let
|
||||||
|
struct = import ./struct.nix {inherit attrs result;};
|
||||||
|
in
|
||||||
|
builtins.listToAttrs [
|
||||||
|
# submodule is included directly to this module (ie self.myFunc)
|
||||||
|
struct
|
||||||
|
|
||||||
|
# submodule content is accessible first by submodule name
|
||||||
|
# then by the name of the content (ie self.submodule.myFunc)
|
||||||
|
]
|
||||||
82
nib/parse/struct.nix
Normal file
82
nib/parse/struct.nix
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
{
|
||||||
|
attrs,
|
||||||
|
result,
|
||||||
|
}: rec {
|
||||||
|
cmpStructErr' = errBadKeys: errBadValues: path: S: T:
|
||||||
|
if builtins.isAttrs S && builtins.isAttrSet T
|
||||||
|
then let
|
||||||
|
keysS = builtins.attrNames S;
|
||||||
|
keysT = builtins.attrNames T;
|
||||||
|
in
|
||||||
|
# ensure all key names match, then recurse
|
||||||
|
if !(keysS == keysT)
|
||||||
|
then errBadKeys path keysS keysT
|
||||||
|
else
|
||||||
|
(result.firstErr
|
||||||
|
(builtins.map
|
||||||
|
(k: cmpStructErr' errBadKeys errBadValues (path ++ [k]) (keysS.${k}) (keysT.${k}))
|
||||||
|
keysS))
|
||||||
|
else
|
||||||
|
# terminating leaf in recursion tree reached
|
||||||
|
# ensure values' types match
|
||||||
|
(builtins.typeOf S == builtins.typeOf T)
|
||||||
|
|| errBadValues path S T;
|
||||||
|
|
||||||
|
cmpStructErr = errBadKeys: errBadValues: cmpStructErr' errBadKeys errBadValues [];
|
||||||
|
|
||||||
|
cmpStruct =
|
||||||
|
cmpStructErr
|
||||||
|
(path: keysS: keysT:
|
||||||
|
result.Err {
|
||||||
|
reason = "keys";
|
||||||
|
inherit path;
|
||||||
|
})
|
||||||
|
(path: S: T:
|
||||||
|
result.Ok "ok");
|
||||||
|
|
||||||
|
cmpTypedStruct =
|
||||||
|
cmpStructErr
|
||||||
|
(path: keysS: keysT:
|
||||||
|
result.Err {
|
||||||
|
reason = "keys";
|
||||||
|
inherit path;
|
||||||
|
})
|
||||||
|
(path: S: T:
|
||||||
|
result.Err {
|
||||||
|
reason = "values";
|
||||||
|
inherit path;
|
||||||
|
});
|
||||||
|
|
||||||
|
# check is a function taking two structs
|
||||||
|
# and returning a result monad.
|
||||||
|
mergeStruct' = check: template: S: let
|
||||||
|
res = check template S;
|
||||||
|
in
|
||||||
|
result.errOr res ({...}:
|
||||||
|
attrs.mapAttrsRecursive (
|
||||||
|
path: value: let
|
||||||
|
valueS = attrs.attrValueAt S path;
|
||||||
|
in
|
||||||
|
if valueS != null
|
||||||
|
then valueS
|
||||||
|
else value
|
||||||
|
)
|
||||||
|
template);
|
||||||
|
|
||||||
|
mergeStruct = mergeStruct' (S: T: result.Ok "ok");
|
||||||
|
|
||||||
|
mergeTypedStruct = mergeStruct' (
|
||||||
|
cmpStructErr
|
||||||
|
(path: keysS: keysT:
|
||||||
|
result.Ok "ok")
|
||||||
|
(path: S: T:
|
||||||
|
result.Err {
|
||||||
|
reason = "values";
|
||||||
|
inherit path;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
mergeStructStrict = mergeStruct' cmpStruct;
|
||||||
|
|
||||||
|
mergeTypedStructStrict = mergeStruct' cmpTypedStruct;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue