use super::JsonLdNodes;
use crate::{
JsonLdIndexedNode, JsonLdLenient, JsonLdVisit,
object::{JsonLdObjectMut, JsonLdObjectRef},
};
use btree_indexmap::{BTreeIndexMap, BTreeIndexMultiSet, Comparable};
use educe::Educe;
use rdf_syntax::Id;
use std::hash::Hash;
pub type JsonLdReversePropertyNodes = BTreeIndexMultiSet<JsonLdIndexedNode>;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct JsonLdReverseProperties(BTreeIndexMap<JsonLdLenient<Id>, JsonLdReversePropertyNodes>);
impl Default for JsonLdReverseProperties {
fn default() -> Self {
Self::new()
}
}
impl JsonLdReverseProperties {
pub fn new() -> Self {
Self(BTreeIndexMap::new())
}
#[inline(always)]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline(always)]
pub fn iter(&self) -> JsonLdReversePropertiesIter<'_> {
JsonLdReversePropertiesIter {
inner: self.0.iter(),
}
}
#[inline(always)]
pub fn iter_mut(&mut self) -> JsonLdReversePropertiesIterMut<'_> {
self.0.iter_mut()
}
#[inline(always)]
pub fn clear(&mut self) {
self.0.clear()
}
#[inline(always)]
pub fn contains<Q: ?Sized + Hash + Comparable<JsonLdLenient<Id>>>(&self, prop: &Q) -> bool {
self.0.get(prop).is_some()
}
#[inline(always)]
pub fn get<Q: ?Sized + Hash + Comparable<JsonLdLenient<Id>>>(
&self,
prop: &Q,
) -> JsonLdNodes<'_> {
match self.0.get(prop) {
Some(values) => JsonLdNodes::new(Some(values.iter())),
None => JsonLdNodes::new(None),
}
}
#[inline(always)]
pub fn get_any<Q: ?Sized + Hash + Comparable<JsonLdLenient<Id>>>(
&self,
prop: &Q,
) -> Option<&JsonLdIndexedNode> {
match self.0.get(prop) {
Some(values) => values.iter().next(),
None => None,
}
}
#[inline(always)]
pub fn insert(&mut self, prop: JsonLdLenient<Id>, value: JsonLdIndexedNode) {
if let Some(node_values) = self.0.get_mut(&prop) {
node_values.insert(value);
} else {
self.0.insert(prop, BTreeIndexMultiSet::singleton(value));
}
}
#[inline(always)]
pub fn insert_unique(&mut self, prop: JsonLdLenient<Id>, value: JsonLdIndexedNode) {
if let Some(node_values) = self.0.get_mut(&prop) {
if node_values.iter().all(|v| !v.equivalent(&value)) {
node_values.insert(value);
}
} else {
self.0.insert(prop, BTreeIndexMultiSet::singleton(value));
}
}
#[inline(always)]
pub fn insert_all<Objects: IntoIterator<Item = JsonLdIndexedNode>>(
&mut self,
prop: JsonLdLenient<Id>,
values: Objects,
) {
if let Some(node_values) = self.0.get_mut(&prop) {
node_values.extend(values);
} else {
self.0.insert(prop, values.into_iter().collect());
}
}
#[inline(always)]
pub fn insert_all_unique<Nodes: IntoIterator<Item = JsonLdIndexedNode>>(
&mut self,
prop: JsonLdLenient<Id>,
values: Nodes,
) {
if let Some(node_values) = self.0.get_mut(&prop) {
for value in values {
if node_values.iter().all(|v| !v.equivalent(&value)) {
node_values.insert(value);
}
}
} else {
let values = values.into_iter();
let mut node_values: JsonLdReversePropertyNodes =
BTreeIndexMultiSet::with_capacity(values.size_hint().0);
for value in values {
if node_values.iter().all(|v| !v.equivalent(&value)) {
node_values.insert(value);
}
}
self.0.insert(prop, node_values);
}
}
pub fn set(&mut self, prop: JsonLdLenient<Id>, values: JsonLdReversePropertyNodes) {
self.0.insert(prop, values);
}
pub fn extend_unique<N>(&mut self, iter: impl IntoIterator<Item = (JsonLdLenient<Id>, N)>)
where
N: IntoIterator<Item = JsonLdIndexedNode>,
{
for (prop, values) in iter {
self.insert_all_unique(prop, values)
}
}
#[inline(always)]
pub fn remove(&mut self, prop: &JsonLdLenient<Id>) -> Option<JsonLdReversePropertyNodes> {
self.0.swap_remove(prop)
}
}
impl JsonLdVisit for JsonLdReverseProperties {
fn visit_with(&self, f: &mut impl FnMut(JsonLdObjectRef)) {
for (_, t) in self {
t.visit_with(f);
}
}
fn visit_mut_with(&mut self, f: &mut impl FnMut(JsonLdObjectMut)) {
for (_, t) in self {
t.visit_mut_with(f);
}
}
}
impl<N> FromIterator<(JsonLdLenient<Id>, N)> for JsonLdReverseProperties
where
N: IntoIterator<Item = JsonLdIndexedNode>,
{
fn from_iter<I: IntoIterator<Item = (JsonLdLenient<Id>, N)>>(iter: I) -> Self {
let mut result = Self::default();
for (id, values) in iter {
result.insert_all(id, values);
}
result
}
}
impl Extend<(JsonLdLenient<Id>, Vec<JsonLdIndexedNode>)> for JsonLdReverseProperties {
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = (JsonLdLenient<Id>, Vec<JsonLdIndexedNode>)>,
{
for (prop, values) in iter {
self.insert_all(prop, values)
}
}
}
pub type JsonLdReverseBinding = (JsonLdLenient<Id>, JsonLdReversePropertyNodes);
pub type JsonLdReverseBindingRef<'a> = (&'a JsonLdLenient<Id>, &'a [JsonLdIndexedNode]);
pub type JsonLdReverseBindingMut<'a> = (&'a JsonLdLenient<Id>, &'a mut JsonLdReversePropertyNodes);
impl IntoIterator for JsonLdReverseProperties {
type Item = JsonLdReverseBinding;
type IntoIter = JsonLdReversePropertiesIntoIter;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a> IntoIterator for &'a JsonLdReverseProperties {
type Item = JsonLdReverseBindingRef<'a>;
type IntoIter = JsonLdReversePropertiesIter<'a>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut JsonLdReverseProperties {
type Item = JsonLdReverseBindingMut<'a>;
type IntoIter = JsonLdReversePropertiesIterMut<'a>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
pub type JsonLdReversePropertiesIntoIter =
btree_indexmap::map::IntoIter<JsonLdLenient<Id>, JsonLdReversePropertyNodes>;
#[derive(Educe)]
#[educe(Clone)]
pub struct JsonLdReversePropertiesIter<'a> {
inner: btree_indexmap::map::Iter<'a, JsonLdLenient<Id>, JsonLdReversePropertyNodes>,
}
impl<'a> Iterator for JsonLdReversePropertiesIter<'a> {
type Item = JsonLdReverseBindingRef<'a>;
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
self.inner
.next()
.map(|(property, objects)| (property, objects.as_slice()))
}
}
impl<'a> ExactSizeIterator for JsonLdReversePropertiesIter<'a> {}
impl<'a> std::iter::FusedIterator for JsonLdReversePropertiesIter<'a> {}
pub type JsonLdReversePropertiesIterMut<'a> =
btree_indexmap::map::IterMut<'a, JsonLdLenient<Id>, JsonLdReversePropertyNodes>;