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