use crate::feature::*;
use std::collections::{hash_map, HashMap};
use std::ffi::{c_void, CStr};
use std::iter::Map;
#[derive(Clone)]
pub struct FeatureCache<'a> {
internal: HashMap<&'a CStr, *const c_void>,
}
impl<'a> FeatureCache<'a> {
pub unsafe fn from_raw(raw: *const *const ::sys::LV2_Feature) -> Self {
let mut internal_map = HashMap::new();
let mut feature_ptr = raw;
if !raw.is_null() {
while !(*feature_ptr).is_null() {
let uri = CStr::from_ptr((**feature_ptr).URI);
let data = (**feature_ptr).data as *const c_void;
internal_map.insert(uri, data);
feature_ptr = feature_ptr.add(1);
}
}
Self {
internal: internal_map,
}
}
pub fn contains<T: Feature>(&self) -> bool {
self.internal.contains_key(T::uri())
}
pub fn retrieve_feature<F: Feature, T: FromResolvedFeature<F>>(
&mut self,
class: ThreadingClass,
) -> Result<T, MissingFeatureError> {
T::from_resolved_feature(
self.internal
.remove(F::uri())
.and_then(|ptr| unsafe { F::from_feature_ptr(ptr, class) }),
)
}
}
type HashMapIterator<'a> = hash_map::IntoIter<&'a CStr, *const c_void>;
type DescriptorBuildFn<'a> = fn((&'a CStr, *const c_void)) -> FeatureDescriptor<'a>;
impl<'a> std::iter::IntoIterator for FeatureCache<'a> {
type Item = FeatureDescriptor<'a>;
type IntoIter = Map<HashMapIterator<'a>, DescriptorBuildFn<'a>>;
fn into_iter(self) -> Self::IntoIter {
self.internal.into_iter().map(|element| {
let uri = element.0;
let data = element.1;
FeatureDescriptor { uri, data }
})
}
}
impl<'a> FeatureCollection<'a> for FeatureCache<'a> {
fn from_cache(
cache: &mut FeatureCache<'a>,
_: ThreadingClass,
) -> Result<Self, MissingFeatureError> {
Ok(FeatureCache {
internal: cache.internal.clone(),
})
}
}
pub trait FromResolvedFeature<F: Feature>: Sized {
fn from_resolved_feature(feature: Option<F>) -> Result<Self, MissingFeatureError>;
}
impl<F: Feature> FromResolvedFeature<F> for F {
fn from_resolved_feature(feature: Option<F>) -> Result<Self, MissingFeatureError> {
feature.ok_or_else(|| MissingFeatureError { uri: F::uri() })
}
}
impl<F: Feature> FromResolvedFeature<F> for Option<F> {
#[inline]
fn from_resolved_feature(feature: Option<F>) -> Result<Self, MissingFeatureError> {
Ok(feature)
}
}