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#[derive(Debug, Default, Clone)]
62pub enum Signature {
63 #[default]
74 Unit,
75 U8,
77 Bool,
79 I16,
81 U16,
83 I32,
85 U32,
87 I64,
89 U64,
91 F64,
93 Str,
95 Signature,
97 ObjectPath,
99 Variant,
101 #[cfg(unix)]
103 Fd,
104
105 Array(Child),
108 Dict {
110 key: Child,
112 value: Child,
114 },
115 Structure(Fields),
117 #[cfg(feature = "gvariant")]
119 Maybe(Child),
120}
121
122impl Signature {
123 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 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 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 #[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 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
196 parse(bytes, false)
197 }
198
199 pub fn structure<F>(fields: F) -> Self
201 where
202 F: Into<Fields>,
203 {
204 Signature::Structure(fields.into())
205 }
206
207 pub const fn static_structure(fields: &'static [&'static Signature]) -> Self {
209 Signature::Structure(Fields::Static { fields })
210 }
211
212 pub fn array<C>(child: C) -> Self
214 where
215 C: Into<Child>,
216 {
217 Signature::Array(child.into())
218 }
219
220 pub const fn static_array(child: &'static Signature) -> Self {
222 Signature::Array(Child::Static { child })
223 }
224
225 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 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 #[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 #[cfg(feature = "gvariant")]
256 pub const fn static_maybe(child: &'static Signature) -> Self {
257 Signature::Maybe(Child::Static { child })
258 }
259
260 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::Bool => 1,
298 Signature::Unit
299 | Signature::U8
300 | Signature::I16
301 | Signature::U16
302 | Signature::I32
303 | Signature::U32
304 | Signature::F64
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 #[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
424pub fn validate(bytes: &[u8]) -> Result<(), Error> {
426 parse(bytes, true).map(|_| ())
427}
428
429fn 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 type ManyError = winnow::error::ErrMode<()>;
445
446 const MAX_STRUCT_DEPTH: u8 = 32;
452 const MAX_ARRAY_DEPTH: u8 = 32;
453
454 #[derive(Debug, Default, Clone, Copy)]
456 struct Depth {
457 structure: u8,
458 array: u8,
459 }
460
461 impl Depth {
462 fn inc_structure(mut self) -> Self {
463 self.structure += 1;
464 self
465 }
466
467 fn inc_array(mut self) -> Self {
468 self.array += 1;
469 self
470 }
471
472 fn exceeded(self) -> bool {
474 self.structure > MAX_STRUCT_DEPTH || self.array > MAX_ARRAY_DEPTH
475 }
476 }
477
478 fn many(
479 bytes: &mut &[u8],
480 check_only: bool,
481 top_level: bool,
482 depth: Depth,
483 ) -> Result<Signature, ManyError> {
484 let parser = |s: &mut _| parse_signature(s, check_only, depth);
485 if check_only {
486 return repeat(1.., parser)
487 .map(|_: ()| Signature::Unit)
488 .parse_next(bytes);
489 }
490
491 enum SignatureList {
495 Unit,
496 One(Signature),
497 Structure(Vec<Signature>),
498 }
499
500 repeat(1.., parser)
501 .fold(
502 || SignatureList::Unit,
503 |acc, signature| match acc {
504 SignatureList::Unit if top_level => SignatureList::One(signature),
507 SignatureList::Unit => SignatureList::Structure(vec![signature]),
508 SignatureList::One(one) => SignatureList::Structure(vec![one, signature]),
509 SignatureList::Structure(mut signatures) => {
510 signatures.push(signature);
511 SignatureList::Structure(signatures)
512 }
513 },
514 )
515 .map(|sig_list| match sig_list {
516 SignatureList::Unit => Signature::Unit,
517 SignatureList::One(sig) => sig,
518 SignatureList::Structure(signatures) => Signature::structure(signatures),
519 })
520 .parse_next(bytes)
521 }
522
523 fn parse_signature(
524 bytes: &mut &[u8],
525 check_only: bool,
526 depth: Depth,
527 ) -> Result<Signature, ManyError> {
528 if depth.exceeded() {
532 return fail.parse_next(bytes);
533 }
534 let array_depth = depth.inc_array();
535 let struct_depth = depth.inc_structure();
536
537 let simple_type = dispatch! {any;
538 b'y' => empty.value(Signature::U8),
539 b'b' => empty.value(Signature::Bool),
540 b'n' => empty.value(Signature::I16),
541 b'q' => empty.value(Signature::U16),
542 b'i' => empty.value(Signature::I32),
543 b'u' => empty.value(Signature::U32),
544 b'x' => empty.value(Signature::I64),
545 b't' => empty.value(Signature::U64),
546 b'd' => empty.value(Signature::F64),
547 b's' => empty.value(Signature::Str),
548 b'g' => empty.value(Signature::Signature),
549 b'o' => empty.value(Signature::ObjectPath),
550 b'v' => empty.value(Signature::Variant),
551 _ => fail,
552 };
553
554 let dict = (
555 b'a',
556 delimited(
557 b'{',
558 (
559 move |s: &mut _| parse_signature(s, check_only, array_depth),
560 move |s: &mut _| parse_signature(s, check_only, array_depth),
561 ),
562 b'}',
563 ),
564 )
565 .map(|(_, (key, value))| {
566 if check_only {
567 return Signature::Dict {
568 key: Signature::Unit.into(),
569 value: Signature::Unit.into(),
570 };
571 }
572
573 Signature::Dict {
574 key: key.into(),
575 value: value.into(),
576 }
577 });
578
579 let array = (b'a', move |s: &mut _| {
580 parse_signature(s, check_only, array_depth)
581 })
582 .map(|(_, child)| {
583 if check_only {
584 return Signature::Array(Signature::Unit.into());
585 }
586
587 Signature::Array(child.into())
588 });
589
590 let structure = delimited(
591 b'(',
592 move |s: &mut _| many(s, check_only, false, struct_depth),
593 b')',
594 );
595
596 #[cfg(feature = "gvariant")]
599 let maybe =
600 (b'm', move |s: &mut _| parse_signature(s, check_only, depth)).map(|(_, child)| {
601 if check_only {
602 return Signature::Maybe(Signature::Unit.into());
603 }
604
605 Signature::Maybe(child.into())
606 });
607
608 alt((
609 simple_type,
610 dict,
611 array,
612 structure,
613 #[cfg(feature = "gvariant")]
614 maybe,
615 #[cfg(unix)]
618 b'h'.map(|_| Signature::Fd),
619 ))
620 .parse_next(bytes)
621 }
622
623 let signature = alt((unit, |s: &mut _| {
624 many(s, check_only, true, Depth::default())
625 }))
626 .parse(bytes)
627 .map_err(|_| Error::InvalidSignature)?;
628
629 Ok(signature)
630}
631
632impl PartialEq for Signature {
633 fn eq(&self, other: &Self) -> bool {
634 match (self, other) {
635 (Signature::Unit, Signature::Unit)
636 | (Signature::U8, Signature::U8)
637 | (Signature::Bool, Signature::Bool)
638 | (Signature::I16, Signature::I16)
639 | (Signature::U16, Signature::U16)
640 | (Signature::I32, Signature::I32)
641 | (Signature::U32, Signature::U32)
642 | (Signature::I64, Signature::I64)
643 | (Signature::U64, Signature::U64)
644 | (Signature::F64, Signature::F64)
645 | (Signature::Str, Signature::Str)
646 | (Signature::Signature, Signature::Signature)
647 | (Signature::ObjectPath, Signature::ObjectPath)
648 | (Signature::Variant, Signature::Variant) => true,
649 #[cfg(unix)]
650 (Signature::Fd, Signature::Fd) => true,
651 (Signature::Array(a), Signature::Array(b)) => a.eq(&**b),
652 (
653 Signature::Dict {
654 key: key_a,
655 value: value_a,
656 },
657 Signature::Dict {
658 key: key_b,
659 value: value_b,
660 },
661 ) => key_a.eq(&**key_b) && value_a.eq(&**value_b),
662 (Signature::Structure(a), Signature::Structure(b)) => a.iter().eq(b.iter()),
663 #[cfg(feature = "gvariant")]
664 (Signature::Maybe(a), Signature::Maybe(b)) => a.eq(&**b),
665 _ => false,
666 }
667 }
668}
669
670impl Eq for Signature {}
671
672impl PartialEq<&str> for Signature {
673 fn eq(&self, other: &&str) -> bool {
674 match self {
675 Signature::Unit => other.is_empty(),
676 Self::Bool => *other == "b",
677 Self::U8 => *other == "y",
678 Self::I16 => *other == "n",
679 Self::U16 => *other == "q",
680 Self::I32 => *other == "i",
681 Self::U32 => *other == "u",
682 Self::I64 => *other == "x",
683 Self::U64 => *other == "t",
684 Self::F64 => *other == "d",
685 Self::Str => *other == "s",
686 Self::Signature => *other == "g",
687 Self::ObjectPath => *other == "o",
688 Self::Variant => *other == "v",
689 #[cfg(unix)]
690 Self::Fd => *other == "h",
691 Self::Array(child) => {
692 if other.len() < 2 || !other.starts_with('a') {
693 return false;
694 }
695
696 child.eq(&other[1..])
697 }
698 Self::Dict { key, value } => {
699 if other.len() < 4 || !other.starts_with("a{") || !other.ends_with('}') {
700 return false;
701 }
702
703 let (key_str, value_str) = other[2..other.len() - 1].split_at(1);
704
705 key.eq(key_str) && value.eq(value_str)
706 }
707 Self::Structure(fields) => {
708 let string_len = self.string_len();
709 if string_len < other.len()
712 || (string_len != other.len() && string_len != other.len() + 2)
715 {
716 return false;
717 }
718
719 let fields_str = if string_len == other.len() {
720 &other[1..other.len() - 1]
721 } else {
722 if other.is_empty() {
724 return false;
725 }
726
727 other
728 };
729
730 let mut start = 0;
731 for field in fields.iter() {
732 let len = field.string_len();
733 let end = start + len;
734 if end > fields_str.len() {
735 return false;
736 }
737 if !field.eq(&fields_str[start..end]) {
738 return false;
739 }
740
741 start += len;
742 }
743
744 true
745 }
746 #[cfg(feature = "gvariant")]
747 Self::Maybe(child) => {
748 if other.len() < 2 || !other.starts_with('m') {
749 return false;
750 }
751
752 child.eq(&other[1..])
753 }
754 }
755 }
756}
757
758impl PartialEq<str> for Signature {
759 fn eq(&self, other: &str) -> bool {
760 self.eq(&other)
761 }
762}
763
764impl PartialOrd for Signature {
765 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
766 Some(self.cmp(other))
767 }
768}
769
770impl Ord for Signature {
771 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
772 match (self, other) {
773 (Signature::Unit, Signature::Unit)
774 | (Signature::U8, Signature::U8)
775 | (Signature::Bool, Signature::Bool)
776 | (Signature::I16, Signature::I16)
777 | (Signature::U16, Signature::U16)
778 | (Signature::I32, Signature::I32)
779 | (Signature::U32, Signature::U32)
780 | (Signature::I64, Signature::I64)
781 | (Signature::U64, Signature::U64)
782 | (Signature::F64, Signature::F64)
783 | (Signature::Str, Signature::Str)
784 | (Signature::Signature, Signature::Signature)
785 | (Signature::ObjectPath, Signature::ObjectPath)
786 | (Signature::Variant, Signature::Variant) => std::cmp::Ordering::Equal,
787 #[cfg(unix)]
788 (Signature::Fd, Signature::Fd) => std::cmp::Ordering::Equal,
789 (Signature::Array(a), Signature::Array(b)) => a.cmp(b),
790 (
791 Signature::Dict {
792 key: key_a,
793 value: value_a,
794 },
795 Signature::Dict {
796 key: key_b,
797 value: value_b,
798 },
799 ) => match key_a.cmp(key_b) {
800 std::cmp::Ordering::Equal => value_a.cmp(value_b),
801 other => other,
802 },
803 (Signature::Structure(a), Signature::Structure(b)) => a.iter().cmp(b.iter()),
804 #[cfg(feature = "gvariant")]
805 (Signature::Maybe(a), Signature::Maybe(b)) => a.cmp(b),
806 (_, _) => std::cmp::Ordering::Equal,
807 }
808 }
809}
810
811impl Serialize for Signature {
812 fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
813 serializer.serialize_str(&self.to_string())
814 }
815}
816
817impl<'de> Deserialize<'de> for Signature {
818 fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
819 <&str>::deserialize(deserializer).and_then(|s| {
820 Signature::from_str(s).map_err(|e| serde::de::Error::custom(e.to_string()))
821 })
822 }
823}
824
825impl Hash for Signature {
826 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
827 match self {
828 Signature::Unit => 0.hash(state),
829 Signature::U8 => 1.hash(state),
830 Signature::Bool => 2.hash(state),
831 Signature::I16 => 3.hash(state),
832 Signature::U16 => 4.hash(state),
833 Signature::I32 => 5.hash(state),
834 Signature::U32 => 6.hash(state),
835 Signature::I64 => 7.hash(state),
836 Signature::U64 => 8.hash(state),
837 Signature::F64 => 9.hash(state),
838 Signature::Str => 10.hash(state),
839 Signature::Signature => 11.hash(state),
840 Signature::ObjectPath => 12.hash(state),
841 Signature::Variant => 13.hash(state),
842 #[cfg(unix)]
843 Signature::Fd => 14.hash(state),
844 Signature::Array(child) => {
845 15.hash(state);
846 child.hash(state);
847 }
848 Signature::Dict { key, value } => {
849 16.hash(state);
850 key.hash(state);
851 value.hash(state);
852 }
853 Signature::Structure(fields) => {
854 17.hash(state);
855 fields.iter().for_each(|f| f.hash(state));
856 }
857 #[cfg(feature = "gvariant")]
858 Signature::Maybe(child) => {
859 18.hash(state);
860 child.hash(state);
861 }
862 }
863 }
864}
865
866impl From<&Signature> for Signature {
867 fn from(value: &Signature) -> Self {
868 value.clone()
869 }
870}
871
872#[cfg(test)]
873mod tests;