ferrex-model 0.1.2-alpha

Shared data models for the Ferrex media platform
Documentation
use crate::{
    ids::{EpisodeID, MovieID, SeasonID, SeriesID},
    media_type::VideoMediaType,
};
use uuid::Uuid;

#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
    feature = "rkyv",
    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv", rkyv(derive(Debug, PartialEq, Eq, Hash)))]
pub enum MediaID {
    Movie(MovieID),
    Series(SeriesID),
    Season(SeasonID),
    Episode(EpisodeID),
}

impl Default for MediaID {
    fn default() -> Self {
        MediaID::Movie(MovieID(Uuid::now_v7()))
    }
}

impl From<(Uuid, VideoMediaType)> for MediaID {
    fn from(v: (Uuid, VideoMediaType)) -> Self {
        match v.1 {
            VideoMediaType::Movie => MediaID::Movie(v.0.into()),
            VideoMediaType::Series => MediaID::Series(v.0.into()),
            VideoMediaType::Season => MediaID::Season(v.0.into()),
            VideoMediaType::Episode => MediaID::Episode(v.0.into()),
        }
    }
}

impl MediaID {
    pub fn new(media_type: VideoMediaType) -> MediaID {
        match media_type {
            VideoMediaType::Movie => MediaID::Movie(MovieID(Uuid::now_v7())),
            VideoMediaType::Series => MediaID::Series(SeriesID(Uuid::now_v7())),
            VideoMediaType::Season => MediaID::Season(SeasonID(Uuid::now_v7())),
            VideoMediaType::Episode => {
                MediaID::Episode(EpisodeID(Uuid::now_v7()))
            }
        }
    }

    pub fn as_uuid(&self) -> &Uuid {
        match &self {
            MediaID::Movie(movie_id) => movie_id.as_uuid(),
            MediaID::Series(series_id) => series_id.as_uuid(),
            MediaID::Season(season_id) => season_id.as_uuid(),
            MediaID::Episode(episode_id) => episode_id.as_uuid(),
        }
    }

    pub fn eq_movie(&self, other: &MovieID) -> bool {
        match (self, other) {
            (MediaID::Movie(MovieID(a)), MovieID(b)) => a == b,
            _ => false,
        }
    }
    pub fn eq_series(&self, other: &SeriesID) -> bool {
        match (self, other) {
            (MediaID::Series(SeriesID(a)), SeriesID(b)) => a == b,
            _ => false,
        }
    }
    pub fn eq_episode(&self, other: &EpisodeID) -> bool {
        match (self, other) {
            (MediaID::Episode(EpisodeID(a)), EpisodeID(b)) => a == b,
            _ => false,
        }
    }
}
impl std::fmt::Display for MediaID {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            MediaID::Movie(id) => write!(f, "Movie({})", id.as_str()),
            MediaID::Series(id) => write!(f, "Series({})", id.as_str()),
            MediaID::Season(id) => write!(f, "Season({})", id.as_str()),
            MediaID::Episode(id) => write!(f, "Episode({})", id.as_str()),
        }
    }
}

impl From<MovieID> for MediaID {
    fn from(id: MovieID) -> Self {
        MediaID::Movie(id)
    }
}

impl From<SeriesID> for MediaID {
    fn from(id: SeriesID) -> Self {
        MediaID::Series(id)
    }
}

impl From<SeasonID> for MediaID {
    fn from(id: SeasonID) -> Self {
        MediaID::Season(id)
    }
}

impl From<EpisodeID> for MediaID {
    fn from(id: EpisodeID) -> Self {
        MediaID::Episode(id)
    }
}

#[cfg(feature = "rkyv")]
mod archived {
    use super::*;
    use crate::{
        ids::{
            ArchivedEpisodeID, ArchivedMovieID, ArchivedSeasonID,
            ArchivedSeriesID,
        },
        media::{ArchivedMedia, ArchivedMovieReference},
    };
    use rkyv::rancor::Error;
    use rkyv::{boxed::ArchivedBox, deserialize};

    impl ArchivedMediaID {
        pub fn eq_movie(&self, other: &ArchivedMovieID) -> bool {
            matches!(
                (self, other),
                (
                    ArchivedMediaID::Movie(ArchivedMovieID(a)),
                    ArchivedMovieID(b)
                ) if a == b
            )
        }

        pub fn eq_series(&self, other: &ArchivedSeriesID) -> bool {
            matches!(
                (self, other),
                (
                    ArchivedMediaID::Series(ArchivedSeriesID(a)),
                    ArchivedSeriesID(b)
                ) if a == b
            )
        }

        pub fn eq_episode(&self, other: &ArchivedEpisodeID) -> bool {
            matches!(
                (self, other),
                (
                    ArchivedMediaID::Episode(ArchivedEpisodeID(a)),
                    ArchivedEpisodeID(b)
                ) if a == b
            )
        }
    }

    impl From<ArchivedMedia> for ArchivedBox<ArchivedMovieReference> {
        fn from(med_ref: ArchivedMedia) -> Self {
            match med_ref {
                ArchivedMedia::Movie(data) => data,
                _ => panic!(
                    "Cannot convert non-movie reference to movie reference"
                ),
            }
        }
    }

    impl From<ArchivedMovieID> for ArchivedMediaID {
        fn from(id: ArchivedMovieID) -> Self {
            ArchivedMediaID::Movie(id)
        }
    }

    impl From<ArchivedSeriesID> for ArchivedMediaID {
        fn from(id: ArchivedSeriesID) -> Self {
            ArchivedMediaID::Series(id)
        }
    }

    impl From<ArchivedSeasonID> for ArchivedMediaID {
        fn from(id: ArchivedSeasonID) -> Self {
            ArchivedMediaID::Season(id)
        }
    }

    impl From<ArchivedEpisodeID> for ArchivedMediaID {
        fn from(id: ArchivedEpisodeID) -> Self {
            ArchivedMediaID::Episode(id)
        }
    }

    impl From<ArchivedMovieID> for MediaID {
        fn from(id: ArchivedMovieID) -> Self {
            let id = deserialize::<MovieID, Error>(&id).unwrap();
            MediaID::Movie(id)
        }
    }

    impl From<ArchivedSeriesID> for MediaID {
        fn from(id: ArchivedSeriesID) -> Self {
            let id = deserialize::<SeriesID, Error>(&id).unwrap();
            MediaID::Series(id)
        }
    }

    impl From<ArchivedSeasonID> for MediaID {
        fn from(id: ArchivedSeasonID) -> Self {
            let id = deserialize::<SeasonID, Error>(&id).unwrap();
            MediaID::Season(id)
        }
    }

    impl From<ArchivedEpisodeID> for MediaID {
        fn from(id: ArchivedEpisodeID) -> Self {
            let id = deserialize::<EpisodeID, Error>(&id).unwrap();
            MediaID::Episode(id)
        }
    }
}