use crate::{
buffa::error::BuffaError,
domain::{primitives::LocalLocation, Location, Uuid7},
generated::media::v1 as wire,
};
#[cfg(all(not(feature = "std"), feature = "alloc"))]
#[allow(unused_imports)]
use std::{
borrow::ToOwned,
string::{String, ToString},
};
impl TryFrom<&wire::Local> for Location<Uuid7> {
type Error = BuffaError;
fn try_from(w: &wire::Local) -> Result<Self, Self::Error> {
let wire_vol = w
.volume
.as_option()
.ok_or(BuffaError::MissingLocationVolume)?;
let volume = Uuid7::try_from(wire_vol)?;
Location::try_local_uuid7(volume, w.components.iter().cloned()).map_err(BuffaError::from)
}
}
impl From<&Location<Uuid7>> for wire::Local {
fn from(d: &Location<Uuid7>) -> Self {
let local = d.unwrap_local_ref();
let volume_wire = wire::Id::from(local.volume_ref());
let components = local
.components_slice()
.iter()
.map(|c| c.as_str().to_owned().into())
.collect();
wire::Local {
volume: ::buffa::MessageField::some(volume_wire),
components,
__buffa_unknown_fields: Default::default(),
}
}
}
impl TryFrom<&wire::Location> for Option<Location<Uuid7>> {
type Error = BuffaError;
fn try_from(w: &wire::Location) -> Result<Self, Self::Error> {
match &w.kind {
None => Ok(None),
Some(wire::location::Kind::Local(local)) => Ok(Some(Location::try_from(local.as_ref())?)),
#[allow(unreachable_patterns)]
Some(_) => Err(BuffaError::UnsupportedLocationKind),
}
}
}
impl From<&Option<Location<Uuid7>>> for wire::Location {
fn from(d: &Option<Location<Uuid7>>) -> Self {
let kind = d.as_ref().map(|loc| {
wire::location::Kind::Local(::buffa::alloc::boxed::Box::new(wire::Local::from(loc)))
});
wire::Location {
kind,
__buffa_unknown_fields: Default::default(),
}
}
}
impl From<&Location<Uuid7>> for wire::Location {
fn from(d: &Location<Uuid7>) -> Self {
let kind = Some(wire::location::Kind::Local(
::buffa::alloc::boxed::Box::new(wire::Local::from(d)),
));
wire::Location {
kind,
__buffa_unknown_fields: Default::default(),
}
}
}
#[allow(dead_code)]
type _LocalLocationAlias = LocalLocation<Uuid7>;
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
fn fresh() -> (Uuid7, Uuid7) {
(Uuid7::new(), Uuid7::new())
}
#[test]
fn local_roundtrip() {
let (_id, vol) = fresh();
let d = Location::try_local_uuid7(vol, ["Movies", "Holiday"]).unwrap();
let w: wire::Local = wire::Local::from(&d);
let d2 = Location::try_from(&w).expect("roundtrip");
assert_eq!(d, d2);
}
#[test]
fn local_rejects_missing_volume() {
let w = wire::Local {
volume: ::buffa::MessageField::none(),
components: std::vec!["foo".into()],
__buffa_unknown_fields: Default::default(),
};
let err = Location::try_from(&w).unwrap_err();
assert!(err.is_missing_location_volume());
}
#[test]
fn local_rejects_empty_path() {
let vol = Uuid7::new();
let w = wire::Local {
volume: ::buffa::MessageField::some(wire::Id::from(&vol)),
components: std::vec::Vec::new(),
__buffa_unknown_fields: Default::default(),
};
let err = Location::try_from(&w).unwrap_err();
assert!(err.is_location(), "{:?}", err);
}
#[test]
fn location_oneof_some_roundtrip() {
let (_id, vol) = fresh();
let d: Option<Location<Uuid7>> = Some(Location::try_local_uuid7(vol, ["a", "b"]).unwrap());
let w: wire::Location = wire::Location::from(&d);
let d2: Option<Location<Uuid7>> = Option::<Location<Uuid7>>::try_from(&w).expect("roundtrip");
assert_eq!(d, d2);
}
#[test]
fn location_oneof_none_roundtrip() {
let d: Option<Location<Uuid7>> = None;
let w: wire::Location = wire::Location::from(&d);
assert!(w.kind.is_none());
let d2: Option<Location<Uuid7>> = Option::<Location<Uuid7>>::try_from(&w).expect("roundtrip");
assert!(d2.is_none());
}
#[test]
fn plain_location_to_wire_sets_kind() {
let vol = Uuid7::new();
let d = Location::try_local_uuid7(vol, ["x"]).unwrap();
let w = wire::Location::from(&d);
assert!(w.kind.is_some());
}
}