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