1 | use std::{collections::HashMap, hash::BuildHasher}; |
2 | |
3 | #[cfg (feature = "gvariant" )] |
4 | use crate::Maybe; |
5 | use crate::{Array, Dict, NoneValue, ObjectPath, Optional, Signature, Str, Structure, Type, Value}; |
6 | |
7 | #[cfg (unix)] |
8 | use crate::Fd; |
9 | |
10 | // |
11 | // Conversions from encodable types to `Value` |
12 | |
13 | macro_rules! into_value { |
14 | ($from:ty, $kind:ident) => { |
15 | impl<'a> From<$from> for Value<'a> { |
16 | fn from(v: $from) -> Self { |
17 | Value::$kind(v.into()) |
18 | } |
19 | } |
20 | }; |
21 | } |
22 | |
23 | macro_rules! into_value_from_ref { |
24 | ($from:ty, $kind:ident) => { |
25 | impl<'a> From<&'a $from> for Value<'a> { |
26 | fn from(v: &'a $from) -> Self { |
27 | Value::$kind(v.clone().into()) |
28 | } |
29 | } |
30 | }; |
31 | } |
32 | |
33 | macro_rules! into_value_from_both { |
34 | ($from:ty, $kind:ident) => { |
35 | into_value!($from, $kind); |
36 | into_value_from_ref!($from, $kind); |
37 | }; |
38 | } |
39 | |
40 | into_value_from_both!(u8, U8); |
41 | into_value_from_both!(i8, I16); |
42 | into_value_from_both!(bool, Bool); |
43 | into_value_from_both!(u16, U16); |
44 | into_value_from_both!(i16, I16); |
45 | into_value_from_both!(u32, U32); |
46 | into_value_from_both!(i32, I32); |
47 | into_value_from_both!(u64, U64); |
48 | into_value_from_both!(i64, I64); |
49 | into_value_from_both!(f32, F64); |
50 | into_value_from_both!(f64, F64); |
51 | |
52 | into_value_from_both!(&'a str, Str); |
53 | into_value_from_both!(Str<'a>, Str); |
54 | into_value_from_both!(Signature<'a>, Signature); |
55 | into_value_from_both!(ObjectPath<'a>, ObjectPath); |
56 | |
57 | macro_rules! try_into_value_from_ref { |
58 | ($from:ty, $kind:ident) => { |
59 | impl<'a> TryFrom<&'a $from> for Value<'a> { |
60 | type Error = crate::Error; |
61 | |
62 | fn try_from(v: &'a $from) -> crate::Result<Self> { |
63 | v.try_clone().map(Value::$kind) |
64 | } |
65 | } |
66 | }; |
67 | } |
68 | |
69 | into_value!(Array<'a>, Array); |
70 | try_into_value_from_ref!(Array<'a>, Array); |
71 | into_value!(Dict<'a, 'a>, Dict); |
72 | try_into_value_from_ref!(Dict<'a, 'a>, Dict); |
73 | #[cfg (feature = "gvariant" )] |
74 | into_value!(Maybe<'a>, Maybe); |
75 | #[cfg (feature = "gvariant" )] |
76 | try_into_value_from_ref!(Maybe<'a>, Maybe); |
77 | #[cfg (unix)] |
78 | into_value!(Fd<'a>, Fd); |
79 | #[cfg (unix)] |
80 | try_into_value_from_ref!(Fd<'a>, Fd); |
81 | |
82 | impl From<String> for Value<'_> { |
83 | fn from(v: String) -> Self { |
84 | Value::Str(crate::Str::from(v)) |
85 | } |
86 | } |
87 | |
88 | impl<'v, 's: 'v, T> From<T> for Value<'v> |
89 | where |
90 | T: Into<Structure<'s>>, |
91 | { |
92 | fn from(v: T) -> Value<'v> { |
93 | Value::Structure(v.into()) |
94 | } |
95 | } |
96 | |
97 | impl<'v, V> From<&'v [V]> for Value<'v> |
98 | where |
99 | &'v [V]: Into<Array<'v>>, |
100 | { |
101 | fn from(v: &'v [V]) -> Value<'v> { |
102 | Value::Array(v.into()) |
103 | } |
104 | } |
105 | |
106 | impl<'v, V> From<Vec<V>> for Value<'v> |
107 | where |
108 | Vec<V>: Into<Array<'v>>, |
109 | { |
110 | fn from(v: Vec<V>) -> Value<'v> { |
111 | Value::Array(v.into()) |
112 | } |
113 | } |
114 | |
115 | impl<'v, V> From<&'v Vec<V>> for Value<'v> |
116 | where |
117 | &'v Vec<V>: Into<Array<'v>>, |
118 | { |
119 | fn from(v: &'v Vec<V>) -> Value<'v> { |
120 | Value::Array(v.into()) |
121 | } |
122 | } |
123 | |
124 | impl<'a, 'k, 'v, K, V, H> From<HashMap<K, V, H>> for Value<'a> |
125 | where |
126 | 'k: 'a, |
127 | 'v: 'a, |
128 | K: Type + Into<Value<'k>> + std::hash::Hash + std::cmp::Eq, |
129 | V: Type + Into<Value<'v>>, |
130 | H: BuildHasher + Default, |
131 | { |
132 | fn from(value: HashMap<K, V, H>) -> Self { |
133 | Self::Dict(value.into()) |
134 | } |
135 | } |
136 | |
137 | impl<'v> From<&'v String> for Value<'v> { |
138 | fn from(v: &'v String) -> Value<'v> { |
139 | Value::Str(v.into()) |
140 | } |
141 | } |
142 | |
143 | impl<'v, V> From<Optional<V>> for Value<'v> |
144 | where |
145 | V: Into<Value<'v>> + NoneValue<NoneType = V>, |
146 | { |
147 | fn from(v: Optional<V>) -> Value<'v> { |
148 | OptionV::<V>::from(v) |
149 | .unwrap_or_else(|| V::null_value()) |
150 | .into() |
151 | } |
152 | } |
153 | |
154 | #[cfg (all(feature = "gvariant" , not(feature = "option-as-array" )))] |
155 | impl<'v, V> From<Option<V>> for Value<'v> |
156 | where |
157 | Option<V>: Into<Maybe<'v>>, |
158 | { |
159 | fn from(v: Option<V>) -> Value<'v> { |
160 | Value::Maybe(v.into()) |
161 | } |
162 | } |
163 | |
164 | #[cfg (feature = "option-as-array" )] |
165 | impl<'v, V> From<Option<V>> for Value<'v> |
166 | where |
167 | V: Into<Value<'v>> + Type, |
168 | { |
169 | fn from(v: Option<V>) -> Value<'v> { |
170 | let mut array = Array::new(V::signature()); |
171 | if let Some(v) = v { |
172 | // We got the signature from the `Type` impl, so this should never panic. |
173 | array.append(v.into()).expect("signature mismatch" ); |
174 | } |
175 | |
176 | array.into() |
177 | } |
178 | } |
179 | |