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::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 #[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 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 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 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 #[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 if string_len < other.len()
644 || (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 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;