summaryrefslogtreecommitdiff
path: root/lib/gvariant.nix
diff options
context:
space:
mode:
authorlinsui <linsui555@gmail.com>2023-06-14 16:14:23 +0800
committerlinsui <linsui@inbox.lv>2023-08-15 19:20:39 +0800
commitda614d98e9540002bb1a1a9165177c3a6719f07f (patch)
treecfa9f6a302a58eab7f313f1ac4169a7d07430e43 /lib/gvariant.nix
parentMerge pull request #249125 from Ma27/bump-gitea (diff)
downloadnixpkgs-da614d98e9540002bb1a1a9165177c3a6719f07f.tar.gz
lib/gvariant: init
Diffstat (limited to 'lib/gvariant.nix')
-rw-r--r--lib/gvariant.nix290
1 files changed, 290 insertions, 0 deletions
diff --git a/lib/gvariant.nix b/lib/gvariant.nix
new file mode 100644
index 000000000000..3142ffc5f149
--- /dev/null
+++ b/lib/gvariant.nix
@@ -0,0 +1,290 @@
+# This file is based on https://github.com/nix-community/home-manager
+# Copyright (c) 2017-2022 Home Manager contributors
+#
+
+
+{ lib }:
+
+/* A partial and basic implementation of GVariant formatted strings.
+ See https://docs.gtk.org/glib/gvariant-format-strings.html for detauls.
+
+ Note, this API is not considered fully stable and it might therefore
+ change in backwards incompatible ways without prior notice.
+*/
+let
+ inherit (lib)
+ concatMapStringsSep concatStrings escape head replaceStrings;
+
+ mkPrimitive = t: v: {
+ _type = "gvariant";
+ type = t;
+ value = v;
+ __toString = self: "@${self.type} ${toString self.value}"; # https://docs.gtk.org/glib/gvariant-text.html
+ };
+
+ type = {
+ arrayOf = t: "a${t}";
+ maybeOf = t: "m${t}";
+ tupleOf = ts: "(${concatStrings ts})";
+ dictionaryEntryOf = nameType: valueType: "{${nameType}${valueType}}";
+ string = "s";
+ boolean = "b";
+ uchar = "y";
+ int16 = "n";
+ uint16 = "q";
+ int32 = "i";
+ uint32 = "u";
+ int64 = "x";
+ uint64 = "t";
+ double = "d";
+ variant = "v";
+ };
+
+ /* Check if a value is a GVariant value
+
+ Type:
+ isGVariant :: Any -> Bool
+ */
+ isGVariant = v: v._type or "" == "gvariant";
+
+in
+rec {
+
+ inherit type isGVariant;
+
+ /* Returns the GVariant value that most closely matches the given Nix value.
+ If no GVariant value can be found unambiguously then error is thrown.
+
+ Type:
+ mkValue :: Any -> gvariant
+ */
+ mkValue = v:
+ if builtins.isBool v then
+ mkBoolean v
+ else if builtins.isFloat v then
+ mkDouble v
+ else if builtins.isString v then
+ mkString v
+ else if builtins.isList v then
+ mkArray v
+ else if isGVariant v then
+ v
+ else
+ throw "The GVariant type of ${v} can't be inferred.";
+
+ /* Returns the GVariant array from the given type of the elements and a Nix list.
+
+ Type:
+ mkArray :: [Any] -> gvariant
+
+ Example:
+ # Creating a string array
+ lib.gvariant.mkArray [ "a" "b" "c" ]
+ */
+ mkArray = elems:
+ let
+ vs = map mkValue (lib.throwIf (elems == [ ]) "Please create empty array with mkEmptyArray." elems);
+ elemType = lib.throwIfNot (lib.all (t: (head vs).type == t) (map (v: v.type) vs))
+ "Elements in a list should have same type."
+ (head vs).type;
+ in
+ mkPrimitive (type.arrayOf elemType) vs // {
+ __toString = self:
+ "@${self.type} [${concatMapStringsSep "," toString self.value}]";
+ };
+
+ /* Returns the GVariant array from the given empty Nix list.
+
+ Type:
+ mkEmptyArray :: gvariant.type -> gvariant
+
+ Example:
+ # Creating an empty string array
+ lib.gvariant.mkEmptyArray (lib.gvariant.type.string)
+ */
+ mkEmptyArray = elemType: mkPrimitive (type.arrayOf elemType) [ ] // {
+ __toString = self: "@${self.type} []";
+ };
+
+
+ /* Returns the GVariant variant from the given Nix value. Variants are containers
+ of different GVariant type.
+
+ Type:
+ mkVariant :: Any -> gvariant
+
+ Example:
+ lib.gvariant.mkArray [
+ (lib.gvariant.mkVariant "a string")
+ (lib.gvariant.mkVariant (lib.gvariant.mkInt32 1))
+ ]
+ */
+ mkVariant = elem:
+ let gvarElem = mkValue elem;
+ in mkPrimitive type.variant gvarElem // {
+ __toString = self: "<${toString self.value}>";
+ };
+
+ /* Returns the GVariant dictionary entry from the given key and value.
+
+ Type:
+ mkDictionaryEntry :: String -> Any -> gvariant
+
+ Example:
+ # A dictionary describing an Epiphany’s search provider
+ [
+ (lib.gvariant.mkDictionaryEntry "url" (lib.gvariant.mkVariant "https://duckduckgo.com/?q=%s&t=epiphany"))
+ (lib.gvariant.mkDictionaryEntry "bang" (lib.gvariant.mkVariant "!d"))
+ (lib.gvariant.mkDictionaryEntry "name" (lib.gvariant.mkVariant "DuckDuckGo"))
+ ]
+ */
+ mkDictionaryEntry =
+ # The key of the entry
+ name:
+ # The value of the entry
+ value:
+ let
+ name' = mkValue name;
+ value' = mkValue value;
+ dictionaryType = type.dictionaryEntryOf name'.type value'.type;
+ in
+ mkPrimitive dictionaryType { inherit name value; } // {
+ __toString = self: "@${self.type} {${name'},${value'}}";
+ };
+
+ /* Returns the GVariant maybe from the given element type.
+
+ Type:
+ mkMaybe :: gvariant.type -> Any -> gvariant
+ */
+ mkMaybe = elemType: elem:
+ mkPrimitive (type.maybeOf elemType) elem // {
+ __toString = self:
+ if self.value == null then
+ "@${self.type} nothing"
+ else
+ "just ${toString self.value}";
+ };
+
+ /* Returns the GVariant nothing from the given element type.
+
+ Type:
+ mkNothing :: gvariant.type -> gvariant
+ */
+ mkNothing = elemType: mkMaybe elemType null;
+
+ /* Returns the GVariant just from the given Nix value.
+
+ Type:
+ mkJust :: Any -> gvariant
+ */
+ mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem;
+
+ /* Returns the GVariant tuple from the given Nix list.
+
+ Type:
+ mkTuple :: [Any] -> gvariant
+ */
+ mkTuple = elems:
+ let
+ gvarElems = map mkValue elems;
+ tupleType = type.tupleOf (map (e: e.type) gvarElems);
+ in
+ mkPrimitive tupleType gvarElems // {
+ __toString = self:
+ "@${self.type} (${concatMapStringsSep "," toString self.value})";
+ };
+
+ /* Returns the GVariant boolean from the given Nix bool value.
+
+ Type:
+ mkBoolean :: Bool -> gvariant
+ */
+ mkBoolean = v:
+ mkPrimitive type.boolean v // {
+ __toString = self: if self.value then "true" else "false";
+ };
+
+ /* Returns the GVariant string from the given Nix string value.
+
+ Type:
+ mkString :: String -> gvariant
+ */
+ mkString = v:
+ let sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s);
+ in mkPrimitive type.string v // {
+ __toString = self: "'${sanitize self.value}'";
+ };
+
+ /* Returns the GVariant object path from the given Nix string value.
+
+ Type:
+ mkObjectpath :: String -> gvariant
+ */
+ mkObjectpath = v:
+ mkPrimitive type.string v // {
+ __toString = self: "objectpath '${escape [ "'" ] self.value}'";
+ };
+
+ /* Returns the GVariant uchar from the given Nix int value.
+
+ Type:
+ mkUchar :: Int -> gvariant
+ */
+ mkUchar = mkPrimitive type.uchar;
+
+ /* Returns the GVariant int16 from the given Nix int value.
+
+ Type:
+ mkInt16 :: Int -> gvariant
+ */
+ mkInt16 = mkPrimitive type.int16;
+
+ /* Returns the GVariant uint16 from the given Nix int value.
+
+ Type:
+ mkUint16 :: Int -> gvariant
+ */
+ mkUint16 = mkPrimitive type.uint16;
+
+ /* Returns the GVariant int32 from the given Nix int value.
+
+ Type:
+ mkInt32 :: Int -> gvariant
+ */
+ mkInt32 = v:
+ mkPrimitive type.int32 v // {
+ __toString = self: toString self.value;
+ };
+
+ /* Returns the GVariant uint32 from the given Nix int value.
+
+ Type:
+ mkUint32 :: Int -> gvariant
+ */
+ mkUint32 = mkPrimitive type.uint32;
+
+ /* Returns the GVariant int64 from the given Nix int value.
+
+ Type:
+ mkInt64 :: Int -> gvariant
+ */
+ mkInt64 = mkPrimitive type.int64;
+
+ /* Returns the GVariant uint64 from the given Nix int value.
+
+ Type:
+ mkUint64 :: Int -> gvariant
+ */
+ mkUint64 = mkPrimitive type.uint64;
+
+ /* Returns the GVariant double from the given Nix float value.
+
+ Type:
+ mkDouble :: Float -> gvariant
+ */
+ mkDouble = v:
+ mkPrimitive type.double v // {
+ __toString = self: toString self.value;
+ };
+}