zvariant_utils/signature/
mod.rs

1mod child;
2pub use child::Child;
3mod fields;
4pub use fields::Fields;
5mod error;
6pub use error::Error;
7
8use serde::{Deserialize, Serialize};
9
10use core::fmt;
11use std::{
12    fmt::{Display, Formatter},
13    hash::Hash,
14    str::FromStr,
15};
16
17use crate::serialized::Format;
18
19/// A D-Bus signature in parsed form.
20///
21/// This is similar to the [`zvariant::Signature`] type, but unlike `zvariant::Signature`, this is a
22/// parsed representation of a signature. Our (de)serialization API primarily uses this type for
23/// efficiency.
24///
25/// # Examples
26///
27/// ## Using the `signature!` macro
28///
29/// The recommended way to create a `Signature` is using the [`signature!`] macro, which provides
30/// compile-time validation and can be used in const contexts:
31///
32/// ```
33/// use zvariant::signature;
34/// use zvariant::Signature;
35///
36/// // Compile-time validated signatures
37/// let sig = signature!("a{sv}");
38/// assert_eq!(sig.to_string(), "a{sv}");
39///
40/// let sig = signature!("(xa{bs}as)");
41/// assert_eq!(sig.to_string(), "(xa{bs}as)");
42///
43/// // Can be used in const contexts
44/// const SIGNATURE: Signature = signature!("a{sv}");
45/// ```
46///
47/// ## Creating from a string at runtime
48///
49/// If you need to create a `Signature` from a runtime string, use `from_str`:
50///
51/// ```
52/// use std::str::FromStr;
53/// use zvariant::Signature;
54///
55/// let sig = Signature::from_str("a{sv}").unwrap();
56/// assert_eq!(sig.to_string(), "a{sv}");
57/// ```
58///
59/// [`signature!`]: https://docs.rs/zvariant/latest/zvariant/macro.signature.html
60/// [`zvariant::Signature`]: https://docs.rs/zvariant/latest/zvariant/struct.Signature.html
61#[derive(Debug, Default, Clone)]
62pub enum Signature {
63    // Basic types
64    /// The signature for the unit type (`()`). This is not a valid D-Bus signature, but is used to
65    /// represnt "no data" (for example, a D-Bus method call without any arguments will have this
66    /// as its body signature).
67    ///
68    /// # Warning
69    ///
70    /// This variant only exists for convenience and must only be used as a top-level signature. If
71    /// used inside container signatures, it will cause errors and in somce cases, panics. It's
72    /// best to not use it directly.
73    #[default]
74    Unit,
75    /// The signature for an 8-bit unsigned integer (AKA a byte).
76    U8,
77    /// The signature for a boolean.
78    Bool,
79    /// The signature for a 16-bit signed integer.
80    I16,
81    /// The signature for a 16-bit unsigned integer.
82    U16,
83    /// The signature for a 32-bit signed integer.
84    I32,
85    /// The signature for a 32-bit unsigned integer.
86    U32,
87    /// The signature for a 64-bit signed integer.
88    I64,
89    /// The signature for a 64-bit unsigned integer.
90    U64,
91    /// The signature for a 64-bit floating point number.
92    F64,
93    /// The signature for a string.
94    Str,
95    /// The signature for a signature.
96    Signature,
97    /// The signature for an object path.
98    ObjectPath,
99    /// The signature for a variant.
100    Variant,
101    /// The signature for a file descriptor.
102    #[cfg(unix)]
103    Fd,
104
105    // Container types
106    /// The signature for an array.
107    Array(Child),
108    /// The signature for a dictionary.
109    Dict {
110        /// The signature for the key.
111        key: Child,
112        /// The signature for the value.
113        value: Child,
114    },
115    /// The signature for a structure.
116    Structure(Fields),
117    /// The signature for a maybe type (gvariant-specific).
118    #[cfg(feature = "gvariant")]
119    Maybe(Child),
120}
121
122impl Signature {
123    /// The size of the string form of `self`.
124    pub const fn string_len(&self) -> usize {
125        match self {
126            Signature::Unit => 0,
127            Signature::U8
128            | Signature::Bool
129            | Signature::I16
130            | Signature::U16
131            | Signature::I32
132            | Signature::U32
133            | Signature::I64
134            | Signature::U64
135            | Signature::F64
136            | Signature::Str
137            | Signature::Signature
138            | Signature::ObjectPath
139            | Signature::Variant => 1,
140            #[cfg(unix)]
141            Signature::Fd => 1,
142            Signature::Array(child) => 1 + child.string_len(),
143            Signature::Dict { key, value } => 3 + key.string_len() + value.string_len(),
144            Signature::Structure(fields) => {
145                let mut len = 2;
146                let mut i = 0;
147                while i < fields.len() {
148                    len += match fields {
149                        Fields::Static { fields } => fields[i].string_len(),
150                        Fields::Dynamic { fields } => fields[i].string_len(),
151                    };
152                    i += 1;
153                }
154                len
155            }
156            #[cfg(feature = "gvariant")]
157            Signature::Maybe(child) => 1 + child.string_len(),
158        }
159    }
160
161    /// Write the string form of `self` to the given formatter.
162    ///
163    /// This produces the same output as the `Display::fmt`, unless `self` is a
164    /// [`Signature::Structure`], in which case the written string will **not** be wrapped in
165    /// parenthesis (`()`).
166    pub fn write_as_string_no_parens(&self, write: &mut impl std::fmt::Write) -> fmt::Result {
167        self.write_as_string(write, false)
168    }
169
170    /// Convert `self` to a string, without any enclosing parenthesis.
171    ///
172    /// This produces the same output as the [`Signature::to_string`], unless `self` is a
173    /// [`Signature::Structure`], in which case the written string will **not** be wrapped in
174    /// parenthesis (`()`).
175    pub fn to_string_no_parens(&self) -> String {
176        let mut s = String::with_capacity(self.string_len());
177        self.write_as_string(&mut s, false).unwrap();
178
179        s
180    }
181
182    /// Convert `self` to a string.
183    ///
184    /// This produces the same output as the `ToString::to_string`, except it preallocates the
185    /// required memory and hence avoids reallocations and moving of data.
186    #[allow(clippy::inherent_to_string_shadow_display)]
187    pub fn to_string(&self) -> String {
188        let mut s = String::with_capacity(self.string_len());
189        self.write_as_string(&mut s, true).unwrap();
190
191        s
192    }
193
194    /// Parse signature from a byte slice.
195    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
196        parse(bytes, false)
197    }
198
199    /// Create a `Signature::Structure` for a given set of field signatures.
200    pub fn structure<F>(fields: F) -> Self
201    where
202        F: Into<Fields>,
203    {
204        Signature::Structure(fields.into())
205    }
206
207    /// Create a `Signature::Structure` for a given set of static field signatures.
208    pub const fn static_structure(fields: &'static [&'static Signature]) -> Self {
209        Signature::Structure(Fields::Static { fields })
210    }
211
212    /// Create a `Signature::Array` for a given child signature.
213    pub fn array<C>(child: C) -> Self
214    where
215        C: Into<Child>,
216    {
217        Signature::Array(child.into())
218    }
219
220    /// Create a `Signature::Array` for a given static child signature.
221    pub const fn static_array(child: &'static Signature) -> Self {
222        Signature::Array(Child::Static { child })
223    }
224
225    /// Create a `Signature::Dict` for a given key and value signatures.
226    pub fn dict<K, V>(key: K, value: V) -> Self
227    where
228        K: Into<Child>,
229        V: Into<Child>,
230    {
231        Signature::Dict {
232            key: key.into(),
233            value: value.into(),
234        }
235    }
236
237    /// Create a `Signature::Dict` for a given static key and value signatures.
238    pub const fn static_dict(key: &'static Signature, value: &'static Signature) -> Self {
239        Signature::Dict {
240            key: Child::Static { child: key },
241            value: Child::Static { child: value },
242        }
243    }
244
245    /// Create a `Signature::Maybe` for a given child signature.
246    #[cfg(feature = "gvariant")]
247    pub fn maybe<C>(child: C) -> Self
248    where
249        C: Into<Child>,
250    {
251        Signature::Maybe(child.into())
252    }
253
254    /// Create a `Signature::Maybe` for a given static child signature.
255    #[cfg(feature = "gvariant")]
256    pub const fn static_maybe(child: &'static Signature) -> Self {
257        Signature::Maybe(Child::Static { child })
258    }
259
260    /// The required padding alignment for the given format.
261    pub fn alignment(&self, format: Format) -> usize {
262        match format {
263            Format::DBus => self.alignment_dbus(),
264            #[cfg(feature = "gvariant")]
265            Format::GVariant => self.alignment_gvariant(),
266        }
267    }
268
269    fn alignment_dbus(&self) -> usize {
270        match self {
271            Signature::U8 | Signature::Variant | Signature::Signature => 1,
272            Signature::I16 | Signature::U16 => 2,
273            Signature::I32
274            | Signature::U32
275            | Signature::Bool
276            | Signature::Str
277            | Signature::ObjectPath
278            | Signature::Array(_)
279            | Signature::Dict { .. } => 4,
280            Signature::I64
281            | Signature::U64
282            | Signature::F64
283            | Signature::Unit
284            | Signature::Structure(_) => 8,
285            #[cfg(unix)]
286            Signature::Fd => 4,
287            #[cfg(feature = "gvariant")]
288            Signature::Maybe(_) => unreachable!("Maybe type is not supported in D-Bus"),
289        }
290    }
291
292    #[cfg(feature = "gvariant")]
293    fn alignment_gvariant(&self) -> usize {
294        use std::cmp::max;
295
296        match self {
297            Signature::Unit
298            | Signature::U8
299            | Signature::I16
300            | Signature::U16
301            | Signature::I32
302            | Signature::U32
303            | Signature::F64
304            | Signature::Bool
305            | Signature::I64
306            | Signature::U64
307            | Signature::Signature => self.alignment_dbus(),
308            #[cfg(unix)]
309            Signature::Fd => self.alignment_dbus(),
310            Signature::Str | Signature::ObjectPath => 1,
311            Signature::Variant => 8,
312            Signature::Array(child) | Signature::Maybe(child) => child.alignment_gvariant(),
313            Signature::Dict { key, value } => {
314                max(key.alignment_gvariant(), value.alignment_gvariant())
315            }
316            Signature::Structure(fields) => fields
317                .iter()
318                .map(Signature::alignment_gvariant)
319                .max()
320                .unwrap_or(1),
321        }
322    }
323
324    /// Check if the signature is of a fixed-sized type.
325    #[cfg(feature = "gvariant")]
326    pub fn is_fixed_sized(&self) -> bool {
327        match self {
328            Signature::Unit
329            | Signature::U8
330            | Signature::Bool
331            | Signature::I16
332            | Signature::U16
333            | Signature::I32
334            | Signature::U32
335            | Signature::I64
336            | Signature::U64
337            | Signature::F64 => true,
338            #[cfg(unix)]
339            Signature::Fd => true,
340            Signature::Str
341            | Signature::Signature
342            | Signature::ObjectPath
343            | Signature::Variant
344            | Signature::Array(_)
345            | Signature::Dict { .. }
346            | Signature::Maybe(_) => false,
347            Signature::Structure(fields) => fields.iter().all(|f| f.is_fixed_sized()),
348        }
349    }
350
351    fn write_as_string(&self, w: &mut impl std::fmt::Write, outer_parens: bool) -> fmt::Result {
352        match self {
353            Signature::Unit => write!(w, ""),
354            Signature::U8 => write!(w, "y"),
355            Signature::Bool => write!(w, "b"),
356            Signature::I16 => write!(w, "n"),
357            Signature::U16 => write!(w, "q"),
358            Signature::I32 => write!(w, "i"),
359            Signature::U32 => write!(w, "u"),
360            Signature::I64 => write!(w, "x"),
361            Signature::U64 => write!(w, "t"),
362            Signature::F64 => write!(w, "d"),
363            Signature::Str => write!(w, "s"),
364            Signature::Signature => write!(w, "g"),
365            Signature::ObjectPath => write!(w, "o"),
366            Signature::Variant => write!(w, "v"),
367            #[cfg(unix)]
368            Signature::Fd => write!(w, "h"),
369            Signature::Array(array) => write!(w, "a{}", **array),
370            Signature::Dict { key, value } => {
371                write!(w, "a{{")?;
372                write!(w, "{}{}", **key, **value)?;
373                write!(w, "}}")
374            }
375            Signature::Structure(fields) => {
376                if outer_parens {
377                    write!(w, "(")?;
378                }
379                for field in fields.iter() {
380                    write!(w, "{field}")?;
381                }
382                if outer_parens {
383                    write!(w, ")")?;
384                }
385
386                Ok(())
387            }
388            #[cfg(feature = "gvariant")]
389            Signature::Maybe(maybe) => write!(w, "m{}", **maybe),
390        }
391    }
392}
393
394impl Display for Signature {
395    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
396        self.write_as_string(f, true)
397    }
398}
399
400impl FromStr for Signature {
401    type Err = Error;
402
403    fn from_str(s: &str) -> Result<Self, Self::Err> {
404        parse(s.as_bytes(), false)
405    }
406}
407
408impl TryFrom<&str> for Signature {
409    type Error = Error;
410
411    fn try_from(value: &str) -> Result<Self, Self::Error> {
412        Signature::from_str(value)
413    }
414}
415
416impl TryFrom<&[u8]> for Signature {
417    type Error = Error;
418
419    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
420        parse(value, false)
421    }
422}
423
424/// Validate the given signature string.
425pub fn validate(bytes: &[u8]) -> Result<(), Error> {
426    parse(bytes, true).map(|_| ())
427}
428
429/// Parse a signature string into a `Signature`.
430///
431/// When `check_only` is true, the function will not allocate memory for the dynamic types.
432/// Instead it will return dummy values in the parsed Signature.
433fn parse(bytes: &[u8], check_only: bool) -> Result<Signature, Error> {
434    use winnow::{
435        Parser,
436        combinator::{alt, delimited, empty, eof, fail, repeat},
437        dispatch,
438        token::any,
439    };
440
441    let unit = eof.map(|_| Signature::Unit);
442
443    // `many1` allocates so we only want to use it when `check_only == false`
444    type ManyError = winnow::error::ErrMode<()>;
445    fn many(bytes: &mut &[u8], check_only: bool, top_level: bool) -> Result<Signature, ManyError> {
446        let parser = |s: &mut _| parse_signature(s, check_only);
447        if check_only {
448            return repeat(1.., parser)
449                .map(|_: ()| Signature::Unit)
450                .parse_next(bytes);
451        }
452
453        // Avoid the allocation of `Vec<Signature>` in case of a single signature on the top-level.
454        // This is a a very common case, especially in variants, where the signature needs to be
455        // parsed at runtime.
456        enum SignatureList {
457            Unit,
458            One(Signature),
459            Structure(Vec<Signature>),
460        }
461
462        repeat(1.., parser)
463            .fold(
464                || SignatureList::Unit,
465                |acc, signature| match acc {
466                    // On the top-level, we want to return the signature directly if there is only
467                    // one.
468                    SignatureList::Unit if top_level => SignatureList::One(signature),
469                    SignatureList::Unit => SignatureList::Structure(vec![signature]),
470                    SignatureList::One(one) => SignatureList::Structure(vec![one, signature]),
471                    SignatureList::Structure(mut signatures) => {
472                        signatures.push(signature);
473                        SignatureList::Structure(signatures)
474                    }
475                },
476            )
477            .map(|sig_list| match sig_list {
478                SignatureList::Unit => Signature::Unit,
479                SignatureList::One(sig) => sig,
480                SignatureList::Structure(signatures) => Signature::structure(signatures),
481            })
482            .parse_next(bytes)
483    }
484
485    fn parse_signature(bytes: &mut &[u8], check_only: bool) -> Result<Signature, ManyError> {
486        let parse_with_context = |bytes: &mut _| parse_signature(bytes, check_only);
487
488        let simple_type = dispatch! {any;
489            b'y' => empty.value(Signature::U8),
490            b'b' => empty.value(Signature::Bool),
491            b'n' => empty.value(Signature::I16),
492            b'q' => empty.value(Signature::U16),
493            b'i' => empty.value(Signature::I32),
494            b'u' => empty.value(Signature::U32),
495            b'x' => empty.value(Signature::I64),
496            b't' => empty.value(Signature::U64),
497            b'd' => empty.value(Signature::F64),
498            b's' => empty.value(Signature::Str),
499            b'g' => empty.value(Signature::Signature),
500            b'o' => empty.value(Signature::ObjectPath),
501            b'v' => empty.value(Signature::Variant),
502            _ => fail,
503        };
504
505        let dict = (
506            b'a',
507            delimited(b'{', (parse_with_context, parse_with_context), b'}'),
508        )
509            .map(|(_, (key, value))| {
510                if check_only {
511                    return Signature::Dict {
512                        key: Signature::Unit.into(),
513                        value: Signature::Unit.into(),
514                    };
515                }
516
517                Signature::Dict {
518                    key: key.into(),
519                    value: value.into(),
520                }
521            });
522
523        let array = (b'a', parse_with_context).map(|(_, child)| {
524            if check_only {
525                return Signature::Array(Signature::Unit.into());
526            }
527
528            Signature::Array(child.into())
529        });
530
531        let structure = delimited(b'(', |s: &mut _| many(s, check_only, false), b')');
532
533        #[cfg(feature = "gvariant")]
534        let maybe = (b'm', parse_with_context).map(|(_, child)| {
535            if check_only {
536                return Signature::Maybe(Signature::Unit.into());
537            }
538
539            Signature::Maybe(child.into())
540        });
541
542        alt((
543            simple_type,
544            dict,
545            array,
546            structure,
547            #[cfg(feature = "gvariant")]
548            maybe,
549            // FIXME: Should be part of `simple_type` but that's not possible right now:
550            // https://github.com/winnow-rs/winnow/issues/609
551            #[cfg(unix)]
552            b'h'.map(|_| Signature::Fd),
553        ))
554        .parse_next(bytes)
555    }
556
557    let signature = alt((unit, |s: &mut _| many(s, check_only, true)))
558        .parse(bytes)
559        .map_err(|_| Error::InvalidSignature)?;
560
561    Ok(signature)
562}
563
564impl PartialEq for Signature {
565    fn eq(&self, other: &Self) -> bool {
566        match (self, other) {
567            (Signature::Unit, Signature::Unit)
568            | (Signature::U8, Signature::U8)
569            | (Signature::Bool, Signature::Bool)
570            | (Signature::I16, Signature::I16)
571            | (Signature::U16, Signature::U16)
572            | (Signature::I32, Signature::I32)
573            | (Signature::U32, Signature::U32)
574            | (Signature::I64, Signature::I64)
575            | (Signature::U64, Signature::U64)
576            | (Signature::F64, Signature::F64)
577            | (Signature::Str, Signature::Str)
578            | (Signature::Signature, Signature::Signature)
579            | (Signature::ObjectPath, Signature::ObjectPath)
580            | (Signature::Variant, Signature::Variant) => true,
581            #[cfg(unix)]
582            (Signature::Fd, Signature::Fd) => true,
583            (Signature::Array(a), Signature::Array(b)) => a.eq(&**b),
584            (
585                Signature::Dict {
586                    key: key_a,
587                    value: value_a,
588                },
589                Signature::Dict {
590                    key: key_b,
591                    value: value_b,
592                },
593            ) => key_a.eq(&**key_b) && value_a.eq(&**value_b),
594            (Signature::Structure(a), Signature::Structure(b)) => a.iter().eq(b.iter()),
595            #[cfg(feature = "gvariant")]
596            (Signature::Maybe(a), Signature::Maybe(b)) => a.eq(&**b),
597            _ => false,
598        }
599    }
600}
601
602impl Eq for Signature {}
603
604impl PartialEq<&str> for Signature {
605    fn eq(&self, other: &&str) -> bool {
606        match self {
607            Signature::Unit => other.is_empty(),
608            Self::Bool => *other == "b",
609            Self::U8 => *other == "y",
610            Self::I16 => *other == "n",
611            Self::U16 => *other == "q",
612            Self::I32 => *other == "i",
613            Self::U32 => *other == "u",
614            Self::I64 => *other == "x",
615            Self::U64 => *other == "t",
616            Self::F64 => *other == "d",
617            Self::Str => *other == "s",
618            Self::Signature => *other == "g",
619            Self::ObjectPath => *other == "o",
620            Self::Variant => *other == "v",
621            #[cfg(unix)]
622            Self::Fd => *other == "h",
623            Self::Array(child) => {
624                if other.len() < 2 || !other.starts_with('a') {
625                    return false;
626                }
627
628                child.eq(&other[1..])
629            }
630            Self::Dict { key, value } => {
631                if other.len() < 4 || !other.starts_with("a{") || !other.ends_with('}') {
632                    return false;
633                }
634
635                let (key_str, value_str) = other[2..other.len() - 1].split_at(1);
636
637                key.eq(key_str) && value.eq(value_str)
638            }
639            Self::Structure(fields) => {
640                let string_len = self.string_len();
641                // self.string_len() will always take `()` into account so it can't be a smaller
642                // number than `other.len()`.
643                if string_len < other.len()
644                    // Their length is either equal (i-e `other` has outer `()`) or `other` has no
645                    // outer `()`.
646                    || (string_len != other.len() && string_len != other.len() + 2)
647                {
648                    return false;
649                }
650
651                let fields_str = if string_len == other.len() {
652                    &other[1..other.len() - 1]
653                } else {
654                    // No outer `()`.
655                    if other.is_empty() {
656                        return false;
657                    }
658
659                    other
660                };
661
662                let mut start = 0;
663                for field in fields.iter() {
664                    let len = field.string_len();
665                    let end = start + len;
666                    if end > fields_str.len() {
667                        return false;
668                    }
669                    if !field.eq(&fields_str[start..end]) {
670                        return false;
671                    }
672
673                    start += len;
674                }
675
676                true
677            }
678            #[cfg(feature = "gvariant")]
679            Self::Maybe(child) => {
680                if other.len() < 2 || !other.starts_with('m') {
681                    return false;
682                }
683
684                child.eq(&other[1..])
685            }
686        }
687    }
688}
689
690impl PartialEq<str> for Signature {
691    fn eq(&self, other: &str) -> bool {
692        self.eq(&other)
693    }
694}
695
696impl PartialOrd for Signature {
697    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
698        Some(self.cmp(other))
699    }
700}
701
702impl Ord for Signature {
703    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
704        match (self, other) {
705            (Signature::Unit, Signature::Unit)
706            | (Signature::U8, Signature::U8)
707            | (Signature::Bool, Signature::Bool)
708            | (Signature::I16, Signature::I16)
709            | (Signature::U16, Signature::U16)
710            | (Signature::I32, Signature::I32)
711            | (Signature::U32, Signature::U32)
712            | (Signature::I64, Signature::I64)
713            | (Signature::U64, Signature::U64)
714            | (Signature::F64, Signature::F64)
715            | (Signature::Str, Signature::Str)
716            | (Signature::Signature, Signature::Signature)
717            | (Signature::ObjectPath, Signature::ObjectPath)
718            | (Signature::Variant, Signature::Variant) => std::cmp::Ordering::Equal,
719            #[cfg(unix)]
720            (Signature::Fd, Signature::Fd) => std::cmp::Ordering::Equal,
721            (Signature::Array(a), Signature::Array(b)) => a.cmp(b),
722            (
723                Signature::Dict {
724                    key: key_a,
725                    value: value_a,
726                },
727                Signature::Dict {
728                    key: key_b,
729                    value: value_b,
730                },
731            ) => match key_a.cmp(key_b) {
732                std::cmp::Ordering::Equal => value_a.cmp(value_b),
733                other => other,
734            },
735            (Signature::Structure(a), Signature::Structure(b)) => a.iter().cmp(b.iter()),
736            #[cfg(feature = "gvariant")]
737            (Signature::Maybe(a), Signature::Maybe(b)) => a.cmp(b),
738            (_, _) => std::cmp::Ordering::Equal,
739        }
740    }
741}
742
743impl Serialize for Signature {
744    fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
745        serializer.serialize_str(&self.to_string())
746    }
747}
748
749impl<'de> Deserialize<'de> for Signature {
750    fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
751        <&str>::deserialize(deserializer).and_then(|s| {
752            Signature::from_str(s).map_err(|e| serde::de::Error::custom(e.to_string()))
753        })
754    }
755}
756
757impl Hash for Signature {
758    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
759        match self {
760            Signature::Unit => 0.hash(state),
761            Signature::U8 => 1.hash(state),
762            Signature::Bool => 2.hash(state),
763            Signature::I16 => 3.hash(state),
764            Signature::U16 => 4.hash(state),
765            Signature::I32 => 5.hash(state),
766            Signature::U32 => 6.hash(state),
767            Signature::I64 => 7.hash(state),
768            Signature::U64 => 8.hash(state),
769            Signature::F64 => 9.hash(state),
770            Signature::Str => 10.hash(state),
771            Signature::Signature => 11.hash(state),
772            Signature::ObjectPath => 12.hash(state),
773            Signature::Variant => 13.hash(state),
774            #[cfg(unix)]
775            Signature::Fd => 14.hash(state),
776            Signature::Array(child) => {
777                15.hash(state);
778                child.hash(state);
779            }
780            Signature::Dict { key, value } => {
781                16.hash(state);
782                key.hash(state);
783                value.hash(state);
784            }
785            Signature::Structure(fields) => {
786                17.hash(state);
787                fields.iter().for_each(|f| f.hash(state));
788            }
789            #[cfg(feature = "gvariant")]
790            Signature::Maybe(child) => {
791                18.hash(state);
792                child.hash(state);
793            }
794        }
795    }
796}
797
798impl From<&Signature> for Signature {
799    fn from(value: &Signature) -> Self {
800        value.clone()
801    }
802}
803
804#[cfg(test)]
805mod tests;