glib/variant.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3// rustdoc-stripper-ignore-next
4//! `Variant` binding and helper traits.
5//!
6//! [`Variant`](struct.Variant.html) is an immutable dynamically-typed generic
7//! container. Its type and value are defined at construction and never change.
8//!
9//! `Variant` types are described by [`VariantType`](../struct.VariantType.html)
10//! "type strings".
11//!
12//! `GVariant` supports arbitrarily complex types built from primitives like integers, floating point
13//! numbers, strings, arrays, tuples and dictionaries. See [`ToVariant#foreign-impls`] for
14//! a full list of supported types. You may also implement [`ToVariant`] and [`FromVariant`]
15//! manually, or derive them using the [`Variant`](derive@crate::Variant) derive macro.
16//!
17//! # Examples
18//!
19//! ```
20//! use glib::prelude::*; // or `use gtk::prelude::*;`
21//! use glib::variant::{Variant, FromVariant};
22//! use std::collections::HashMap;
23//!
24//! // Using the `ToVariant` trait.
25//! let num = 10.to_variant();
26//!
27//! // `is` tests the type of the value.
28//! assert!(num.is::<i32>());
29//!
30//! // `get` tries to extract the value.
31//! assert_eq!(num.get::<i32>(), Some(10));
32//! assert_eq!(num.get::<u32>(), None);
33//!
34//! // `get_str` tries to borrow a string slice.
35//! let hello = "Hello!".to_variant();
36//! assert_eq!(hello.str(), Some("Hello!"));
37//! assert_eq!(num.str(), None);
38//!
39//! // `fixed_array` tries to borrow a fixed size array (u8, bool, i16, etc.),
40//! // rather than creating a deep copy which would be expensive for
41//! // nontrivially sized arrays of fixed size elements.
42//! // The test data here is the zstd compression header, which
43//! // stands in for arbitrary binary data (e.g. not UTF-8).
44//! let bufdata = b"\xFD\x2F\xB5\x28";
45//! let bufv = glib::Variant::array_from_fixed_array(&bufdata[..]);
46//! assert_eq!(bufv.fixed_array::<u8>().unwrap(), bufdata);
47//! assert!(num.fixed_array::<u8>().is_err());
48//!
49//! // Variant carrying a Variant
50//! let variant = Variant::from_variant(&hello);
51//! let variant = variant.as_variant().unwrap();
52//! assert_eq!(variant.str(), Some("Hello!"));
53//!
54//! // Variant carrying an array
55//! let array = ["Hello", "there!"];
56//! let variant = array.into_iter().collect::<Variant>();
57//! assert_eq!(variant.n_children(), 2);
58//! assert_eq!(variant.child_value(0).str(), Some("Hello"));
59//! assert_eq!(variant.child_value(1).str(), Some("there!"));
60//!
61//! // You can also convert from and to a Vec
62//! let variant = vec!["Hello", "there!"].to_variant();
63//! assert_eq!(variant.n_children(), 2);
64//! let vec = <Vec<String>>::from_variant(&variant).unwrap();
65//! assert_eq!(vec[0], "Hello");
66//!
67//! // Conversion to and from HashMap and BTreeMap is also possible
68//! let mut map: HashMap<u16, &str> = HashMap::new();
69//! map.insert(1, "hi");
70//! map.insert(2, "there");
71//! let variant = map.to_variant();
72//! assert_eq!(variant.n_children(), 2);
73//! let map: HashMap<u16, String> = HashMap::from_variant(&variant).unwrap();
74//! assert_eq!(map[&1], "hi");
75//! assert_eq!(map[&2], "there");
76//!
77//! // And conversion to and from tuples.
78//! let variant = ("hello", 42u16, vec![ "there", "you" ],).to_variant();
79//! assert_eq!(variant.n_children(), 3);
80//! assert_eq!(variant.type_().as_str(), "(sqas)");
81//! let tuple = <(String, u16, Vec<String>)>::from_variant(&variant).unwrap();
82//! assert_eq!(tuple.0, "hello");
83//! assert_eq!(tuple.1, 42);
84//! assert_eq!(tuple.2, &[ "there", "you"]);
85//!
86//! // `Option` is supported as well, through maybe types
87//! let variant = Some("hello").to_variant();
88//! assert_eq!(variant.n_children(), 1);
89//! let mut s = <Option<String>>::from_variant(&variant).unwrap();
90//! assert_eq!(s.unwrap(), "hello");
91//! s = None;
92//! let variant = s.to_variant();
93//! assert_eq!(variant.n_children(), 0);
94//! let s = <Option<String>>::from_variant(&variant).unwrap();
95//! assert!(s.is_none());
96//!
97//! // Paths may be converted, too. Please note the portability warning above!
98//! use std::path::{Path, PathBuf};
99//! let path = Path::new("foo/bar");
100//! let path_variant = path.to_variant();
101//! assert_eq!(PathBuf::from_variant(&path_variant).as_deref(), Some(path));
102//! ```
103
104use std::{
105 borrow::Cow,
106 cmp::Ordering,
107 collections::{BTreeMap, HashMap},
108 fmt,
109 fmt::Display,
110 hash::{BuildHasher, Hash, Hasher},
111 mem, ptr, slice, str,
112};
113
114use crate::{
115 ffi, gobject_ffi, prelude::*, translate::*, Bytes, Type, VariantIter, VariantStrIter,
116 VariantTy, VariantType,
117};
118
119wrapper! {
120 // rustdoc-stripper-ignore-next
121 /// A generic immutable value capable of carrying various types.
122 ///
123 /// See the [module documentation](index.html) for more details.
124 // rustdoc-stripper-ignore-next-stop
125 /// `GVariant` is a variant datatype; it can contain one or more values
126 /// along with information about the type of the values.
127 ///
128 /// A `GVariant` may contain simple types, like an integer, or a boolean value;
129 /// or complex types, like an array of two strings, or a dictionary of key
130 /// value pairs. A `GVariant` is also immutable: once it’s been created neither
131 /// its type nor its content can be modified further.
132 ///
133 /// `GVariant` is useful whenever data needs to be serialized, for example when
134 /// sending method parameters in D-Bus, or when saving settings using
135 /// [`GSettings`](../gio/class.Settings.html).
136 ///
137 /// When creating a new `GVariant`, you pass the data you want to store in it
138 /// along with a string representing the type of data you wish to pass to it.
139 ///
140 /// For instance, if you want to create a `GVariant` holding an integer value you
141 /// can use:
142 ///
143 /// **⚠️ The following code is in c ⚠️**
144 ///
145 /// ```c
146 /// GVariant *v = g_variant_new ("u", 40);
147 /// ```
148 ///
149 /// The string `u` in the first argument tells `GVariant` that the data passed to
150 /// the constructor (`40`) is going to be an unsigned integer.
151 ///
152 /// More advanced examples of `GVariant` in use can be found in documentation for
153 /// [`GVariant` format strings](gvariant-format-strings.html#pointers).
154 ///
155 /// The range of possible values is determined by the type.
156 ///
157 /// The type system used by `GVariant` is [type@GLib.VariantType].
158 ///
159 /// `GVariant` instances always have a type and a value (which are given
160 /// at construction time). The type and value of a `GVariant` instance
161 /// can never change other than by the `GVariant` itself being
162 /// destroyed. A `GVariant` cannot contain a pointer.
163 ///
164 /// `GVariant` is reference counted using `GLib::Variant::ref()` and
165 /// `GLib::Variant::unref()`. `GVariant` also has floating reference counts —
166 /// see [`ref_sink()`][Self::ref_sink()].
167 ///
168 /// `GVariant` is completely threadsafe. A `GVariant` instance can be
169 /// concurrently accessed in any way from any number of threads without
170 /// problems.
171 ///
172 /// `GVariant` is heavily optimised for dealing with data in serialized
173 /// form. It works particularly well with data located in memory-mapped
174 /// files. It can perform nearly all deserialization operations in a
175 /// small constant time, usually touching only a single memory page.
176 /// Serialized `GVariant` data can also be sent over the network.
177 ///
178 /// `GVariant` is largely compatible with D-Bus. Almost all types of
179 /// `GVariant` instances can be sent over D-Bus. See [type@GLib.VariantType] for
180 /// exceptions. (However, `GVariant`’s serialization format is not the same
181 /// as the serialization format of a D-Bus message body: use
182 /// [GDBusMessage](../gio/class.DBusMessage.html), in the GIO library, for those.)
183 ///
184 /// For space-efficiency, the `GVariant` serialization format does not
185 /// automatically include the variant’s length, type or endianness,
186 /// which must either be implied from context (such as knowledge that a
187 /// particular file format always contains a little-endian
188 /// `G_VARIANT_TYPE_VARIANT` which occupies the whole length of the file)
189 /// or supplied out-of-band (for instance, a length, type and/or endianness
190 /// indicator could be placed at the beginning of a file, network message
191 /// or network stream).
192 ///
193 /// A `GVariant`’s size is limited mainly by any lower level operating
194 /// system constraints, such as the number of bits in `gsize`. For
195 /// example, it is reasonable to have a 2GB file mapped into memory
196 /// with `GLib::MappedFile`, and call `GLib::Variant::new_from_data()` on
197 /// it.
198 ///
199 /// For convenience to C programmers, `GVariant` features powerful
200 /// varargs-based value construction and destruction. This feature is
201 /// designed to be embedded in other libraries.
202 ///
203 /// There is a Python-inspired text language for describing `GVariant`
204 /// values. `GVariant` includes a printer for this language and a parser
205 /// with type inferencing.
206 ///
207 /// ## Memory Use
208 ///
209 /// `GVariant` tries to be quite efficient with respect to memory use.
210 /// This section gives a rough idea of how much memory is used by the
211 /// current implementation. The information here is subject to change
212 /// in the future.
213 ///
214 /// The memory allocated by `GVariant` can be grouped into 4 broad
215 /// purposes: memory for serialized data, memory for the type
216 /// information cache, buffer management memory and memory for the
217 /// `GVariant` structure itself.
218 ///
219 /// ## Serialized Data Memory
220 ///
221 /// This is the memory that is used for storing `GVariant` data in
222 /// serialized form. This is what would be sent over the network or
223 /// what would end up on disk, not counting any indicator of the
224 /// endianness, or of the length or type of the top-level variant.
225 ///
226 /// The amount of memory required to store a boolean is 1 byte. 16,
227 /// 32 and 64 bit integers and double precision floating point numbers
228 /// use their ‘natural’ size. Strings (including object path and
229 /// signature strings) are stored with a nul terminator, and as such
230 /// use the length of the string plus 1 byte.
231 ///
232 /// ‘Maybe’ types use no space at all to represent the null value and
233 /// use the same amount of space (sometimes plus one byte) as the
234 /// equivalent non-maybe-typed value to represent the non-null case.
235 ///
236 /// Arrays use the amount of space required to store each of their
237 /// members, concatenated. Additionally, if the items stored in an
238 /// array are not of a fixed-size (ie: strings, other arrays, etc)
239 /// then an additional framing offset is stored for each item. The
240 /// size of this offset is either 1, 2 or 4 bytes depending on the
241 /// overall size of the container. Additionally, extra padding bytes
242 /// are added as required for alignment of child values.
243 ///
244 /// Tuples (including dictionary entries) use the amount of space
245 /// required to store each of their members, concatenated, plus one
246 /// framing offset (as per arrays) for each non-fixed-sized item in
247 /// the tuple, except for the last one. Additionally, extra padding
248 /// bytes are added as required for alignment of child values.
249 ///
250 /// Variants use the same amount of space as the item inside of the
251 /// variant, plus 1 byte, plus the length of the type string for the
252 /// item inside the variant.
253 ///
254 /// As an example, consider a dictionary mapping strings to variants.
255 /// In the case that the dictionary is empty, 0 bytes are required for
256 /// the serialization.
257 ///
258 /// If we add an item ‘width’ that maps to the int32 value of 500 then
259 /// we will use 4 bytes to store the int32 (so 6 for the variant
260 /// containing it) and 6 bytes for the string. The variant must be
261 /// aligned to 8 after the 6 bytes of the string, so that’s 2 extra
262 /// bytes. 6 (string) + 2 (padding) + 6 (variant) is 14 bytes used
263 /// for the dictionary entry. An additional 1 byte is added to the
264 /// array as a framing offset making a total of 15 bytes.
265 ///
266 /// If we add another entry, ‘title’ that maps to a nullable string
267 /// that happens to have a value of null, then we use 0 bytes for the
268 /// null value (and 3 bytes for the variant to contain it along with
269 /// its type string) plus 6 bytes for the string. Again, we need 2
270 /// padding bytes. That makes a total of 6 + 2 + 3 = 11 bytes.
271 ///
272 /// We now require extra padding between the two items in the array.
273 /// After the 14 bytes of the first item, that’s 2 bytes required.
274 /// We now require 2 framing offsets for an extra two
275 /// bytes. 14 + 2 + 11 + 2 = 29 bytes to encode the entire two-item
276 /// dictionary.
277 ///
278 /// ## Type Information Cache
279 ///
280 /// For each `GVariant` type that currently exists in the program a type
281 /// information structure is kept in the type information cache. The
282 /// type information structure is required for rapid deserialization.
283 ///
284 /// Continuing with the above example, if a `GVariant` exists with the
285 /// type `a{sv}` then a type information struct will exist for
286 /// `a{sv}`, `{sv}`, `s`, and `v`. Multiple uses of the same type
287 /// will share the same type information. Additionally, all
288 /// single-digit types are stored in read-only static memory and do
289 /// not contribute to the writable memory footprint of a program using
290 /// `GVariant`.
291 ///
292 /// Aside from the type information structures stored in read-only
293 /// memory, there are two forms of type information. One is used for
294 /// container types where there is a single element type: arrays and
295 /// maybe types. The other is used for container types where there
296 /// are multiple element types: tuples and dictionary entries.
297 ///
298 /// Array type info structures are `6 * sizeof (void *)`, plus the
299 /// memory required to store the type string itself. This means that
300 /// on 32-bit systems, the cache entry for `a{sv}` would require 30
301 /// bytes of memory (plus allocation overhead).
302 ///
303 /// Tuple type info structures are `6 * sizeof (void *)`, plus `4 *
304 /// sizeof (void *)` for each item in the tuple, plus the memory
305 /// required to store the type string itself. A 2-item tuple, for
306 /// example, would have a type information structure that consumed
307 /// writable memory in the size of `14 * sizeof (void *)` (plus type
308 /// string) This means that on 32-bit systems, the cache entry for
309 /// `{sv}` would require 61 bytes of memory (plus allocation overhead).
310 ///
311 /// This means that in total, for our `a{sv}` example, 91 bytes of
312 /// type information would be allocated.
313 ///
314 /// The type information cache, additionally, uses a `GLib::HashTable` to
315 /// store and look up the cached items and stores a pointer to this
316 /// hash table in static storage. The hash table is freed when there
317 /// are zero items in the type cache.
318 ///
319 /// Although these sizes may seem large it is important to remember
320 /// that a program will probably only have a very small number of
321 /// different types of values in it and that only one type information
322 /// structure is required for many different values of the same type.
323 ///
324 /// ## Buffer Management Memory
325 ///
326 /// `GVariant` uses an internal buffer management structure to deal
327 /// with the various different possible sources of serialized data
328 /// that it uses. The buffer is responsible for ensuring that the
329 /// correct call is made when the data is no longer in use by
330 /// `GVariant`. This may involve a `free()` or
331 /// even `GLib::MappedFile::unref()`.
332 ///
333 /// One buffer management structure is used for each chunk of
334 /// serialized data. The size of the buffer management structure
335 /// is `4 * (void *)`. On 32-bit systems, that’s 16 bytes.
336 ///
337 /// ## GVariant structure
338 ///
339 /// The size of a `GVariant` structure is `6 * (void *)`. On 32-bit
340 /// systems, that’s 24 bytes.
341 ///
342 /// `GVariant` structures only exist if they are explicitly created
343 /// with API calls. For example, if a `GVariant` is constructed out of
344 /// serialized data for the example given above (with the dictionary)
345 /// then although there are 9 individual values that comprise the
346 /// entire dictionary (two keys, two values, two variants containing
347 /// the values, two dictionary entries, plus the dictionary itself),
348 /// only 1 `GVariant` instance exists — the one referring to the
349 /// dictionary.
350 ///
351 /// If calls are made to start accessing the other values then
352 /// `GVariant` instances will exist for those values only for as long
353 /// as they are in use (ie: until you call `GLib::Variant::unref()`). The
354 /// type information is shared. The serialized data and the buffer
355 /// management structure for that serialized data is shared by the
356 /// child.
357 ///
358 /// ## Summary
359 ///
360 /// To put the entire example together, for our dictionary mapping
361 /// strings to variants (with two entries, as given above), we are
362 /// using 91 bytes of memory for type information, 29 bytes of memory
363 /// for the serialized data, 16 bytes for buffer management and 24
364 /// bytes for the `GVariant` instance, or a total of 160 bytes, plus
365 /// allocation overhead. If we were to use [`child_value()`][Self::child_value()]
366 /// to access the two dictionary entries, we would use an additional 48
367 /// bytes. If we were to have other dictionaries of the same type, we
368 /// would use more memory for the serialized data and buffer
369 /// management for those dictionaries, but the type information would
370 /// be shared.
371 // rustdoc-stripper-ignore-next-stop
372 /// `GVariant` is a variant datatype; it can contain one or more values
373 /// along with information about the type of the values.
374 ///
375 /// A `GVariant` may contain simple types, like an integer, or a boolean value;
376 /// or complex types, like an array of two strings, or a dictionary of key
377 /// value pairs. A `GVariant` is also immutable: once it’s been created neither
378 /// its type nor its content can be modified further.
379 ///
380 /// `GVariant` is useful whenever data needs to be serialized, for example when
381 /// sending method parameters in D-Bus, or when saving settings using
382 /// [`GSettings`](../gio/class.Settings.html).
383 ///
384 /// When creating a new `GVariant`, you pass the data you want to store in it
385 /// along with a string representing the type of data you wish to pass to it.
386 ///
387 /// For instance, if you want to create a `GVariant` holding an integer value you
388 /// can use:
389 ///
390 /// **⚠️ The following code is in c ⚠️**
391 ///
392 /// ```c
393 /// GVariant *v = g_variant_new ("u", 40);
394 /// ```
395 ///
396 /// The string `u` in the first argument tells `GVariant` that the data passed to
397 /// the constructor (`40`) is going to be an unsigned integer.
398 ///
399 /// More advanced examples of `GVariant` in use can be found in documentation for
400 /// [`GVariant` format strings](gvariant-format-strings.html#pointers).
401 ///
402 /// The range of possible values is determined by the type.
403 ///
404 /// The type system used by `GVariant` is [type@GLib.VariantType].
405 ///
406 /// `GVariant` instances always have a type and a value (which are given
407 /// at construction time). The type and value of a `GVariant` instance
408 /// can never change other than by the `GVariant` itself being
409 /// destroyed. A `GVariant` cannot contain a pointer.
410 ///
411 /// `GVariant` is reference counted using `GLib::Variant::ref()` and
412 /// `GLib::Variant::unref()`. `GVariant` also has floating reference counts —
413 /// see [`ref_sink()`][Self::ref_sink()].
414 ///
415 /// `GVariant` is completely threadsafe. A `GVariant` instance can be
416 /// concurrently accessed in any way from any number of threads without
417 /// problems.
418 ///
419 /// `GVariant` is heavily optimised for dealing with data in serialized
420 /// form. It works particularly well with data located in memory-mapped
421 /// files. It can perform nearly all deserialization operations in a
422 /// small constant time, usually touching only a single memory page.
423 /// Serialized `GVariant` data can also be sent over the network.
424 ///
425 /// `GVariant` is largely compatible with D-Bus. Almost all types of
426 /// `GVariant` instances can be sent over D-Bus. See [type@GLib.VariantType] for
427 /// exceptions. (However, `GVariant`’s serialization format is not the same
428 /// as the serialization format of a D-Bus message body: use
429 /// [GDBusMessage](../gio/class.DBusMessage.html), in the GIO library, for those.)
430 ///
431 /// For space-efficiency, the `GVariant` serialization format does not
432 /// automatically include the variant’s length, type or endianness,
433 /// which must either be implied from context (such as knowledge that a
434 /// particular file format always contains a little-endian
435 /// `G_VARIANT_TYPE_VARIANT` which occupies the whole length of the file)
436 /// or supplied out-of-band (for instance, a length, type and/or endianness
437 /// indicator could be placed at the beginning of a file, network message
438 /// or network stream).
439 ///
440 /// A `GVariant`’s size is limited mainly by any lower level operating
441 /// system constraints, such as the number of bits in `gsize`. For
442 /// example, it is reasonable to have a 2GB file mapped into memory
443 /// with `GLib::MappedFile`, and call `GLib::Variant::new_from_data()` on
444 /// it.
445 ///
446 /// For convenience to C programmers, `GVariant` features powerful
447 /// varargs-based value construction and destruction. This feature is
448 /// designed to be embedded in other libraries.
449 ///
450 /// There is a Python-inspired text language for describing `GVariant`
451 /// values. `GVariant` includes a printer for this language and a parser
452 /// with type inferencing.
453 ///
454 /// ## Memory Use
455 ///
456 /// `GVariant` tries to be quite efficient with respect to memory use.
457 /// This section gives a rough idea of how much memory is used by the
458 /// current implementation. The information here is subject to change
459 /// in the future.
460 ///
461 /// The memory allocated by `GVariant` can be grouped into 4 broad
462 /// purposes: memory for serialized data, memory for the type
463 /// information cache, buffer management memory and memory for the
464 /// `GVariant` structure itself.
465 ///
466 /// ## Serialized Data Memory
467 ///
468 /// This is the memory that is used for storing `GVariant` data in
469 /// serialized form. This is what would be sent over the network or
470 /// what would end up on disk, not counting any indicator of the
471 /// endianness, or of the length or type of the top-level variant.
472 ///
473 /// The amount of memory required to store a boolean is 1 byte. 16,
474 /// 32 and 64 bit integers and double precision floating point numbers
475 /// use their ‘natural’ size. Strings (including object path and
476 /// signature strings) are stored with a nul terminator, and as such
477 /// use the length of the string plus 1 byte.
478 ///
479 /// ‘Maybe’ types use no space at all to represent the null value and
480 /// use the same amount of space (sometimes plus one byte) as the
481 /// equivalent non-maybe-typed value to represent the non-null case.
482 ///
483 /// Arrays use the amount of space required to store each of their
484 /// members, concatenated. Additionally, if the items stored in an
485 /// array are not of a fixed-size (ie: strings, other arrays, etc)
486 /// then an additional framing offset is stored for each item. The
487 /// size of this offset is either 1, 2 or 4 bytes depending on the
488 /// overall size of the container. Additionally, extra padding bytes
489 /// are added as required for alignment of child values.
490 ///
491 /// Tuples (including dictionary entries) use the amount of space
492 /// required to store each of their members, concatenated, plus one
493 /// framing offset (as per arrays) for each non-fixed-sized item in
494 /// the tuple, except for the last one. Additionally, extra padding
495 /// bytes are added as required for alignment of child values.
496 ///
497 /// Variants use the same amount of space as the item inside of the
498 /// variant, plus 1 byte, plus the length of the type string for the
499 /// item inside the variant.
500 ///
501 /// As an example, consider a dictionary mapping strings to variants.
502 /// In the case that the dictionary is empty, 0 bytes are required for
503 /// the serialization.
504 ///
505 /// If we add an item ‘width’ that maps to the int32 value of 500 then
506 /// we will use 4 bytes to store the int32 (so 6 for the variant
507 /// containing it) and 6 bytes for the string. The variant must be
508 /// aligned to 8 after the 6 bytes of the string, so that’s 2 extra
509 /// bytes. 6 (string) + 2 (padding) + 6 (variant) is 14 bytes used
510 /// for the dictionary entry. An additional 1 byte is added to the
511 /// array as a framing offset making a total of 15 bytes.
512 ///
513 /// If we add another entry, ‘title’ that maps to a nullable string
514 /// that happens to have a value of null, then we use 0 bytes for the
515 /// null value (and 3 bytes for the variant to contain it along with
516 /// its type string) plus 6 bytes for the string. Again, we need 2
517 /// padding bytes. That makes a total of 6 + 2 + 3 = 11 bytes.
518 ///
519 /// We now require extra padding between the two items in the array.
520 /// After the 14 bytes of the first item, that’s 2 bytes required.
521 /// We now require 2 framing offsets for an extra two
522 /// bytes. 14 + 2 + 11 + 2 = 29 bytes to encode the entire two-item
523 /// dictionary.
524 ///
525 /// ## Type Information Cache
526 ///
527 /// For each `GVariant` type that currently exists in the program a type
528 /// information structure is kept in the type information cache. The
529 /// type information structure is required for rapid deserialization.
530 ///
531 /// Continuing with the above example, if a `GVariant` exists with the
532 /// type `a{sv}` then a type information struct will exist for
533 /// `a{sv}`, `{sv}`, `s`, and `v`. Multiple uses of the same type
534 /// will share the same type information. Additionally, all
535 /// single-digit types are stored in read-only static memory and do
536 /// not contribute to the writable memory footprint of a program using
537 /// `GVariant`.
538 ///
539 /// Aside from the type information structures stored in read-only
540 /// memory, there are two forms of type information. One is used for
541 /// container types where there is a single element type: arrays and
542 /// maybe types. The other is used for container types where there
543 /// are multiple element types: tuples and dictionary entries.
544 ///
545 /// Array type info structures are `6 * sizeof (void *)`, plus the
546 /// memory required to store the type string itself. This means that
547 /// on 32-bit systems, the cache entry for `a{sv}` would require 30
548 /// bytes of memory (plus allocation overhead).
549 ///
550 /// Tuple type info structures are `6 * sizeof (void *)`, plus `4 *
551 /// sizeof (void *)` for each item in the tuple, plus the memory
552 /// required to store the type string itself. A 2-item tuple, for
553 /// example, would have a type information structure that consumed
554 /// writable memory in the size of `14 * sizeof (void *)` (plus type
555 /// string) This means that on 32-bit systems, the cache entry for
556 /// `{sv}` would require 61 bytes of memory (plus allocation overhead).
557 ///
558 /// This means that in total, for our `a{sv}` example, 91 bytes of
559 /// type information would be allocated.
560 ///
561 /// The type information cache, additionally, uses a `GLib::HashTable` to
562 /// store and look up the cached items and stores a pointer to this
563 /// hash table in static storage. The hash table is freed when there
564 /// are zero items in the type cache.
565 ///
566 /// Although these sizes may seem large it is important to remember
567 /// that a program will probably only have a very small number of
568 /// different types of values in it and that only one type information
569 /// structure is required for many different values of the same type.
570 ///
571 /// ## Buffer Management Memory
572 ///
573 /// `GVariant` uses an internal buffer management structure to deal
574 /// with the various different possible sources of serialized data
575 /// that it uses. The buffer is responsible for ensuring that the
576 /// correct call is made when the data is no longer in use by
577 /// `GVariant`. This may involve a `free()` or
578 /// even `GLib::MappedFile::unref()`.
579 ///
580 /// One buffer management structure is used for each chunk of
581 /// serialized data. The size of the buffer management structure
582 /// is `4 * (void *)`. On 32-bit systems, that’s 16 bytes.
583 ///
584 /// ## GVariant structure
585 ///
586 /// The size of a `GVariant` structure is `6 * (void *)`. On 32-bit
587 /// systems, that’s 24 bytes.
588 ///
589 /// `GVariant` structures only exist if they are explicitly created
590 /// with API calls. For example, if a `GVariant` is constructed out of
591 /// serialized data for the example given above (with the dictionary)
592 /// then although there are 9 individual values that comprise the
593 /// entire dictionary (two keys, two values, two variants containing
594 /// the values, two dictionary entries, plus the dictionary itself),
595 /// only 1 `GVariant` instance exists — the one referring to the
596 /// dictionary.
597 ///
598 /// If calls are made to start accessing the other values then
599 /// `GVariant` instances will exist for those values only for as long
600 /// as they are in use (ie: until you call `GLib::Variant::unref()`). The
601 /// type information is shared. The serialized data and the buffer
602 /// management structure for that serialized data is shared by the
603 /// child.
604 ///
605 /// ## Summary
606 ///
607 /// To put the entire example together, for our dictionary mapping
608 /// strings to variants (with two entries, as given above), we are
609 /// using 91 bytes of memory for type information, 29 bytes of memory
610 /// for the serialized data, 16 bytes for buffer management and 24
611 /// bytes for the `GVariant` instance, or a total of 160 bytes, plus
612 /// allocation overhead. If we were to use [`child_value()`][Self::child_value()]
613 /// to access the two dictionary entries, we would use an additional 48
614 /// bytes. If we were to have other dictionaries of the same type, we
615 /// would use more memory for the serialized data and buffer
616 /// management for those dictionaries, but the type information would
617 /// be shared.
618 #[doc(alias = "GVariant")]
619 pub struct Variant(Shared<ffi::GVariant>);
620
621 match fn {
622 ref => |ptr| ffi::g_variant_ref_sink(ptr),
623 unref => |ptr| ffi::g_variant_unref(ptr),
624 }
625}
626
627impl StaticType for Variant {
628 #[inline]
629 fn static_type() -> Type {
630 Type::VARIANT
631 }
632}
633
634#[doc(hidden)]
635impl crate::value::ValueType for Variant {
636 type Type = Variant;
637}
638
639#[doc(hidden)]
640impl crate::value::ValueTypeOptional for Variant {}
641
642#[doc(hidden)]
643unsafe impl<'a> crate::value::FromValue<'a> for Variant {
644 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
645
646 unsafe fn from_value(value: &'a crate::Value) -> Self {
647 let ptr = gobject_ffi::g_value_dup_variant(value.to_glib_none().0);
648 debug_assert!(!ptr.is_null());
649 from_glib_full(ptr)
650 }
651}
652
653#[doc(hidden)]
654impl crate::value::ToValue for Variant {
655 fn to_value(&self) -> crate::Value {
656 unsafe {
657 let mut value = crate::Value::from_type_unchecked(Variant::static_type());
658 gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, self.to_glib_full());
659 value
660 }
661 }
662
663 fn value_type(&self) -> crate::Type {
664 Variant::static_type()
665 }
666}
667
668#[doc(hidden)]
669impl From<Variant> for crate::Value {
670 #[inline]
671 fn from(v: Variant) -> Self {
672 unsafe {
673 let mut value = crate::Value::from_type_unchecked(Variant::static_type());
674 gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, v.into_glib_ptr());
675 value
676 }
677 }
678}
679
680#[doc(hidden)]
681impl crate::value::ToValueOptional for Variant {
682 fn to_value_optional(s: Option<&Self>) -> crate::Value {
683 let mut value = crate::Value::for_value_type::<Self>();
684 unsafe {
685 gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, s.to_glib_full());
686 }
687
688 value
689 }
690}
691
692// rustdoc-stripper-ignore-next
693/// An error returned from the [`try_get`](struct.Variant.html#method.try_get) function
694/// on a [`Variant`](struct.Variant.html) when the expected type does not match the actual type.
695#[derive(Clone, PartialEq, Eq, Debug)]
696pub struct VariantTypeMismatchError {
697 pub actual: VariantType,
698 pub expected: VariantType,
699}
700
701impl VariantTypeMismatchError {
702 pub fn new(actual: VariantType, expected: VariantType) -> Self {
703 Self { actual, expected }
704 }
705}
706
707impl fmt::Display for VariantTypeMismatchError {
708 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
709 write!(
710 f,
711 "Type mismatch: Expected '{}' got '{}'",
712 self.expected, self.actual
713 )
714 }
715}
716
717impl std::error::Error for VariantTypeMismatchError {}
718
719impl Variant {
720 // rustdoc-stripper-ignore-next
721 /// Returns the type of the value.
722 // rustdoc-stripper-ignore-next-stop
723 /// Determines the type of @self.
724 ///
725 /// The return value is valid for the lifetime of @self and must not
726 /// be freed.
727 ///
728 /// # Returns
729 ///
730 /// a #GVariantType
731 // rustdoc-stripper-ignore-next-stop
732 /// Determines the type of @self.
733 ///
734 /// The return value is valid for the lifetime of @self and must not
735 /// be freed.
736 ///
737 /// # Returns
738 ///
739 /// a #GVariantType
740 #[doc(alias = "g_variant_get_type")]
741 pub fn type_(&self) -> &VariantTy {
742 unsafe { VariantTy::from_ptr(ffi::g_variant_get_type(self.to_glib_none().0)) }
743 }
744
745 // rustdoc-stripper-ignore-next
746 /// Returns `true` if the type of the value corresponds to `T`.
747 #[inline]
748 #[doc(alias = "g_variant_is_of_type")]
749 pub fn is<T: StaticVariantType>(&self) -> bool {
750 self.is_type(&T::static_variant_type())
751 }
752
753 // rustdoc-stripper-ignore-next
754 /// Returns `true` if the type of the value corresponds to `type_`.
755 ///
756 /// This is equivalent to [`self.type_().is_subtype_of(type_)`](VariantTy::is_subtype_of).
757 #[inline]
758 #[doc(alias = "g_variant_is_of_type")]
759 pub fn is_type(&self, type_: &VariantTy) -> bool {
760 unsafe {
761 from_glib(ffi::g_variant_is_of_type(
762 self.to_glib_none().0,
763 type_.to_glib_none().0,
764 ))
765 }
766 }
767
768 // rustdoc-stripper-ignore-next
769 /// Returns the classification of the variant.
770 // rustdoc-stripper-ignore-next-stop
771 /// Classifies @self according to its top-level type.
772 ///
773 /// # Returns
774 ///
775 /// the #GVariantClass of @self
776 // rustdoc-stripper-ignore-next-stop
777 /// Classifies @self according to its top-level type.
778 ///
779 /// # Returns
780 ///
781 /// the #GVariantClass of @self
782 #[doc(alias = "g_variant_classify")]
783 pub fn classify(&self) -> crate::VariantClass {
784 unsafe { from_glib(ffi::g_variant_classify(self.to_glib_none().0)) }
785 }
786
787 // rustdoc-stripper-ignore-next
788 /// Tries to extract a value of type `T`.
789 ///
790 /// Returns `Some` if `T` matches the variant's type.
791 // rustdoc-stripper-ignore-next-stop
792 /// Deconstructs a #GVariant instance.
793 ///
794 /// Think of this function as an analogue to scanf().
795 ///
796 /// The arguments that are expected by this function are entirely
797 /// determined by @format_string. @format_string also restricts the
798 /// permissible types of @self. It is an error to give a value with
799 /// an incompatible type. See the section on
800 /// [GVariant format strings](gvariant-format-strings.html).
801 /// Please note that the syntax of the format string is very likely to be
802 /// extended in the future.
803 ///
804 /// @format_string determines the C types that are used for unpacking
805 /// the values and also determines if the values are copied or borrowed,
806 /// see the section on
807 /// [`GVariant` format strings](gvariant-format-strings.html#pointers).
808 /// ## `format_string`
809 /// a #GVariant format string
810 // rustdoc-stripper-ignore-next-stop
811 /// Deconstructs a #GVariant instance.
812 ///
813 /// Think of this function as an analogue to scanf().
814 ///
815 /// The arguments that are expected by this function are entirely
816 /// determined by @format_string. @format_string also restricts the
817 /// permissible types of @self. It is an error to give a value with
818 /// an incompatible type. See the section on
819 /// [GVariant format strings](gvariant-format-strings.html).
820 /// Please note that the syntax of the format string is very likely to be
821 /// extended in the future.
822 ///
823 /// @format_string determines the C types that are used for unpacking
824 /// the values and also determines if the values are copied or borrowed,
825 /// see the section on
826 /// [`GVariant` format strings](gvariant-format-strings.html#pointers).
827 /// ## `format_string`
828 /// a #GVariant format string
829 #[inline]
830 pub fn get<T: FromVariant>(&self) -> Option<T> {
831 T::from_variant(self)
832 }
833
834 // rustdoc-stripper-ignore-next
835 /// Tries to extract a value of type `T`.
836 pub fn try_get<T: FromVariant>(&self) -> Result<T, VariantTypeMismatchError> {
837 self.get().ok_or_else(|| {
838 VariantTypeMismatchError::new(
839 self.type_().to_owned(),
840 T::static_variant_type().into_owned(),
841 )
842 })
843 }
844
845 // rustdoc-stripper-ignore-next
846 /// Boxes value.
847 #[inline]
848 pub fn from_variant(value: &Variant) -> Self {
849 unsafe { from_glib_none(ffi::g_variant_new_variant(value.to_glib_none().0)) }
850 }
851
852 // rustdoc-stripper-ignore-next
853 /// Unboxes self.
854 ///
855 /// Returns `Some` if self contains a `Variant`.
856 #[inline]
857 #[doc(alias = "get_variant")]
858 pub fn as_variant(&self) -> Option<Variant> {
859 unsafe { from_glib_full(ffi::g_variant_get_variant(self.to_glib_none().0)) }
860 }
861
862 // rustdoc-stripper-ignore-next
863 /// Reads a child item out of a container `Variant` instance.
864 ///
865 /// # Panics
866 ///
867 /// * if `self` is not a container type.
868 /// * if given `index` is larger than number of children.
869 // rustdoc-stripper-ignore-next-stop
870 /// Reads a child item out of a container #GVariant instance. This
871 /// includes variants, maybes, arrays, tuples and dictionary
872 /// entries. It is an error to call this function on any other type of
873 /// #GVariant.
874 ///
875 /// It is an error if @index_ is greater than the number of child items
876 /// in the container. See g_variant_n_children().
877 ///
878 /// The returned value is never floating. You should free it with
879 /// g_variant_unref() when you're done with it.
880 ///
881 /// Note that values borrowed from the returned child are not guaranteed to
882 /// still be valid after the child is freed even if you still hold a reference
883 /// to @self, if @self has not been serialized at the time this function is
884 /// called. To avoid this, you can serialize @self by calling
885 /// g_variant_get_data() and optionally ignoring the return value.
886 ///
887 /// There may be implementation specific restrictions on deeply nested values,
888 /// which would result in the unit tuple being returned as the child value,
889 /// instead of further nested children. #GVariant is guaranteed to handle
890 /// nesting up to at least 64 levels.
891 ///
892 /// This function is O(1).
893 /// ## `index_`
894 /// the index of the child to fetch
895 ///
896 /// # Returns
897 ///
898 /// the child at the specified index
899 // rustdoc-stripper-ignore-next-stop
900 /// Reads a child item out of a container #GVariant instance. This
901 /// includes variants, maybes, arrays, tuples and dictionary
902 /// entries. It is an error to call this function on any other type of
903 /// #GVariant.
904 ///
905 /// It is an error if @index_ is greater than the number of child items
906 /// in the container. See g_variant_n_children().
907 ///
908 /// The returned value is never floating. You should free it with
909 /// g_variant_unref() when you're done with it.
910 ///
911 /// Note that values borrowed from the returned child are not guaranteed to
912 /// still be valid after the child is freed even if you still hold a reference
913 /// to @self, if @self has not been serialized at the time this function is
914 /// called. To avoid this, you can serialize @self by calling
915 /// g_variant_get_data() and optionally ignoring the return value.
916 ///
917 /// There may be implementation specific restrictions on deeply nested values,
918 /// which would result in the unit tuple being returned as the child value,
919 /// instead of further nested children. #GVariant is guaranteed to handle
920 /// nesting up to at least 64 levels.
921 ///
922 /// This function is O(1).
923 /// ## `index_`
924 /// the index of the child to fetch
925 ///
926 /// # Returns
927 ///
928 /// the child at the specified index
929 #[doc(alias = "get_child_value")]
930 #[doc(alias = "g_variant_get_child_value")]
931 #[must_use]
932 pub fn child_value(&self, index: usize) -> Variant {
933 assert!(self.is_container());
934 assert!(index < self.n_children());
935
936 unsafe { from_glib_full(ffi::g_variant_get_child_value(self.to_glib_none().0, index)) }
937 }
938
939 // rustdoc-stripper-ignore-next
940 /// Try to read a child item out of a container `Variant` instance.
941 ///
942 /// It returns `None` if `self` is not a container type or if the given
943 /// `index` is larger than number of children.
944 pub fn try_child_value(&self, index: usize) -> Option<Variant> {
945 if !(self.is_container() && index < self.n_children()) {
946 return None;
947 }
948
949 let v =
950 unsafe { from_glib_full(ffi::g_variant_get_child_value(self.to_glib_none().0, index)) };
951 Some(v)
952 }
953
954 // rustdoc-stripper-ignore-next
955 /// Try to read a child item out of a container `Variant` instance.
956 ///
957 /// It returns `Ok(None)` if `self` is not a container type or if the given
958 /// `index` is larger than number of children. An error is thrown if the
959 /// type does not match.
960 pub fn try_child_get<T: StaticVariantType + FromVariant>(
961 &self,
962 index: usize,
963 ) -> Result<Option<T>, VariantTypeMismatchError> {
964 // TODO: In the future optimize this by using g_variant_get_child()
965 // directly to avoid allocating a GVariant.
966 self.try_child_value(index).map(|v| v.try_get()).transpose()
967 }
968
969 // rustdoc-stripper-ignore-next
970 /// Read a child item out of a container `Variant` instance.
971 ///
972 /// # Panics
973 ///
974 /// * if `self` is not a container type.
975 /// * if given `index` is larger than number of children.
976 /// * if the expected variant type does not match
977 pub fn child_get<T: StaticVariantType + FromVariant>(&self, index: usize) -> T {
978 // TODO: In the future optimize this by using g_variant_get_child()
979 // directly to avoid allocating a GVariant.
980 self.child_value(index).get().unwrap()
981 }
982
983 // rustdoc-stripper-ignore-next
984 /// Tries to extract a `&str`.
985 ///
986 /// Returns `Some` if the variant has a string type (`s`, `o` or `g` type
987 /// strings).
988 #[doc(alias = "get_str")]
989 #[doc(alias = "g_variant_get_string")]
990 pub fn str(&self) -> Option<&str> {
991 unsafe {
992 match self.type_().as_str() {
993 "s" | "o" | "g" => {
994 let mut len = 0;
995 let ptr = ffi::g_variant_get_string(self.to_glib_none().0, &mut len);
996 if len == 0 {
997 Some("")
998 } else {
999 let ret = str::from_utf8_unchecked(slice::from_raw_parts(
1000 ptr as *const u8,
1001 len as _,
1002 ));
1003 Some(ret)
1004 }
1005 }
1006 _ => None,
1007 }
1008 }
1009 }
1010
1011 // rustdoc-stripper-ignore-next
1012 /// Tries to extract a `&[T]` from a variant of array type with a suitable element type.
1013 ///
1014 /// Returns an error if the type is wrong.
1015 // rustdoc-stripper-ignore-next-stop
1016 /// Provides access to the serialized data for an array of fixed-sized
1017 /// items.
1018 ///
1019 /// @self must be an array with fixed-sized elements. Numeric types are
1020 /// fixed-size, as are tuples containing only other fixed-sized types.
1021 ///
1022 /// @element_size must be the size of a single element in the array,
1023 /// as given by the section on
1024 /// [serialized data memory](struct.Variant.html#serialized-data-memory).
1025 ///
1026 /// In particular, arrays of these fixed-sized types can be interpreted
1027 /// as an array of the given C type, with @element_size set to the size
1028 /// the appropriate type:
1029 /// - `G_VARIANT_TYPE_INT16` (etc.): #gint16 (etc.)
1030 /// - `G_VARIANT_TYPE_BOOLEAN`: #guchar (not #gboolean!)
1031 /// - `G_VARIANT_TYPE_BYTE`: #guint8
1032 /// - `G_VARIANT_TYPE_HANDLE`: #guint32
1033 /// - `G_VARIANT_TYPE_DOUBLE`: #gdouble
1034 ///
1035 /// For example, if calling this function for an array of 32-bit integers,
1036 /// you might say `sizeof(gint32)`. This value isn't used except for the purpose
1037 /// of a double-check that the form of the serialized data matches the caller's
1038 /// expectation.
1039 ///
1040 /// @n_elements, which must be non-[`None`], is set equal to the number of
1041 /// items in the array.
1042 /// ## `element_size`
1043 /// the size of each element
1044 ///
1045 /// # Returns
1046 ///
1047 /// a pointer to
1048 /// the fixed array
1049 // rustdoc-stripper-ignore-next-stop
1050 /// Provides access to the serialized data for an array of fixed-sized
1051 /// items.
1052 ///
1053 /// @self must be an array with fixed-sized elements. Numeric types are
1054 /// fixed-size, as are tuples containing only other fixed-sized types.
1055 ///
1056 /// @element_size must be the size of a single element in the array,
1057 /// as given by the section on
1058 /// [serialized data memory](struct.Variant.html#serialized-data-memory).
1059 ///
1060 /// In particular, arrays of these fixed-sized types can be interpreted
1061 /// as an array of the given C type, with @element_size set to the size
1062 /// the appropriate type:
1063 /// - `G_VARIANT_TYPE_INT16` (etc.): #gint16 (etc.)
1064 /// - `G_VARIANT_TYPE_BOOLEAN`: #guchar (not #gboolean!)
1065 /// - `G_VARIANT_TYPE_BYTE`: #guint8
1066 /// - `G_VARIANT_TYPE_HANDLE`: #guint32
1067 /// - `G_VARIANT_TYPE_DOUBLE`: #gdouble
1068 ///
1069 /// For example, if calling this function for an array of 32-bit integers,
1070 /// you might say `sizeof(gint32)`. This value isn't used except for the purpose
1071 /// of a double-check that the form of the serialized data matches the caller's
1072 /// expectation.
1073 ///
1074 /// @n_elements, which must be non-[`None`], is set equal to the number of
1075 /// items in the array.
1076 /// ## `element_size`
1077 /// the size of each element
1078 ///
1079 /// # Returns
1080 ///
1081 /// a pointer to
1082 /// the fixed array
1083 #[doc(alias = "g_variant_get_fixed_array")]
1084 pub fn fixed_array<T: FixedSizeVariantType>(&self) -> Result<&[T], VariantTypeMismatchError> {
1085 unsafe {
1086 let expected_ty = T::static_variant_type().as_array();
1087 if self.type_() != expected_ty {
1088 return Err(VariantTypeMismatchError {
1089 actual: self.type_().to_owned(),
1090 expected: expected_ty.into_owned(),
1091 });
1092 }
1093
1094 let mut n_elements = mem::MaybeUninit::uninit();
1095 let ptr = ffi::g_variant_get_fixed_array(
1096 self.to_glib_none().0,
1097 n_elements.as_mut_ptr(),
1098 mem::size_of::<T>(),
1099 );
1100
1101 let n_elements = n_elements.assume_init();
1102 if n_elements == 0 {
1103 Ok(&[])
1104 } else {
1105 debug_assert!(!ptr.is_null());
1106 Ok(slice::from_raw_parts(ptr as *const T, n_elements))
1107 }
1108 }
1109 }
1110
1111 // rustdoc-stripper-ignore-next
1112 /// Creates a new Variant array from children.
1113 ///
1114 /// # Panics
1115 ///
1116 /// This function panics if not all variants are of type `T`.
1117 #[doc(alias = "g_variant_new_array")]
1118 pub fn array_from_iter<T: StaticVariantType>(
1119 children: impl IntoIterator<Item = Variant>,
1120 ) -> Self {
1121 Self::array_from_iter_with_type(&T::static_variant_type(), children)
1122 }
1123
1124 // rustdoc-stripper-ignore-next
1125 /// Creates a new Variant array from children with the specified type.
1126 ///
1127 /// # Panics
1128 ///
1129 /// This function panics if not all variants are of type `type_`.
1130 #[doc(alias = "g_variant_new_array")]
1131 pub fn array_from_iter_with_type(
1132 type_: &VariantTy,
1133 children: impl IntoIterator<Item = impl AsRef<Variant>>,
1134 ) -> Self {
1135 unsafe {
1136 let mut builder = mem::MaybeUninit::uninit();
1137 ffi::g_variant_builder_init(builder.as_mut_ptr(), type_.as_array().to_glib_none().0);
1138 let mut builder = builder.assume_init();
1139 for value in children.into_iter() {
1140 let value = value.as_ref();
1141 if ffi::g_variant_is_of_type(value.to_glib_none().0, type_.to_glib_none().0)
1142 == ffi::GFALSE
1143 {
1144 ffi::g_variant_builder_clear(&mut builder);
1145 assert!(value.is_type(type_));
1146 }
1147
1148 ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
1149 }
1150 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1151 }
1152 }
1153
1154 // rustdoc-stripper-ignore-next
1155 /// Creates a new Variant array from a fixed array.
1156 #[doc(alias = "g_variant_new_fixed_array")]
1157 pub fn array_from_fixed_array<T: FixedSizeVariantType>(array: &[T]) -> Self {
1158 let type_ = T::static_variant_type();
1159
1160 unsafe {
1161 from_glib_none(ffi::g_variant_new_fixed_array(
1162 type_.as_ptr(),
1163 array.as_ptr() as ffi::gconstpointer,
1164 array.len(),
1165 mem::size_of::<T>(),
1166 ))
1167 }
1168 }
1169
1170 // rustdoc-stripper-ignore-next
1171 /// Creates a new Variant tuple from children.
1172 #[doc(alias = "g_variant_new_tuple")]
1173 pub fn tuple_from_iter(children: impl IntoIterator<Item = impl AsRef<Variant>>) -> Self {
1174 unsafe {
1175 let mut builder = mem::MaybeUninit::uninit();
1176 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
1177 let mut builder = builder.assume_init();
1178 for value in children.into_iter() {
1179 ffi::g_variant_builder_add_value(&mut builder, value.as_ref().to_glib_none().0);
1180 }
1181 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1182 }
1183 }
1184
1185 // rustdoc-stripper-ignore-next
1186 /// Creates a new dictionary entry Variant.
1187 ///
1188 /// [DictEntry] should be preferred over this when the types are known statically.
1189 #[doc(alias = "g_variant_new_dict_entry")]
1190 pub fn from_dict_entry(key: &Variant, value: &Variant) -> Self {
1191 unsafe {
1192 from_glib_none(ffi::g_variant_new_dict_entry(
1193 key.to_glib_none().0,
1194 value.to_glib_none().0,
1195 ))
1196 }
1197 }
1198
1199 // rustdoc-stripper-ignore-next
1200 /// Creates a new maybe Variant.
1201 #[doc(alias = "g_variant_new_maybe")]
1202 pub fn from_maybe<T: StaticVariantType>(child: Option<&Variant>) -> Self {
1203 let type_ = T::static_variant_type();
1204 match child {
1205 Some(child) => {
1206 assert_eq!(type_, child.type_());
1207
1208 Self::from_some(child)
1209 }
1210 None => Self::from_none(&type_),
1211 }
1212 }
1213
1214 // rustdoc-stripper-ignore-next
1215 /// Creates a new maybe Variant from a child.
1216 #[doc(alias = "g_variant_new_maybe")]
1217 pub fn from_some(child: &Variant) -> Self {
1218 unsafe {
1219 from_glib_none(ffi::g_variant_new_maybe(
1220 ptr::null(),
1221 child.to_glib_none().0,
1222 ))
1223 }
1224 }
1225
1226 // rustdoc-stripper-ignore-next
1227 /// Creates a new maybe Variant with Nothing.
1228 #[doc(alias = "g_variant_new_maybe")]
1229 pub fn from_none(type_: &VariantTy) -> Self {
1230 unsafe {
1231 from_glib_none(ffi::g_variant_new_maybe(
1232 type_.to_glib_none().0,
1233 ptr::null_mut(),
1234 ))
1235 }
1236 }
1237
1238 // rustdoc-stripper-ignore-next
1239 /// Extract the value of a maybe Variant.
1240 ///
1241 /// Returns the child value, or `None` if the value is Nothing.
1242 ///
1243 /// # Panics
1244 ///
1245 /// Panics if the variant is not maybe-typed.
1246 #[inline]
1247 pub fn as_maybe(&self) -> Option<Variant> {
1248 assert!(self.type_().is_maybe());
1249
1250 unsafe { from_glib_full(ffi::g_variant_get_maybe(self.to_glib_none().0)) }
1251 }
1252
1253 // rustdoc-stripper-ignore-next
1254 /// Pretty-print the contents of this variant in a human-readable form.
1255 ///
1256 /// A variant can be recreated from this output via [`Variant::parse`].
1257 // rustdoc-stripper-ignore-next-stop
1258 /// Pretty-prints @self in the format understood by g_variant_parse().
1259 ///
1260 /// The format is described [here](gvariant-text-format.html).
1261 ///
1262 /// If @type_annotate is [`true`], then type information is included in
1263 /// the output.
1264 /// ## `type_annotate`
1265 /// [`true`] if type information should be included in
1266 /// the output
1267 ///
1268 /// # Returns
1269 ///
1270 /// a newly-allocated string holding the result.
1271 // rustdoc-stripper-ignore-next-stop
1272 /// Pretty-prints @self in the format understood by g_variant_parse().
1273 ///
1274 /// The format is described [here](gvariant-text-format.html).
1275 ///
1276 /// If @type_annotate is [`true`], then type information is included in
1277 /// the output.
1278 /// ## `type_annotate`
1279 /// [`true`] if type information should be included in
1280 /// the output
1281 ///
1282 /// # Returns
1283 ///
1284 /// a newly-allocated string holding the result.
1285 #[doc(alias = "g_variant_print")]
1286 pub fn print(&self, type_annotate: bool) -> crate::GString {
1287 unsafe {
1288 from_glib_full(ffi::g_variant_print(
1289 self.to_glib_none().0,
1290 type_annotate.into_glib(),
1291 ))
1292 }
1293 }
1294
1295 // rustdoc-stripper-ignore-next
1296 /// Parses a GVariant from the text representation produced by [`print()`](Self::print).
1297 #[doc(alias = "g_variant_parse")]
1298 pub fn parse(type_: Option<&VariantTy>, text: &str) -> Result<Self, crate::Error> {
1299 unsafe {
1300 let mut error = ptr::null_mut();
1301 let text = text.as_bytes().as_ptr_range();
1302 let variant = ffi::g_variant_parse(
1303 type_.to_glib_none().0,
1304 text.start as *const _,
1305 text.end as *const _,
1306 ptr::null_mut(),
1307 &mut error,
1308 );
1309 if variant.is_null() {
1310 debug_assert!(!error.is_null());
1311 Err(from_glib_full(error))
1312 } else {
1313 debug_assert!(error.is_null());
1314 Ok(from_glib_full(variant))
1315 }
1316 }
1317 }
1318
1319 // rustdoc-stripper-ignore-next
1320 /// Constructs a new serialized-mode GVariant instance.
1321 // rustdoc-stripper-ignore-next-stop
1322 /// Constructs a new serialized-mode #GVariant instance. This is the
1323 /// inner interface for creation of new serialized values that gets
1324 /// called from various functions in gvariant.c.
1325 ///
1326 /// A reference is taken on @bytes.
1327 ///
1328 /// The data in @bytes must be aligned appropriately for the @type_ being loaded.
1329 /// Otherwise this function will internally create a copy of the memory (since
1330 /// GLib 2.60) or (in older versions) fail and exit the process.
1331 /// ## `type_`
1332 /// a #GVariantType
1333 /// ## `bytes`
1334 /// a #GBytes
1335 /// ## `trusted`
1336 /// if the contents of @bytes are trusted
1337 ///
1338 /// # Returns
1339 ///
1340 /// a new #GVariant with a floating reference
1341 // rustdoc-stripper-ignore-next-stop
1342 /// Constructs a new serialized-mode #GVariant instance. This is the
1343 /// inner interface for creation of new serialized values that gets
1344 /// called from various functions in gvariant.c.
1345 ///
1346 /// A reference is taken on @bytes.
1347 ///
1348 /// The data in @bytes must be aligned appropriately for the @type_ being loaded.
1349 /// Otherwise this function will internally create a copy of the memory (since
1350 /// GLib 2.60) or (in older versions) fail and exit the process.
1351 /// ## `type_`
1352 /// a #GVariantType
1353 /// ## `bytes`
1354 /// a #GBytes
1355 /// ## `trusted`
1356 /// if the contents of @bytes are trusted
1357 ///
1358 /// # Returns
1359 ///
1360 /// a new #GVariant with a floating reference
1361 #[doc(alias = "g_variant_new_from_bytes")]
1362 pub fn from_bytes<T: StaticVariantType>(bytes: &Bytes) -> Self {
1363 Variant::from_bytes_with_type(bytes, &T::static_variant_type())
1364 }
1365
1366 // rustdoc-stripper-ignore-next
1367 /// Constructs a new serialized-mode GVariant instance.
1368 ///
1369 /// This is the same as `from_bytes`, except that checks on the passed
1370 /// data are skipped.
1371 ///
1372 /// You should not use this function on data from external sources.
1373 ///
1374 /// # Safety
1375 ///
1376 /// Since the data is not validated, this is potentially dangerous if called
1377 /// on bytes which are not guaranteed to have come from serialising another
1378 /// Variant. The caller is responsible for ensuring bad data is not passed in.
1379 pub unsafe fn from_bytes_trusted<T: StaticVariantType>(bytes: &Bytes) -> Self {
1380 Variant::from_bytes_with_type_trusted(bytes, &T::static_variant_type())
1381 }
1382
1383 // rustdoc-stripper-ignore-next
1384 /// Constructs a new serialized-mode GVariant instance.
1385 // rustdoc-stripper-ignore-next-stop
1386 /// Creates a new #GVariant instance from serialized data.
1387 ///
1388 /// @type_ is the type of #GVariant instance that will be constructed.
1389 /// The interpretation of @data depends on knowing the type.
1390 ///
1391 /// @data is not modified by this function and must remain valid with an
1392 /// unchanging value until such a time as @notify is called with
1393 /// @user_data. If the contents of @data change before that time then
1394 /// the result is undefined.
1395 ///
1396 /// If @data is trusted to be serialized data in normal form then
1397 /// @trusted should be [`true`]. This applies to serialized data created
1398 /// within this process or read from a trusted location on the disk (such
1399 /// as a file installed in /usr/lib alongside your application). You
1400 /// should set trusted to [`false`] if @data is read from the network, a
1401 /// file in the user's home directory, etc.
1402 ///
1403 /// If @data was not stored in this machine's native endianness, any multi-byte
1404 /// numeric values in the returned variant will also be in non-native
1405 /// endianness. g_variant_byteswap() can be used to recover the original values.
1406 ///
1407 /// @notify will be called with @user_data when @data is no longer
1408 /// needed. The exact time of this call is unspecified and might even be
1409 /// before this function returns.
1410 ///
1411 /// Note: @data must be backed by memory that is aligned appropriately for the
1412 /// @type_ being loaded. Otherwise this function will internally create a copy of
1413 /// the memory (since GLib 2.60) or (in older versions) fail and exit the
1414 /// process.
1415 /// ## `type_`
1416 /// a definite #GVariantType
1417 /// ## `data`
1418 /// the serialized data
1419 /// ## `trusted`
1420 /// [`true`] if @data is definitely in normal form
1421 /// ## `notify`
1422 /// function to call when @data is no longer needed
1423 ///
1424 /// # Returns
1425 ///
1426 /// a new floating #GVariant of type @type_
1427 // rustdoc-stripper-ignore-next-stop
1428 /// Creates a new #GVariant instance from serialized data.
1429 ///
1430 /// @type_ is the type of #GVariant instance that will be constructed.
1431 /// The interpretation of @data depends on knowing the type.
1432 ///
1433 /// @data is not modified by this function and must remain valid with an
1434 /// unchanging value until such a time as @notify is called with
1435 /// @user_data. If the contents of @data change before that time then
1436 /// the result is undefined.
1437 ///
1438 /// If @data is trusted to be serialized data in normal form then
1439 /// @trusted should be [`true`]. This applies to serialized data created
1440 /// within this process or read from a trusted location on the disk (such
1441 /// as a file installed in /usr/lib alongside your application). You
1442 /// should set trusted to [`false`] if @data is read from the network, a
1443 /// file in the user's home directory, etc.
1444 ///
1445 /// If @data was not stored in this machine's native endianness, any multi-byte
1446 /// numeric values in the returned variant will also be in non-native
1447 /// endianness. g_variant_byteswap() can be used to recover the original values.
1448 ///
1449 /// @notify will be called with @user_data when @data is no longer
1450 /// needed. The exact time of this call is unspecified and might even be
1451 /// before this function returns.
1452 ///
1453 /// Note: @data must be backed by memory that is aligned appropriately for the
1454 /// @type_ being loaded. Otherwise this function will internally create a copy of
1455 /// the memory (since GLib 2.60) or (in older versions) fail and exit the
1456 /// process.
1457 /// ## `type_`
1458 /// a definite #GVariantType
1459 /// ## `data`
1460 /// the serialized data
1461 /// ## `trusted`
1462 /// [`true`] if @data is definitely in normal form
1463 /// ## `notify`
1464 /// function to call when @data is no longer needed
1465 ///
1466 /// # Returns
1467 ///
1468 /// a new floating #GVariant of type @type_
1469 #[doc(alias = "g_variant_new_from_data")]
1470 pub fn from_data<T: StaticVariantType, A: AsRef<[u8]>>(data: A) -> Self {
1471 Variant::from_data_with_type(data, &T::static_variant_type())
1472 }
1473
1474 // rustdoc-stripper-ignore-next
1475 /// Constructs a new serialized-mode GVariant instance.
1476 ///
1477 /// This is the same as `from_data`, except that checks on the passed
1478 /// data are skipped.
1479 ///
1480 /// You should not use this function on data from external sources.
1481 ///
1482 /// # Safety
1483 ///
1484 /// Since the data is not validated, this is potentially dangerous if called
1485 /// on bytes which are not guaranteed to have come from serialising another
1486 /// Variant. The caller is responsible for ensuring bad data is not passed in.
1487 pub unsafe fn from_data_trusted<T: StaticVariantType, A: AsRef<[u8]>>(data: A) -> Self {
1488 Variant::from_data_with_type_trusted(data, &T::static_variant_type())
1489 }
1490
1491 // rustdoc-stripper-ignore-next
1492 /// Constructs a new serialized-mode GVariant instance with a given type.
1493 #[doc(alias = "g_variant_new_from_bytes")]
1494 pub fn from_bytes_with_type(bytes: &Bytes, type_: &VariantTy) -> Self {
1495 unsafe {
1496 from_glib_none(ffi::g_variant_new_from_bytes(
1497 type_.as_ptr() as *const _,
1498 bytes.to_glib_none().0,
1499 false.into_glib(),
1500 ))
1501 }
1502 }
1503
1504 // rustdoc-stripper-ignore-next
1505 /// Constructs a new serialized-mode GVariant instance with a given type.
1506 ///
1507 /// This is the same as `from_bytes`, except that checks on the passed
1508 /// data are skipped.
1509 ///
1510 /// You should not use this function on data from external sources.
1511 ///
1512 /// # Safety
1513 ///
1514 /// Since the data is not validated, this is potentially dangerous if called
1515 /// on bytes which are not guaranteed to have come from serialising another
1516 /// Variant. The caller is responsible for ensuring bad data is not passed in.
1517 pub unsafe fn from_bytes_with_type_trusted(bytes: &Bytes, type_: &VariantTy) -> Self {
1518 from_glib_none(ffi::g_variant_new_from_bytes(
1519 type_.as_ptr() as *const _,
1520 bytes.to_glib_none().0,
1521 true.into_glib(),
1522 ))
1523 }
1524
1525 // rustdoc-stripper-ignore-next
1526 /// Constructs a new serialized-mode GVariant instance with a given type.
1527 #[doc(alias = "g_variant_new_from_data")]
1528 pub fn from_data_with_type<A: AsRef<[u8]>>(data: A, type_: &VariantTy) -> Self {
1529 unsafe {
1530 let data = Box::new(data);
1531 let (data_ptr, len) = {
1532 let data = (*data).as_ref();
1533 (data.as_ptr(), data.len())
1534 };
1535
1536 unsafe extern "C" fn free_data<A: AsRef<[u8]>>(ptr: ffi::gpointer) {
1537 let _ = Box::from_raw(ptr as *mut A);
1538 }
1539
1540 from_glib_none(ffi::g_variant_new_from_data(
1541 type_.as_ptr() as *const _,
1542 data_ptr as ffi::gconstpointer,
1543 len,
1544 false.into_glib(),
1545 Some(free_data::<A>),
1546 Box::into_raw(data) as ffi::gpointer,
1547 ))
1548 }
1549 }
1550
1551 // rustdoc-stripper-ignore-next
1552 /// Constructs a new serialized-mode GVariant instance with a given type.
1553 ///
1554 /// This is the same as `from_data`, except that checks on the passed
1555 /// data are skipped.
1556 ///
1557 /// You should not use this function on data from external sources.
1558 ///
1559 /// # Safety
1560 ///
1561 /// Since the data is not validated, this is potentially dangerous if called
1562 /// on bytes which are not guaranteed to have come from serialising another
1563 /// Variant. The caller is responsible for ensuring bad data is not passed in.
1564 pub unsafe fn from_data_with_type_trusted<A: AsRef<[u8]>>(data: A, type_: &VariantTy) -> Self {
1565 let data = Box::new(data);
1566 let (data_ptr, len) = {
1567 let data = (*data).as_ref();
1568 (data.as_ptr(), data.len())
1569 };
1570
1571 unsafe extern "C" fn free_data<A: AsRef<[u8]>>(ptr: ffi::gpointer) {
1572 let _ = Box::from_raw(ptr as *mut A);
1573 }
1574
1575 from_glib_none(ffi::g_variant_new_from_data(
1576 type_.as_ptr() as *const _,
1577 data_ptr as ffi::gconstpointer,
1578 len,
1579 true.into_glib(),
1580 Some(free_data::<A>),
1581 Box::into_raw(data) as ffi::gpointer,
1582 ))
1583 }
1584
1585 // rustdoc-stripper-ignore-next
1586 /// Returns the serialized form of a GVariant instance.
1587 // rustdoc-stripper-ignore-next-stop
1588 /// Returns a pointer to the serialized form of a #GVariant instance.
1589 /// The semantics of this function are exactly the same as
1590 /// g_variant_get_data(), except that the returned #GBytes holds
1591 /// a reference to the variant data.
1592 ///
1593 /// # Returns
1594 ///
1595 /// A new #GBytes representing the variant data
1596 // rustdoc-stripper-ignore-next-stop
1597 /// Returns a pointer to the serialized form of a #GVariant instance.
1598 /// The semantics of this function are exactly the same as
1599 /// g_variant_get_data(), except that the returned #GBytes holds
1600 /// a reference to the variant data.
1601 ///
1602 /// # Returns
1603 ///
1604 /// A new #GBytes representing the variant data
1605 #[doc(alias = "get_data_as_bytes")]
1606 #[doc(alias = "g_variant_get_data_as_bytes")]
1607 pub fn data_as_bytes(&self) -> Bytes {
1608 unsafe { from_glib_full(ffi::g_variant_get_data_as_bytes(self.to_glib_none().0)) }
1609 }
1610
1611 // rustdoc-stripper-ignore-next
1612 /// Returns the serialized form of a GVariant instance.
1613 // rustdoc-stripper-ignore-next-stop
1614 /// Returns a pointer to the serialized form of a #GVariant instance.
1615 /// The returned data may not be in fully-normalised form if read from an
1616 /// untrusted source. The returned data must not be freed; it remains
1617 /// valid for as long as @self exists.
1618 ///
1619 /// If @self is a fixed-sized value that was deserialized from a
1620 /// corrupted serialized container then [`None`] may be returned. In this
1621 /// case, the proper thing to do is typically to use the appropriate
1622 /// number of nul bytes in place of @self. If @self is not fixed-sized
1623 /// then [`None`] is never returned.
1624 ///
1625 /// In the case that @self is already in serialized form, this function
1626 /// is O(1). If the value is not already in serialized form,
1627 /// serialization occurs implicitly and is approximately O(n) in the size
1628 /// of the result.
1629 ///
1630 /// To deserialize the data returned by this function, in addition to the
1631 /// serialized data, you must know the type of the #GVariant, and (if the
1632 /// machine might be different) the endianness of the machine that stored
1633 /// it. As a result, file formats or network messages that incorporate
1634 /// serialized #GVariants must include this information either
1635 /// implicitly (for instance "the file always contains a
1636 /// `G_VARIANT_TYPE_VARIANT` and it is always in little-endian order") or
1637 /// explicitly (by storing the type and/or endianness in addition to the
1638 /// serialized data).
1639 ///
1640 /// # Returns
1641 ///
1642 /// the serialized form of @self, or [`None`]
1643 // rustdoc-stripper-ignore-next-stop
1644 /// Returns a pointer to the serialized form of a #GVariant instance.
1645 /// The returned data may not be in fully-normalised form if read from an
1646 /// untrusted source. The returned data must not be freed; it remains
1647 /// valid for as long as @self exists.
1648 ///
1649 /// If @self is a fixed-sized value that was deserialized from a
1650 /// corrupted serialized container then [`None`] may be returned. In this
1651 /// case, the proper thing to do is typically to use the appropriate
1652 /// number of nul bytes in place of @self. If @self is not fixed-sized
1653 /// then [`None`] is never returned.
1654 ///
1655 /// In the case that @self is already in serialized form, this function
1656 /// is O(1). If the value is not already in serialized form,
1657 /// serialization occurs implicitly and is approximately O(n) in the size
1658 /// of the result.
1659 ///
1660 /// To deserialize the data returned by this function, in addition to the
1661 /// serialized data, you must know the type of the #GVariant, and (if the
1662 /// machine might be different) the endianness of the machine that stored
1663 /// it. As a result, file formats or network messages that incorporate
1664 /// serialized #GVariants must include this information either
1665 /// implicitly (for instance "the file always contains a
1666 /// `G_VARIANT_TYPE_VARIANT` and it is always in little-endian order") or
1667 /// explicitly (by storing the type and/or endianness in addition to the
1668 /// serialized data).
1669 ///
1670 /// # Returns
1671 ///
1672 /// the serialized form of @self, or [`None`]
1673 #[doc(alias = "g_variant_get_data")]
1674 pub fn data(&self) -> &[u8] {
1675 unsafe {
1676 let selfv = self.to_glib_none();
1677 let len = ffi::g_variant_get_size(selfv.0);
1678 if len == 0 {
1679 return &[];
1680 }
1681 let ptr = ffi::g_variant_get_data(selfv.0);
1682 slice::from_raw_parts(ptr as *const _, len as _)
1683 }
1684 }
1685
1686 // rustdoc-stripper-ignore-next
1687 /// Returns the size of serialized form of a GVariant instance.
1688 // rustdoc-stripper-ignore-next-stop
1689 /// Determines the number of bytes that would be required to store @self
1690 /// with g_variant_store().
1691 ///
1692 /// If @self has a fixed-sized type then this function always returned
1693 /// that fixed size.
1694 ///
1695 /// In the case that @self is already in serialized form or the size has
1696 /// already been calculated (ie: this function has been called before)
1697 /// then this function is O(1). Otherwise, the size is calculated, an
1698 /// operation which is approximately O(n) in the number of values
1699 /// involved.
1700 ///
1701 /// # Returns
1702 ///
1703 /// the serialized size of @self
1704 // rustdoc-stripper-ignore-next-stop
1705 /// Determines the number of bytes that would be required to store @self
1706 /// with g_variant_store().
1707 ///
1708 /// If @self has a fixed-sized type then this function always returned
1709 /// that fixed size.
1710 ///
1711 /// In the case that @self is already in serialized form or the size has
1712 /// already been calculated (ie: this function has been called before)
1713 /// then this function is O(1). Otherwise, the size is calculated, an
1714 /// operation which is approximately O(n) in the number of values
1715 /// involved.
1716 ///
1717 /// # Returns
1718 ///
1719 /// the serialized size of @self
1720 #[doc(alias = "g_variant_get_size")]
1721 pub fn size(&self) -> usize {
1722 unsafe { ffi::g_variant_get_size(self.to_glib_none().0) }
1723 }
1724
1725 // rustdoc-stripper-ignore-next
1726 /// Stores the serialized form of a GVariant instance into the given slice.
1727 ///
1728 /// The slice needs to be big enough.
1729 // rustdoc-stripper-ignore-next-stop
1730 /// Stores the serialized form of @self at @data. @data should be
1731 /// large enough. See g_variant_get_size().
1732 ///
1733 /// The stored data is in machine native byte order but may not be in
1734 /// fully-normalised form if read from an untrusted source. See
1735 /// g_variant_get_normal_form() for a solution.
1736 ///
1737 /// As with g_variant_get_data(), to be able to deserialize the
1738 /// serialized variant successfully, its type and (if the destination
1739 /// machine might be different) its endianness must also be available.
1740 ///
1741 /// This function is approximately O(n) in the size of @data.
1742 // rustdoc-stripper-ignore-next-stop
1743 /// Stores the serialized form of @self at @data. @data should be
1744 /// large enough. See g_variant_get_size().
1745 ///
1746 /// The stored data is in machine native byte order but may not be in
1747 /// fully-normalised form if read from an untrusted source. See
1748 /// g_variant_get_normal_form() for a solution.
1749 ///
1750 /// As with g_variant_get_data(), to be able to deserialize the
1751 /// serialized variant successfully, its type and (if the destination
1752 /// machine might be different) its endianness must also be available.
1753 ///
1754 /// This function is approximately O(n) in the size of @data.
1755 #[doc(alias = "g_variant_store")]
1756 pub fn store(&self, data: &mut [u8]) -> Result<usize, crate::BoolError> {
1757 unsafe {
1758 let size = ffi::g_variant_get_size(self.to_glib_none().0);
1759 if data.len() < size {
1760 return Err(bool_error!("Provided slice is too small"));
1761 }
1762
1763 ffi::g_variant_store(self.to_glib_none().0, data.as_mut_ptr() as ffi::gpointer);
1764
1765 Ok(size)
1766 }
1767 }
1768
1769 // rustdoc-stripper-ignore-next
1770 /// Returns a copy of the variant in normal form.
1771 // rustdoc-stripper-ignore-next-stop
1772 /// Gets a #GVariant instance that has the same value as @self and is
1773 /// trusted to be in normal form.
1774 ///
1775 /// If @self is already trusted to be in normal form then a new
1776 /// reference to @self is returned.
1777 ///
1778 /// If @self is not already trusted, then it is scanned to check if it
1779 /// is in normal form. If it is found to be in normal form then it is
1780 /// marked as trusted and a new reference to it is returned.
1781 ///
1782 /// If @self is found not to be in normal form then a new trusted
1783 /// #GVariant is created with the same value as @self. The non-normal parts of
1784 /// @self will be replaced with default values which are guaranteed to be in
1785 /// normal form.
1786 ///
1787 /// It makes sense to call this function if you've received #GVariant
1788 /// data from untrusted sources and you want to ensure your serialized
1789 /// output is definitely in normal form.
1790 ///
1791 /// If @self is already in normal form, a new reference will be returned
1792 /// (which will be floating if @self is floating). If it is not in normal form,
1793 /// the newly created #GVariant will be returned with a single non-floating
1794 /// reference. Typically, g_variant_take_ref() should be called on the return
1795 /// value from this function to guarantee ownership of a single non-floating
1796 /// reference to it.
1797 ///
1798 /// # Returns
1799 ///
1800 /// a trusted #GVariant
1801 // rustdoc-stripper-ignore-next-stop
1802 /// Gets a #GVariant instance that has the same value as @self and is
1803 /// trusted to be in normal form.
1804 ///
1805 /// If @self is already trusted to be in normal form then a new
1806 /// reference to @self is returned.
1807 ///
1808 /// If @self is not already trusted, then it is scanned to check if it
1809 /// is in normal form. If it is found to be in normal form then it is
1810 /// marked as trusted and a new reference to it is returned.
1811 ///
1812 /// If @self is found not to be in normal form then a new trusted
1813 /// #GVariant is created with the same value as @self. The non-normal parts of
1814 /// @self will be replaced with default values which are guaranteed to be in
1815 /// normal form.
1816 ///
1817 /// It makes sense to call this function if you've received #GVariant
1818 /// data from untrusted sources and you want to ensure your serialized
1819 /// output is definitely in normal form.
1820 ///
1821 /// If @self is already in normal form, a new reference will be returned
1822 /// (which will be floating if @self is floating). If it is not in normal form,
1823 /// the newly created #GVariant will be returned with a single non-floating
1824 /// reference. Typically, g_variant_take_ref() should be called on the return
1825 /// value from this function to guarantee ownership of a single non-floating
1826 /// reference to it.
1827 ///
1828 /// # Returns
1829 ///
1830 /// a trusted #GVariant
1831 #[doc(alias = "g_variant_get_normal_form")]
1832 #[must_use]
1833 pub fn normal_form(&self) -> Self {
1834 unsafe { from_glib_full(ffi::g_variant_get_normal_form(self.to_glib_none().0)) }
1835 }
1836
1837 // rustdoc-stripper-ignore-next
1838 /// Returns a copy of the variant in the opposite endianness.
1839 // rustdoc-stripper-ignore-next-stop
1840 /// Performs a byteswapping operation on the contents of @self. The
1841 /// result is that all multi-byte numeric data contained in @self is
1842 /// byteswapped. That includes 16, 32, and 64bit signed and unsigned
1843 /// integers as well as file handles and double precision floating point
1844 /// values.
1845 ///
1846 /// This function is an identity mapping on any value that does not
1847 /// contain multi-byte numeric data. That include strings, booleans,
1848 /// bytes and containers containing only these things (recursively).
1849 ///
1850 /// While this function can safely handle untrusted, non-normal data, it is
1851 /// recommended to check whether the input is in normal form beforehand, using
1852 /// g_variant_is_normal_form(), and to reject non-normal inputs if your
1853 /// application can be strict about what inputs it rejects.
1854 ///
1855 /// The returned value is always in normal form and is marked as trusted.
1856 /// A full, not floating, reference is returned.
1857 ///
1858 /// # Returns
1859 ///
1860 /// the byteswapped form of @self
1861 // rustdoc-stripper-ignore-next-stop
1862 /// Performs a byteswapping operation on the contents of @self. The
1863 /// result is that all multi-byte numeric data contained in @self is
1864 /// byteswapped. That includes 16, 32, and 64bit signed and unsigned
1865 /// integers as well as file handles and double precision floating point
1866 /// values.
1867 ///
1868 /// This function is an identity mapping on any value that does not
1869 /// contain multi-byte numeric data. That include strings, booleans,
1870 /// bytes and containers containing only these things (recursively).
1871 ///
1872 /// While this function can safely handle untrusted, non-normal data, it is
1873 /// recommended to check whether the input is in normal form beforehand, using
1874 /// g_variant_is_normal_form(), and to reject non-normal inputs if your
1875 /// application can be strict about what inputs it rejects.
1876 ///
1877 /// The returned value is always in normal form and is marked as trusted.
1878 /// A full, not floating, reference is returned.
1879 ///
1880 /// # Returns
1881 ///
1882 /// the byteswapped form of @self
1883 #[doc(alias = "g_variant_byteswap")]
1884 #[must_use]
1885 pub fn byteswap(&self) -> Self {
1886 unsafe { from_glib_full(ffi::g_variant_byteswap(self.to_glib_none().0)) }
1887 }
1888
1889 // rustdoc-stripper-ignore-next
1890 /// Determines the number of children in a container GVariant instance.
1891 // rustdoc-stripper-ignore-next-stop
1892 /// Determines the number of children in a container #GVariant instance.
1893 /// This includes variants, maybes, arrays, tuples and dictionary
1894 /// entries. It is an error to call this function on any other type of
1895 /// #GVariant.
1896 ///
1897 /// For variants, the return value is always 1. For values with maybe
1898 /// types, it is always zero or one. For arrays, it is the length of the
1899 /// array. For tuples it is the number of tuple items (which depends
1900 /// only on the type). For dictionary entries, it is always 2
1901 ///
1902 /// This function is O(1).
1903 ///
1904 /// # Returns
1905 ///
1906 /// the number of children in the container
1907 // rustdoc-stripper-ignore-next-stop
1908 /// Determines the number of children in a container #GVariant instance.
1909 /// This includes variants, maybes, arrays, tuples and dictionary
1910 /// entries. It is an error to call this function on any other type of
1911 /// #GVariant.
1912 ///
1913 /// For variants, the return value is always 1. For values with maybe
1914 /// types, it is always zero or one. For arrays, it is the length of the
1915 /// array. For tuples it is the number of tuple items (which depends
1916 /// only on the type). For dictionary entries, it is always 2
1917 ///
1918 /// This function is O(1).
1919 ///
1920 /// # Returns
1921 ///
1922 /// the number of children in the container
1923 #[doc(alias = "g_variant_n_children")]
1924 pub fn n_children(&self) -> usize {
1925 assert!(self.is_container());
1926
1927 unsafe { ffi::g_variant_n_children(self.to_glib_none().0) }
1928 }
1929
1930 // rustdoc-stripper-ignore-next
1931 /// Create an iterator over items in the variant.
1932 ///
1933 /// Note that this heap allocates a variant for each element,
1934 /// which can be particularly expensive for large arrays.
1935 pub fn iter(&self) -> VariantIter {
1936 assert!(self.is_container());
1937
1938 VariantIter::new(self.clone())
1939 }
1940
1941 // rustdoc-stripper-ignore-next
1942 /// Create an iterator over borrowed strings from a GVariant of type `as` (array of string).
1943 ///
1944 /// This will fail if the variant is not an array of with
1945 /// the expected child type.
1946 ///
1947 /// A benefit of this API over [`Self::iter()`] is that it
1948 /// minimizes allocation, and provides strongly typed access.
1949 ///
1950 /// ```
1951 /// # use glib::prelude::*;
1952 /// let strs = &["foo", "bar"];
1953 /// let strs_variant: glib::Variant = strs.to_variant();
1954 /// for s in strs_variant.array_iter_str()? {
1955 /// println!("{}", s);
1956 /// }
1957 /// # Ok::<(), Box<dyn std::error::Error>>(())
1958 /// ```
1959 pub fn array_iter_str(&self) -> Result<VariantStrIter<'_>, VariantTypeMismatchError> {
1960 let child_ty = String::static_variant_type();
1961 let actual_ty = self.type_();
1962 let expected_ty = child_ty.as_array();
1963 if actual_ty != expected_ty {
1964 return Err(VariantTypeMismatchError {
1965 actual: actual_ty.to_owned(),
1966 expected: expected_ty.into_owned(),
1967 });
1968 }
1969
1970 Ok(VariantStrIter::new(self))
1971 }
1972
1973 // rustdoc-stripper-ignore-next
1974 /// Return whether this Variant is a container type.
1975 // rustdoc-stripper-ignore-next-stop
1976 /// Checks if @self is a container.
1977 ///
1978 /// # Returns
1979 ///
1980 /// [`true`] if @self is a container
1981 // rustdoc-stripper-ignore-next-stop
1982 /// Checks if @self is a container.
1983 ///
1984 /// # Returns
1985 ///
1986 /// [`true`] if @self is a container
1987 #[doc(alias = "g_variant_is_container")]
1988 pub fn is_container(&self) -> bool {
1989 unsafe { from_glib(ffi::g_variant_is_container(self.to_glib_none().0)) }
1990 }
1991
1992 // rustdoc-stripper-ignore-next
1993 /// Return whether this Variant is in normal form.
1994 // rustdoc-stripper-ignore-next-stop
1995 /// Checks if @self is in normal form.
1996 ///
1997 /// The main reason to do this is to detect if a given chunk of
1998 /// serialized data is in normal form: load the data into a #GVariant
1999 /// using g_variant_new_from_data() and then use this function to
2000 /// check.
2001 ///
2002 /// If @self is found to be in normal form then it will be marked as
2003 /// being trusted. If the value was already marked as being trusted then
2004 /// this function will immediately return [`true`].
2005 ///
2006 /// There may be implementation specific restrictions on deeply nested values.
2007 /// GVariant is guaranteed to handle nesting up to at least 64 levels.
2008 ///
2009 /// # Returns
2010 ///
2011 /// [`true`] if @self is in normal form
2012 // rustdoc-stripper-ignore-next-stop
2013 /// Checks if @self is in normal form.
2014 ///
2015 /// The main reason to do this is to detect if a given chunk of
2016 /// serialized data is in normal form: load the data into a #GVariant
2017 /// using g_variant_new_from_data() and then use this function to
2018 /// check.
2019 ///
2020 /// If @self is found to be in normal form then it will be marked as
2021 /// being trusted. If the value was already marked as being trusted then
2022 /// this function will immediately return [`true`].
2023 ///
2024 /// There may be implementation specific restrictions on deeply nested values.
2025 /// GVariant is guaranteed to handle nesting up to at least 64 levels.
2026 ///
2027 /// # Returns
2028 ///
2029 /// [`true`] if @self is in normal form
2030 #[doc(alias = "g_variant_is_normal_form")]
2031 pub fn is_normal_form(&self) -> bool {
2032 unsafe { from_glib(ffi::g_variant_is_normal_form(self.to_glib_none().0)) }
2033 }
2034
2035 // rustdoc-stripper-ignore-next
2036 /// Return whether input string is a valid `VariantClass::ObjectPath`.
2037 // rustdoc-stripper-ignore-next-stop
2038 /// Determines if a given string is a valid D-Bus object path. You
2039 /// should ensure that a string is a valid D-Bus object path before
2040 /// passing it to g_variant_new_object_path().
2041 ///
2042 /// A valid object path starts with `/` followed by zero or more
2043 /// sequences of characters separated by `/` characters. Each sequence
2044 /// must contain only the characters `[A-Z][a-z][0-9]_`. No sequence
2045 /// (including the one following the final `/` character) may be empty.
2046 /// ## `string`
2047 /// a normal C nul-terminated string
2048 ///
2049 /// # Returns
2050 ///
2051 /// [`true`] if @string is a D-Bus object path
2052 // rustdoc-stripper-ignore-next-stop
2053 /// Determines if a given string is a valid D-Bus object path. You
2054 /// should ensure that a string is a valid D-Bus object path before
2055 /// passing it to g_variant_new_object_path().
2056 ///
2057 /// A valid object path starts with `/` followed by zero or more
2058 /// sequences of characters separated by `/` characters. Each sequence
2059 /// must contain only the characters `[A-Z][a-z][0-9]_`. No sequence
2060 /// (including the one following the final `/` character) may be empty.
2061 /// ## `string`
2062 /// a normal C nul-terminated string
2063 ///
2064 /// # Returns
2065 ///
2066 /// [`true`] if @string is a D-Bus object path
2067 #[doc(alias = "g_variant_is_object_path")]
2068 pub fn is_object_path(string: &str) -> bool {
2069 unsafe { from_glib(ffi::g_variant_is_object_path(string.to_glib_none().0)) }
2070 }
2071
2072 // rustdoc-stripper-ignore-next
2073 /// Return whether input string is a valid `VariantClass::Signature`.
2074 // rustdoc-stripper-ignore-next-stop
2075 /// Determines if a given string is a valid D-Bus type signature. You
2076 /// should ensure that a string is a valid D-Bus type signature before
2077 /// passing it to g_variant_new_signature().
2078 ///
2079 /// D-Bus type signatures consist of zero or more definite #GVariantType
2080 /// strings in sequence.
2081 /// ## `string`
2082 /// a normal C nul-terminated string
2083 ///
2084 /// # Returns
2085 ///
2086 /// [`true`] if @string is a D-Bus type signature
2087 // rustdoc-stripper-ignore-next-stop
2088 /// Determines if a given string is a valid D-Bus type signature. You
2089 /// should ensure that a string is a valid D-Bus type signature before
2090 /// passing it to g_variant_new_signature().
2091 ///
2092 /// D-Bus type signatures consist of zero or more definite #GVariantType
2093 /// strings in sequence.
2094 /// ## `string`
2095 /// a normal C nul-terminated string
2096 ///
2097 /// # Returns
2098 ///
2099 /// [`true`] if @string is a D-Bus type signature
2100 #[doc(alias = "g_variant_is_signature")]
2101 pub fn is_signature(string: &str) -> bool {
2102 unsafe { from_glib(ffi::g_variant_is_signature(string.to_glib_none().0)) }
2103 }
2104}
2105
2106unsafe impl Send for Variant {}
2107unsafe impl Sync for Variant {}
2108
2109impl fmt::Debug for Variant {
2110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2111 f.debug_struct("Variant")
2112 .field("ptr", &ToGlibPtr::<*const _>::to_glib_none(self).0)
2113 .field("type", &self.type_())
2114 .field("value", &self.to_string())
2115 .finish()
2116 }
2117}
2118
2119impl fmt::Display for Variant {
2120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2121 f.write_str(&self.print(true))
2122 }
2123}
2124
2125impl str::FromStr for Variant {
2126 type Err = crate::Error;
2127
2128 fn from_str(s: &str) -> Result<Self, Self::Err> {
2129 Self::parse(None, s)
2130 }
2131}
2132
2133impl PartialEq for Variant {
2134 #[doc(alias = "g_variant_equal")]
2135 fn eq(&self, other: &Self) -> bool {
2136 unsafe {
2137 from_glib(ffi::g_variant_equal(
2138 ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
2139 ToGlibPtr::<*const _>::to_glib_none(other).0 as *const _,
2140 ))
2141 }
2142 }
2143}
2144
2145impl Eq for Variant {}
2146
2147impl PartialOrd for Variant {
2148 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2149 unsafe {
2150 if ffi::g_variant_classify(self.to_glib_none().0)
2151 != ffi::g_variant_classify(other.to_glib_none().0)
2152 {
2153 return None;
2154 }
2155
2156 if self.is_container() {
2157 return None;
2158 }
2159
2160 let res = ffi::g_variant_compare(
2161 ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
2162 ToGlibPtr::<*const _>::to_glib_none(other).0 as *const _,
2163 );
2164
2165 Some(res.cmp(&0))
2166 }
2167 }
2168}
2169
2170impl Hash for Variant {
2171 #[doc(alias = "g_variant_hash")]
2172 fn hash<H: Hasher>(&self, state: &mut H) {
2173 unsafe {
2174 state.write_u32(ffi::g_variant_hash(
2175 ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
2176 ))
2177 }
2178 }
2179}
2180
2181impl AsRef<Variant> for Variant {
2182 #[inline]
2183 fn as_ref(&self) -> &Self {
2184 self
2185 }
2186}
2187
2188// rustdoc-stripper-ignore-next
2189/// Converts to `Variant`.
2190pub trait ToVariant {
2191 // rustdoc-stripper-ignore-next
2192 /// Returns a `Variant` clone of `self`.
2193 fn to_variant(&self) -> Variant;
2194}
2195
2196// rustdoc-stripper-ignore-next
2197/// Extracts a value.
2198pub trait FromVariant: Sized + StaticVariantType {
2199 // rustdoc-stripper-ignore-next
2200 /// Tries to extract a value.
2201 ///
2202 /// Returns `Some` if the variant's type matches `Self`.
2203 fn from_variant(variant: &Variant) -> Option<Self>;
2204}
2205
2206// rustdoc-stripper-ignore-next
2207/// Returns `VariantType` of `Self`.
2208pub trait StaticVariantType {
2209 // rustdoc-stripper-ignore-next
2210 /// Returns the `VariantType` corresponding to `Self`.
2211 fn static_variant_type() -> Cow<'static, VariantTy>;
2212}
2213
2214impl StaticVariantType for Variant {
2215 fn static_variant_type() -> Cow<'static, VariantTy> {
2216 Cow::Borrowed(VariantTy::VARIANT)
2217 }
2218}
2219
2220impl<T: ?Sized + ToVariant> ToVariant for &T {
2221 fn to_variant(&self) -> Variant {
2222 <T as ToVariant>::to_variant(self)
2223 }
2224}
2225
2226impl<'a, T: Into<Variant> + Clone> From<&'a T> for Variant {
2227 #[inline]
2228 fn from(v: &'a T) -> Self {
2229 v.clone().into()
2230 }
2231}
2232
2233impl<T: ?Sized + StaticVariantType> StaticVariantType for &T {
2234 fn static_variant_type() -> Cow<'static, VariantTy> {
2235 <T as StaticVariantType>::static_variant_type()
2236 }
2237}
2238
2239macro_rules! impl_numeric {
2240 ($name:ty, $typ:expr, $new_fn:ident, $get_fn:ident) => {
2241 impl StaticVariantType for $name {
2242 fn static_variant_type() -> Cow<'static, VariantTy> {
2243 Cow::Borrowed($typ)
2244 }
2245 }
2246
2247 impl ToVariant for $name {
2248 fn to_variant(&self) -> Variant {
2249 unsafe { from_glib_none(ffi::$new_fn(*self)) }
2250 }
2251 }
2252
2253 impl From<$name> for Variant {
2254 #[inline]
2255 fn from(v: $name) -> Self {
2256 v.to_variant()
2257 }
2258 }
2259
2260 impl FromVariant for $name {
2261 fn from_variant(variant: &Variant) -> Option<Self> {
2262 unsafe {
2263 if variant.is::<Self>() {
2264 Some(ffi::$get_fn(variant.to_glib_none().0))
2265 } else {
2266 None
2267 }
2268 }
2269 }
2270 }
2271 };
2272}
2273
2274impl_numeric!(u8, VariantTy::BYTE, g_variant_new_byte, g_variant_get_byte);
2275impl_numeric!(
2276 i16,
2277 VariantTy::INT16,
2278 g_variant_new_int16,
2279 g_variant_get_int16
2280);
2281impl_numeric!(
2282 u16,
2283 VariantTy::UINT16,
2284 g_variant_new_uint16,
2285 g_variant_get_uint16
2286);
2287impl_numeric!(
2288 i32,
2289 VariantTy::INT32,
2290 g_variant_new_int32,
2291 g_variant_get_int32
2292);
2293impl_numeric!(
2294 u32,
2295 VariantTy::UINT32,
2296 g_variant_new_uint32,
2297 g_variant_get_uint32
2298);
2299impl_numeric!(
2300 i64,
2301 VariantTy::INT64,
2302 g_variant_new_int64,
2303 g_variant_get_int64
2304);
2305impl_numeric!(
2306 u64,
2307 VariantTy::UINT64,
2308 g_variant_new_uint64,
2309 g_variant_get_uint64
2310);
2311impl_numeric!(
2312 f64,
2313 VariantTy::DOUBLE,
2314 g_variant_new_double,
2315 g_variant_get_double
2316);
2317
2318impl StaticVariantType for () {
2319 fn static_variant_type() -> Cow<'static, VariantTy> {
2320 Cow::Borrowed(VariantTy::UNIT)
2321 }
2322}
2323
2324impl ToVariant for () {
2325 fn to_variant(&self) -> Variant {
2326 unsafe { from_glib_none(ffi::g_variant_new_tuple(ptr::null(), 0)) }
2327 }
2328}
2329
2330impl From<()> for Variant {
2331 #[inline]
2332 fn from(_: ()) -> Self {
2333 ().to_variant()
2334 }
2335}
2336
2337impl FromVariant for () {
2338 fn from_variant(variant: &Variant) -> Option<Self> {
2339 if variant.is::<Self>() {
2340 Some(())
2341 } else {
2342 None
2343 }
2344 }
2345}
2346
2347impl StaticVariantType for bool {
2348 fn static_variant_type() -> Cow<'static, VariantTy> {
2349 Cow::Borrowed(VariantTy::BOOLEAN)
2350 }
2351}
2352
2353impl ToVariant for bool {
2354 fn to_variant(&self) -> Variant {
2355 unsafe { from_glib_none(ffi::g_variant_new_boolean(self.into_glib())) }
2356 }
2357}
2358
2359impl From<bool> for Variant {
2360 #[inline]
2361 fn from(v: bool) -> Self {
2362 v.to_variant()
2363 }
2364}
2365
2366impl FromVariant for bool {
2367 fn from_variant(variant: &Variant) -> Option<Self> {
2368 unsafe {
2369 if variant.is::<Self>() {
2370 Some(from_glib(ffi::g_variant_get_boolean(
2371 variant.to_glib_none().0,
2372 )))
2373 } else {
2374 None
2375 }
2376 }
2377 }
2378}
2379
2380impl StaticVariantType for String {
2381 fn static_variant_type() -> Cow<'static, VariantTy> {
2382 Cow::Borrowed(VariantTy::STRING)
2383 }
2384}
2385
2386impl ToVariant for String {
2387 fn to_variant(&self) -> Variant {
2388 self[..].to_variant()
2389 }
2390}
2391
2392impl From<String> for Variant {
2393 #[inline]
2394 fn from(s: String) -> Self {
2395 s.to_variant()
2396 }
2397}
2398
2399impl FromVariant for String {
2400 fn from_variant(variant: &Variant) -> Option<Self> {
2401 variant.str().map(String::from)
2402 }
2403}
2404
2405impl StaticVariantType for str {
2406 fn static_variant_type() -> Cow<'static, VariantTy> {
2407 String::static_variant_type()
2408 }
2409}
2410
2411impl ToVariant for str {
2412 fn to_variant(&self) -> Variant {
2413 unsafe { from_glib_none(ffi::g_variant_new_take_string(self.to_glib_full())) }
2414 }
2415}
2416
2417impl From<&str> for Variant {
2418 #[inline]
2419 fn from(s: &str) -> Self {
2420 s.to_variant()
2421 }
2422}
2423
2424impl StaticVariantType for std::path::PathBuf {
2425 fn static_variant_type() -> Cow<'static, VariantTy> {
2426 std::path::Path::static_variant_type()
2427 }
2428}
2429
2430impl ToVariant for std::path::PathBuf {
2431 fn to_variant(&self) -> Variant {
2432 self.as_path().to_variant()
2433 }
2434}
2435
2436impl From<std::path::PathBuf> for Variant {
2437 #[inline]
2438 fn from(p: std::path::PathBuf) -> Self {
2439 p.to_variant()
2440 }
2441}
2442
2443impl FromVariant for std::path::PathBuf {
2444 fn from_variant(variant: &Variant) -> Option<Self> {
2445 unsafe {
2446 let ptr = ffi::g_variant_get_bytestring(variant.to_glib_none().0);
2447 Some(crate::translate::c_to_path_buf(ptr as *const _))
2448 }
2449 }
2450}
2451
2452impl StaticVariantType for std::path::Path {
2453 fn static_variant_type() -> Cow<'static, VariantTy> {
2454 <&[u8]>::static_variant_type()
2455 }
2456}
2457
2458impl ToVariant for std::path::Path {
2459 fn to_variant(&self) -> Variant {
2460 let tmp = crate::translate::path_to_c(self);
2461 unsafe { from_glib_none(ffi::g_variant_new_bytestring(tmp.as_ptr() as *const u8)) }
2462 }
2463}
2464
2465impl From<&std::path::Path> for Variant {
2466 #[inline]
2467 fn from(p: &std::path::Path) -> Self {
2468 p.to_variant()
2469 }
2470}
2471
2472impl StaticVariantType for std::ffi::OsString {
2473 fn static_variant_type() -> Cow<'static, VariantTy> {
2474 std::ffi::OsStr::static_variant_type()
2475 }
2476}
2477
2478impl ToVariant for std::ffi::OsString {
2479 fn to_variant(&self) -> Variant {
2480 self.as_os_str().to_variant()
2481 }
2482}
2483
2484impl From<std::ffi::OsString> for Variant {
2485 #[inline]
2486 fn from(s: std::ffi::OsString) -> Self {
2487 s.to_variant()
2488 }
2489}
2490
2491impl FromVariant for std::ffi::OsString {
2492 fn from_variant(variant: &Variant) -> Option<Self> {
2493 unsafe {
2494 let ptr = ffi::g_variant_get_bytestring(variant.to_glib_none().0);
2495 Some(crate::translate::c_to_os_string(ptr as *const _))
2496 }
2497 }
2498}
2499
2500impl StaticVariantType for std::ffi::OsStr {
2501 fn static_variant_type() -> Cow<'static, VariantTy> {
2502 <&[u8]>::static_variant_type()
2503 }
2504}
2505
2506impl ToVariant for std::ffi::OsStr {
2507 fn to_variant(&self) -> Variant {
2508 let tmp = crate::translate::os_str_to_c(self);
2509 unsafe { from_glib_none(ffi::g_variant_new_bytestring(tmp.as_ptr() as *const u8)) }
2510 }
2511}
2512
2513impl From<&std::ffi::OsStr> for Variant {
2514 #[inline]
2515 fn from(s: &std::ffi::OsStr) -> Self {
2516 s.to_variant()
2517 }
2518}
2519
2520impl<T: StaticVariantType> StaticVariantType for Option<T> {
2521 fn static_variant_type() -> Cow<'static, VariantTy> {
2522 Cow::Owned(VariantType::new_maybe(&T::static_variant_type()))
2523 }
2524}
2525
2526impl<T: StaticVariantType + ToVariant> ToVariant for Option<T> {
2527 fn to_variant(&self) -> Variant {
2528 Variant::from_maybe::<T>(self.as_ref().map(|m| m.to_variant()).as_ref())
2529 }
2530}
2531
2532impl<T: StaticVariantType + Into<Variant>> From<Option<T>> for Variant {
2533 #[inline]
2534 fn from(v: Option<T>) -> Self {
2535 Variant::from_maybe::<T>(v.map(|v| v.into()).as_ref())
2536 }
2537}
2538
2539impl<T: StaticVariantType + FromVariant> FromVariant for Option<T> {
2540 fn from_variant(variant: &Variant) -> Option<Self> {
2541 unsafe {
2542 if variant.is::<Self>() {
2543 let c_child = ffi::g_variant_get_maybe(variant.to_glib_none().0);
2544 if !c_child.is_null() {
2545 let child: Variant = from_glib_full(c_child);
2546
2547 Some(T::from_variant(&child))
2548 } else {
2549 Some(None)
2550 }
2551 } else {
2552 None
2553 }
2554 }
2555 }
2556}
2557
2558impl<T: StaticVariantType> StaticVariantType for [T] {
2559 fn static_variant_type() -> Cow<'static, VariantTy> {
2560 T::static_variant_type().as_array()
2561 }
2562}
2563
2564impl<T: StaticVariantType + ToVariant> ToVariant for [T] {
2565 fn to_variant(&self) -> Variant {
2566 unsafe {
2567 if self.is_empty() {
2568 return from_glib_none(ffi::g_variant_new_array(
2569 T::static_variant_type().to_glib_none().0,
2570 ptr::null(),
2571 0,
2572 ));
2573 }
2574
2575 let mut builder = mem::MaybeUninit::uninit();
2576 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2577 let mut builder = builder.assume_init();
2578 for value in self {
2579 let value = value.to_variant();
2580 ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
2581 }
2582 from_glib_none(ffi::g_variant_builder_end(&mut builder))
2583 }
2584 }
2585}
2586
2587impl<T: StaticVariantType + ToVariant> From<&[T]> for Variant {
2588 #[inline]
2589 fn from(s: &[T]) -> Self {
2590 s.to_variant()
2591 }
2592}
2593
2594impl<T: FromVariant> FromVariant for Vec<T> {
2595 fn from_variant(variant: &Variant) -> Option<Self> {
2596 if !variant.is_container() {
2597 return None;
2598 }
2599
2600 let mut vec = Vec::with_capacity(variant.n_children());
2601
2602 for i in 0..variant.n_children() {
2603 match variant.child_value(i).get() {
2604 Some(child) => vec.push(child),
2605 None => return None,
2606 }
2607 }
2608
2609 Some(vec)
2610 }
2611}
2612
2613impl<T: StaticVariantType + ToVariant> ToVariant for Vec<T> {
2614 fn to_variant(&self) -> Variant {
2615 self.as_slice().to_variant()
2616 }
2617}
2618
2619impl<T: StaticVariantType + Into<Variant>> From<Vec<T>> for Variant {
2620 fn from(v: Vec<T>) -> Self {
2621 unsafe {
2622 if v.is_empty() {
2623 return from_glib_none(ffi::g_variant_new_array(
2624 T::static_variant_type().to_glib_none().0,
2625 ptr::null(),
2626 0,
2627 ));
2628 }
2629
2630 let mut builder = mem::MaybeUninit::uninit();
2631 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2632 let mut builder = builder.assume_init();
2633 for value in v {
2634 let value = value.into();
2635 ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
2636 }
2637 from_glib_none(ffi::g_variant_builder_end(&mut builder))
2638 }
2639 }
2640}
2641
2642impl<T: StaticVariantType> StaticVariantType for Vec<T> {
2643 fn static_variant_type() -> Cow<'static, VariantTy> {
2644 <[T]>::static_variant_type()
2645 }
2646}
2647
2648impl<K, V, H> FromVariant for HashMap<K, V, H>
2649where
2650 K: FromVariant + Eq + Hash,
2651 V: FromVariant,
2652 H: BuildHasher + Default,
2653{
2654 fn from_variant(variant: &Variant) -> Option<Self> {
2655 if !variant.is_container() {
2656 return None;
2657 }
2658
2659 let mut map = HashMap::default();
2660
2661 for i in 0..variant.n_children() {
2662 let entry = variant.child_value(i);
2663 let key = entry.child_value(0).get()?;
2664 let val = entry.child_value(1).get()?;
2665
2666 map.insert(key, val);
2667 }
2668
2669 Some(map)
2670 }
2671}
2672
2673impl<K, V> FromVariant for BTreeMap<K, V>
2674where
2675 K: FromVariant + Eq + Ord,
2676 V: FromVariant,
2677{
2678 fn from_variant(variant: &Variant) -> Option<Self> {
2679 if !variant.is_container() {
2680 return None;
2681 }
2682
2683 let mut map = BTreeMap::default();
2684
2685 for i in 0..variant.n_children() {
2686 let entry = variant.child_value(i);
2687 let key = entry.child_value(0).get()?;
2688 let val = entry.child_value(1).get()?;
2689
2690 map.insert(key, val);
2691 }
2692
2693 Some(map)
2694 }
2695}
2696
2697impl<K, V> ToVariant for HashMap<K, V>
2698where
2699 K: StaticVariantType + ToVariant + Eq + Hash,
2700 V: StaticVariantType + ToVariant,
2701{
2702 fn to_variant(&self) -> Variant {
2703 unsafe {
2704 if self.is_empty() {
2705 return from_glib_none(ffi::g_variant_new_array(
2706 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
2707 ptr::null(),
2708 0,
2709 ));
2710 }
2711
2712 let mut builder = mem::MaybeUninit::uninit();
2713 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2714 let mut builder = builder.assume_init();
2715 for (key, value) in self {
2716 let entry = DictEntry::new(key, value).to_variant();
2717 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
2718 }
2719 from_glib_none(ffi::g_variant_builder_end(&mut builder))
2720 }
2721 }
2722}
2723
2724impl<K, V> From<HashMap<K, V>> for Variant
2725where
2726 K: StaticVariantType + Into<Variant> + Eq + Hash,
2727 V: StaticVariantType + Into<Variant>,
2728{
2729 fn from(m: HashMap<K, V>) -> Self {
2730 unsafe {
2731 if m.is_empty() {
2732 return from_glib_none(ffi::g_variant_new_array(
2733 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
2734 ptr::null(),
2735 0,
2736 ));
2737 }
2738
2739 let mut builder = mem::MaybeUninit::uninit();
2740 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2741 let mut builder = builder.assume_init();
2742 for (key, value) in m {
2743 let entry = Variant::from(DictEntry::new(key, value));
2744 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
2745 }
2746 from_glib_none(ffi::g_variant_builder_end(&mut builder))
2747 }
2748 }
2749}
2750
2751impl<K, V> ToVariant for BTreeMap<K, V>
2752where
2753 K: StaticVariantType + ToVariant + Eq + Hash,
2754 V: StaticVariantType + ToVariant,
2755{
2756 fn to_variant(&self) -> Variant {
2757 unsafe {
2758 if self.is_empty() {
2759 return from_glib_none(ffi::g_variant_new_array(
2760 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
2761 ptr::null(),
2762 0,
2763 ));
2764 }
2765
2766 let mut builder = mem::MaybeUninit::uninit();
2767 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2768 let mut builder = builder.assume_init();
2769 for (key, value) in self {
2770 let entry = DictEntry::new(key, value).to_variant();
2771 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
2772 }
2773 from_glib_none(ffi::g_variant_builder_end(&mut builder))
2774 }
2775 }
2776}
2777
2778impl<K, V> From<BTreeMap<K, V>> for Variant
2779where
2780 K: StaticVariantType + Into<Variant> + Eq + Hash,
2781 V: StaticVariantType + Into<Variant>,
2782{
2783 fn from(m: BTreeMap<K, V>) -> Self {
2784 unsafe {
2785 if m.is_empty() {
2786 return from_glib_none(ffi::g_variant_new_array(
2787 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
2788 ptr::null(),
2789 0,
2790 ));
2791 }
2792
2793 let mut builder = mem::MaybeUninit::uninit();
2794 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2795 let mut builder = builder.assume_init();
2796 for (key, value) in m {
2797 let entry = Variant::from(DictEntry::new(key, value));
2798 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
2799 }
2800 from_glib_none(ffi::g_variant_builder_end(&mut builder))
2801 }
2802 }
2803}
2804
2805/// A Dictionary entry.
2806///
2807/// While GVariant format allows a dictionary entry to be an independent type, typically you'll need
2808/// to use this in a dictionary, which is simply an array of dictionary entries. The following code
2809/// creates a dictionary:
2810///
2811/// ```
2812///# use glib::prelude::*; // or `use gtk::prelude::*;`
2813/// use glib::variant::{Variant, FromVariant, DictEntry};
2814///
2815/// let entries = [
2816/// DictEntry::new("uuid", 1000u32),
2817/// DictEntry::new("guid", 1001u32),
2818/// ];
2819/// let dict = entries.into_iter().collect::<Variant>();
2820/// assert_eq!(dict.n_children(), 2);
2821/// assert_eq!(dict.type_().as_str(), "a{su}");
2822/// ```
2823#[derive(Debug, Clone)]
2824pub struct DictEntry<K, V> {
2825 key: K,
2826 value: V,
2827}
2828
2829impl<K, V> DictEntry<K, V>
2830where
2831 K: StaticVariantType,
2832 V: StaticVariantType,
2833{
2834 pub fn new(key: K, value: V) -> Self {
2835 Self { key, value }
2836 }
2837
2838 pub fn key(&self) -> &K {
2839 &self.key
2840 }
2841
2842 pub fn value(&self) -> &V {
2843 &self.value
2844 }
2845}
2846
2847impl<K, V> FromVariant for DictEntry<K, V>
2848where
2849 K: FromVariant,
2850 V: FromVariant,
2851{
2852 fn from_variant(variant: &Variant) -> Option<Self> {
2853 if !variant.type_().is_subtype_of(VariantTy::DICT_ENTRY) {
2854 return None;
2855 }
2856
2857 let key = variant.child_value(0).get()?;
2858 let value = variant.child_value(1).get()?;
2859
2860 Some(Self { key, value })
2861 }
2862}
2863
2864impl<K, V> ToVariant for DictEntry<K, V>
2865where
2866 K: StaticVariantType + ToVariant,
2867 V: StaticVariantType + ToVariant,
2868{
2869 fn to_variant(&self) -> Variant {
2870 Variant::from_dict_entry(&self.key.to_variant(), &self.value.to_variant())
2871 }
2872}
2873
2874impl<K, V> From<DictEntry<K, V>> for Variant
2875where
2876 K: StaticVariantType + Into<Variant>,
2877 V: StaticVariantType + Into<Variant>,
2878{
2879 fn from(e: DictEntry<K, V>) -> Self {
2880 Variant::from_dict_entry(&e.key.into(), &e.value.into())
2881 }
2882}
2883
2884impl ToVariant for Variant {
2885 fn to_variant(&self) -> Variant {
2886 Variant::from_variant(self)
2887 }
2888}
2889
2890impl FromVariant for Variant {
2891 fn from_variant(variant: &Variant) -> Option<Self> {
2892 variant.as_variant()
2893 }
2894}
2895
2896impl<K: StaticVariantType, V: StaticVariantType> StaticVariantType for DictEntry<K, V> {
2897 fn static_variant_type() -> Cow<'static, VariantTy> {
2898 Cow::Owned(VariantType::new_dict_entry(
2899 &K::static_variant_type(),
2900 &V::static_variant_type(),
2901 ))
2902 }
2903}
2904
2905fn static_variant_mapping<K, V>() -> Cow<'static, VariantTy>
2906where
2907 K: StaticVariantType,
2908 V: StaticVariantType,
2909{
2910 use std::fmt::Write;
2911
2912 let key_type = K::static_variant_type();
2913 let value_type = V::static_variant_type();
2914
2915 if key_type == VariantTy::STRING && value_type == VariantTy::VARIANT {
2916 return Cow::Borrowed(VariantTy::VARDICT);
2917 }
2918
2919 let mut builder = crate::GStringBuilder::default();
2920 write!(builder, "a{{{}{}}}", key_type.as_str(), value_type.as_str()).unwrap();
2921
2922 Cow::Owned(VariantType::from_string(builder.into_string()).unwrap())
2923}
2924
2925impl<K, V, H> StaticVariantType for HashMap<K, V, H>
2926where
2927 K: StaticVariantType,
2928 V: StaticVariantType,
2929 H: BuildHasher + Default,
2930{
2931 fn static_variant_type() -> Cow<'static, VariantTy> {
2932 static_variant_mapping::<K, V>()
2933 }
2934}
2935
2936impl<K, V> StaticVariantType for BTreeMap<K, V>
2937where
2938 K: StaticVariantType,
2939 V: StaticVariantType,
2940{
2941 fn static_variant_type() -> Cow<'static, VariantTy> {
2942 static_variant_mapping::<K, V>()
2943 }
2944}
2945
2946macro_rules! tuple_impls {
2947 ($($len:expr => ($($n:tt $name:ident)+))+) => {
2948 $(
2949 impl<$($name),+> StaticVariantType for ($($name,)+)
2950 where
2951 $($name: StaticVariantType,)+
2952 {
2953 fn static_variant_type() -> Cow<'static, VariantTy> {
2954 Cow::Owned(VariantType::new_tuple(&[
2955 $(
2956 $name::static_variant_type(),
2957 )+
2958 ]))
2959 }
2960 }
2961
2962 impl<$($name),+> FromVariant for ($($name,)+)
2963 where
2964 $($name: FromVariant,)+
2965 {
2966 fn from_variant(variant: &Variant) -> Option<Self> {
2967 if !variant.type_().is_subtype_of(VariantTy::TUPLE) {
2968 return None;
2969 }
2970
2971 Some((
2972 $(
2973 match variant.try_child_get::<$name>($n) {
2974 Ok(Some(field)) => field,
2975 _ => return None,
2976 },
2977 )+
2978 ))
2979 }
2980 }
2981
2982 impl<$($name),+> ToVariant for ($($name,)+)
2983 where
2984 $($name: ToVariant,)+
2985 {
2986 fn to_variant(&self) -> Variant {
2987 unsafe {
2988 let mut builder = mem::MaybeUninit::uninit();
2989 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
2990 let mut builder = builder.assume_init();
2991
2992 $(
2993 let field = self.$n.to_variant();
2994 ffi::g_variant_builder_add_value(&mut builder, field.to_glib_none().0);
2995 )+
2996
2997 from_glib_none(ffi::g_variant_builder_end(&mut builder))
2998 }
2999 }
3000 }
3001
3002 impl<$($name),+> From<($($name,)+)> for Variant
3003 where
3004 $($name: Into<Variant>,)+
3005 {
3006 fn from(t: ($($name,)+)) -> Self {
3007 unsafe {
3008 let mut builder = mem::MaybeUninit::uninit();
3009 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
3010 let mut builder = builder.assume_init();
3011
3012 $(
3013 let field = t.$n.into();
3014 ffi::g_variant_builder_add_value(&mut builder, field.to_glib_none().0);
3015 )+
3016
3017 from_glib_none(ffi::g_variant_builder_end(&mut builder))
3018 }
3019 }
3020 }
3021 )+
3022 }
3023}
3024
3025tuple_impls! {
3026 1 => (0 T0)
3027 2 => (0 T0 1 T1)
3028 3 => (0 T0 1 T1 2 T2)
3029 4 => (0 T0 1 T1 2 T2 3 T3)
3030 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
3031 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
3032 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
3033 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
3034 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
3035 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
3036 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
3037 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
3038 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
3039 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
3040 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
3041 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
3042}
3043
3044impl<T: Into<Variant> + StaticVariantType> FromIterator<T> for Variant {
3045 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
3046 Variant::array_from_iter::<T>(iter.into_iter().map(|v| v.into()))
3047 }
3048}
3049
3050/// Trait for fixed size variant types.
3051pub unsafe trait FixedSizeVariantType: StaticVariantType + Sized + Copy {}
3052unsafe impl FixedSizeVariantType for u8 {}
3053unsafe impl FixedSizeVariantType for i16 {}
3054unsafe impl FixedSizeVariantType for u16 {}
3055unsafe impl FixedSizeVariantType for i32 {}
3056unsafe impl FixedSizeVariantType for u32 {}
3057unsafe impl FixedSizeVariantType for i64 {}
3058unsafe impl FixedSizeVariantType for u64 {}
3059unsafe impl FixedSizeVariantType for f64 {}
3060unsafe impl FixedSizeVariantType for bool {}
3061
3062/// Wrapper type for fixed size type arrays.
3063///
3064/// Converting this from/to a `Variant` is generally more efficient than working on the type
3065/// directly. This is especially important when deriving `Variant` trait implementations on custom
3066/// types.
3067///
3068/// This wrapper type can hold for example `Vec<u8>`, `Box<[u8]>` and similar types.
3069#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
3070pub struct FixedSizeVariantArray<A, T>(A, std::marker::PhantomData<T>)
3071where
3072 A: AsRef<[T]>,
3073 T: FixedSizeVariantType;
3074
3075impl<A: AsRef<[T]>, T: FixedSizeVariantType> From<A> for FixedSizeVariantArray<A, T> {
3076 fn from(array: A) -> Self {
3077 FixedSizeVariantArray(array, std::marker::PhantomData)
3078 }
3079}
3080
3081impl<A: AsRef<[T]>, T: FixedSizeVariantType> FixedSizeVariantArray<A, T> {
3082 pub fn into_inner(self) -> A {
3083 self.0
3084 }
3085}
3086
3087impl<A: AsRef<[T]>, T: FixedSizeVariantType> std::ops::Deref for FixedSizeVariantArray<A, T> {
3088 type Target = A;
3089
3090 #[inline]
3091 fn deref(&self) -> &Self::Target {
3092 &self.0
3093 }
3094}
3095
3096impl<A: AsRef<[T]>, T: FixedSizeVariantType> std::ops::DerefMut for FixedSizeVariantArray<A, T> {
3097 #[inline]
3098 fn deref_mut(&mut self) -> &mut Self::Target {
3099 &mut self.0
3100 }
3101}
3102
3103impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsRef<A> for FixedSizeVariantArray<A, T> {
3104 #[inline]
3105 fn as_ref(&self) -> &A {
3106 &self.0
3107 }
3108}
3109
3110impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsMut<A> for FixedSizeVariantArray<A, T> {
3111 #[inline]
3112 fn as_mut(&mut self) -> &mut A {
3113 &mut self.0
3114 }
3115}
3116
3117impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsRef<[T]> for FixedSizeVariantArray<A, T> {
3118 #[inline]
3119 fn as_ref(&self) -> &[T] {
3120 self.0.as_ref()
3121 }
3122}
3123
3124impl<A: AsRef<[T]> + AsMut<[T]>, T: FixedSizeVariantType> AsMut<[T]>
3125 for FixedSizeVariantArray<A, T>
3126{
3127 #[inline]
3128 fn as_mut(&mut self) -> &mut [T] {
3129 self.0.as_mut()
3130 }
3131}
3132
3133impl<A: AsRef<[T]>, T: FixedSizeVariantType> StaticVariantType for FixedSizeVariantArray<A, T> {
3134 fn static_variant_type() -> Cow<'static, VariantTy> {
3135 <[T]>::static_variant_type()
3136 }
3137}
3138
3139impl<A: AsRef<[T]> + for<'a> From<&'a [T]>, T: FixedSizeVariantType> FromVariant
3140 for FixedSizeVariantArray<A, T>
3141{
3142 fn from_variant(variant: &Variant) -> Option<Self> {
3143 Some(FixedSizeVariantArray(
3144 A::from(variant.fixed_array::<T>().ok()?),
3145 std::marker::PhantomData,
3146 ))
3147 }
3148}
3149
3150impl<A: AsRef<[T]>, T: FixedSizeVariantType> ToVariant for FixedSizeVariantArray<A, T> {
3151 fn to_variant(&self) -> Variant {
3152 Variant::array_from_fixed_array(self.0.as_ref())
3153 }
3154}
3155
3156impl<A: AsRef<[T]>, T: FixedSizeVariantType> From<FixedSizeVariantArray<A, T>> for Variant {
3157 #[doc(alias = "g_variant_new_from_data")]
3158 fn from(a: FixedSizeVariantArray<A, T>) -> Self {
3159 unsafe {
3160 let data = Box::new(a.0);
3161 let (data_ptr, len) = {
3162 let data = (*data).as_ref();
3163 (data.as_ptr(), mem::size_of_val(data))
3164 };
3165
3166 unsafe extern "C" fn free_data<A: AsRef<[T]>, T: FixedSizeVariantType>(
3167 ptr: ffi::gpointer,
3168 ) {
3169 let _ = Box::from_raw(ptr as *mut A);
3170 }
3171
3172 from_glib_none(ffi::g_variant_new_from_data(
3173 T::static_variant_type().to_glib_none().0,
3174 data_ptr as ffi::gconstpointer,
3175 len,
3176 false.into_glib(),
3177 Some(free_data::<A, T>),
3178 Box::into_raw(data) as ffi::gpointer,
3179 ))
3180 }
3181 }
3182}
3183
3184/// A wrapper type around `Variant` handles.
3185#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
3186pub struct Handle(pub i32);
3187
3188impl From<i32> for Handle {
3189 fn from(v: i32) -> Self {
3190 Handle(v)
3191 }
3192}
3193
3194impl From<Handle> for i32 {
3195 fn from(v: Handle) -> Self {
3196 v.0
3197 }
3198}
3199
3200impl StaticVariantType for Handle {
3201 fn static_variant_type() -> Cow<'static, VariantTy> {
3202 Cow::Borrowed(VariantTy::HANDLE)
3203 }
3204}
3205
3206impl ToVariant for Handle {
3207 fn to_variant(&self) -> Variant {
3208 unsafe { from_glib_none(ffi::g_variant_new_handle(self.0)) }
3209 }
3210}
3211
3212impl From<Handle> for Variant {
3213 #[inline]
3214 fn from(h: Handle) -> Self {
3215 h.to_variant()
3216 }
3217}
3218
3219impl FromVariant for Handle {
3220 fn from_variant(variant: &Variant) -> Option<Self> {
3221 unsafe {
3222 if variant.is::<Self>() {
3223 Some(Handle(ffi::g_variant_get_handle(variant.to_glib_none().0)))
3224 } else {
3225 None
3226 }
3227 }
3228 }
3229}
3230
3231/// A wrapper type around `Variant` object paths.
3232///
3233/// Values of these type are guaranteed to be valid object paths.
3234#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
3235pub struct ObjectPath(String);
3236
3237impl ObjectPath {
3238 pub fn as_str(&self) -> &str {
3239 &self.0
3240 }
3241}
3242
3243impl Display for ObjectPath {
3244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3245 self.0.fmt(f)
3246 }
3247}
3248
3249impl std::ops::Deref for ObjectPath {
3250 type Target = str;
3251
3252 #[inline]
3253 fn deref(&self) -> &Self::Target {
3254 &self.0
3255 }
3256}
3257
3258impl TryFrom<String> for ObjectPath {
3259 type Error = crate::BoolError;
3260
3261 fn try_from(v: String) -> Result<Self, Self::Error> {
3262 if !Variant::is_object_path(&v) {
3263 return Err(bool_error!("Invalid object path"));
3264 }
3265
3266 Ok(ObjectPath(v))
3267 }
3268}
3269
3270impl<'a> TryFrom<&'a str> for ObjectPath {
3271 type Error = crate::BoolError;
3272
3273 fn try_from(v: &'a str) -> Result<Self, Self::Error> {
3274 ObjectPath::try_from(String::from(v))
3275 }
3276}
3277
3278impl From<ObjectPath> for String {
3279 fn from(v: ObjectPath) -> Self {
3280 v.0
3281 }
3282}
3283
3284impl StaticVariantType for ObjectPath {
3285 fn static_variant_type() -> Cow<'static, VariantTy> {
3286 Cow::Borrowed(VariantTy::OBJECT_PATH)
3287 }
3288}
3289
3290impl ToVariant for ObjectPath {
3291 fn to_variant(&self) -> Variant {
3292 unsafe { from_glib_none(ffi::g_variant_new_object_path(self.0.to_glib_none().0)) }
3293 }
3294}
3295
3296impl From<ObjectPath> for Variant {
3297 #[inline]
3298 fn from(p: ObjectPath) -> Self {
3299 let mut s = p.0;
3300 s.push('\0');
3301 unsafe { Self::from_data_trusted::<ObjectPath, _>(s) }
3302 }
3303}
3304
3305impl FromVariant for ObjectPath {
3306 #[allow(unused_unsafe)]
3307 fn from_variant(variant: &Variant) -> Option<Self> {
3308 unsafe {
3309 if variant.is::<Self>() {
3310 Some(ObjectPath(String::from(variant.str().unwrap())))
3311 } else {
3312 None
3313 }
3314 }
3315 }
3316}
3317
3318/// A wrapper type around `Variant` signatures.
3319///
3320/// Values of these type are guaranteed to be valid signatures.
3321#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
3322pub struct Signature(String);
3323
3324impl Signature {
3325 pub fn as_str(&self) -> &str {
3326 &self.0
3327 }
3328}
3329
3330impl std::ops::Deref for Signature {
3331 type Target = str;
3332
3333 #[inline]
3334 fn deref(&self) -> &Self::Target {
3335 &self.0
3336 }
3337}
3338
3339impl TryFrom<String> for Signature {
3340 type Error = crate::BoolError;
3341
3342 fn try_from(v: String) -> Result<Self, Self::Error> {
3343 if !Variant::is_signature(&v) {
3344 return Err(bool_error!("Invalid signature"));
3345 }
3346
3347 Ok(Signature(v))
3348 }
3349}
3350
3351impl<'a> TryFrom<&'a str> for Signature {
3352 type Error = crate::BoolError;
3353
3354 fn try_from(v: &'a str) -> Result<Self, Self::Error> {
3355 Signature::try_from(String::from(v))
3356 }
3357}
3358
3359impl From<Signature> for String {
3360 fn from(v: Signature) -> Self {
3361 v.0
3362 }
3363}
3364
3365impl StaticVariantType for Signature {
3366 fn static_variant_type() -> Cow<'static, VariantTy> {
3367 Cow::Borrowed(VariantTy::SIGNATURE)
3368 }
3369}
3370
3371impl ToVariant for Signature {
3372 fn to_variant(&self) -> Variant {
3373 unsafe { from_glib_none(ffi::g_variant_new_signature(self.0.to_glib_none().0)) }
3374 }
3375}
3376
3377impl From<Signature> for Variant {
3378 #[inline]
3379 fn from(s: Signature) -> Self {
3380 let mut s = s.0;
3381 s.push('\0');
3382 unsafe { Self::from_data_trusted::<Signature, _>(s) }
3383 }
3384}
3385
3386impl FromVariant for Signature {
3387 #[allow(unused_unsafe)]
3388 fn from_variant(variant: &Variant) -> Option<Self> {
3389 unsafe {
3390 if variant.is::<Self>() {
3391 Some(Signature(String::from(variant.str().unwrap())))
3392 } else {
3393 None
3394 }
3395 }
3396 }
3397}
3398
3399#[cfg(test)]
3400mod tests {
3401 use std::collections::{HashMap, HashSet};
3402
3403 use super::*;
3404
3405 macro_rules! unsigned {
3406 ($name:ident, $ty:ident) => {
3407 #[test]
3408 fn $name() {
3409 let mut n = $ty::MAX;
3410 while n > 0 {
3411 let v = n.to_variant();
3412 assert_eq!(v.get(), Some(n));
3413 n /= 2;
3414 }
3415 }
3416 };
3417 }
3418
3419 macro_rules! signed {
3420 ($name:ident, $ty:ident) => {
3421 #[test]
3422 fn $name() {
3423 let mut n = $ty::MAX;
3424 while n > 0 {
3425 let v = n.to_variant();
3426 assert_eq!(v.get(), Some(n));
3427 let v = (-n).to_variant();
3428 assert_eq!(v.get(), Some(-n));
3429 n /= 2;
3430 }
3431 }
3432 };
3433 }
3434
3435 unsigned!(test_u8, u8);
3436 unsigned!(test_u16, u16);
3437 unsigned!(test_u32, u32);
3438 unsigned!(test_u64, u64);
3439 signed!(test_i16, i16);
3440 signed!(test_i32, i32);
3441 signed!(test_i64, i64);
3442
3443 #[test]
3444 fn test_str() {
3445 let s = "this is a test";
3446 let v = s.to_variant();
3447 assert_eq!(v.str(), Some(s));
3448 assert_eq!(42u32.to_variant().str(), None);
3449 }
3450
3451 #[test]
3452 fn test_fixed_array() {
3453 let b = b"this is a test";
3454 let v = Variant::array_from_fixed_array(&b[..]);
3455 assert_eq!(v.type_().as_str(), "ay");
3456 assert_eq!(v.fixed_array::<u8>().unwrap(), b);
3457 assert!(42u32.to_variant().fixed_array::<u8>().is_err());
3458
3459 let b = [1u32, 10u32, 100u32];
3460 let v = Variant::array_from_fixed_array(&b);
3461 assert_eq!(v.type_().as_str(), "au");
3462 assert_eq!(v.fixed_array::<u32>().unwrap(), b);
3463 assert!(v.fixed_array::<u8>().is_err());
3464
3465 let b = [true, false, true];
3466 let v = Variant::array_from_fixed_array(&b);
3467 assert_eq!(v.type_().as_str(), "ab");
3468 assert_eq!(v.fixed_array::<bool>().unwrap(), b);
3469 assert!(v.fixed_array::<u8>().is_err());
3470
3471 let b = [1.0f64, 2.0f64, 3.0f64];
3472 let v = Variant::array_from_fixed_array(&b);
3473 assert_eq!(v.type_().as_str(), "ad");
3474 #[allow(clippy::float_cmp)]
3475 {
3476 assert_eq!(v.fixed_array::<f64>().unwrap(), b);
3477 }
3478 assert!(v.fixed_array::<u64>().is_err());
3479 }
3480
3481 #[test]
3482 fn test_fixed_variant_array() {
3483 let b = FixedSizeVariantArray::from(&b"this is a test"[..]);
3484 let v = b.to_variant();
3485 assert_eq!(v.type_().as_str(), "ay");
3486 assert_eq!(
3487 &*v.get::<FixedSizeVariantArray<Vec<u8>, u8>>().unwrap(),
3488 &*b
3489 );
3490
3491 let b = FixedSizeVariantArray::from(vec![1i32, 2, 3]);
3492 let v = b.to_variant();
3493 assert_eq!(v.type_().as_str(), "ai");
3494 assert_eq!(v.get::<FixedSizeVariantArray<Vec<i32>, i32>>().unwrap(), b);
3495 }
3496
3497 #[test]
3498 fn test_string() {
3499 let s = String::from("this is a test");
3500 let v = s.to_variant();
3501 assert_eq!(v.get(), Some(s));
3502 assert_eq!(v.normal_form(), v);
3503 }
3504
3505 #[test]
3506 fn test_eq() {
3507 let v1 = "this is a test".to_variant();
3508 let v2 = "this is a test".to_variant();
3509 let v3 = "test".to_variant();
3510 assert_eq!(v1, v2);
3511 assert_ne!(v1, v3);
3512 }
3513
3514 #[test]
3515 fn test_hash() {
3516 let v1 = "this is a test".to_variant();
3517 let v2 = "this is a test".to_variant();
3518 let v3 = "test".to_variant();
3519 let mut set = HashSet::new();
3520 set.insert(v1);
3521 assert!(set.contains(&v2));
3522 assert!(!set.contains(&v3));
3523
3524 assert_eq!(
3525 <HashMap<&str, (&str, u8, u32)>>::static_variant_type().as_str(),
3526 "a{s(syu)}"
3527 );
3528 }
3529
3530 #[test]
3531 fn test_array() {
3532 assert_eq!(<Vec<&str>>::static_variant_type().as_str(), "as");
3533 assert_eq!(
3534 <Vec<(&str, u8, u32)>>::static_variant_type().as_str(),
3535 "a(syu)"
3536 );
3537 let a = ["foo", "bar", "baz"].to_variant();
3538 assert_eq!(a.normal_form(), a);
3539 assert_eq!(a.array_iter_str().unwrap().len(), 3);
3540 let o = 0u32.to_variant();
3541 assert!(o.array_iter_str().is_err());
3542 }
3543
3544 #[test]
3545 fn test_array_from_iter() {
3546 let a = Variant::array_from_iter::<String>(
3547 ["foo", "bar", "baz"].into_iter().map(|s| s.to_variant()),
3548 );
3549 assert_eq!(a.type_().as_str(), "as");
3550 assert_eq!(a.n_children(), 3);
3551
3552 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
3553 assert_eq!(a.try_child_get::<String>(1), Ok(Some(String::from("bar"))));
3554 assert_eq!(a.try_child_get::<String>(2), Ok(Some(String::from("baz"))));
3555 }
3556
3557 #[test]
3558 fn test_array_collect() {
3559 let a = ["foo", "bar", "baz"].into_iter().collect::<Variant>();
3560 assert_eq!(a.type_().as_str(), "as");
3561 assert_eq!(a.n_children(), 3);
3562
3563 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
3564 assert_eq!(a.try_child_get::<String>(1), Ok(Some(String::from("bar"))));
3565 assert_eq!(a.try_child_get::<String>(2), Ok(Some(String::from("baz"))));
3566 }
3567
3568 #[test]
3569 fn test_tuple() {
3570 assert_eq!(<(&str, u32)>::static_variant_type().as_str(), "(su)");
3571 assert_eq!(<(&str, u8, u32)>::static_variant_type().as_str(), "(syu)");
3572 let a = ("test", 1u8, 2u32).to_variant();
3573 assert_eq!(a.normal_form(), a);
3574 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("test"))));
3575 assert_eq!(a.try_child_get::<u8>(1), Ok(Some(1u8)));
3576 assert_eq!(a.try_child_get::<u32>(2), Ok(Some(2u32)));
3577 assert_eq!(
3578 a.try_get::<(String, u8, u32)>(),
3579 Ok((String::from("test"), 1u8, 2u32))
3580 );
3581 }
3582
3583 #[test]
3584 fn test_tuple_from_iter() {
3585 let a = Variant::tuple_from_iter(["foo".to_variant(), 1u8.to_variant(), 2i32.to_variant()]);
3586 assert_eq!(a.type_().as_str(), "(syi)");
3587 assert_eq!(a.n_children(), 3);
3588
3589 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
3590 assert_eq!(a.try_child_get::<u8>(1), Ok(Some(1u8)));
3591 assert_eq!(a.try_child_get::<i32>(2), Ok(Some(2i32)));
3592 }
3593
3594 #[test]
3595 fn test_empty() {
3596 assert_eq!(<()>::static_variant_type().as_str(), "()");
3597 let a = ().to_variant();
3598 assert_eq!(a.type_().as_str(), "()");
3599 assert_eq!(a.get::<()>(), Some(()));
3600 }
3601
3602 #[test]
3603 fn test_maybe() {
3604 assert!(<Option<()>>::static_variant_type().is_maybe());
3605 let m1 = Some(()).to_variant();
3606 assert_eq!(m1.type_().as_str(), "m()");
3607
3608 assert_eq!(m1.get::<Option<()>>(), Some(Some(())));
3609 assert!(m1.as_maybe().is_some());
3610
3611 let m2 = None::<()>.to_variant();
3612 assert!(m2.as_maybe().is_none());
3613 }
3614
3615 #[test]
3616 fn test_btreemap() {
3617 assert_eq!(
3618 <BTreeMap<String, u32>>::static_variant_type().as_str(),
3619 "a{su}"
3620 );
3621 // Validate that BTreeMap adds entries to dict in sorted order
3622 let mut m = BTreeMap::new();
3623 let total = 20;
3624 for n in 0..total {
3625 let k = format!("v{n:04}");
3626 m.insert(k, n as u32);
3627 }
3628 let v = m.to_variant();
3629 let n = v.n_children();
3630 assert_eq!(total, n);
3631 for n in 0..total {
3632 let child = v
3633 .try_child_get::<DictEntry<String, u32>>(n)
3634 .unwrap()
3635 .unwrap();
3636 assert_eq!(*child.value(), n as u32);
3637 }
3638
3639 assert_eq!(BTreeMap::from_variant(&v).unwrap(), m);
3640 }
3641
3642 #[test]
3643 fn test_get() -> Result<(), Box<dyn std::error::Error>> {
3644 let u = 42u32.to_variant();
3645 assert!(u.get::<i32>().is_none());
3646 assert_eq!(u.get::<u32>().unwrap(), 42);
3647 assert!(u.try_get::<i32>().is_err());
3648 // Test ? conversion
3649 assert_eq!(u.try_get::<u32>()?, 42);
3650 Ok(())
3651 }
3652
3653 #[test]
3654 fn test_byteswap() {
3655 let u = 42u32.to_variant();
3656 assert_eq!(u.byteswap().get::<u32>().unwrap(), 704643072u32);
3657 assert_eq!(u.byteswap().byteswap().get::<u32>().unwrap(), 42u32);
3658 }
3659
3660 #[test]
3661 fn test_try_child() {
3662 let a = ["foo"].to_variant();
3663 assert!(a.try_child_value(0).is_some());
3664 assert_eq!(a.try_child_get::<String>(0).unwrap().unwrap(), "foo");
3665 assert_eq!(a.child_get::<String>(0), "foo");
3666 assert!(a.try_child_get::<u32>(0).is_err());
3667 assert!(a.try_child_value(1).is_none());
3668 assert!(a.try_child_get::<String>(1).unwrap().is_none());
3669 let u = 42u32.to_variant();
3670 assert!(u.try_child_value(0).is_none());
3671 assert!(u.try_child_get::<String>(0).unwrap().is_none());
3672 }
3673
3674 #[test]
3675 fn test_serialize() {
3676 let a = ("test", 1u8, 2u32).to_variant();
3677
3678 let bytes = a.data_as_bytes();
3679 let data = a.data();
3680 let len = a.size();
3681 assert_eq!(bytes.len(), len);
3682 assert_eq!(data.len(), len);
3683
3684 let mut store_data = vec![0u8; len];
3685 assert_eq!(a.store(&mut store_data).unwrap(), len);
3686
3687 assert_eq!(&bytes, data);
3688 assert_eq!(&store_data, data);
3689
3690 let b = Variant::from_data::<(String, u8, u32), _>(store_data);
3691 assert_eq!(a, b);
3692
3693 let c = Variant::from_bytes::<(String, u8, u32)>(&bytes);
3694 assert_eq!(a, c);
3695 }
3696
3697 #[test]
3698 fn test_print_parse() {
3699 let a = ("test", 1u8, 2u32).to_variant();
3700
3701 let a2 = Variant::parse(Some(a.type_()), &a.print(false)).unwrap();
3702 assert_eq!(a, a2);
3703
3704 let a3: Variant = a.to_string().parse().unwrap();
3705 assert_eq!(a, a3);
3706 }
3707
3708 #[cfg(any(unix, windows))]
3709 #[test]
3710 fn test_paths() {
3711 use std::path::PathBuf;
3712
3713 let path = PathBuf::from("foo");
3714 let v = path.to_variant();
3715 assert_eq!(PathBuf::from_variant(&v), Some(path));
3716 }
3717
3718 #[test]
3719 fn test_regression_from_variant_panics() {
3720 let variant = "text".to_variant();
3721 let hashmap: Option<HashMap<u64, u64>> = FromVariant::from_variant(&variant);
3722 assert!(hashmap.is_none());
3723
3724 let variant = HashMap::<u64, u64>::new().to_variant();
3725 let hashmap: Option<HashMap<u64, u64>> = FromVariant::from_variant(&variant);
3726 assert!(hashmap.is_some());
3727 }
3728}