| 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 | |