1#[cfg(feature = "gvariant")]
2use crate::Maybe;
3use crate::{
4 Array, Dict, Error, NoneValue, ObjectPath, Optional, OwnedObjectPath, Signature, Str,
5 Structure, Value,
6};
7
8#[cfg(unix)]
9use crate::Fd;
10
11use std::{collections::HashMap, hash::BuildHasher};
12
13macro_rules! value_try_from {
14 ($kind:ident, $to:ty) => {
15 impl<'a> TryFrom<Value<'a>> for $to {
16 type Error = Error;
17
18 fn try_from(value: Value<'a>) -> Result<Self, Self::Error> {
19 if let Value::$kind(value) = value {
20 Ok(value.into())
21 } else {
22 Err(Error::IncorrectType)
23 }
24 }
25 }
26 };
27}
28
29macro_rules! value_try_from_ref {
30 ($kind:ident, $to:ty) => {
31 impl<'a> TryFrom<&'a Value<'_>> for &'a $to {
32 type Error = Error;
33
34 fn try_from(value: &'a Value<'_>) -> Result<Self, Self::Error> {
35 if let Value::$kind(value) = value {
36 Ok(value)
37 } else {
38 Err(Error::IncorrectType)
39 }
40 }
41 }
42 };
43}
44
45macro_rules! value_try_from_ref_clone {
46 ($kind:ident, $to:ty) => {
47 impl<'a> TryFrom<&Value<'a>> for $to {
48 type Error = Error;
49
50 fn try_from(value: &Value<'a>) -> Result<Self, Self::Error> {
51 if let Value::$kind(value) = value {
52 Ok(value.clone().into())
53 } else {
54 Err(Error::IncorrectType)
55 }
56 }
57 }
58 };
59}
60
61macro_rules! value_try_from_all {
62 ($from:ident, $to:ty) => {
63 value_try_from!($from, $to);
64 value_try_from_ref!($from, $to);
65 value_try_from_ref_clone!($from, $to);
66 };
67}
68
69value_try_from_all!(U8, u8);
70value_try_from_all!(Bool, bool);
71value_try_from_all!(I16, i16);
72value_try_from_all!(U16, u16);
73value_try_from_all!(I32, i32);
74value_try_from_all!(U32, u32);
75value_try_from_all!(I64, i64);
76value_try_from_all!(U64, u64);
77value_try_from_all!(F64, f64);
78
79value_try_from_all!(Str, Str<'a>);
80value_try_from_all!(Signature, Signature);
81value_try_from_all!(ObjectPath, ObjectPath<'a>);
82value_try_from!(Str, String);
83value_try_from_ref!(Str, str);
84
85macro_rules! value_try_from_ref_try_clone {
86 ($kind:ident, $to:ty) => {
87 impl<'a> TryFrom<&Value<'a>> for $to {
88 type Error = Error;
89
90 fn try_from(value: &Value<'a>) -> Result<Self, Self::Error> {
91 if let Value::$kind(value) = value {
92 value.try_clone().map_err(Into::into)
93 } else {
94 Err(Error::IncorrectType)
95 }
96 }
97 }
98 };
99}
100
101value_try_from!(Structure, Structure<'a>);
102value_try_from_ref!(Structure, Structure<'a>);
103value_try_from_ref_try_clone!(Structure, Structure<'a>);
104
105value_try_from!(Dict, Dict<'a, 'a>);
106value_try_from_ref!(Dict, Dict<'a, 'a>);
107value_try_from_ref_try_clone!(Dict, Dict<'a, 'a>);
108
109value_try_from!(Array, Array<'a>);
110value_try_from_ref!(Array, Array<'a>);
111value_try_from_ref_try_clone!(Array, Array<'a>);
112
113#[cfg(feature = "gvariant")]
114value_try_from!(Maybe, Maybe<'a>);
115#[cfg(feature = "gvariant")]
116value_try_from_ref!(Maybe, Maybe<'a>);
117#[cfg(feature = "gvariant")]
118value_try_from_ref_try_clone!(Maybe, Maybe<'a>);
119
120#[cfg(unix)]
121value_try_from!(Fd, Fd<'a>);
122#[cfg(unix)]
123value_try_from_ref!(Fd, Fd<'a>);
124#[cfg(unix)]
125value_try_from_ref_try_clone!(Fd, Fd<'a>);
126
127impl TryFrom<&Value<'_>> for String {
128 type Error = Error;
129
130 fn try_from(value: &Value<'_>) -> Result<Self, Self::Error> {
131 Ok(<&str>::try_from(value)?.into())
132 }
133}
134
135impl<'a, T> TryFrom<Value<'a>> for Vec<T>
136where
137 T: TryFrom<Value<'a>>,
138 T::Error: Into<crate::Error>,
139{
140 type Error = Error;
141
142 fn try_from(value: Value<'a>) -> Result<Self, Self::Error> {
143 if let Value::Array(v) = value {
144 Self::try_from(v)
145 } else {
146 Err(Error::IncorrectType)
147 }
148 }
149}
150
151impl TryFrom<Value<'_>> for OwnedObjectPath {
152 type Error = Error;
153
154 fn try_from(value: Value<'_>) -> Result<Self, Self::Error> {
155 ObjectPath::try_from(value).map(OwnedObjectPath::from)
156 }
157}
158
159#[cfg(feature = "enumflags2")]
162impl<'a, F> TryFrom<Value<'a>> for enumflags2::BitFlags<F>
163where
164 F: enumflags2::BitFlag,
165 F::Numeric: TryFrom<Value<'a>, Error = Error>,
166{
167 type Error = Error;
168
169 fn try_from(value: Value<'a>) -> Result<Self, Self::Error> {
170 Self::from_bits(F::Numeric::try_from(value)?)
171 .map_err(|_| Error::Message("Failed to convert to bitflags".into()))
172 }
173}
174
175impl<'a, K, V, H> TryFrom<Value<'a>> for HashMap<K, V, H>
176where
177 K: crate::Basic + TryFrom<Value<'a>> + std::hash::Hash + std::cmp::Eq,
178 V: TryFrom<Value<'a>>,
179 H: BuildHasher + Default,
180 K::Error: Into<crate::Error>,
181 V::Error: Into<crate::Error>,
182{
183 type Error = crate::Error;
184
185 fn try_from(value: Value<'a>) -> Result<Self, Self::Error> {
186 if let Value::Dict(v) = value {
187 Self::try_from(v)
188 } else {
189 Err(crate::Error::IncorrectType)
190 }
191 }
192}
193
194impl<'a, T> TryFrom<Value<'a>> for Optional<T>
195where
196 T: TryFrom<Value<'a>> + NoneValue + PartialEq<<T as NoneValue>::NoneType>,
197 T::Error: Into<crate::Error>,
198{
199 type Error = crate::Error;
200
201 fn try_from(value: Value<'a>) -> Result<Self, Self::Error> {
202 T::try_from(value).map_err(Into::into).map(|value| {
203 if value == T::null_value() {
204 Optional::from(None)
205 } else {
206 Optional::from(Some(value))
207 }
208 })
209 }
210}
211
212