use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PlaylistEntry {
pub url: Option<String>,
#[serde(default, skip_serializing_if = "SmallVec::is_empty")]
pub urls: SmallVec<[String; 2]>,
pub name: Option<String>,
pub tvg_id: Option<String>,
pub tvg_name: Option<String>,
pub tvg_language: Option<String>,
pub tvg_logo: Option<String>,
pub tvg_url: Option<String>,
pub tvg_rec: Option<String>,
pub tvg_chno: Option<String>,
pub group_title: Option<String>,
pub timeshift: Option<String>,
pub catchup: Option<CatchupConfig>,
pub duration: Option<f64>,
#[serde(default)]
pub is_radio: bool,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub extras: HashMap<String, String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CatchupConfig {
pub catchup_type: Option<CatchupType>,
pub days: Option<u32>,
pub source: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum CatchupType {
Default,
Append,
Shift,
Flussonic,
Fs,
Xc,
}
impl std::fmt::Display for CatchupType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Default => write!(f, "default"),
Self::Append => write!(f, "append"),
Self::Shift => write!(f, "shift"),
Self::Flussonic => write!(f, "flussonic"),
Self::Fs => write!(f, "fs"),
Self::Xc => write!(f, "xc"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_entry_has_no_url() {
let entry = PlaylistEntry::default();
assert!(entry.url.is_none());
assert!(entry.name.is_none());
assert!(entry.extras.is_empty());
assert!(!entry.is_radio);
}
#[test]
fn extras_are_skipped_when_empty_in_json() {
let entry = PlaylistEntry::default();
let json = serde_json::to_string(&entry).unwrap();
assert!(!json.contains("extras"));
}
}