doobs_mpris/types/
playback_status.rs1use std::fmt::{self, Display};
2use std::str::FromStr;
3
4use serde::{Deserialize, Serialize};
5use zvariant::{OwnedValue, Type, Value};
6
7use crate::{Error, Result};
8
9#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
11pub enum PlaybackStatus {
12 Playing,
14 Paused,
16 Stopped,
18}
19
20impl FromStr for PlaybackStatus {
21 type Err = Error;
22
23 fn from_str(s: &str) -> Result<Self> {
24 match s.to_lowercase().trim() {
25 "playing" => Ok(Self::Playing),
26 "paused" => Ok(Self::Paused),
27 "stopped" => Ok(Self::Stopped),
28 _ => Err(Error::InvalidEnum {
29 got: s.to_string(),
30 expected: &["Playing", "Paused", "Stopped"],
31 }),
32 }
33 }
34}
35
36impl Display for PlaybackStatus {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 write!(
39 f,
40 "{}",
41 match self {
42 Self::Playing => "Playing",
43 Self::Paused => "Paused",
44 Self::Stopped => "Stopped",
45 }
46 )
47 }
48}
49
50impl Type for PlaybackStatus {
53 const SIGNATURE: &'static zvariant::Signature = &zvariant::Signature::Str;
54}
55
56impl From<PlaybackStatus> for Value<'_> {
57 fn from(value: PlaybackStatus) -> Self {
58 Value::from(value.to_string())
59 }
60}
61
62impl TryFrom<Value<'_>> for PlaybackStatus {
63 type Error = zvariant::Error;
64
65 fn try_from(value: Value) -> std::result::Result<Self, Self::Error> {
66 let value: &str = value.downcast_ref::<&str>()?;
67 let value = PlaybackStatus::from_str(value)?;
68 Ok(value)
69 }
70}
71
72impl TryFrom<OwnedValue> for PlaybackStatus {
73 type Error = zvariant::Error;
74
75 fn try_from(value: OwnedValue) -> std::result::Result<Self, Self::Error> {
76 let value = value.downcast_ref::<&str>()?;
77 let value = PlaybackStatus::from_str(value)?;
78 Ok(value)
79 }
80}
81
82#[cfg(test)]
83mod test {
84 use zvariant::serialized::Context;
85 use zvariant::{LE, OwnedValue, Value, to_bytes};
86
87 use super::PlaybackStatus;
88
89 #[test]
90 fn success() {
91 let expected = PlaybackStatus::Paused;
92
93 let v = Value::Str("paused".into());
95 let status = PlaybackStatus::try_from(v.clone()).unwrap();
96
97 assert_eq!(status, expected);
98 assert_eq!(Value::Str("Paused".into()), Value::from(expected));
99
100 let ov = OwnedValue::try_from(v.clone()).unwrap();
101 let duration = PlaybackStatus::try_from(ov.clone()).unwrap();
102
103 assert_eq!(duration, expected);
104 }
105
106 #[test]
107 fn wrong_enum_type() {
108 let v = Value::Str("unknown".into());
109 let err = PlaybackStatus::try_from(v.clone()).unwrap_err();
110
111 assert!(matches!(err, zvariant::Error::Message(_)));
112
113 let ov = OwnedValue::try_from(v).unwrap();
114 let err = PlaybackStatus::try_from(ov).unwrap_err();
115
116 assert!(matches!(err, zvariant::Error::Message(_)));
117 }
118
119 #[test]
120 fn wrong_dbus_type() {
121 let v = Value::U64(5);
122 let err = PlaybackStatus::try_from(v.clone()).unwrap_err();
123
124 assert_eq!(zvariant::Error::IncorrectType, err);
125
126 let ov = OwnedValue::try_from(v).unwrap();
127 let err = PlaybackStatus::try_from(ov).unwrap_err();
128
129 assert_eq!(zvariant::Error::IncorrectType, err);
130 }
131
132 #[test]
133 fn serialize() {
134 let ctxt = Context::new_dbus(LE, 0);
135 let encoded = to_bytes(ctxt, &PlaybackStatus::Stopped).unwrap();
136 let decoded: &str = encoded.deserialize().unwrap().0;
137
138 assert_eq!(decoded, "Stopped");
139 }
140
141 #[test]
142 fn deserialize() {
143 let ctxt = Context::new_dbus(LE, 0);
144 let encoded = to_bytes(ctxt, "Stopped").unwrap();
145 let decoded: PlaybackStatus = encoded.deserialize().unwrap().0;
146
147 assert_eq!(decoded, PlaybackStatus::Stopped);
148 }
149}