plex_api/myplex/sharing/
filter.rs

1use serde::{
2    de::{Deserializer, Visitor},
3    Deserialize, Serialize,
4};
5use std::{
6    fmt::{Display, Formatter, Result as FmtResult},
7    result::Result as StdResult,
8};
9
10#[derive(Default, Debug, Clone)]
11pub struct SharingFilter {
12    pub content_rating: Vec<String>,
13    pub exclude_content_rating: Vec<String>,
14    pub label: Vec<String>,
15    pub exclude_label: Vec<String>,
16}
17
18impl<'de> Deserialize<'de> for SharingFilter {
19    fn deserialize<D>(deserializer: D) -> StdResult<Self, D::Error>
20    where
21        D: Deserializer<'de>,
22    {
23        struct V;
24
25        impl<'de> Visitor<'de> for V {
26            type Value = SharingFilter;
27
28            fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
29                formatter.write_str("valid plex filter string")
30            }
31
32            fn visit_str<E>(self, value: &str) -> StdResult<SharingFilter, E>
33            where
34                E: ::serde::de::Error,
35            {
36                let mut ret = SharingFilter::default();
37
38                if value.is_empty() {
39                    return Ok(ret);
40                }
41
42                for filter in value.split('|') {
43                    let decoded_values =
44                        serde_urlencoded::from_str::<Vec<(String, String)>>(filter);
45                    if let Ok(decoded_values) = decoded_values {
46                        for pairs in decoded_values {
47                            match pairs.0.as_str() {
48                                "contentRating" => {
49                                    ret.content_rating =
50                                        pairs.1.split(',').map(|v| v.to_owned()).collect()
51                                }
52                                "contentRating!" => {
53                                    ret.exclude_content_rating =
54                                        pairs.1.split(',').map(|v| v.to_owned()).collect()
55                                }
56                                "label" => {
57                                    ret.label = pairs.1.split(',').map(|v| v.to_owned()).collect()
58                                }
59                                "label!" => {
60                                    ret.exclude_label =
61                                        pairs.1.split(',').map(|v| v.to_owned()).collect()
62                                }
63                                _ => {
64                                    return Err(::serde::de::Error::invalid_value(
65                                        ::serde::de::Unexpected::Str(value),
66                                        &self,
67                                    ));
68                                }
69                            }
70                        }
71                    } else {
72                        return Err(::serde::de::Error::invalid_value(
73                            ::serde::de::Unexpected::Str(value),
74                            &self,
75                        ));
76                    }
77                }
78
79                Ok(ret)
80            }
81        }
82
83        deserializer.deserialize_str(V)
84    }
85}
86
87impl Serialize for SharingFilter {
88    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89    where
90        S: ::serde::ser::Serializer,
91    {
92        serializer.serialize_str(&self.to_string())
93    }
94}
95
96impl Display for SharingFilter {
97    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
98        let mut ret: Vec<String> = vec![];
99
100        if !self.content_rating.is_empty() {
101            ret.push(format!("contentRating={}", self.content_rating.join("%2C")))
102        }
103
104        if !self.exclude_content_rating.is_empty() {
105            ret.push(format!(
106                "contentRating!={}",
107                self.exclude_content_rating.join("%2C")
108            ))
109        }
110
111        if !self.label.is_empty() {
112            ret.push(format!("label={}", self.label.join("%2C")))
113        }
114
115        if !self.exclude_label.is_empty() {
116            ret.push(format!("label!={}", self.exclude_label.join("%2C")))
117        }
118
119        write!(f, "{}", ret.join("|"))
120    }
121}