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}}";
44 /* Check if a value is a GVariant value
47 isGVariant :: Any -> Bool
49 isGVariant = v: v._type or "" == "gvariant";
54 inherit type isGVariant;
56 /* Returns the GVariant value that most closely matches the given Nix value.
57 If no GVariant value can be found unambiguously then error is thrown.
60 mkValue :: Any -> gvariant
63 if builtins.isBool v then
65 else if builtins.isFloat v then
67 else if builtins.isString v then
69 else if builtins.isList v then
71 else if isGVariant v then
74 throw "The GVariant type of ${v} can't be inferred.";
76 /* Returns the GVariant array from the given type of the elements and a Nix list.
79 mkArray :: [Any] -> gvariant
82 # Creating a string array
83 lib.gvariant.mkArray [ "a" "b" "c" ]
87 vs = map mkValue (lib.throwIf (elems == [ ]) "Please create empty array with mkEmptyArray." elems);
88 elemType = lib.throwIfNot (lib.all (t: (head vs).type == t) (map (v: v.type) vs))
89 "Elements in a list should have same type."
92 mkPrimitive (type.arrayOf elemType) vs // {
94 "@${self.type} [${concatMapStringsSep "," toString self.value}]";
97 /* Returns the GVariant array from the given empty Nix list.
100 mkEmptyArray :: gvariant.type -> gvariant
103 # Creating an empty string array
104 lib.gvariant.mkEmptyArray (lib.gvariant.type.string)
106 mkEmptyArray = elemType: mkPrimitive (type.arrayOf elemType) [ ] // {
107 __toString = self: "@${self.type} []";
111 /* Returns the GVariant variant from the given Nix value. Variants are containers
112 of different GVariant type.
115 mkVariant :: Any -> gvariant
118 lib.gvariant.mkArray [
119 (lib.gvariant.mkVariant "a string")
120 (lib.gvariant.mkVariant (lib.gvariant.mkInt32 1))
124 let gvarElem = mkValue elem;
125 in mkPrimitive type.variant gvarElem // {
126 __toString = self: "<${toString self.value}>";
129 /* Returns the GVariant dictionary entry from the given key and value.
132 mkDictionaryEntry :: String -> Any -> gvariant
135 # A dictionary describing an Epiphany’s search provider
137 (lib.gvariant.mkDictionaryEntry "url" (lib.gvariant.mkVariant "https://duckduckgo.com/?q=%s&t=epiphany"))
138 (lib.gvariant.mkDictionaryEntry "bang" (lib.gvariant.mkVariant "!d"))
139 (lib.gvariant.mkDictionaryEntry "name" (lib.gvariant.mkVariant "DuckDuckGo"))
143 # The key of the entry
145 # The value of the entry
148 name' = mkValue name;
149 value' = mkValue value;
150 dictionaryType = type.dictionaryEntryOf name'.type value'.type;
152 mkPrimitive dictionaryType { inherit name value; } // {
153 __toString = self: "@${self.type} {${name'},${value'}}";
156 /* Returns the GVariant maybe from the given element type.
159 mkMaybe :: gvariant.type -> Any -> gvariant
161 mkMaybe = elemType: elem:
162 mkPrimitive (type.maybeOf elemType) elem // {
164 if self.value == null then
165 "@${self.type} nothing"
167 "just ${toString self.value}";
170 /* Returns the GVariant nothing from the given element type.
173 mkNothing :: gvariant.type -> gvariant
175 mkNothing = elemType: mkMaybe elemType null;
177 /* Returns the GVariant just from the given Nix value.
180 mkJust :: Any -> gvariant
182 mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem;
184 /* Returns the GVariant tuple from the given Nix list.
187 mkTuple :: [Any] -> gvariant
191 gvarElems = map mkValue elems;
192 tupleType = type.tupleOf (map (e: e.type) gvarElems);
194 mkPrimitive tupleType gvarElems // {
196 "@${self.type} (${concatMapStringsSep "," toString self.value})";
199 /* Returns the GVariant boolean from the given Nix bool value.
202 mkBoolean :: Bool -> gvariant
205 mkPrimitive type.boolean v // {
206 __toString = self: if self.value then "true" else "false";
209 /* Returns the GVariant string from the given Nix string value.
212 mkString :: String -> gvariant
215 let sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s);
216 in mkPrimitive type.string v // {
217 __toString = self: "'${sanitize self.value}'";
220 /* Returns the GVariant object path from the given Nix string value.
223 mkObjectpath :: String -> gvariant
226 mkPrimitive type.string v // {
227 __toString = self: "objectpath '${escape [ "'" ] self.value}'";
230 /* Returns the GVariant uchar from the given Nix int value.
233 mkUchar :: Int -> gvariant
235 mkUchar = mkPrimitive type.uchar;
237 /* Returns the GVariant int16 from the given Nix int value.
240 mkInt16 :: Int -> gvariant
242 mkInt16 = mkPrimitive type.int16;
244 /* Returns the GVariant uint16 from the given Nix int value.
247 mkUint16 :: Int -> gvariant
249 mkUint16 = mkPrimitive type.uint16;
251 /* Returns the GVariant int32 from the given Nix int value.
254 mkInt32 :: Int -> gvariant
257 mkPrimitive type.int32 v // {
258 __toString = self: toString self.value;
261 /* Returns the GVariant uint32 from the given Nix int value.
264 mkUint32 :: Int -> gvariant
266 mkUint32 = mkPrimitive type.uint32;
268 /* Returns the GVariant int64 from the given Nix int value.
271 mkInt64 :: Int -> gvariant
273 mkInt64 = mkPrimitive type.int64;
275 /* Returns the GVariant uint64 from the given Nix int value.
278 mkUint64 :: Int -> gvariant
280 mkUint64 = mkPrimitive type.uint64;
282 /* Returns the GVariant double from the given Nix float value.
285 mkDouble :: Float -> gvariant
288 mkPrimitive type.double v // {
289 __toString = self: toString self.value;