1use std::fmt::{self, Display};
2
3use tokio_dbus::{
4 Alignment, Body, ObjectPath, ObjectPathBuf, Raw, Signature, SignatureBuf, SignatureBuilder,
5};
6use tokio_dbus_core::signature;
7
8use crate::error::ErrorKind;
9use crate::{Decode, Encode, Error, Result};
10
11#[allow(clippy::large_enum_variant)]
36#[derive(Debug, Clone, PartialEq)]
37#[non_exhaustive]
38pub enum Value {
39 Bool(bool),
41 U8(u8),
43 I16(i16),
45 U16(u16),
47 I32(i32),
49 U32(u32),
51 I64(i64),
53 U64(u64),
55 F64(f64),
57 String(String),
59 ObjectPath(ObjectPathBuf),
61 Signature(SignatureBuf),
63 Array {
68 element: SignatureBuf,
70 values: Vec<Value>,
72 },
73 Dict {
75 key: SignatureBuf,
77 value: SignatureBuf,
79 entries: Vec<(Value, Value)>,
81 },
82 Struct(Vec<Value>),
84 Variant(Box<Value>),
86}
87
88impl Value {
89 pub fn array(element: &str) -> Result<Self> {
101 Ok(Value::Array {
102 element: Signature::new(element)?.to_owned(),
103 values: Vec::new(),
104 })
105 }
106
107 pub fn signature(&self) -> Result<SignatureBuf> {
119 let mut builder = SignatureBuilder::new();
120 self.write_signature(&mut builder)?;
121 Ok(builder.to_signature().to_owned())
122 }
123
124 fn write_signature(&self, builder: &mut SignatureBuilder) -> Result<()> {
125 fn extend(builder: &mut SignatureBuilder, signature: &Signature) -> Result<()> {
126 if !builder.extend_from_signature(signature) {
127 return Err(Error::from(tokio_dbus::SignatureError::too_long()));
128 }
129
130 Ok(())
131 }
132
133 match self {
134 Value::Bool(..) => extend(builder, Signature::BOOLEAN)?,
135 Value::U8(..) => extend(builder, Signature::BYTE)?,
136 Value::I16(..) => extend(builder, Signature::INT16)?,
137 Value::U16(..) => extend(builder, Signature::UINT16)?,
138 Value::I32(..) => extend(builder, Signature::INT32)?,
139 Value::U32(..) => extend(builder, Signature::UINT32)?,
140 Value::I64(..) => extend(builder, Signature::INT64)?,
141 Value::U64(..) => extend(builder, Signature::UINT64)?,
142 Value::F64(..) => extend(builder, Signature::DOUBLE)?,
143 Value::String(..) => extend(builder, Signature::STRING)?,
144 Value::ObjectPath(..) => extend(builder, Signature::OBJECT_PATH)?,
145 Value::Signature(..) => extend(builder, Signature::SIGNATURE)?,
146 Value::Array { element, .. } => {
147 builder.open_array()?;
148 extend(builder, element)?;
149 builder.close_array();
150 }
151 Value::Dict { key, value, .. } => {
152 builder.open_array()?;
153 builder.open_dict()?;
154 extend(builder, key)?;
155 extend(builder, value)?;
156 builder.close_dict()?;
157 builder.close_array();
158 }
159 Value::Struct(fields) => {
160 builder.open_struct()?;
161
162 for field in fields {
163 field.write_signature(builder)?;
164 }
165
166 builder.close_struct()?;
167 }
168 Value::Variant(..) => extend(builder, Signature::VARIANT)?,
169 }
170
171 Ok(())
172 }
173
174 pub(crate) fn encode_value(&self, raw: &mut Raw<'_>) {
176 match self {
177 Value::Bool(value) => raw.store(*value),
178 Value::U8(value) => raw.store(*value),
179 Value::I16(value) => raw.store(*value),
180 Value::U16(value) => raw.store(*value),
181 Value::I32(value) => raw.store(*value),
182 Value::U32(value) => raw.store(*value),
183 Value::I64(value) => raw.store(*value),
184 Value::U64(value) => raw.store(*value),
185 Value::F64(value) => raw.store(*value),
186 Value::String(value) => raw.store(value.as_str()),
187 Value::ObjectPath(value) => raw.store(&**value),
188 Value::Signature(value) => raw.store(&**value),
189 Value::Array { element, values } => {
190 let mut array = raw.store_array(alignment_of(element));
191
192 for value in values {
193 encode_element(value, element, &mut array.as_raw());
194 }
195 }
196 Value::Dict {
197 value: signature,
198 entries,
199 ..
200 } => {
201 let mut array = raw.store_array(Alignment::U64);
202
203 for (key, value) in entries {
204 let mut entry = array.as_raw();
205 entry.align(Alignment::U64);
206 key.encode_value(&mut entry);
207 encode_element(value, signature, &mut entry);
208 }
209 }
210 Value::Struct(fields) => {
211 raw.align(Alignment::U64);
212
213 for field in fields {
214 field.encode_value(raw);
215 }
216 }
217 Value::Variant(value) => {
218 if let Ok(signature) = value.signature() {
222 raw.store_signature(&signature);
223 value.encode_value(raw);
224 }
225 }
226 }
227 }
228
229 pub(crate) fn decode_as(body: &mut Body<'_>, signature: &Signature) -> Result<Value> {
232 let mut iter = signature.iter();
233
234 let Some(ty) = iter.next() else {
235 return Err(Error::new(ErrorKind::UnsupportedType(Box::new(
236 signature.to_owned(),
237 ))));
238 };
239
240 if iter.next().is_some() {
241 return Err(Error::new(ErrorKind::UnsupportedType(Box::new(
244 signature.to_owned(),
245 ))));
246 }
247
248 Value::decode_type(body, ty)
249 }
250
251 fn decode_type(body: &mut Body<'_>, ty: signature::Type<'_>) -> Result<Value> {
252 match ty {
253 signature::Type::Signature(signature) => match signature.as_bytes() {
254 b"b" => Ok(Value::Bool(body.load_bool()?)),
255 b"y" => Ok(Value::U8(body.load()?)),
256 b"n" => Ok(Value::I16(body.load()?)),
257 b"q" => Ok(Value::U16(body.load()?)),
258 b"i" => Ok(Value::I32(body.load()?)),
259 b"u" => Ok(Value::U32(body.load()?)),
260 b"x" => Ok(Value::I64(body.load()?)),
261 b"t" => Ok(Value::U64(body.load()?)),
262 b"d" => Ok(Value::F64(body.load()?)),
263 b"s" => Ok(Value::String(body.read::<str>()?.to_owned())),
264 b"o" => Ok(Value::ObjectPath(body.read::<ObjectPath>()?.to_owned())),
265 b"g" => Ok(Value::Signature(body.read::<Signature>()?.to_owned())),
266 b"v" => {
267 let inner = body.read::<Signature>()?;
268 Ok(Value::Variant(Box::new(Value::decode_as(body, inner)?)))
269 }
270 _ => Err(Error::new(ErrorKind::UnsupportedType(Box::new(
271 signature.to_owned(),
272 )))),
273 },
274 signature::Type::Array(element) => {
275 let mut array = body.load_raw_array(alignment_of(element))?;
276
277 if let Some(signature::Type::Dict(key, value)) = single(element) {
281 let mut entries = Vec::new();
282
283 while !array.is_empty() {
284 array.align_to(Alignment::U64)?;
285 let key = Value::decode_as(&mut array, key)?;
286 let value = Value::decode_as(&mut array, value)?;
287 entries.push((key, value));
288 }
289
290 return Ok(Value::Dict {
291 key: key.to_owned(),
292 value: value.to_owned(),
293 entries,
294 });
295 }
296
297 let mut values = Vec::new();
298
299 while !array.is_empty() {
300 values.push(Value::decode_as(&mut array, element)?);
301 }
302
303 Ok(Value::Array {
304 element: element.to_owned(),
305 values,
306 })
307 }
308 signature::Type::Struct(fields) => {
309 body.align_to(Alignment::U64)?;
310 let mut values = Vec::new();
311
312 for field in fields.iter() {
313 values.push(Value::decode_type(body, field)?);
314 }
315
316 Ok(Value::Struct(values))
317 }
318 signature::Type::Dict(key, value) => {
319 body.align_to(Alignment::U64)?;
320 let key = Value::decode_as(body, key)?;
321 let value = Value::decode_as(body, value)?;
322 Ok(Value::Struct(vec![key, value]))
323 }
324 }
325 }
326}
327
328fn single(signature: &Signature) -> Option<signature::Type<'_>> {
330 let mut iter = signature.iter();
331 let ty = iter.next()?;
332
333 if iter.next().is_some() {
334 return None;
335 }
336
337 Some(ty)
338}
339
340fn encode_element(value: &Value, signature: &Signature, raw: &mut Raw<'_>) {
347 if signature.as_bytes() != b"v" {
348 value.encode_value(raw);
349 return;
350 }
351
352 match value {
353 Value::Variant(inner) => inner.encode(raw),
354 value => value.encode(raw),
355 }
356}
357
358pub(crate) fn alignment_of(signature: &Signature) -> Alignment {
360 match signature.as_bytes().first() {
361 Some(b'y' | b'g' | b'v') => Alignment::BYTE,
362 Some(b'n' | b'q') => Alignment::U16,
363 Some(b'x' | b't' | b'd' | b'(' | b'{') => Alignment::U64,
364 _ => Alignment::U32,
365 }
366}
367
368impl Encode for Value {
369 const ALIGNMENT: Alignment = Alignment::BYTE;
372
373 fn encode(&self, raw: &mut Raw<'_>) {
374 if let Ok(signature) = self.signature() {
375 raw.store_signature(&signature);
376 self.encode_value(raw);
377 }
378 }
379}
380
381impl Decode for Value {
382 const ALIGNMENT: Alignment = Alignment::BYTE;
383
384 fn decode(body: &mut Body<'_>) -> Result<Self> {
385 let signature = body.read::<Signature>()?;
386 Value::decode_as(body, signature)
387 }
388}
389
390impl fmt::Display for Value {
391 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392 match self {
393 Value::Bool(value) => value.fmt(f),
394 Value::U8(value) => value.fmt(f),
395 Value::I16(value) => value.fmt(f),
396 Value::U16(value) => value.fmt(f),
397 Value::I32(value) => value.fmt(f),
398 Value::U32(value) => value.fmt(f),
399 Value::I64(value) => value.fmt(f),
400 Value::U64(value) => value.fmt(f),
401 Value::F64(value) => value.fmt(f),
402 Value::String(value) => value.fmt(f),
403 Value::ObjectPath(value) => value.fmt(f),
404 Value::Signature(value) => value.fmt(f),
405 Value::Array { values, .. } => write_all(f, values.iter(), "[", "]"),
406 Value::Dict { entries, .. } => {
407 f.write_str("{")?;
408
409 for (index, (key, value)) in entries.iter().enumerate() {
410 if index > 0 {
411 f.write_str(", ")?;
412 }
413
414 write!(f, "{key}: {value}")?;
415 }
416
417 f.write_str("}")
418 }
419 Value::Struct(fields) => write_all(f, fields.iter(), "(", ")"),
420 Value::Variant(value) => value.fmt(f),
421 }
422 }
423}
424
425fn write_all<'a, I>(f: &mut fmt::Formatter<'_>, values: I, open: &str, close: &str) -> fmt::Result
426where
427 I: Iterator<Item = &'a Value>,
428{
429 f.write_str(open)?;
430
431 for (index, value) in values.enumerate() {
432 if index > 0 {
433 f.write_str(", ")?;
434 }
435
436 value.fmt(f)?;
437 }
438
439 f.write_str(close)
440}