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)]
42pub enum Signature {
43 #[default]
54 Unit,
55 U8,
57 Bool,
59 I16,
61 U16,
63 I32,
65 U32,
67 I64,
69 U64,
71 F64,
73 Str,
75 Signature,
77 ObjectPath,
79 Variant,
81 #[cfg(unix)]
83 Fd,
84
85 Array(Child),
88 Dict {
90 key: Child,
92 value: Child,
94 },
95 Structure(Fields),
97 #[cfg(feature = "gvariant")]
99 Maybe(Child),
100}
101
102impl Signature {
103 pub const fn string_len(&self) -> usize {
105 match self {
106 Signature::Unit => 0,
107 Signature::U8
108 | Signature::Bool
109 | Signature::I16
110 | Signature::U16
111 | Signature::I32
112 | Signature::U32
113 | Signature::I64
114 | Signature::U64
115 | Signature::F64
116 | Signature::Str
117 | Signature::Signature
118 | Signature::ObjectPath
119 | Signature::Variant => 1,
120 #[cfg(unix)]
121 Signature::Fd => 1,
122 Signature::Array(child) => 1 + child.string_len(),
123 Signature::Dict { key, value } => 3 + key.string_len() + value.string_len(),
124 Signature::Structure(fields) => {
125 let mut len = 2;
126 let mut i = 0;
127 while i < fields.len() {
128 len += match fields {
129 Fields::Static { fields } => fields[i].string_len(),
130 Fields::Dynamic { fields } => fields[i].string_len(),
131 };
132 i += 1;
133 }
134 len
135 }
136 #[cfg(feature = "gvariant")]
137 Signature::Maybe(child) => 1 + child.string_len(),
138 }
139 }
140
141 pub fn write_as_string_no_parens(&self, write: &mut impl std::fmt::Write) -> fmt::Result {
147 self.write_as_string(write, false)
148 }
149
150 pub fn to_string_no_parens(&self) -> String {
156 let mut s = String::with_capacity(self.string_len());
157 self.write_as_string(&mut s, false).unwrap();
158
159 s
160 }
161
162 #[allow(clippy::inherent_to_string_shadow_display)]
167 pub fn to_string(&self) -> String {
168 let mut s = String::with_capacity(self.string_len());
169 self.write_as_string(&mut s, true).unwrap();
170
171 s
172 }
173
174 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
176 parse(bytes, false)
177 }
178
179 pub fn structure<F>(fields: F) -> Self
181 where
182 F: Into<Fields>,
183 {
184 Signature::Structure(fields.into())
185 }
186
187 pub const fn static_structure(fields: &'static [&'static Signature]) -> Self {
189 Signature::Structure(Fields::Static { fields })
190 }
191
192 pub fn array<C>(child: C) -> Self
194 where
195 C: Into<Child>,
196 {
197 Signature::Array(child.into())
198 }
199
200 pub const fn static_array(child: &'static Signature) -> Self {
202 Signature::Array(Child::Static { child })
203 }
204
205 pub fn dict<K, V>(key: K, value: V) -> Self
207 where
208 K: Into<Child>,
209 V: Into<Child>,
210 {
211 Signature::Dict {
212 key: key.into(),
213 value: value.into(),
214 }
215 }
216
217 pub const fn static_dict(key: &'static Signature, value: &'static Signature) -> Self {
219 Signature::Dict {
220 key: Child::Static { child: key },
221 value: Child::Static { child: value },
222 }
223 }
224
225 #[cfg(feature = "gvariant")]
227 pub fn maybe<C>(child: C) -> Self
228 where
229 C: Into<Child>,
230 {
231 Signature::Maybe(child.into())
232 }
233
234 #[cfg(feature = "gvariant")]
236 pub const fn static_maybe(child: &'static Signature) -> Self {
237 Signature::Maybe(Child::Static { child })
238 }
239
240 pub fn alignment(&self, format: Format) -> usize {
242 match format {
243 Format::DBus => self.alignment_dbus(),
244 #[cfg(feature = "gvariant")]
245 Format::GVariant => self.alignment_gvariant(),
246 }
247 }
248
249 fn alignment_dbus(&self) -> usize {
250 match self {
251 Signature::U8 | Signature::Variant | Signature::Signature => 1,
252 Signature::I16 | Signature::U16 => 2,
253 Signature::I32
254 | Signature::U32
255 | Signature::Bool
256 | Signature::Str
257 | Signature::ObjectPath
258 | Signature::Array(_)
259 | Signature::Dict { .. } => 4,
260 Signature::I64
261 | Signature::U64
262 | Signature::F64
263 | Signature::Unit
264 | Signature::Structure(_) => 8,
265 #[cfg(unix)]
266 Signature::Fd => 4,
267 #[cfg(feature = "gvariant")]
268 Signature::Maybe(_) => unreachable!("Maybe type is not supported in D-Bus"),
269 }
270 }
271
272 #[cfg(feature = "gvariant")]
273 fn alignment_gvariant(&self) -> usize {
274 use std::cmp::max;
275
276 match self {
277 Signature::Unit
278 | Signature::U8
279 | Signature::I16
280 | Signature::U16
281 | Signature::I32
282 | Signature::U32
283 | Signature::F64
284 | Signature::Bool
285 | Signature::I64
286 | Signature::U64
287 | Signature::Signature => self.alignment_dbus(),
288 #[cfg(unix)]
289 Signature::Fd => self.alignment_dbus(),
290 Signature::Str | Signature::ObjectPath => 1,
291 Signature::Variant => 8,
292 Signature::Array(child) | Signature::Maybe(child) => child.alignment_gvariant(),
293 Signature::Dict { key, value } => {
294 max(key.alignment_gvariant(), value.alignment_gvariant())
295 }
296 Signature::Structure(fields) => fields
297 .iter()
298 .map(Signature::alignment_gvariant)
299 .max()
300 .unwrap_or(1),
301 }
302 }
303
304 #[cfg(feature = "gvariant")]
306 pub fn is_fixed_sized(&self) -> bool {
307 match self {
308 Signature::Unit
309 | Signature::U8
310 | Signature::Bool
311 | Signature::I16
312 | Signature::U16
313 | Signature::I32
314 | Signature::U32
315 | Signature::I64
316 | Signature::U64
317 | Signature::F64 => true,
318 #[cfg(unix)]
319 Signature::Fd => true,
320 Signature::Str
321 | Signature::Signature
322 | Signature::ObjectPath
323 | Signature::Variant
324 | Signature::Array(_)
325 | Signature::Dict { .. }
326 | Signature::Maybe(_) => false,
327 Signature::Structure(fields) => fields.iter().all(|f| f.is_fixed_sized()),
328 }
329 }
330
331 fn write_as_string(&self, w: &mut impl std::fmt::Write, outer_parens: bool) -> fmt::Result {
332 match self {
333 Signature::Unit => write!(w, ""),
334 Signature::U8 => write!(w, "y"),
335 Signature::Bool => write!(w, "b"),
336 Signature::I16 => write!(w, "n"),
337 Signature::U16 => write!(w, "q"),
338 Signature::I32 => write!(w, "i"),
339 Signature::U32 => write!(w, "u"),
340 Signature::I64 => write!(w, "x"),
341 Signature::U64 => write!(w, "t"),
342 Signature::F64 => write!(w, "d"),
343 Signature::Str => write!(w, "s"),
344 Signature::Signature => write!(w, "g"),
345 Signature::ObjectPath => write!(w, "o"),
346 Signature::Variant => write!(w, "v"),
347 #[cfg(unix)]
348 Signature::Fd => write!(w, "h"),
349 Signature::Array(array) => write!(w, "a{}", **array),
350 Signature::Dict { key, value } => {
351 write!(w, "a{{")?;
352 write!(w, "{}{}", **key, **value)?;
353 write!(w, "}}")
354 }
355 Signature::Structure(fields) => {
356 if outer_parens {
357 write!(w, "(")?;
358 }
359 for field in fields.iter() {
360 write!(w, "{field}")?;
361 }
362 if outer_parens {
363 write!(w, ")")?;
364 }
365
366 Ok(())
367 }
368 #[cfg(feature = "gvariant")]
369 Signature::Maybe(maybe) => write!(w, "m{}", **maybe),
370 }
371 }
372}
373
374impl Display for Signature {
375 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
376 self.write_as_string(f, true)
377 }
378}
379
380impl FromStr for Signature {
381 type Err = Error;
382
383 fn from_str(s: &str) -> Result<Self, Self::Err> {
384 parse(s.as_bytes(), false)
385 }
386}
387
388impl TryFrom<&str> for Signature {
389 type Error = Error;
390
391 fn try_from(value: &str) -> Result<Self, Self::Error> {
392 Signature::from_str(value)
393 }
394}
395
396impl TryFrom<&[u8]> for Signature {
397 type Error = Error;
398
399 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
400 parse(value, false)
401 }
402}
403
404pub fn validate(bytes: &[u8]) -> Result<(), Error> {
406 parse(bytes, true).map(|_| ())
407}
408
409fn parse(bytes: &[u8], check_only: bool) -> Result<Signature, Error> {
414 use winnow::{
415 combinator::{alt, delimited, empty, eof, fail, repeat},
416 dispatch,
417 token::any,
418 Parser,
419 };
420
421 let unit = eof.map(|_| Signature::Unit);
422
423 type ManyError = winnow::error::ErrMode<()>;
425 fn many(bytes: &mut &[u8], check_only: bool, top_level: bool) -> Result<Signature, ManyError> {
426 let parser = |s: &mut _| parse_signature(s, check_only);
427 if check_only {
428 return repeat(1.., parser)
429 .map(|_: ()| Signature::Unit)
430 .parse_next(bytes);
431 }
432
433 enum SignatureList {
437 Unit,
438 One(Signature),
439 Structure(Vec<Signature>),
440 }
441
442 repeat(1.., parser)
443 .fold(
444 || SignatureList::Unit,
445 |acc, signature| match acc {
446 SignatureList::Unit if top_level => SignatureList::One(signature),
449 SignatureList::Unit => SignatureList::Structure(vec![signature]),
450 SignatureList::One(one) => SignatureList::Structure(vec![one, signature]),
451 SignatureList::Structure(mut signatures) => {
452 signatures.push(signature);
453 SignatureList::Structure(signatures)
454 }
455 },
456 )
457 .map(|sig_list| match sig_list {
458 SignatureList::Unit => Signature::Unit,
459 SignatureList::One(sig) => sig,
460 SignatureList::Structure(signatures) => Signature::structure(signatures),
461 })
462 .parse_next(bytes)
463 }
464
465 fn parse_signature(bytes: &mut &[u8], check_only: bool) -> Result<Signature, ManyError> {
466 let parse_with_context = |bytes: &mut _| parse_signature(bytes, check_only);
467
468 let simple_type = dispatch! {any;
469 b'y' => empty.value(Signature::U8),
470 b'b' => empty.value(Signature::Bool),
471 b'n' => empty.value(Signature::I16),
472 b'q' => empty.value(Signature::U16),
473 b'i' => empty.value(Signature::I32),
474 b'u' => empty.value(Signature::U32),
475 b'x' => empty.value(Signature::I64),
476 b't' => empty.value(Signature::U64),
477 b'd' => empty.value(Signature::F64),
478 b's' => empty.value(Signature::Str),
479 b'g' => empty.value(Signature::Signature),
480 b'o' => empty.value(Signature::ObjectPath),
481 b'v' => empty.value(Signature::Variant),
482 _ => fail,
483 };
484
485 let dict = (
486 b'a',
487 delimited(b'{', (parse_with_context, parse_with_context), b'}'),
488 )
489 .map(|(_, (key, value))| {
490 if check_only {
491 return Signature::Dict {
492 key: Signature::Unit.into(),
493 value: Signature::Unit.into(),
494 };
495 }
496
497 Signature::Dict {
498 key: key.into(),
499 value: value.into(),
500 }
501 });
502
503 let array = (b'a', parse_with_context).map(|(_, child)| {
504 if check_only {
505 return Signature::Array(Signature::Unit.into());
506 }
507
508 Signature::Array(child.into())
509 });
510
511 let structure = delimited(b'(', |s: &mut _| many(s, check_only, false), b')');
512
513 #[cfg(feature = "gvariant")]
514 let maybe = (b'm', parse_with_context).map(|(_, child)| {
515 if check_only {
516 return Signature::Maybe(Signature::Unit.into());
517 }
518
519 Signature::Maybe(child.into())
520 });
521
522 alt((
523 simple_type,
524 dict,
525 array,
526 structure,
527 #[cfg(feature = "gvariant")]
528 maybe,
529 #[cfg(unix)]
532 b'h'.map(|_| Signature::Fd),
533 ))
534 .parse_next(bytes)
535 }
536
537 let signature = alt((unit, |s: &mut _| many(s, check_only, true)))
538 .parse(bytes)
539 .map_err(|_| Error::InvalidSignature)?;
540
541 Ok(signature)
542}
543
544impl PartialEq for Signature {
545 fn eq(&self, other: &Self) -> bool {
546 match (self, other) {
547 (Signature::Unit, Signature::Unit)
548 | (Signature::U8, Signature::U8)
549 | (Signature::Bool, Signature::Bool)
550 | (Signature::I16, Signature::I16)
551 | (Signature::U16, Signature::U16)
552 | (Signature::I32, Signature::I32)
553 | (Signature::U32, Signature::U32)
554 | (Signature::I64, Signature::I64)
555 | (Signature::U64, Signature::U64)
556 | (Signature::F64, Signature::F64)
557 | (Signature::Str, Signature::Str)
558 | (Signature::Signature, Signature::Signature)
559 | (Signature::ObjectPath, Signature::ObjectPath)
560 | (Signature::Variant, Signature::Variant) => true,
561 #[cfg(unix)]
562 (Signature::Fd, Signature::Fd) => true,
563 (Signature::Array(a), Signature::Array(b)) => a.eq(&**b),
564 (
565 Signature::Dict {
566 key: key_a,
567 value: value_a,
568 },
569 Signature::Dict {
570 key: key_b,
571 value: value_b,
572 },
573 ) => key_a.eq(&**key_b) && value_a.eq(&**value_b),
574 (Signature::Structure(a), Signature::Structure(b)) => a.iter().eq(b.iter()),
575 #[cfg(feature = "gvariant")]
576 (Signature::Maybe(a), Signature::Maybe(b)) => a.eq(&**b),
577 _ => false,
578 }
579 }
580}
581
582impl Eq for Signature {}
583
584impl PartialEq<&str> for Signature {
585 fn eq(&self, other: &&str) -> bool {
586 match self {
587 Signature::Unit => other.is_empty(),
588 Self::Bool => *other == "b",
589 Self::U8 => *other == "y",
590 Self::I16 => *other == "n",
591 Self::U16 => *other == "q",
592 Self::I32 => *other == "i",
593 Self::U32 => *other == "u",
594 Self::I64 => *other == "x",
595 Self::U64 => *other == "t",
596 Self::F64 => *other == "d",
597 Self::Str => *other == "s",
598 Self::Signature => *other == "g",
599 Self::ObjectPath => *other == "o",
600 Self::Variant => *other == "v",
601 #[cfg(unix)]
602 Self::Fd => *other == "h",
603 Self::Array(child) => {
604 if other.len() < 2 || !other.starts_with('a') {
605 return false;
606 }
607
608 child.eq(&other[1..])
609 }
610 Self::Dict { key, value } => {
611 if other.len() < 4 || !other.starts_with("a{") || !other.ends_with('}') {
612 return false;
613 }
614
615 let (key_str, value_str) = other[2..other.len() - 1].split_at(1);
616
617 key.eq(key_str) && value.eq(value_str)
618 }
619 Self::Structure(fields) => {
620 let string_len = self.string_len();
621 if string_len < other.len()
624 || (string_len != other.len() && string_len != other.len() + 2)
627 {
628 return false;
629 }
630
631 let fields_str = if string_len == other.len() {
632 &other[1..other.len() - 1]
633 } else {
634 if other.is_empty() {
636 return false;
637 }
638
639 other
640 };
641
642 let mut start = 0;
643 for field in fields.iter() {
644 let len = field.string_len();
645 let end = start + len;
646 if end > fields_str.len() {
647 return false;
648 }
649 if !field.eq(&fields_str[start..end]) {
650 return false;
651 }
652
653 start += len;
654 }
655
656 true
657 }
658 #[cfg(feature = "gvariant")]
659 Self::Maybe(child) => {
660 if other.len() < 2 || !other.starts_with('m') {
661 return false;
662 }
663
664 child.eq(&other[1..])
665 }
666 }
667 }
668}
669
670impl PartialEq<str> for Signature {
671 fn eq(&self, other: &str) -> bool {
672 self.eq(&other)
673 }
674}
675
676impl PartialOrd for Signature {
677 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
678 Some(self.cmp(other))
679 }
680}
681
682impl Ord for Signature {
683 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
684 match (self, other) {
685 (Signature::Unit, Signature::Unit)
686 | (Signature::U8, Signature::U8)
687 | (Signature::Bool, Signature::Bool)
688 | (Signature::I16, Signature::I16)
689 | (Signature::U16, Signature::U16)
690 | (Signature::I32, Signature::I32)
691 | (Signature::U32, Signature::U32)
692 | (Signature::I64, Signature::I64)
693 | (Signature::U64, Signature::U64)
694 | (Signature::F64, Signature::F64)
695 | (Signature::Str, Signature::Str)
696 | (Signature::Signature, Signature::Signature)
697 | (Signature::ObjectPath, Signature::ObjectPath)
698 | (Signature::Variant, Signature::Variant) => std::cmp::Ordering::Equal,
699 #[cfg(unix)]
700 (Signature::Fd, Signature::Fd) => std::cmp::Ordering::Equal,
701 (Signature::Array(a), Signature::Array(b)) => a.cmp(b),
702 (
703 Signature::Dict {
704 key: key_a,
705 value: value_a,
706 },
707 Signature::Dict {
708 key: key_b,
709 value: value_b,
710 },
711 ) => match key_a.cmp(key_b) {
712 std::cmp::Ordering::Equal => value_a.cmp(value_b),
713 other => other,
714 },
715 (Signature::Structure(a), Signature::Structure(b)) => a.iter().cmp(b.iter()),
716 #[cfg(feature = "gvariant")]
717 (Signature::Maybe(a), Signature::Maybe(b)) => a.cmp(b),
718 (_, _) => std::cmp::Ordering::Equal,
719 }
720 }
721}
722
723impl Serialize for Signature {
724 fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
725 serializer.serialize_str(&self.to_string())
726 }
727}
728
729impl<'de> Deserialize<'de> for Signature {
730 fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
731 <&str>::deserialize(deserializer).and_then(|s| {
732 Signature::from_str(s).map_err(|e| serde::de::Error::custom(e.to_string()))
733 })
734 }
735}
736
737impl Hash for Signature {
738 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
739 match self {
740 Signature::Unit => 0.hash(state),
741 Signature::U8 => 1.hash(state),
742 Signature::Bool => 2.hash(state),
743 Signature::I16 => 3.hash(state),
744 Signature::U16 => 4.hash(state),
745 Signature::I32 => 5.hash(state),
746 Signature::U32 => 6.hash(state),
747 Signature::I64 => 7.hash(state),
748 Signature::U64 => 8.hash(state),
749 Signature::F64 => 9.hash(state),
750 Signature::Str => 10.hash(state),
751 Signature::Signature => 11.hash(state),
752 Signature::ObjectPath => 12.hash(state),
753 Signature::Variant => 13.hash(state),
754 #[cfg(unix)]
755 Signature::Fd => 14.hash(state),
756 Signature::Array(child) => {
757 15.hash(state);
758 child.hash(state);
759 }
760 Signature::Dict { key, value } => {
761 16.hash(state);
762 key.hash(state);
763 value.hash(state);
764 }
765 Signature::Structure(fields) => {
766 17.hash(state);
767 fields.iter().for_each(|f| f.hash(state));
768 }
769 #[cfg(feature = "gvariant")]
770 Signature::Maybe(child) => {
771 18.hash(state);
772 child.hash(state);
773 }
774 }
775 }
776}
777
778impl From<&Signature> for Signature {
779 fn from(value: &Signature) -> Self {
780 value.clone()
781 }
782}
783
784#[cfg(test)]
785mod tests;