librespot_metadata/
restriction.rs1use std::{
2 fmt::Debug,
3 ops::{Deref, DerefMut},
4};
5
6use crate::util::impl_deref_wrapped;
7use crate::util::{impl_from_repeated, impl_from_repeated_copy};
8
9use protocol::metadata::Restriction as RestrictionMessage;
10
11use librespot_protocol as protocol;
12pub use protocol::metadata::restriction::Catalogue as RestrictionCatalogue;
13pub use protocol::metadata::restriction::Type as RestrictionType;
14
15#[derive(Debug, Clone)]
16pub struct Restriction {
17 pub catalogues: RestrictionCatalogues,
18 pub restriction_type: RestrictionType,
19 pub catalogue_strs: Vec<String>,
20 pub countries_allowed: Option<Vec<String>>,
21 pub countries_forbidden: Option<Vec<String>>,
22}
23
24#[derive(Debug, Clone, Default)]
25pub struct Restrictions(pub Vec<Restriction>);
26
27impl_deref_wrapped!(Restrictions, Vec<Restriction>);
28
29#[derive(Debug, Clone)]
30pub struct RestrictionCatalogues(pub Vec<RestrictionCatalogue>);
31
32impl_deref_wrapped!(RestrictionCatalogues, Vec<RestrictionCatalogue>);
33
34impl Restriction {
35 fn parse_country_codes(country_codes: &str) -> Vec<String> {
36 country_codes
37 .chunks(2)
38 .map(|country_code| country_code.to_owned())
39 .collect()
40 }
41}
42
43impl From<&RestrictionMessage> for Restriction {
44 fn from(restriction: &RestrictionMessage) -> Self {
45 let countries_allowed = if restriction.has_countries_allowed() {
46 Some(Self::parse_country_codes(restriction.countries_allowed()))
47 } else {
48 None
49 };
50
51 let countries_forbidden = if restriction.has_countries_forbidden() {
52 Some(Self::parse_country_codes(restriction.countries_forbidden()))
53 } else {
54 None
55 };
56
57 Self {
58 catalogues: restriction
59 .catalogue
60 .iter()
61 .map(|c| c.enum_value_or_default())
62 .collect::<Vec<RestrictionCatalogue>>()
63 .as_slice()
64 .into(),
65 restriction_type: restriction
66 .type_
67 .unwrap_or_default()
68 .enum_value_or_default(),
69 catalogue_strs: restriction.catalogue_str.to_vec(),
70 countries_allowed,
71 countries_forbidden,
72 }
73 }
74}
75
76impl_from_repeated!(RestrictionMessage, Restrictions);
77impl_from_repeated_copy!(RestrictionCatalogue, RestrictionCatalogues);
78
79struct StrChunks<'s>(&'s str, usize);
80
81trait StrChunksExt {
82 fn chunks(&self, size: usize) -> StrChunks<'_>;
83}
84
85impl StrChunksExt for str {
86 fn chunks(&self, size: usize) -> StrChunks<'_> {
87 StrChunks(self, size)
88 }
89}
90
91impl<'s> Iterator for StrChunks<'s> {
92 type Item = &'s str;
93 fn next(&mut self) -> Option<&'s str> {
94 let &mut StrChunks(data, size) = self;
95 if data.is_empty() {
96 None
97 } else {
98 let ret = Some(&data[..size]);
99 self.0 = &data[size..];
100 ret
101 }
102 }
103}