use crate::db::api::properties::{internal::*, temporal_props::TemporalProperties};
use raphtory_api::{
core::{entities::properties::prop::Prop, storage::arc_str::ArcStr},
iter::IntoDynBoxed,
};
use raphtory_core::utils::iter::GenLockedIter;
use std::{
collections::HashMap,
fmt::{Debug, Formatter},
};
#[derive(Clone, PartialEq)]
pub struct Properties<P: InternalPropertiesOps + Clone> {
pub(crate) props: P,
}
impl<P: InternalPropertiesOps + Clone> Debug for Properties<P> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Properties({:?})", self.iter().collect::<Vec<_>>())
}
}
pub trait PropertiesOps: Send + Sync {
fn get(&self, key: &str) -> Option<Prop> {
self.get_by_id(self.get_id(key)?)
}
fn get_by_id(&self, id: usize) -> Option<Prop>;
fn get_id(&self, key: &str) -> Option<usize>;
fn contains(&self, key: &str) -> bool {
self.get_id(key).is_some()
}
fn keys(&self) -> impl Iterator<Item = ArcStr> + Send + Sync + '_;
fn ids(&self) -> impl Iterator<Item = usize> + Send + Sync + '_;
fn values(&self) -> impl Iterator<Item = Option<Prop>> + Send + Sync + '_ {
self.ids().map(|id| self.get_by_id(id))
}
fn iter(&self) -> impl Iterator<Item = (ArcStr, Option<Prop>)> + Send + Sync + '_ {
self.keys().zip(self.values())
}
fn iter_filtered(&self) -> impl Iterator<Item = (ArcStr, Prop)> + Send + Sync + '_ {
self.iter().flat_map(|(key, value)| Some((key, value?)))
}
fn as_vec(&self) -> Vec<(ArcStr, Prop)> {
self.iter()
.filter_map(|(k, v)| v.map(move |v| (k, v)))
.collect()
}
fn as_map(&self) -> HashMap<ArcStr, Prop> {
self.iter()
.filter_map(|(k, v)| v.map(move |v| (k, v)))
.collect()
}
fn len(&self) -> usize {
self.ids().count()
}
fn is_empty(&self) -> bool {
self.ids().next().is_none()
}
}
impl<P: InternalPropertiesOps + Clone> Properties<P> {
pub fn new(props: P) -> Properties<P> {
Self { props }
}
pub fn temporal(&self) -> TemporalProperties<P> {
TemporalProperties::new(self.props.clone())
}
}
impl<P: InternalPropertiesOps + Clone> PropertiesOps for Properties<P> {
fn get_by_id(&self, id: usize) -> Option<Prop> {
self.props.temporal_value(id)
}
fn get_id(&self, key: &str) -> Option<usize> {
self.props.get_temporal_prop_id(key)
}
fn ids(&self) -> impl Iterator<Item = usize> + Send + Sync + '_ {
self.props.temporal_prop_ids()
}
fn keys(&self) -> impl Iterator<Item = ArcStr> + Send + Sync + '_ {
self.props.temporal_prop_keys()
}
}
impl<P: InternalPropertiesOps + Clone + 'static> IntoIterator for Properties<P> {
type Item = (ArcStr, Option<Prop>);
type IntoIter = GenLockedIter<'static, Properties<P>, (ArcStr, Option<Prop>)>;
fn into_iter(self) -> Self::IntoIter {
GenLockedIter::from(self, |props| {
props.keys().zip(props.values()).into_dyn_boxed()
})
}
}
impl<'a, P: InternalPropertiesOps + Clone + 'a> IntoIterator for &'a Properties<P> {
type Item = (ArcStr, Option<Prop>);
type IntoIter = Box<dyn Iterator<Item = Self::Item> + 'a>;
fn into_iter(self) -> Self::IntoIter {
Box::new(self.iter())
}
}