zvariant/
from_value.rs
1#[cfg(feature = "gvariant")]
2use crate::Maybe;
3use crate::{
4 Array, Dict, Error, NoneValue, ObjectPath, Optional, OwnedObjectPath, OwnedSignature,
5 Signature, Str, 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<'a>);
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
159impl TryFrom<Value<'_>> for OwnedSignature {
160 type Error = Error;
161
162 fn try_from(value: Value<'_>) -> Result<Self, Self::Error> {
163 Signature::try_from(value).map(OwnedSignature::from)
164 }
165}
166
167#[cfg(feature = "enumflags2")]
170impl<'a, F> TryFrom<Value<'a>> for enumflags2::BitFlags<F>
171where
172 F: enumflags2::BitFlag,
173 F::Numeric: TryFrom<Value<'a>, Error = Error>,
174{
175 type Error = Error;
176
177 fn try_from(value: Value<'a>) -> Result<Self, Self::Error> {
178 Self::from_bits(F::Numeric::try_from(value)?)
179 .map_err(|_| Error::Message("Failed to convert to bitflags".into()))
180 }
181}
182
183impl<'a, K, V, H> TryFrom<Value<'a>> for HashMap<K, V, H>
184where
185 K: crate::Basic + TryFrom<Value<'a>> + std::hash::Hash + std::cmp::Eq,
186 V: TryFrom<Value<'a>>,
187 H: BuildHasher + Default,
188 K::Error: Into<crate::Error>,
189 V::Error: Into<crate::Error>,
190{
191 type Error = crate::Error;
192
193 fn try_from(value: Value<'a>) -> Result<Self, Self::Error> {
194 if let Value::Dict(v) = value {
195 Self::try_from(v)
196 } else {
197 Err(crate::Error::IncorrectType)
198 }
199 }
200}
201
202impl<'a, T> TryFrom<Value<'a>> for Optional<T>
203where
204 T: TryFrom<Value<'a>> + NoneValue + PartialEq<<T as NoneValue>::NoneType>,
205 T::Error: Into<crate::Error>,
206{
207 type Error = crate::Error;
208
209 fn try_from(value: Value<'a>) -> Result<Self, Self::Error> {
210 T::try_from(value).map_err(Into::into).map(|value| {
211 if value == T::null_value() {
212 Optional::from(None)
213 } else {
214 Optional::from(Some(value))
215 }
216 })
217 }
218}
219
220