tokio_dbus_codegen/
types.rs1use genco::prelude::*;
4use tokio_dbus_core::signature::{self, Signature};
5
6use crate::error::ErrorKind;
7use crate::{Error, Result};
8
9fn single(signature: &Signature) -> Result<signature::Type<'_>> {
11 let mut iter = signature.iter();
12
13 let Some(ty) = iter.next() else {
14 return Err(Error::new(ErrorKind::EmptyType));
15 };
16
17 if iter.next().is_some() {
18 return Err(Error::new(ErrorKind::CompoundType(signature.to_owned())));
19 }
20
21 Ok(ty)
22}
23
24pub fn owned_type(signature: &str) -> Result<rust::Tokens> {
38 let signature = Signature::new(signature)?;
39 owned(single(signature)?)
40}
41
42pub fn parameter_type(signature: &str) -> Result<rust::Tokens> {
57 let signature = Signature::new(signature)?;
58 parameter(single(signature)?)
59}
60
61fn owned(ty: signature::Type<'_>) -> Result<rust::Tokens> {
62 Ok(match ty {
63 signature::Type::Signature(signature) => basic(signature)?,
64 signature::Type::Array(element) => {
65 if let Ok(signature::Type::Dict(key, value)) = single(element) {
68 let key = owned(single(key)?)?;
69 let value = owned(single(value)?)?;
70 quote!(HashMap<$key, $value>)
71 } else {
72 let element = owned(single(element)?)?;
73 quote!(Vec<$element>)
74 }
75 }
76 signature::Type::Struct(fields) => {
77 let mut out = rust::Tokens::new();
78
79 for (index, field) in fields.iter().enumerate() {
80 if index > 0 {
81 out.append(quote!(,));
82 out.space();
83 }
84
85 out.append(owned(field)?);
86 }
87
88 if fields.iter().count() == 1 {
90 out.append(quote!(,));
91 }
92
93 quote!(($out))
94 }
95 signature::Type::Dict(..) => {
96 return Err(Error::new(ErrorKind::LooseDictEntry));
97 }
98 })
99}
100
101fn parameter(ty: signature::Type<'_>) -> Result<rust::Tokens> {
102 Ok(match ty {
103 signature::Type::Signature(signature) => match signature.as_bytes() {
104 b"s" => quote!(&str),
105 b"o" => quote!(&ObjectPath),
106 b"g" => quote!(&Signature),
107 b"v" => quote!(&Value),
108 _ => basic(signature)?,
111 },
112 signature::Type::Array(element) => {
113 if single(element).is_ok_and(|t| matches!(t, signature::Type::Dict(..))) {
114 let map = owned(ty)?;
115 quote!(&$map)
116 } else {
117 let element = owned(single(element)?)?;
118 quote!(&[$element])
119 }
120 }
121 signature::Type::Struct(..) => {
122 let fields = owned(ty)?;
123 quote!(&$fields)
124 }
125 signature::Type::Dict(..) => {
126 return Err(Error::new(ErrorKind::LooseDictEntry));
127 }
128 })
129}
130
131fn basic(signature: &Signature) -> Result<rust::Tokens> {
132 Ok(match signature.as_bytes() {
133 b"y" => quote!(u8),
134 b"b" => quote!(bool),
135 b"n" => quote!(i16),
136 b"q" => quote!(u16),
137 b"i" => quote!(i32),
138 b"u" => quote!(u32),
139 b"x" => quote!(i64),
140 b"t" => quote!(u64),
141 b"d" => quote!(f64),
142 b"s" => quote!(String),
143 b"o" => quote!(ObjectPathBuf),
144 b"g" => quote!(SignatureBuf),
145 b"v" => quote!(Value),
146 b"h" => return Err(Error::new(ErrorKind::UnixFd)),
149 _ => {
150 return Err(Error::new(ErrorKind::UnknownType(signature.to_owned())));
151 }
152 })
153}