2 A partial and basic implementation of GVariant formatted strings.
3 See [GVariant Format Strings](https://docs.gtk.org/glib/gvariant-format-strings.html) for details.
6 This API is not considered fully stable and it might therefore
7 change in backwards incompatible ways without prior notice.
11 # This file is based on https://github.com/nix-community/home-manager
12 # Copyright (c) 2017-2022 Home Manager contributors
17 concatMapStringsSep concatStrings escape head replaceStrings;
23 __toString = self: "@${self.type} ${toString self.value}"; # https://docs.gtk.org/glib/gvariant-text.html
29 tupleOf = ts: "(${concatStrings ts})";
30 dictionaryEntryOf = nameType: valueType: "{${nameType}${valueType}}";
50 Check if a value is a GVariant value
62 isGVariant :: Any -> Bool
65 isGVariant = v: v._type or "" == "gvariant";
83 # Nix does not support such large numbers.
91 # Nix does not support such large numbers.
115 Returns the GVariant value that most closely matches the given Nix value.
116 If no GVariant value can be found unambiguously then error is thrown.
123 : 1\. Function argument
128 mkValue :: Any -> gvariant
132 if builtins.isBool v then
134 else if builtins.isFloat v then
136 else if builtins.isString v then
138 else if builtins.isList v then
140 else if isGVariant v then
142 else if builtins.isInt v then
144 validConstructors = builtins.filter ({ min, max, ... }: (min == null || min <= v) && (max == null || v <= max)) intConstructors;
147 The GVariant type for number “${builtins.toString v}” is unclear.
148 Please wrap the value with one of the following, depending on the value type in GSettings schema:
150 ${lib.concatMapStringsSep "\n" ({ name, type, ...}: "- `lib.gvariant.${name}` for `${type}`") validConstructors}
152 else if builtins.isAttrs v then
153 throw "Cannot construct GVariant value from an attribute set. If you want to construct a dictionary, you will need to create an array containing items constructed with `lib.gvariant.mkDictionaryEntry`."
155 throw "The GVariant type of “${builtins.typeOf v}” can't be inferred.";
158 Returns the GVariant array from the given type of the elements and a Nix list.
165 : 1\. Function argument
170 mkArray :: [Any] -> gvariant
175 ## `lib.gvariant.mkArray` usage example
178 # Creating a string array
179 lib.gvariant.mkArray [ "a" "b" "c" ]
186 vs = map mkValue (lib.throwIf (elems == [ ]) "Please create empty array with mkEmptyArray." elems);
187 elemType = lib.throwIfNot (lib.all (t: (head vs).type == t) (map (v: v.type) vs))
188 "Elements in a list should have same type."
191 mkPrimitive (type.arrayOf elemType) vs // {
193 "@${self.type} [${concatMapStringsSep "," toString self.value}]";
197 Returns the GVariant array from the given empty Nix list.
204 : 1\. Function argument
209 mkEmptyArray :: gvariant.type -> gvariant
214 ## `lib.gvariant.mkEmptyArray` usage example
217 # Creating an empty string array
218 lib.gvariant.mkEmptyArray (lib.gvariant.type.string)
223 mkEmptyArray = elemType: mkPrimitive (type.arrayOf elemType) [ ] // {
224 __toString = self: "@${self.type} []";
229 Returns the GVariant variant from the given Nix value. Variants are containers
230 of different GVariant type.
237 : 1\. Function argument
242 mkVariant :: Any -> gvariant
247 ## `lib.gvariant.mkVariant` usage example
250 lib.gvariant.mkArray [
251 (lib.gvariant.mkVariant "a string")
252 (lib.gvariant.mkVariant (lib.gvariant.mkInt32 1))
259 let gvarElem = mkValue elem;
260 in mkPrimitive type.variant gvarElem // {
261 __toString = self: "<${toString self.value}>";
265 Returns the GVariant dictionary entry from the given key and value.
272 : The key of the entry
276 : The value of the entry
281 mkDictionaryEntry :: String -> Any -> gvariant
286 ## `lib.gvariant.mkDictionaryEntry` usage example
289 # A dictionary describing an Epiphany’s search provider
291 (lib.gvariant.mkDictionaryEntry "url" (lib.gvariant.mkVariant "https://duckduckgo.com/?q=%s&t=epiphany"))
292 (lib.gvariant.mkDictionaryEntry "bang" (lib.gvariant.mkVariant "!d"))
293 (lib.gvariant.mkDictionaryEntry "name" (lib.gvariant.mkVariant "DuckDuckGo"))
303 name' = mkValue name;
304 value' = mkValue value;
305 dictionaryType = type.dictionaryEntryOf name'.type value'.type;
307 mkPrimitive dictionaryType { inherit name value; } // {
308 __toString = self: "@${self.type} {${name'},${value'}}";
312 Returns the GVariant maybe from the given element type.
319 : 1\. Function argument
323 : 2\. Function argument
328 mkMaybe :: gvariant.type -> Any -> gvariant
331 mkMaybe = elemType: elem:
332 mkPrimitive (type.maybeOf elemType) elem // {
334 if self.value == null then
335 "@${self.type} nothing"
337 "just ${toString self.value}";
341 Returns the GVariant nothing from the given element type.
348 : 1\. Function argument
353 mkNothing :: gvariant.type -> gvariant
356 mkNothing = elemType: mkMaybe elemType null;
359 Returns the GVariant just from the given Nix value.
366 : 1\. Function argument
371 mkJust :: Any -> gvariant
374 mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem;
377 Returns the GVariant tuple from the given Nix list.
384 : 1\. Function argument
389 mkTuple :: [Any] -> gvariant
394 gvarElems = map mkValue elems;
395 tupleType = type.tupleOf (map (e: e.type) gvarElems);
397 mkPrimitive tupleType gvarElems // {
399 "@${self.type} (${concatMapStringsSep "," toString self.value})";
403 Returns the GVariant boolean from the given Nix bool value.
410 : 1\. Function argument
415 mkBoolean :: Bool -> gvariant
419 mkPrimitive type.boolean v // {
420 __toString = self: if self.value then "true" else "false";
424 Returns the GVariant string from the given Nix string value.
431 : 1\. Function argument
436 mkString :: String -> gvariant
440 let sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s);
441 in mkPrimitive type.string v // {
442 __toString = self: "'${sanitize self.value}'";
446 Returns the GVariant object path from the given Nix string value.
453 : 1\. Function argument
458 mkObjectpath :: String -> gvariant
462 mkPrimitive type.string v // {
463 __toString = self: "objectpath '${escape [ "'" ] self.value}'";
467 Returns the GVariant uchar from the given Nix int value.
472 mkUchar :: Int -> gvariant
475 mkUchar = mkPrimitive type.uchar;
478 Returns the GVariant int16 from the given Nix int value.
483 mkInt16 :: Int -> gvariant
486 mkInt16 = mkPrimitive type.int16;
489 Returns the GVariant uint16 from the given Nix int value.
494 mkUint16 :: Int -> gvariant
497 mkUint16 = mkPrimitive type.uint16;
500 Returns the GVariant int32 from the given Nix int value.
507 : 1\. Function argument
512 mkInt32 :: Int -> gvariant
516 mkPrimitive type.int32 v // {
517 __toString = self: toString self.value;
521 Returns the GVariant uint32 from the given Nix int value.
526 mkUint32 :: Int -> gvariant
529 mkUint32 = mkPrimitive type.uint32;
532 Returns the GVariant int64 from the given Nix int value.
537 mkInt64 :: Int -> gvariant
540 mkInt64 = mkPrimitive type.int64;
543 Returns the GVariant uint64 from the given Nix int value.
548 mkUint64 :: Int -> gvariant
551 mkUint64 = mkPrimitive type.uint64;
554 Returns the GVariant double from the given Nix float value.
561 : 1\. Function argument
566 mkDouble :: Float -> gvariant
570 mkPrimitive type.double v // {
571 __toString = self: toString self.value;