use ::bson::{Bson, Document};
use crate::domain::{aggregates::media_file::MediaFile, Uuid7};
use super::{error::MongoError, util::*};
impl From<&MediaFile<Uuid7>> for Document {
fn from(f: &MediaFile<Uuid7>) -> Self {
let mut d = Document::new();
d.insert("_id", uuid7_to_bson(*f.id_ref()));
d.insert("media_id", uuid7_to_bson(*f.media_id_ref()));
d.insert(
"created_at",
f.created_at_ref()
.map(|t| jiff_to_bson(*t))
.unwrap_or(Bson::Null),
);
d.insert("location", location_to_bson(f.location_ref()));
d.insert(
"watched_location_id",
uuid7_to_bson(*f.watched_location_id_ref()),
);
d.insert("watch_volume", uuid7_to_bson(*f.watch_volume_ref()));
d
}
}
impl TryFrom<Document> for MediaFile<Uuid7> {
type Error = MongoError;
fn try_from(mut d: Document) -> Result<Self, Self::Error> {
let id = uuid7_from_bson(take(&mut d, "_id")?, "_id")?;
let media_id = uuid7_from_bson(take(&mut d, "media_id")?, "media_id")?;
let created_at = opt(take_opt(&mut d, "created_at"), |b| {
jiff_from_bson(b, "created_at")
})?;
let location = location_from_bson(take(&mut d, "location")?, "location")?;
let watched_location_id =
uuid7_from_bson(take(&mut d, "watched_location_id")?, "watched_location_id")?;
let watch_volume = uuid7_from_bson(take(&mut d, "watch_volume")?, "watch_volume")?;
Ok(MediaFile::from_parts(
id,
media_id,
created_at,
location,
watched_location_id,
watch_volume,
))
}
}
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
use crate::domain::{Location, WatchedLocation};
use jiff::Timestamp as JiffTimestamp;
fn loc(volume: Uuid7) -> Location<Uuid7> {
Location::try_local_uuid7(volume, ["Movies", "clip.mp4"]).expect("valid location")
}
fn watch(volume: Uuid7) -> WatchedLocation<Uuid7> {
WatchedLocation::try_new(Uuid7::new(), volume, JiffTimestamp::default()).expect("valid watch")
}
#[test]
fn media_file_minimal_roundtrip() {
let vol = Uuid7::new();
let wl = watch(vol);
let f = MediaFile::try_new(Uuid7::new(), Uuid7::new(), None, loc(vol), &wl).unwrap();
let doc: Document = (&f).into();
let f2: MediaFile<Uuid7> = doc.try_into().unwrap();
assert_eq!(f, f2);
}
#[test]
fn media_file_full_roundtrip() {
let vol = Uuid7::new();
let wl = watch(vol);
let created = JiffTimestamp::from_millisecond(1_700_000_000_000).unwrap();
let f = MediaFile::try_new(Uuid7::new(), Uuid7::new(), Some(created), loc(vol), &wl).unwrap();
let doc: Document = (&f).into();
let f2: MediaFile<Uuid7> = doc.try_into().unwrap();
assert_eq!(f, f2);
assert_eq!(f2.name(), "clip.mp4");
}
#[test]
fn media_file_missing_id_errors() {
let mut d = Document::new();
d.insert("media_id", uuid7_to_bson(Uuid7::new()));
let err = MediaFile::<Uuid7>::try_from(d).unwrap_err();
assert!(err.is_missing_field());
}
#[test]
fn media_file_missing_location_errors() {
let mut d = Document::new();
d.insert("_id", uuid7_to_bson(Uuid7::new()));
d.insert("media_id", uuid7_to_bson(Uuid7::new()));
let err = MediaFile::<Uuid7>::try_from(d).unwrap_err();
assert!(err.is_missing_field());
}
}