diff --git a/doc/writing-modules.adoc b/doc/writing-modules.adoc index 41678c30d..0f3336ff2 100644 --- a/doc/writing-modules.adoc +++ b/doc/writing-modules.adoc @@ -168,13 +168,20 @@ Builds a GVariant array containing the given list of elements, where each elemen - `hm.gvariant.type.uint64` - `hm.gvariant.type.double` - `hm.gvariant.type.arrayOf type` +- `hm.gvariant.type.maybeOf type` - `hm.gvariant.type.tupleOf types` -- + -where `type` and `types` are themselve a type and list of types, respectively. +where `type` and `types` are themselves a type and list of types, respectively. + `hm.gvariant.mkEmptyArray type`::: An alias of `hm.gvariant.mkArray type []`. + +`hm.gvariant.mkNothing type`::: +Builds a GVariant maybe value whose (non-existent) element is of the given type. The `type` value is constructed as described for the `mkArray` function above. ++ +`hm.gvariant.mkJust element`::: +Builds a GVariant maybe value containing the given GVariant element. ++ `hm.gvariant.mkTuple elements`::: Builds a GVariant tuple containing the given list of elements, where each element is a GVariant value. diff --git a/modules/lib/gvariant.nix b/modules/lib/gvariant.nix index 83951c207..3bfa18cb4 100644 --- a/modules/lib/gvariant.nix +++ b/modules/lib/gvariant.nix @@ -18,6 +18,7 @@ let type = { arrayOf = t: "a${t}"; + maybeOf = t: "m${t}"; tupleOf = ts: "(${concatStrings ts})"; string = "s"; boolean = "b"; @@ -57,11 +58,21 @@ let else ""; + mkMaybe = elemType: elem: + mkPrimitive (type.maybeOf elemType) elem // { + __toString = self: + if self.value == null then + "@${self.type} nothing" + else + "just ${toString self.value}"; + }; + in rec { inherit type typeOf; isArray = hasPrefix "a"; + isMaybe = hasPrefix "m"; isTuple = hasPrefix "("; # Returns the GVariant value that most closely matches the given Nix @@ -92,6 +103,10 @@ in rec { mkEmptyArray = elemType: mkArray elemType [ ]; + mkNothing = elemType: mkMaybe elemType null; + + mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem; + mkTuple = elems: let gvarElems = map mkValue elems; diff --git a/modules/lib/types.nix b/modules/lib/types.nix index 46db1157d..64a6b4a34 100644 --- a/modules/lib/types.nix +++ b/modules/lib/types.nix @@ -77,6 +77,8 @@ in rec { (map (d: d // { value = d.value.value; }) vdefs) else if gvar.isTuple sharedDefType && allChecked then mergeOneOption loc defs + else if gvar.isMaybe sharedDefType && allChecked then + mergeOneOption loc defs else if gvar.type.string == sharedDefType && allChecked then types.str.merge loc defs else if gvar.type.double == sharedDefType && allChecked then diff --git a/tests/lib/types/gvariant-merge.nix b/tests/lib/types/gvariant-merge.nix index 0eeccf7f7..fce50e0da 100644 --- a/tests/lib/types/gvariant-merge.nix +++ b/tests/lib/types/gvariant-merge.nix @@ -28,6 +28,9 @@ in { { string = "foo"; } { tuple = mkTuple [ 1 [ "foo" ] ]; } + + { maybe1 = mkNothing type.string; } + { maybe2 = mkJust (mkUint32 4); } ]; home.file."result.txt".text = let @@ -46,6 +49,8 @@ in { float = 3.140000 int = 42 list = @as ['one','two'] + maybe1 = @ms nothing + maybe2 = just @u 4 string = 'foo' tuple = @(ias) (1,@as ['foo']) ''