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")]
121 Maybe(Child),
122}
123
124impl Signature {
125 pub const fn string_len(&self) -> usize {
127 match self {
128 Signature::Unit => 0,
129 Signature::U8
130 | Signature::Bool
131 | Signature::I16
132 | Signature::U16
133 | Signature::I32
134 | Signature::U32
135 | Signature::I64
136 | Signature::U64
137 | Signature::F64
138 | Signature::Str
139 | Signature::Signature
140 | Signature::ObjectPath
141 | Signature::Variant => 1,
142 #[cfg(unix)]
143 Signature::Fd => 1,
144 Signature::Array(child) => 1 + child.string_len(),
145 Signature::Dict { key, value } => 3 + key.string_len() + value.string_len(),
146 Signature::Structure(fields) => {
147 let mut len = 2;
148 let mut i = 0;
149 while i < fields.len() {
150 len += match fields {
151 Fields::Static { fields } => fields[i].string_len(),
152 Fields::Dynamic { fields } => fields[i].string_len(),
153 };
154 i += 1;
155 }
156 len
157 }
158 #[cfg(feature = "gvariant")]
159 Signature::Maybe(child) => 1 + child.string_len(),
160 }
161 }
162
163 pub fn write_as_string_no_parens(&self, write: &mut impl std::fmt::Write) -> fmt::Result {
169 self.write_as_string(write, false)
170 }
171
172 pub fn to_string_no_parens(&self) -> String {
178 let mut s = String::with_capacity(self.string_len());
179 self.write_as_string(&mut s, false).unwrap();
180
181 s
182 }
183
184 #[allow(clippy::inherent_to_string_shadow_display)]
189 pub fn to_string(&self) -> String {
190 let mut s = String::with_capacity(self.string_len());
191 self.write_as_string(&mut s, true).unwrap();
192
193 s
194 }
195
196 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
198 parse(bytes, false)
199 }
200
201 pub fn structure<F>(fields: F) -> Self
203 where
204 F: Into<Fields>,
205 {
206 Signature::Structure(fields.into())
207 }
208
209 pub const fn static_structure(fields: &'static [&'static Signature]) -> Self {
211 Signature::Structure(Fields::Static { fields })
212 }
213
214 pub fn array<C>(child: C) -> Self
216 where
217 C: Into<Child>,
218 {
219 Signature::Array(child.into())
220 }
221
222 pub const fn static_array(child: &'static Signature) -> Self {
224 Signature::Array(Child::Static { child })
225 }
226
227 pub fn dict<K, V>(key: K, value: V) -> Self
229 where
230 K: Into<Child>,
231 V: Into<Child>,
232 {
233 Signature::Dict {
234 key: key.into(),
235 value: value.into(),
236 }
237 }
238
239 pub const fn static_dict(key: &'static Signature, value: &'static Signature) -> Self {
241 Signature::Dict {
242 key: Child::Static { child: key },
243 value: Child::Static { child: value },
244 }
245 }
246
247 #[cfg(feature = "gvariant")]
249 pub fn maybe<C>(child: C) -> Self
250 where
251 C: Into<Child>,
252 {
253 Signature::Maybe(child.into())
254 }
255
256 #[cfg(feature = "gvariant")]
258 pub const fn static_maybe(child: &'static Signature) -> Self {
259 Signature::Maybe(Child::Static { child })
260 }
261
262 pub fn alignment(&self, format: Format) -> usize {
264 match format {
265 Format::DBus => self.alignment_dbus(),
266 #[cfg(feature = "gvariant")]
267 Format::GVariant => self.alignment_gvariant(),
268 }
269 }
270
271 pub fn contains_maybe(&self) -> bool {
277 match self {
278 Signature::Array(child) => child.contains_maybe(),
279 Signature::Dict { key, value } => key.contains_maybe() || value.contains_maybe(),
280 Signature::Structure(fields) => fields.iter().any(Signature::contains_maybe),
281 #[cfg(feature = "gvariant")]
282 Signature::Maybe(_) => true,
283 _ => false,
284 }
285 }
286
287 fn alignment_dbus(&self) -> usize {
288 match self {
289 Signature::U8 | Signature::Variant | Signature::Signature => 1,
290 Signature::I16 | Signature::U16 => 2,
291 Signature::I32
292 | Signature::U32
293 | Signature::Bool
294 | Signature::Str
295 | Signature::ObjectPath
296 | Signature::Array(_)
297 | Signature::Dict { .. } => 4,
298 Signature::I64
299 | Signature::U64
300 | Signature::F64
301 | Signature::Unit
302 | Signature::Structure(_) => 8,
303 #[cfg(unix)]
304 Signature::Fd => 4,
305 #[cfg(feature = "gvariant")]
306 Signature::Maybe(_) => unreachable!("Maybe type is not supported in D-Bus"),
307 }
308 }
309
310 #[cfg(feature = "gvariant")]
311 fn alignment_gvariant(&self) -> usize {
312 use std::cmp::max;
313
314 match self {
315 Signature::Bool => 1,
316 Signature::Unit
317 | Signature::U8
318 | Signature::I16
319 | Signature::U16
320 | Signature::I32
321 | Signature::U32
322 | Signature::F64
323 | Signature::I64
324 | Signature::U64
325 | Signature::Signature => self.alignment_dbus(),
326 #[cfg(unix)]
327 Signature::Fd => self.alignment_dbus(),
328 Signature::Str | Signature::ObjectPath => 1,
329 Signature::Variant => 8,
330 Signature::Array(child) | Signature::Maybe(child) => child.alignment_gvariant(),
331 Signature::Dict { key, value } => {
332 max(key.alignment_gvariant(), value.alignment_gvariant())
333 }
334 Signature::Structure(fields) => fields
335 .iter()
336 .map(Signature::alignment_gvariant)
337 .max()
338 .unwrap_or(1),
339 }
340 }
341
342 #[cfg(feature = "gvariant")]
344 pub fn is_fixed_sized(&self) -> bool {
345 match self {
346 Signature::Unit
347 | Signature::U8
348 | Signature::Bool
349 | Signature::I16
350 | Signature::U16
351 | Signature::I32
352 | Signature::U32
353 | Signature::I64
354 | Signature::U64
355 | Signature::F64 => true,
356 #[cfg(unix)]
357 Signature::Fd => true,
358 Signature::Str
359 | Signature::Signature
360 | Signature::ObjectPath
361 | Signature::Variant
362 | Signature::Array(_)
363 | Signature::Dict { .. }
364 | Signature::Maybe(_) => false,
365 Signature::Structure(fields) => fields.iter().all(|f| f.is_fixed_sized()),
366 }
367 }
368
369 fn write_as_string(&self, w: &mut impl std::fmt::Write, outer_parens: bool) -> fmt::Result {
370 match self {
371 Signature::Unit => write!(w, ""),
372 Signature::U8 => write!(w, "y"),
373 Signature::Bool => write!(w, "b"),
374 Signature::I16 => write!(w, "n"),
375 Signature::U16 => write!(w, "q"),
376 Signature::I32 => write!(w, "i"),
377 Signature::U32 => write!(w, "u"),
378 Signature::I64 => write!(w, "x"),
379 Signature::U64 => write!(w, "t"),
380 Signature::F64 => write!(w, "d"),
381 Signature::Str => write!(w, "s"),
382 Signature::Signature => write!(w, "g"),
383 Signature::ObjectPath => write!(w, "o"),
384 Signature::Variant => write!(w, "v"),
385 #[cfg(unix)]
386 Signature::Fd => write!(w, "h"),
387 Signature::Array(array) => write!(w, "a{}", **array),
388 Signature::Dict { key, value } => {
389 write!(w, "a{{")?;
390 write!(w, "{}{}", **key, **value)?;
391 write!(w, "}}")
392 }
393 Signature::Structure(fields) => {
394 if outer_parens {
395 write!(w, "(")?;
396 }
397 for field in fields.iter() {
398 write!(w, "{field}")?;
399 }
400 if outer_parens {
401 write!(w, ")")?;
402 }
403
404 Ok(())
405 }
406 #[cfg(feature = "gvariant")]
407 Signature::Maybe(maybe) => write!(w, "m{}", **maybe),
408 }
409 }
410}
411
412impl Display for Signature {
413 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
414 self.write_as_string(f, true)
415 }
416}
417
418impl FromStr for Signature {
419 type Err = Error;
420
421 fn from_str(s: &str) -> Result<Self, Self::Err> {
422 parse(s.as_bytes(), false)
423 }
424}
425
426impl TryFrom<&str> for Signature {
427 type Error = Error;
428
429 fn try_from(value: &str) -> Result<Self, Self::Error> {
430 Signature::from_str(value)
431 }
432}
433
434impl TryFrom<&[u8]> for Signature {
435 type Error = Error;
436
437 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
438 parse(value, false)
439 }
440}
441
442pub fn validate(bytes: &[u8]) -> Result<(), Error> {
444 parse(bytes, true).map(|_| ())
445}
446
447fn parse(bytes: &[u8], check_only: bool) -> Result<Signature, Error> {
452 use winnow::{
453 Parser,
454 combinator::{alt, delimited, empty, eof, fail, repeat},
455 dispatch,
456 token::any,
457 };
458
459 let unit = eof.map(|_| Signature::Unit);
460
461 type ManyError = winnow::error::ErrMode<()>;
463
464 const MAX_STRUCT_DEPTH: u8 = 32;
470 const MAX_ARRAY_DEPTH: u8 = 32;
471
472 #[derive(Debug, Default, Clone, Copy)]
474 struct Depth {
475 structure: u8,
476 array: u8,
477 }
478
479 impl Depth {
480 fn inc_structure(mut self) -> Self {
481 self.structure += 1;
482 self
483 }
484
485 fn inc_array(mut self) -> Self {
486 self.array += 1;
487 self
488 }
489
490 fn exceeded(self) -> bool {
492 self.structure > MAX_STRUCT_DEPTH || self.array > MAX_ARRAY_DEPTH
493 }
494 }
495
496 fn many(
497 bytes: &mut &[u8],
498 check_only: bool,
499 top_level: bool,
500 depth: Depth,
501 ) -> Result<Signature, ManyError> {
502 let parser = |s: &mut _| parse_signature(s, check_only, depth);
503 if check_only {
504 return repeat(1.., parser)
505 .map(|_: ()| Signature::Unit)
506 .parse_next(bytes);
507 }
508
509 enum SignatureList {
513 Unit,
514 One(Signature),
515 Structure(Vec<Signature>),
516 }
517
518 repeat(1.., parser)
519 .fold(
520 || SignatureList::Unit,
521 |acc, signature| match acc {
522 SignatureList::Unit if top_level => SignatureList::One(signature),
525 SignatureList::Unit => SignatureList::Structure(vec![signature]),
526 SignatureList::One(one) => SignatureList::Structure(vec![one, signature]),
527 SignatureList::Structure(mut signatures) => {
528 signatures.push(signature);
529 SignatureList::Structure(signatures)
530 }
531 },
532 )
533 .map(|sig_list| match sig_list {
534 SignatureList::Unit => Signature::Unit,
535 SignatureList::One(sig) => sig,
536 SignatureList::Structure(signatures) => Signature::structure(signatures),
537 })
538 .parse_next(bytes)
539 }
540
541 fn parse_signature(
542 bytes: &mut &[u8],
543 check_only: bool,
544 depth: Depth,
545 ) -> Result<Signature, ManyError> {
546 if depth.exceeded() {
550 return fail.parse_next(bytes);
551 }
552 let array_depth = depth.inc_array();
553 let struct_depth = depth.inc_structure();
554
555 let simple_type = dispatch! {any;
556 b'y' => empty.value(Signature::U8),
557 b'b' => empty.value(Signature::Bool),
558 b'n' => empty.value(Signature::I16),
559 b'q' => empty.value(Signature::U16),
560 b'i' => empty.value(Signature::I32),
561 b'u' => empty.value(Signature::U32),
562 b'x' => empty.value(Signature::I64),
563 b't' => empty.value(Signature::U64),
564 b'd' => empty.value(Signature::F64),
565 b's' => empty.value(Signature::Str),
566 b'g' => empty.value(Signature::Signature),
567 b'o' => empty.value(Signature::ObjectPath),
568 b'v' => empty.value(Signature::Variant),
569 _ => fail,
570 };
571
572 let dict = (
573 b'a',
574 delimited(
575 b'{',
576 (
577 move |s: &mut _| parse_signature(s, check_only, array_depth),
578 move |s: &mut _| parse_signature(s, check_only, array_depth),
579 ),
580 b'}',
581 ),
582 )
583 .map(|(_, (key, value))| {
584 if check_only {
585 return Signature::Dict {
586 key: Signature::Unit.into(),
587 value: Signature::Unit.into(),
588 };
589 }
590
591 Signature::Dict {
592 key: key.into(),
593 value: value.into(),
594 }
595 });
596
597 let array = (b'a', move |s: &mut _| {
598 parse_signature(s, check_only, array_depth)
599 })
600 .map(|(_, child)| {
601 if check_only {
602 return Signature::Array(Signature::Unit.into());
603 }
604
605 Signature::Array(child.into())
606 });
607
608 let structure = delimited(
609 b'(',
610 move |s: &mut _| many(s, check_only, false, struct_depth),
611 b')',
612 );
613
614 #[cfg(feature = "gvariant")]
617 let maybe =
618 (b'm', move |s: &mut _| parse_signature(s, check_only, depth)).map(|(_, child)| {
619 if check_only {
620 return Signature::Maybe(Signature::Unit.into());
621 }
622
623 Signature::Maybe(child.into())
624 });
625
626 alt((
627 simple_type,
628 dict,
629 array,
630 structure,
631 #[cfg(feature = "gvariant")]
632 maybe,
633 #[cfg(unix)]
636 b'h'.map(|_| Signature::Fd),
637 ))
638 .parse_next(bytes)
639 }
640
641 let signature = alt((unit, |s: &mut _| {
642 many(s, check_only, true, Depth::default())
643 }))
644 .parse(bytes)
645 .map_err(|_| Error::InvalidSignature)?;
646
647 Ok(signature)
648}
649
650impl PartialEq for Signature {
651 fn eq(&self, other: &Self) -> bool {
652 match (self, other) {
653 (Signature::Unit, Signature::Unit)
654 | (Signature::U8, Signature::U8)
655 | (Signature::Bool, Signature::Bool)
656 | (Signature::I16, Signature::I16)
657 | (Signature::U16, Signature::U16)
658 | (Signature::I32, Signature::I32)
659 | (Signature::U32, Signature::U32)
660 | (Signature::I64, Signature::I64)
661 | (Signature::U64, Signature::U64)
662 | (Signature::F64, Signature::F64)
663 | (Signature::Str, Signature::Str)
664 | (Signature::Signature, Signature::Signature)
665 | (Signature::ObjectPath, Signature::ObjectPath)
666 | (Signature::Variant, Signature::Variant) => true,
667 #[cfg(unix)]
668 (Signature::Fd, Signature::Fd) => true,
669 (Signature::Array(a), Signature::Array(b)) => a.eq(&**b),
670 (
671 Signature::Dict {
672 key: key_a,
673 value: value_a,
674 },
675 Signature::Dict {
676 key: key_b,
677 value: value_b,
678 },
679 ) => key_a.eq(&**key_b) && value_a.eq(&**value_b),
680 (Signature::Structure(a), Signature::Structure(b)) => a.iter().eq(b.iter()),
681 #[cfg(feature = "gvariant")]
682 (Signature::Maybe(a), Signature::Maybe(b)) => a.eq(&**b),
683 _ => false,
684 }
685 }
686}
687
688impl Eq for Signature {}
689
690impl PartialEq<&str> for Signature {
691 fn eq(&self, other: &&str) -> bool {
692 match self {
693 Signature::Unit => other.is_empty(),
694 Self::Bool => *other == "b",
695 Self::U8 => *other == "y",
696 Self::I16 => *other == "n",
697 Self::U16 => *other == "q",
698 Self::I32 => *other == "i",
699 Self::U32 => *other == "u",
700 Self::I64 => *other == "x",
701 Self::U64 => *other == "t",
702 Self::F64 => *other == "d",
703 Self::Str => *other == "s",
704 Self::Signature => *other == "g",
705 Self::ObjectPath => *other == "o",
706 Self::Variant => *other == "v",
707 #[cfg(unix)]
708 Self::Fd => *other == "h",
709 Self::Array(child) => {
710 if other.len() < 2 || !other.starts_with('a') {
711 return false;
712 }
713
714 child.eq(&other[1..])
715 }
716 Self::Dict { key, value } => {
717 if other.len() < 4 || !other.starts_with("a{") || !other.ends_with('}') {
718 return false;
719 }
720
721 let (key_str, value_str) = other[2..other.len() - 1].split_at(1);
722
723 key.eq(key_str) && value.eq(value_str)
724 }
725 Self::Structure(fields) => {
726 let string_len = self.string_len();
727 if string_len < other.len()
730 || (string_len != other.len() && string_len != other.len() + 2)
733 {
734 return false;
735 }
736
737 let fields_str = if string_len == other.len() {
738 &other[1..other.len() - 1]
739 } else {
740 if other.is_empty() {
742 return false;
743 }
744
745 other
746 };
747
748 let mut start = 0;
749 for field in fields.iter() {
750 let len = field.string_len();
751 let end = start + len;
752 if end > fields_str.len() {
753 return false;
754 }
755 if !field.eq(&fields_str[start..end]) {
756 return false;
757 }
758
759 start += len;
760 }
761
762 true
763 }
764 #[cfg(feature = "gvariant")]
765 Self::Maybe(child) => {
766 if other.len() < 2 || !other.starts_with('m') {
767 return false;
768 }
769
770 child.eq(&other[1..])
771 }
772 }
773 }
774}
775
776impl PartialEq<str> for Signature {
777 fn eq(&self, other: &str) -> bool {
778 self.eq(&other)
779 }
780}
781
782impl PartialOrd for Signature {
783 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
784 Some(self.cmp(other))
785 }
786}
787
788impl Ord for Signature {
789 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
790 match (self, other) {
791 (Signature::Unit, Signature::Unit)
792 | (Signature::U8, Signature::U8)
793 | (Signature::Bool, Signature::Bool)
794 | (Signature::I16, Signature::I16)
795 | (Signature::U16, Signature::U16)
796 | (Signature::I32, Signature::I32)
797 | (Signature::U32, Signature::U32)
798 | (Signature::I64, Signature::I64)
799 | (Signature::U64, Signature::U64)
800 | (Signature::F64, Signature::F64)
801 | (Signature::Str, Signature::Str)
802 | (Signature::Signature, Signature::Signature)
803 | (Signature::ObjectPath, Signature::ObjectPath)
804 | (Signature::Variant, Signature::Variant) => std::cmp::Ordering::Equal,
805 #[cfg(unix)]
806 (Signature::Fd, Signature::Fd) => std::cmp::Ordering::Equal,
807 (Signature::Array(a), Signature::Array(b)) => a.cmp(b),
808 (
809 Signature::Dict {
810 key: key_a,
811 value: value_a,
812 },
813 Signature::Dict {
814 key: key_b,
815 value: value_b,
816 },
817 ) => match key_a.cmp(key_b) {
818 std::cmp::Ordering::Equal => value_a.cmp(value_b),
819 other => other,
820 },
821 (Signature::Structure(a), Signature::Structure(b)) => a.iter().cmp(b.iter()),
822 #[cfg(feature = "gvariant")]
823 (Signature::Maybe(a), Signature::Maybe(b)) => a.cmp(b),
824 (_, _) => std::cmp::Ordering::Equal,
825 }
826 }
827}
828
829impl Serialize for Signature {
830 fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
831 serializer.serialize_str(&self.to_string())
832 }
833}
834
835impl<'de> Deserialize<'de> for Signature {
836 fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
837 <&str>::deserialize(deserializer).and_then(|s| {
838 Signature::from_str(s).map_err(|e| serde::de::Error::custom(e.to_string()))
839 })
840 }
841}
842
843impl Hash for Signature {
844 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
845 match self {
846 Signature::Unit => 0.hash(state),
847 Signature::U8 => 1.hash(state),
848 Signature::Bool => 2.hash(state),
849 Signature::I16 => 3.hash(state),
850 Signature::U16 => 4.hash(state),
851 Signature::I32 => 5.hash(state),
852 Signature::U32 => 6.hash(state),
853 Signature::I64 => 7.hash(state),
854 Signature::U64 => 8.hash(state),
855 Signature::F64 => 9.hash(state),
856 Signature::Str => 10.hash(state),
857 Signature::Signature => 11.hash(state),
858 Signature::ObjectPath => 12.hash(state),
859 Signature::Variant => 13.hash(state),
860 #[cfg(unix)]
861 Signature::Fd => 14.hash(state),
862 Signature::Array(child) => {
863 15.hash(state);
864 child.hash(state);
865 }
866 Signature::Dict { key, value } => {
867 16.hash(state);
868 key.hash(state);
869 value.hash(state);
870 }
871 Signature::Structure(fields) => {
872 17.hash(state);
873 fields.iter().for_each(|f| f.hash(state));
874 }
875 #[cfg(feature = "gvariant")]
876 Signature::Maybe(child) => {
877 18.hash(state);
878 child.hash(state);
879 }
880 }
881 }
882}
883
884impl From<&Signature> for Signature {
885 fn from(value: &Signature) -> Self {
886 value.clone()
887 }
888}
889
890#[cfg(test)]
891mod tests;