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