typos: 1.16.22 -> 1.16.23
[NixPkgs.git] / lib / gvariant.nix
blob3142ffc5f14943d8a93e37ccb3bf62a71551567c
1 # This file is based on https://github.com/nix-community/home-manager
2 # Copyright (c) 2017-2022 Home Manager contributors
6 { lib }:
8 /* A partial and basic implementation of GVariant formatted strings.
9    See https://docs.gtk.org/glib/gvariant-format-strings.html for detauls.
11    Note, this API is not considered fully stable and it might therefore
12    change in backwards incompatible ways without prior notice.
14 let
15   inherit (lib)
16     concatMapStringsSep concatStrings escape head replaceStrings;
18   mkPrimitive = t: v: {
19     _type = "gvariant";
20     type = t;
21     value = v;
22     __toString = self: "@${self.type} ${toString self.value}"; # https://docs.gtk.org/glib/gvariant-text.html
23   };
25   type = {
26     arrayOf = t: "a${t}";
27     maybeOf = t: "m${t}";
28     tupleOf = ts: "(${concatStrings ts})";
29     dictionaryEntryOf = nameType: valueType: "{${nameType}${valueType}}";
30     string = "s";
31     boolean = "b";
32     uchar = "y";
33     int16 = "n";
34     uint16 = "q";
35     int32 = "i";
36     uint32 = "u";
37     int64 = "x";
38     uint64 = "t";
39     double = "d";
40     variant = "v";
41   };
43   /* Check if a value is a GVariant value
45      Type:
46        isGVariant :: Any -> Bool
47   */
48   isGVariant = v: v._type or "" == "gvariant";
51 rec {
53   inherit type isGVariant;
55   /* Returns the GVariant value that most closely matches the given Nix value.
56      If no GVariant value can be found unambiguously then error is thrown.
58      Type:
59        mkValue :: Any -> gvariant
60   */
61   mkValue = v:
62     if builtins.isBool v then
63       mkBoolean v
64     else if builtins.isFloat v then
65       mkDouble v
66     else if builtins.isString v then
67       mkString v
68     else if builtins.isList v then
69       mkArray v
70     else if isGVariant v then
71       v
72     else
73       throw "The GVariant type of ${v} can't be inferred.";
75   /* Returns the GVariant array from the given type of the elements and a Nix list.
77      Type:
78        mkArray :: [Any] -> gvariant
80      Example:
81        # Creating a string array
82        lib.gvariant.mkArray [ "a" "b" "c" ]
83   */
84   mkArray = elems:
85     let
86       vs = map mkValue (lib.throwIf (elems == [ ]) "Please create empty array with mkEmptyArray." elems);
87       elemType = lib.throwIfNot (lib.all (t: (head vs).type == t) (map (v: v.type) vs))
88         "Elements in a list should have same type."
89         (head vs).type;
90     in
91     mkPrimitive (type.arrayOf elemType) vs // {
92       __toString = self:
93         "@${self.type} [${concatMapStringsSep "," toString self.value}]";
94     };
96   /* Returns the GVariant array from the given empty Nix list.
98      Type:
99        mkEmptyArray :: gvariant.type -> gvariant
101      Example:
102        # Creating an empty string array
103        lib.gvariant.mkEmptyArray (lib.gvariant.type.string)
104   */
105   mkEmptyArray = elemType: mkPrimitive (type.arrayOf elemType) [ ] // {
106     __toString = self: "@${self.type} []";
107   };
110   /* Returns the GVariant variant from the given Nix value. Variants are containers
111      of different GVariant type.
113      Type:
114        mkVariant :: Any -> gvariant
116      Example:
117        lib.gvariant.mkArray [
118          (lib.gvariant.mkVariant "a string")
119          (lib.gvariant.mkVariant (lib.gvariant.mkInt32 1))
120        ]
121   */
122   mkVariant = elem:
123     let gvarElem = mkValue elem;
124     in mkPrimitive type.variant gvarElem // {
125       __toString = self: "<${toString self.value}>";
126     };
128   /* Returns the GVariant dictionary entry from the given key and value.
130      Type:
131        mkDictionaryEntry :: String -> Any -> gvariant
133      Example:
134        # A dictionary describing an Epiphany’s search provider
135        [
136          (lib.gvariant.mkDictionaryEntry "url" (lib.gvariant.mkVariant "https://duckduckgo.com/?q=%s&t=epiphany"))
137          (lib.gvariant.mkDictionaryEntry "bang" (lib.gvariant.mkVariant "!d"))
138          (lib.gvariant.mkDictionaryEntry "name" (lib.gvariant.mkVariant "DuckDuckGo"))
139        ]
140   */
141   mkDictionaryEntry =
142     # The key of the entry
143     name:
144     # The value of the entry
145     value:
146     let
147       name' = mkValue name;
148       value' = mkValue value;
149       dictionaryType = type.dictionaryEntryOf name'.type value'.type;
150     in
151     mkPrimitive dictionaryType { inherit name value; } // {
152       __toString = self: "@${self.type} {${name'},${value'}}";
153     };
155   /* Returns the GVariant maybe from the given element type.
157      Type:
158        mkMaybe :: gvariant.type -> Any -> gvariant
159   */
160   mkMaybe = elemType: elem:
161     mkPrimitive (type.maybeOf elemType) elem // {
162       __toString = self:
163         if self.value == null then
164           "@${self.type} nothing"
165         else
166           "just ${toString self.value}";
167     };
169   /* Returns the GVariant nothing from the given element type.
171      Type:
172        mkNothing :: gvariant.type -> gvariant
173   */
174   mkNothing = elemType: mkMaybe elemType null;
176   /* Returns the GVariant just from the given Nix value.
178      Type:
179        mkJust :: Any -> gvariant
180   */
181   mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem;
183   /* Returns the GVariant tuple from the given Nix list.
185      Type:
186        mkTuple :: [Any] -> gvariant
187   */
188   mkTuple = elems:
189     let
190       gvarElems = map mkValue elems;
191       tupleType = type.tupleOf (map (e: e.type) gvarElems);
192     in
193     mkPrimitive tupleType gvarElems // {
194       __toString = self:
195         "@${self.type} (${concatMapStringsSep "," toString self.value})";
196     };
198   /* Returns the GVariant boolean from the given Nix bool value.
200      Type:
201        mkBoolean :: Bool -> gvariant
202   */
203   mkBoolean = v:
204     mkPrimitive type.boolean v // {
205       __toString = self: if self.value then "true" else "false";
206     };
208   /* Returns the GVariant string from the given Nix string value.
210      Type:
211        mkString :: String -> gvariant
212   */
213   mkString = v:
214     let sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s);
215     in mkPrimitive type.string v // {
216       __toString = self: "'${sanitize self.value}'";
217     };
219   /* Returns the GVariant object path from the given Nix string value.
221      Type:
222        mkObjectpath :: String -> gvariant
223   */
224   mkObjectpath = v:
225     mkPrimitive type.string v // {
226       __toString = self: "objectpath '${escape [ "'" ] self.value}'";
227     };
229   /* Returns the GVariant uchar from the given Nix int value.
231      Type:
232        mkUchar :: Int -> gvariant
233   */
234   mkUchar = mkPrimitive type.uchar;
236   /* Returns the GVariant int16 from the given Nix int value.
238      Type:
239        mkInt16 :: Int -> gvariant
240   */
241   mkInt16 = mkPrimitive type.int16;
243   /* Returns the GVariant uint16 from the given Nix int value.
245      Type:
246        mkUint16 :: Int -> gvariant
247   */
248   mkUint16 = mkPrimitive type.uint16;
250   /* Returns the GVariant int32 from the given Nix int value.
252      Type:
253        mkInt32 :: Int -> gvariant
254   */
255   mkInt32 = v:
256     mkPrimitive type.int32 v // {
257       __toString = self: toString self.value;
258     };
260   /* Returns the GVariant uint32 from the given Nix int value.
262      Type:
263        mkUint32 :: Int -> gvariant
264   */
265   mkUint32 = mkPrimitive type.uint32;
267   /* Returns the GVariant int64 from the given Nix int value.
269      Type:
270        mkInt64 :: Int -> gvariant
271   */
272   mkInt64 = mkPrimitive type.int64;
274   /* Returns the GVariant uint64 from the given Nix int value.
276      Type:
277        mkUint64 :: Int -> gvariant
278   */
279   mkUint64 = mkPrimitive type.uint64;
281   /* Returns the GVariant double from the given Nix float value.
283      Type:
284        mkDouble :: Float -> gvariant
285   */
286   mkDouble = v:
287     mkPrimitive type.double v // {
288       __toString = self: toString self.value;
289     };