| 1 | use serde::{Deserialize, Deserializer, Serialize}; |
| 2 | use static_assertions::assert_impl_all; |
| 3 | use std::{collections::HashMap, hash::BuildHasher}; |
| 4 | |
| 5 | use crate::{ |
| 6 | Array, Dict, NoneValue, ObjectPath, Optional, OwnedObjectPath, OwnedSignature, Signature, Str, |
| 7 | Structure, Type, Value, |
| 8 | }; |
| 9 | |
| 10 | #[cfg (unix)] |
| 11 | use crate::Fd; |
| 12 | |
| 13 | #[cfg (feature = "gvariant" )] |
| 14 | use crate::Maybe; |
| 15 | |
| 16 | // FIXME: Replace with a generic impl<T: TryFrom<Value>> TryFrom<OwnedValue> for T? |
| 17 | // https://github.com/dbus2/zbus/issues/138 |
| 18 | |
| 19 | /// Owned [`Value`](enum.Value.html) |
| 20 | #[derive (Debug, PartialEq, Serialize, Type)] |
| 21 | pub struct OwnedValue(pub(crate) Value<'static>); |
| 22 | |
| 23 | assert_impl_all!(OwnedValue: Send, Sync, Unpin); |
| 24 | |
| 25 | impl OwnedValue { |
| 26 | /// Attempt to clone the value. |
| 27 | pub fn try_clone(&self) -> Result<Self, crate::Error> { |
| 28 | self.0.try_clone().map(Self) |
| 29 | } |
| 30 | |
| 31 | pub(crate) fn into_inner(self) -> Value<'static> { |
| 32 | self.0 |
| 33 | } |
| 34 | |
| 35 | pub(crate) fn inner(&self) -> &Value<'_> { |
| 36 | &self.0 |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | macro_rules! ov_try_from { |
| 41 | ($to:ty) => { |
| 42 | impl TryFrom<OwnedValue> for $to { |
| 43 | type Error = crate::Error; |
| 44 | |
| 45 | fn try_from(v: OwnedValue) -> Result<Self, Self::Error> { |
| 46 | <$to>::try_from(v.0) |
| 47 | } |
| 48 | } |
| 49 | }; |
| 50 | } |
| 51 | |
| 52 | macro_rules! ov_try_from_ref { |
| 53 | ($to:ty) => { |
| 54 | impl<'a> TryFrom<&'a OwnedValue> for $to { |
| 55 | type Error = crate::Error; |
| 56 | |
| 57 | fn try_from(v: &'a OwnedValue) -> Result<Self, Self::Error> { |
| 58 | <$to>::try_from(&v.0) |
| 59 | } |
| 60 | } |
| 61 | }; |
| 62 | } |
| 63 | |
| 64 | ov_try_from!(u8); |
| 65 | ov_try_from!(bool); |
| 66 | ov_try_from!(i16); |
| 67 | ov_try_from!(u16); |
| 68 | ov_try_from!(i32); |
| 69 | ov_try_from!(u32); |
| 70 | ov_try_from!(i64); |
| 71 | ov_try_from!(u64); |
| 72 | ov_try_from!(f64); |
| 73 | ov_try_from!(String); |
| 74 | ov_try_from!(Signature<'static>); |
| 75 | ov_try_from!(OwnedSignature); |
| 76 | ov_try_from!(ObjectPath<'static>); |
| 77 | ov_try_from!(OwnedObjectPath); |
| 78 | ov_try_from!(Array<'static>); |
| 79 | ov_try_from!(Dict<'static, 'static>); |
| 80 | #[cfg (feature = "gvariant" )] |
| 81 | ov_try_from!(Maybe<'static>); |
| 82 | ov_try_from!(Str<'static>); |
| 83 | ov_try_from!(Structure<'static>); |
| 84 | #[cfg (unix)] |
| 85 | ov_try_from!(Fd<'static>); |
| 86 | |
| 87 | ov_try_from_ref!(u8); |
| 88 | ov_try_from_ref!(bool); |
| 89 | ov_try_from_ref!(i16); |
| 90 | ov_try_from_ref!(u16); |
| 91 | ov_try_from_ref!(i32); |
| 92 | ov_try_from_ref!(u32); |
| 93 | ov_try_from_ref!(i64); |
| 94 | ov_try_from_ref!(u64); |
| 95 | ov_try_from_ref!(f64); |
| 96 | ov_try_from_ref!(&'a str); |
| 97 | ov_try_from_ref!(&'a Signature<'a>); |
| 98 | ov_try_from_ref!(&'a ObjectPath<'a>); |
| 99 | ov_try_from_ref!(&'a Array<'a>); |
| 100 | ov_try_from_ref!(&'a Dict<'a, 'a>); |
| 101 | ov_try_from_ref!(&'a Str<'a>); |
| 102 | ov_try_from_ref!(&'a Structure<'a>); |
| 103 | #[cfg (feature = "gvariant" )] |
| 104 | ov_try_from_ref!(&'a Maybe<'a>); |
| 105 | #[cfg (unix)] |
| 106 | ov_try_from_ref!(&'a Fd<'a>); |
| 107 | |
| 108 | impl<'a, T> TryFrom<OwnedValue> for Vec<T> |
| 109 | where |
| 110 | T: TryFrom<Value<'a>>, |
| 111 | T::Error: Into<crate::Error>, |
| 112 | { |
| 113 | type Error = crate::Error; |
| 114 | |
| 115 | fn try_from(value: OwnedValue) -> Result<Self, Self::Error> { |
| 116 | if let Value::Array(v: Array<'_>) = value.0 { |
| 117 | Self::try_from(v) |
| 118 | } else { |
| 119 | Err(crate::Error::IncorrectType) |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | #[cfg (feature = "enumflags2" )] |
| 125 | impl<'a, F> TryFrom<OwnedValue> for enumflags2::BitFlags<F> |
| 126 | where |
| 127 | F: enumflags2::BitFlag, |
| 128 | F::Numeric: TryFrom<Value<'a>, Error = crate::Error>, |
| 129 | { |
| 130 | type Error = crate::Error; |
| 131 | |
| 132 | fn try_from(value: OwnedValue) -> Result<Self, Self::Error> { |
| 133 | Self::try_from(value.0) |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | impl<'k, 'v, K, V, H> TryFrom<OwnedValue> for HashMap<K, V, H> |
| 138 | where |
| 139 | K: crate::Basic + TryFrom<Value<'k>> + std::hash::Hash + std::cmp::Eq, |
| 140 | V: TryFrom<Value<'v>>, |
| 141 | H: BuildHasher + Default, |
| 142 | K::Error: Into<crate::Error>, |
| 143 | V::Error: Into<crate::Error>, |
| 144 | { |
| 145 | type Error = crate::Error; |
| 146 | |
| 147 | fn try_from(value: OwnedValue) -> Result<Self, Self::Error> { |
| 148 | if let Value::Dict(v: Dict<'_, '_>) = value.0 { |
| 149 | Self::try_from(v) |
| 150 | } else { |
| 151 | Err(crate::Error::IncorrectType) |
| 152 | } |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | impl<K, V, H> From<HashMap<K, V, H>> for OwnedValue |
| 157 | where |
| 158 | K: Type + Into<Value<'static>> + std::hash::Hash + std::cmp::Eq, |
| 159 | V: Type + Into<Value<'static>>, |
| 160 | H: BuildHasher + Default, |
| 161 | { |
| 162 | fn from(value: HashMap<K, V, H>) -> Self { |
| 163 | Self(value.into()) |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | impl<'a, T> TryFrom<OwnedValue> for Optional<T> |
| 168 | where |
| 169 | T: TryFrom<Value<'a>> + NoneValue + PartialEq<<T as NoneValue>::NoneType>, |
| 170 | T::Error: Into<crate::Error>, |
| 171 | { |
| 172 | type Error = crate::Error; |
| 173 | |
| 174 | fn try_from(value: OwnedValue) -> Result<Self, Self::Error> { |
| 175 | Self::try_from(value.0) |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | impl<V> From<Optional<V>> for OwnedValue |
| 180 | where |
| 181 | V: Into<Value<'static>> + NoneValue<NoneType = V>, |
| 182 | { |
| 183 | fn from(v: Optional<V>) -> OwnedValue { |
| 184 | Self(Value::from(v)) |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | // tuple conversions in `structure` module for avoiding code-duplication. |
| 189 | |
| 190 | impl<'a> TryFrom<Value<'a>> for OwnedValue { |
| 191 | type Error = crate::Error; |
| 192 | |
| 193 | fn try_from(v: Value<'a>) -> crate::Result<Self> { |
| 194 | // TODO: add into_owned, avoiding copy if already owned.. |
| 195 | v.try_to_owned() |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | impl<'a> TryFrom<&Value<'a>> for OwnedValue { |
| 200 | type Error = crate::Error; |
| 201 | |
| 202 | fn try_from(v: &Value<'a>) -> crate::Result<Self> { |
| 203 | v.try_to_owned() |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | macro_rules! to_value { |
| 208 | ($from:ty, $variant:ident) => { |
| 209 | impl<'a> From<$from> for OwnedValue { |
| 210 | fn from(v: $from) -> Self { |
| 211 | OwnedValue(<Value<'static>>::$variant(v.to_owned())) |
| 212 | } |
| 213 | } |
| 214 | }; |
| 215 | } |
| 216 | |
| 217 | to_value!(u8, U8); |
| 218 | to_value!(bool, Bool); |
| 219 | to_value!(i16, I16); |
| 220 | to_value!(u16, U16); |
| 221 | to_value!(i32, I32); |
| 222 | to_value!(u32, U32); |
| 223 | to_value!(i64, I64); |
| 224 | to_value!(u64, U64); |
| 225 | to_value!(f64, F64); |
| 226 | to_value!(Str<'a>, Str); |
| 227 | to_value!(Signature<'a>, Signature); |
| 228 | to_value!(ObjectPath<'a>, ObjectPath); |
| 229 | |
| 230 | macro_rules! try_to_value { |
| 231 | ($from:ty) => { |
| 232 | impl<'a> TryFrom<$from> for OwnedValue { |
| 233 | type Error = crate::Error; |
| 234 | |
| 235 | fn try_from(v: $from) -> crate::Result<Self> { |
| 236 | OwnedValue::try_from(<Value<'a>>::from(v)) |
| 237 | } |
| 238 | } |
| 239 | }; |
| 240 | } |
| 241 | |
| 242 | try_to_value!(Array<'a>); |
| 243 | try_to_value!(Dict<'a, 'a>); |
| 244 | #[cfg (feature = "gvariant" )] |
| 245 | try_to_value!(Maybe<'a>); |
| 246 | try_to_value!(Structure<'a>); |
| 247 | #[cfg (unix)] |
| 248 | try_to_value!(Fd<'a>); |
| 249 | |
| 250 | impl From<OwnedValue> for Value<'_> { |
| 251 | fn from(v: OwnedValue) -> Self { |
| 252 | v.into_inner() |
| 253 | } |
| 254 | } |
| 255 | |
| 256 | impl<'o> TryFrom<&'o OwnedValue> for Value<'o> { |
| 257 | type Error = crate::Error; |
| 258 | |
| 259 | fn try_from(v: &'o OwnedValue) -> crate::Result<Value<'o>> { |
| 260 | v.inner().try_clone() |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | impl std::ops::Deref for OwnedValue { |
| 265 | type Target = Value<'static>; |
| 266 | |
| 267 | fn deref(&self) -> &Self::Target { |
| 268 | &self.0 |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | impl<'de> Deserialize<'de> for OwnedValue { |
| 273 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
| 274 | where |
| 275 | D: Deserializer<'de>, |
| 276 | { |
| 277 | Value::deserialize(deserializer) |
| 278 | .and_then(|v: Value<'_>| v.try_to_owned().map_err(op:serde::de::Error::custom)) |
| 279 | } |
| 280 | } |
| 281 | |
| 282 | #[cfg (test)] |
| 283 | mod tests { |
| 284 | use std::{collections::HashMap, error::Error}; |
| 285 | |
| 286 | use crate::{serialized::Context, to_bytes, OwnedValue, Value, LE}; |
| 287 | |
| 288 | #[cfg (feature = "enumflags2" )] |
| 289 | #[test ] |
| 290 | fn bitflags() -> Result<(), Box<dyn Error>> { |
| 291 | #[repr (u32)] |
| 292 | #[enumflags2::bitflags ] |
| 293 | #[derive (Copy, Clone, Debug)] |
| 294 | pub enum Flaggy { |
| 295 | One = 0x1, |
| 296 | Two = 0x2, |
| 297 | } |
| 298 | |
| 299 | let v = Value::from(0x2u32); |
| 300 | let ov: OwnedValue = v.try_into()?; |
| 301 | assert_eq!(<enumflags2::BitFlags<Flaggy>>::try_from(ov)?, Flaggy::Two); |
| 302 | Ok(()) |
| 303 | } |
| 304 | |
| 305 | #[test ] |
| 306 | fn from_value() -> Result<(), Box<dyn Error>> { |
| 307 | let v = Value::from("hi!" ); |
| 308 | let ov: OwnedValue = v.try_into()?; |
| 309 | assert_eq!(<&str>::try_from(&ov)?, "hi!" ); |
| 310 | Ok(()) |
| 311 | } |
| 312 | |
| 313 | #[test ] |
| 314 | fn serde() -> Result<(), Box<dyn Error>> { |
| 315 | let ec = Context::new_dbus(LE, 0); |
| 316 | let ov: OwnedValue = Value::from("hi!" ).try_into()?; |
| 317 | let ser = to_bytes(ec, &ov)?; |
| 318 | let (de, parsed): (Value<'_>, _) = ser.deserialize()?; |
| 319 | assert_eq!(<&str>::try_from(&de)?, "hi!" ); |
| 320 | assert_eq!(parsed, ser.len()); |
| 321 | Ok(()) |
| 322 | } |
| 323 | |
| 324 | #[test ] |
| 325 | fn map_conversion() -> Result<(), Box<dyn Error>> { |
| 326 | let mut map = HashMap::<String, String>::new(); |
| 327 | map.insert("one" .to_string(), "1" .to_string()); |
| 328 | map.insert("two" .to_string(), "2" .to_string()); |
| 329 | let value = OwnedValue::from(map.clone()); |
| 330 | // Now convert back |
| 331 | let map2 = <HashMap<String, String>>::try_from(value)?; |
| 332 | assert_eq!(map, map2); |
| 333 | |
| 334 | Ok(()) |
| 335 | } |
| 336 | } |
| 337 | |