use std::{convert::TryFrom, str::FromStr};
use tf_core::Subscription;
macro_rules! match_subscription {
($sub: ident, $func_name: ident) => {
match_subscription!($sub, $func_name())
};
($sub: ident, $($func_name: ident ($($arg: ident),*)).*) => {
match $sub {
#[cfg(feature = "youtube")]
AnySubscription::Youtube(s) => s.$($func_name($($arg)*))*,
#[cfg(feature = "peertube")]
AnySubscription::Peertube(s) => s.$($func_name($($arg)*))*,
#[cfg(feature = "lbry")]
AnySubscription::Lbry(s) => s.$($func_name($($arg)*))*,
#[cfg(test)]
AnySubscription::Test(s) => s.$($func_name($($arg)*))*,
}
};
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum AnySubscription {
#[cfg(feature = "youtube")]
Youtube(tf_yt::YTSubscription),
#[cfg(feature = "peertube")]
Peertube(tf_pt::PTSubscription),
#[cfg(feature = "lbry")]
Lbry(tf_lbry::LbrySubscription),
#[cfg(test)]
Test(tf_test::TestSubscription),
}
impl AnySubscription {
pub fn platform(&self) -> Platform {
match &self {
#[cfg(feature = "youtube")]
AnySubscription::Youtube(_) => Platform::Youtube,
#[cfg(feature = "peertube")]
AnySubscription::Peertube(_) => Platform::Peertube,
#[cfg(feature = "lbry")]
AnySubscription::Lbry(_) => Platform::Lbry,
#[cfg(test)]
AnySubscription::Test(_) => Platform::Test,
}
}
}
impl Subscription for AnySubscription {
type Video = crate::AnyVideo;
fn name(&self) -> Option<String> {
match_subscription!(self, name)
}
}
impl std::fmt::Display for AnySubscription {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
#[cfg(feature = "youtube")]
AnySubscription::Youtube(s) => write!(f, "{}", s),
#[cfg(feature = "peertube")]
AnySubscription::Peertube(s) => write!(f, "{}", s),
#[cfg(feature = "lbry")]
AnySubscription::Lbry(s) => write!(f, "{}", s),
#[cfg(test)]
AnySubscription::Test(s) => write!(f, "{}", s),
}
}
}
impl TryFrom<Vec<String>> for AnySubscription {
type Error = ();
fn try_from(value: Vec<String>) -> Result<Self, Self::Error> {
if value.len() == 0 {
return Err(());
}
let mut value_mut = value.clone();
let platform = Platform::from_str(value_mut.remove(0).as_str());
match platform {
#[cfg(feature = "youtube")]
Ok(Platform::Youtube) => tf_yt::YTSubscription::try_from(value_mut).map(|s| s.into()),
#[cfg(feature = "peertube")]
Ok(Platform::Peertube) => tf_pt::PTSubscription::try_from(value_mut).map(|s| s.into()),
#[cfg(feature = "lbry")]
Ok(Platform::Lbry) => tf_lbry::LbrySubscription::try_from(value_mut).map(|s| s.into()),
#[cfg(test)]
Ok(Platform::Test) => tf_test::TestSubscription::try_from(value_mut).map(|s| s.into()),
_ => Err(()),
}
}
}
impl From<AnySubscription> for Vec<String> {
fn from(sub: AnySubscription) -> Self {
let mut result = vec![sub.platform().into()];
let sub_vec: Vec<String> = match_subscription!(sub, into());
result.extend(sub_vec);
result
}
}
#[cfg(feature = "youtube")]
impl From<tf_yt::YTSubscription> for AnySubscription {
fn from(s: tf_yt::YTSubscription) -> Self {
AnySubscription::Youtube(s)
}
}
#[cfg(feature = "peertube")]
impl From<tf_pt::PTSubscription> for AnySubscription {
fn from(s: tf_pt::PTSubscription) -> Self {
AnySubscription::Peertube(s)
}
}
#[cfg(feature = "lbry")]
impl From<tf_lbry::LbrySubscription> for AnySubscription {
fn from(s: tf_lbry::LbrySubscription) -> Self {
AnySubscription::Lbry(s)
}
}
#[cfg(test)]
impl From<tf_test::TestSubscription> for AnySubscription {
fn from(s: tf_test::TestSubscription) -> Self {
AnySubscription::Test(s)
}
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum Platform {
#[cfg(feature = "youtube")]
Youtube,
#[cfg(feature = "peertube")]
Peertube,
#[cfg(feature = "lbry")]
Lbry,
#[cfg(test)]
Test,
}
impl FromStr for Platform {
type Err = ();
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value.to_lowercase().as_str() {
#[cfg(feature = "youtube")]
"youtube" => Ok(Platform::Youtube),
#[cfg(feature = "peertube")]
"peertube" => Ok(Platform::Peertube),
#[cfg(feature = "lbry")]
"lbry" => Ok(Platform::Lbry),
#[cfg(test)]
"test" => Ok(Platform::Test),
_ => Err(()),
}
}
}
impl From<Platform> for String {
fn from(p: Platform) -> Self {
match p {
#[cfg(feature = "youtube")]
Platform::Youtube => "youtube".to_owned(),
#[cfg(feature = "peertube")]
Platform::Peertube => "peertube".to_owned(),
#[cfg(feature = "lbry")]
Platform::Lbry => "lbry".to_owned(),
#[cfg(test)]
Platform::Test => "test".to_owned(),
}
}
}
impl std::fmt::Display for Platform {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
#[cfg(feature = "youtube")]
Platform::Youtube => write!(f, "YouTube"),
#[cfg(feature = "peertube")]
Platform::Peertube => write!(f, "PeerTube"),
#[cfg(feature = "lbry")]
Platform::Lbry => write!(f, "LBRY"),
#[cfg(test)]
Platform::Test => write!(f, "Test"),
}
}
}
impl Platform {
pub fn values() -> Vec<Self> {
let mut result = vec![];
#[cfg(feature = "youtube")]
result.push(Platform::Youtube);
#[cfg(feature = "peertube")]
result.push(Platform::Peertube);
#[cfg(feature = "lbry")]
result.push(Platform::Lbry);
#[cfg(test)]
result.push(Platform::Test);
result
}
}
#[cfg(test)]
mod test {
use std::convert::TryInto;
use super::*;
use tf_test::TestSubscription;
#[cfg(feature = "youtube")]
use tf_yt::YTSubscription;
#[test]
#[cfg(feature = "youtube")]
fn anysubscription_conversion_youtube() {
let row = vec!["youtube".to_string(), "abcdef".to_string()];
let subscription_res: Result<AnySubscription, ()> = row.try_into();
assert!(subscription_res.is_ok());
let subscription = subscription_res.unwrap();
assert_eq!(subscription.platform(), Platform::Youtube);
assert_eq!(subscription.to_string(), "abcdef");
}
#[test]
#[cfg(feature = "youtube")]
fn anysubscription_conversion_youtube_back() {
let row = vec!["youtube".to_string(), "abcdef".to_string()];
let subscription: AnySubscription = YTSubscription::new("abcdef").into();
assert_eq!(Vec::<String>::from(subscription), row);
}
#[test]
fn anysubscription_conversion_test() {
let row = vec!["test".to_string(), "abcdef".to_string()];
let subscription_res: Result<AnySubscription, ()> = row.try_into();
assert!(subscription_res.is_ok());
let subscription = subscription_res.unwrap();
assert_eq!(subscription.platform(), Platform::Test);
assert_eq!(subscription.to_string(), "abcdef");
}
#[test]
fn anysubscription_conversion_test_back() {
let row = vec!["test".to_string(), "abcdef".to_string()];
let subscription: AnySubscription = TestSubscription::new("abcdef").into();
assert_eq!(Vec::<String>::from(subscription), row);
}
#[test]
fn anysubscription_conversion_fail_no_platform() {
let row = vec!["thiswillfail".to_string(), "abcdef".to_string()];
let subscription_res: Result<AnySubscription, ()> = row.try_into();
assert!(subscription_res.is_err());
}
#[test]
#[cfg(feature = "youtube")]
fn anysubscription_conversion_fail_to_short() {
let row = vec!["youtube".to_string()];
let subscription_res: Result<AnySubscription, ()> = row.try_into();
assert!(subscription_res.is_err());
}
}