use std::marker::PhantomData;
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct NamedRef<
TSource,
TRefLocation,
TResource: DerefByName<Source=TSource, RefLocation=TRefLocation>,
> {
name: String,
phantom: PhantomData<TResource>,
ref_location: TRefLocation,
}
impl<
TSource,
TRefLocation,
TResource: DerefByName<Source=TSource, RefLocation=TRefLocation>,
> NamedRef<TSource, TRefLocation, TResource> {
pub fn name(&self) -> &str {
self.name.as_str()
}
pub fn new(
name: impl AsRef<str>,
ref_location: TRefLocation,
) -> NamedRef<TSource, TRefLocation, TResource> {
NamedRef {
name: name.as_ref().to_string(),
ref_location,
phantom: PhantomData,
}
}
}
impl<
TSource,
TRefLocation,
TResource: DerefByName<Source=TSource, RefLocation=TRefLocation>,
> NamedRef<TSource, TRefLocation, TResource> {
pub fn ref_location(&self) -> &TRefLocation {
&self.ref_location
}
pub fn deref<'a>(
&self,
source: &'a TSource,
) -> Result<&'a TResource, DerefByNameError> {
TResource::deref_name(source, self.name.as_str())
}
}
pub trait DerefByName: Clone + core::fmt::Debug {
type Source;
type RefLocation;
fn deref_name<'a>(
source: &'a Self::Source,
name: &str,
) -> Result<&'a Self, DerefByNameError> where Self: Sized;
fn named_ref(name: &str, ref_location: Self::RefLocation) -> NamedRef<
Self::Source,
Self::RefLocation,
Self,
> {
NamedRef::<Self::Source, Self::RefLocation, Self>::new(
name,
ref_location,
)
}
}
#[derive(Clone, Debug)]
pub enum DerefByNameError {
DanglingReference(String),
}