tokio_dbus/signature/
mod.rs1#[cfg(test)]
2mod tests;
3
4#[cfg(feature = "alloc")]
5mod stack;
6
7#[doc(inline)]
8pub(crate) use tokio_dbus_core::signature::MAX_DEPTH;
9#[doc(inline)]
10pub use tokio_dbus_core::signature::{Signature, SignatureBuf, SignatureBuilder, SignatureError};
11
12use crate::error::Result;
13
14use crate::{Alignment, Body, Read, Write, WriteAligned, WriteUnaligned};
15
16impl crate::write::sealed::Sealed for Signature {}
17
18impl Write for Signature {
19 const SIGNATURE: &'static Signature = Signature::SIGNATURE;
20
21 #[inline]
22 fn write_to<B>(&self, buf: &mut B)
23 where
24 B: ?Sized + WriteAligned,
25 {
26 buf.store_frame(self.len() as u8);
27 buf.extend_from_slice_nul(self.as_bytes());
28 }
29
30 #[inline]
31 fn write_to_unaligned<B>(&self, buf: &mut B)
32 where
33 B: ?Sized + WriteUnaligned,
34 {
35 buf.store(self.len() as u8);
36 buf.extend_from_slice_nul(self.as_bytes());
37 }
38}
39
40impl_traits_for_write!(Signature, Signature::new("us")?, "qg", Signature);
41
42impl crate::read::sealed::Sealed for Signature {}
43
44impl Read for Signature {
45 #[inline]
46 fn read_from<'de>(buf: &mut Body<'de>) -> Result<&'de Self> {
47 let len = buf.load::<u8>()? as usize;
48 let bytes = buf.load_slice_nul(len)?;
49 Ok(Signature::new(bytes)?)
50 }
51}
52
53#[cfg(feature = "alloc")]
58fn alignment_of(byte: Option<u8>) -> Alignment {
59 use crate::proto::Type;
60
61 let Some(byte) = byte else {
62 return Alignment::BYTE;
63 };
64
65 match Type::new(byte) {
66 Type::BYTE | Type::SIGNATURE | Type::VARIANT => Alignment::BYTE,
67 Type::INT16 | Type::UINT16 => Alignment::U16,
68 Type::INT64 | Type::UINT64 | Type::DOUBLE | Type::OPEN_PAREN | Type::OPEN_BRACE => {
69 Alignment::U64
70 }
71 _ => Alignment::U32,
74 }
75}
76
77#[cfg(feature = "alloc")]
79pub(crate) fn skip(this: &Signature, read: &mut Body<'_>) -> Result<()> {
80 use crate::proto::Type;
81
82 use self::stack::Stack;
83
84 #[derive(Debug, Clone, Copy)]
85 enum Step {
86 Fixed(usize),
87 StringNul,
88 Variant,
89 ByteNul,
90 }
91
92 let mut stack = Stack::<bool, MAX_DEPTH>::new();
93 let mut arrays = 0;
94
95 let bytes = this.as_bytes();
96
97 for (n, &b) in bytes.iter().enumerate() {
98 let t = Type::new(b);
99
100 let step = match t {
101 Type::BYTE => Step::Fixed(1),
102 Type::BOOLEAN => Step::Fixed(1),
103 Type::INT16 => Step::Fixed(2),
104 Type::UINT16 => Step::Fixed(2),
105 Type::INT32 => Step::Fixed(4),
106 Type::UINT32 => Step::Fixed(4),
107 Type::INT64 => Step::Fixed(8),
108 Type::UINT64 => Step::Fixed(8),
109 Type::DOUBLE => Step::Fixed(8),
110 Type::STRING => Step::StringNul,
111 Type::OBJECT_PATH => Step::StringNul,
112 Type::SIGNATURE => Step::ByteNul,
113 Type::VARIANT => Step::Variant,
114 Type::UNIX_FD => Step::Fixed(4),
115 Type::ARRAY => {
116 if arrays == 0 {
117 let len = read.load::<u32>()? as usize;
118 read.align_to(alignment_of(bytes.get(n + 1).copied()))?;
122 read.advance(len)?;
123 }
124
125 arrays += 1;
126 stack.try_push(true);
127 continue;
128 }
129 Type::OPEN_PAREN | Type::OPEN_BRACE => {
130 if arrays == 0 {
134 read.align::<u64>()?;
135 }
136
137 stack.try_push(false);
138 continue;
139 }
140 Type::CLOSE_PAREN => {
141 stack.pop();
142 Step::Fixed(0)
143 }
144 Type::CLOSE_BRACE => {
145 stack.pop();
146 Step::Fixed(0)
147 }
148 _ => unreachable!(),
149 };
150
151 let in_array = arrays > 0;
152
153 while let Some(true) = stack.peek() {
155 arrays -= 1;
156 stack.pop();
157 }
158
159 if in_array {
160 continue;
161 }
162
163 match step {
164 Step::Fixed(n) => {
165 read.advance(n)?;
166 }
167 Step::StringNul => {
168 let n = read.load::<u32>()? as usize;
169 read.advance(n.saturating_add(1))?;
170 }
171 Step::ByteNul => {
172 let n = read.load::<u8>()? as usize;
173 read.advance(n.saturating_add(1))?;
174 }
175 Step::Variant => {
176 let sig = read.read::<Signature>()?;
178 skip(sig, read)?;
179 }
180 }
181 }
182
183 Ok(())
184}