use super::{InvalidExpandedJson, Traverse, TryFromJson, TryFromJsonObject};
use crate::{
id, object, utils, Id, Indexed, IndexedObject, Object, Objects, Relabel, StrippedIndexedObject,
Term,
};
use contextual::{IntoRefWithContext, WithContext};
use derivative::Derivative;
use iref::IriBuf;
use json_ld_syntax::{Entry, IntoJson, IntoJsonWithContextMeta, Keyword};
use locspan::{BorrowStripped, Meta, Stripped, StrippedEq, StrippedPartialEq};
use rdf_types::{BlankIdBuf, Subject, Vocabulary, VocabularyMut};
use std::collections::HashSet;
use std::convert::TryFrom;
use std::hash::{Hash, Hasher};
pub mod multiset;
pub mod properties;
pub mod reverse_properties;
pub use multiset::Multiset;
pub use properties::Properties;
pub use reverse_properties::ReverseProperties;
pub type Graph<T, B, M> = HashSet<StrippedIndexedObject<T, B, M>>;
pub type Included<T, B, M> = HashSet<StrippedIndexedNode<T, B, M>>;
pub struct Parts<T = IriBuf, B = BlankIdBuf, M = ()> {
pub id: Option<Entry<Id<T, B>, M>>,
pub types: Option<TypeEntry<T, B, M>>,
pub graph: Option<GraphEntry<T, B, M>>,
pub included: Option<IncludedEntry<T, B, M>>,
pub properties: Properties<T, B, M>,
pub reverse_properties: Option<Entry<ReverseProperties<T, B, M>, M>>,
}
pub type IndexedNode<T, B, M> = Meta<Indexed<Node<T, B, M>, M>, M>;
pub type StrippedIndexedNode<T, B, M> = Stripped<IndexedNode<T, B, M>>;
#[derive(Derivative, Clone)]
#[derivative(Eq(bound = "T: Eq + Hash, B: Eq + Hash, M: Eq"))]
pub struct Node<T = IriBuf, B = BlankIdBuf, M = ()> {
pub(crate) id: Option<Entry<Id<T, B>, M>>,
pub(crate) types: Option<TypeEntry<T, B, M>>,
pub(crate) graph: Option<GraphEntry<T, B, M>>,
pub(crate) included: Option<IncludedEntry<T, B, M>>,
pub(crate) properties: Properties<T, B, M>,
pub(crate) reverse_properties: Option<Entry<ReverseProperties<T, B, M>, M>>,
}
impl<T, B, M> Default for Node<T, B, M> {
#[inline(always)]
fn default() -> Self {
Self::new()
}
}
impl<T, B, M> Node<T, B, M> {
#[inline(always)]
pub fn new() -> Self {
Self {
id: None,
types: None,
graph: None,
included: None,
properties: Properties::new(),
reverse_properties: None,
}
}
#[inline(always)]
pub fn with_id(id: Entry<Id<T, B>, M>) -> Self {
Self {
id: Some(id),
types: None,
graph: None,
included: None,
properties: Properties::new(),
reverse_properties: None,
}
}
pub fn from_parts(parts: Parts<T, B, M>) -> Self {
Self {
id: parts.id,
types: parts.types,
graph: parts.graph,
included: parts.included,
properties: parts.properties,
reverse_properties: parts.reverse_properties,
}
}
pub fn into_parts(self) -> Parts<T, B, M> {
Parts {
id: self.id,
types: self.types,
graph: self.graph,
included: self.included,
properties: self.properties,
reverse_properties: self.reverse_properties,
}
}
#[inline(always)]
pub fn id(&self) -> Option<&Meta<Id<T, B>, M>> {
self.id.as_ref().map(Entry::as_value)
}
#[inline(always)]
pub fn id_entry(&self) -> Option<&Entry<Id<T, B>, M>> {
self.id.as_ref()
}
#[inline(always)]
pub fn set_id(&mut self, id: Option<Entry<Id<T, B>, M>>) {
self.id = id
}
pub fn identify_all_with<V: Vocabulary<Iri = T, BlankId = B>, G: id::Generator<V, M>>(
&mut self,
vocabulary: &mut V,
generator: &mut G,
) where
M: Clone,
T: Eq + Hash,
B: Eq + Hash,
{
if self.id.is_none() {
let value = generator.next(vocabulary);
self.id = Some(Entry::new(value.metadata().clone(), value.cast()))
}
if let Some(Meta(graph, _)) = self.graph_mut() {
*graph = std::mem::take(graph)
.into_iter()
.map(|mut o| {
o.identify_all_with(vocabulary, generator);
o
})
.collect();
}
if let Some(Meta(included, _)) = self.included_mut() {
*included = std::mem::take(included)
.into_iter()
.map(|mut n| {
n.identify_all_with(vocabulary, generator);
n
})
.collect();
}
for (_, objects) in self.properties_mut() {
for object in objects {
object.identify_all_with(vocabulary, generator);
}
}
if let Some(reverse_properties) = self.reverse_properties_mut() {
for (_, nodes) in reverse_properties.iter_mut() {
for node in nodes {
node.identify_all_with(vocabulary, generator);
}
}
}
}
pub fn identify_all<G: id::Generator<(), M>>(&mut self, generator: &mut G)
where
M: Clone,
T: Eq + Hash,
B: Eq + Hash,
(): Vocabulary<Iri = T, BlankId = B>,
{
self.identify_all_with(&mut (), generator)
}
pub fn canonicalize_with(&mut self, buffer: &mut ryu_js::Buffer) {
for (_, objects) in self.properties_mut() {
for object in objects {
object.canonicalize_with(buffer)
}
}
if let Some(reverse_properties) = self.reverse_properties_mut() {
for (_, nodes) in reverse_properties.iter_mut() {
for node in nodes {
node.canonicalize_with(buffer)
}
}
}
}
pub fn canonicalize(&mut self) {
let mut buffer = ryu_js::Buffer::new();
self.canonicalize_with(&mut buffer)
}
#[inline(always)]
pub fn as_iri(&self) -> Option<&T> {
if let Some(id) = &self.id {
id.as_iri()
} else {
None
}
}
#[inline(always)]
pub fn as_str(&self) -> Option<&str>
where
T: AsRef<str>,
{
match self.as_iri() {
Some(iri) => Some(iri.as_ref()),
None => None,
}
}
#[inline(always)]
pub fn types(&self) -> &[Meta<Id<T, B>, M>] {
match self.types.as_ref() {
Some(entry) => &entry.value,
None => &[],
}
}
#[inline(always)]
pub fn types_mut(&mut self) -> &mut [Meta<Id<T, B>, M>] {
match self.types.as_mut() {
Some(entry) => &mut entry.value,
None => &mut [],
}
}
pub fn type_entry_or_default(
&mut self,
key_metadata: M,
value_metadata: M,
) -> &mut TypeEntry<T, B, M> {
self.types
.get_or_insert_with(|| Entry::new(key_metadata, Meta(Vec::new(), value_metadata)))
}
pub fn type_entry_or_insert(
&mut self,
key_metadata: M,
value: TypeEntryValue<T, B, M>,
) -> &mut TypeEntry<T, B, M> {
self.types
.get_or_insert_with(|| Entry::new(key_metadata, value))
}
pub fn type_entry_or_insert_with(
&mut self,
f: impl FnOnce() -> TypeEntry<T, B, M>,
) -> &mut TypeEntry<T, B, M> {
self.types.get_or_insert_with(f)
}
pub fn type_entry(&self) -> Option<&TypeEntry<T, B, M>> {
self.types.as_ref()
}
pub fn set_type_entry(&mut self, entry: Option<TypeEntry<T, B, M>>) {
self.types = entry
}
#[inline]
pub fn has_type<U>(&self, ty: &U) -> bool
where
Id<T, B>: PartialEq<U>,
{
for self_ty in self.types() {
if self_ty.value() == ty {
return true;
}
}
false
}
#[inline]
pub fn is_empty(&self) -> bool {
self.types.is_none()
&& self.graph.is_none()
&& self.included.is_none()
&& self.properties.is_empty()
&& self.reverse_properties.is_none()
}
#[inline]
pub fn is_graph(&self) -> bool {
self.graph.is_some()
&& self.types.is_none()
&& self.included.is_none()
&& self.properties.is_empty()
&& self.reverse_properties.is_none()
}
#[inline(always)]
pub fn is_simple_graph(&self) -> bool {
self.id.is_none() && self.is_graph()
}
#[inline(always)]
pub fn graph(&self) -> Option<&Meta<Graph<T, B, M>, M>> {
self.graph.as_deref()
}
#[inline(always)]
pub fn graph_mut(&mut self) -> Option<&mut Meta<Graph<T, B, M>, M>> {
self.graph.as_deref_mut()
}
#[inline(always)]
pub fn graph_entry(&self) -> Option<&GraphEntry<T, B, M>> {
self.graph.as_ref()
}
#[inline(always)]
pub fn graph_entry_mut(&mut self) -> Option<&mut GraphEntry<T, B, M>> {
self.graph.as_mut()
}
#[inline(always)]
pub fn set_graph(&mut self, graph: Option<GraphEntry<T, B, M>>) {
self.graph = graph
}
#[inline(always)]
pub fn included_entry(&self) -> Option<&IncludedEntry<T, B, M>> {
self.included.as_ref()
}
#[inline(always)]
pub fn included_entry_mut(&mut self) -> Option<&mut IncludedEntry<T, B, M>> {
self.included.as_mut()
}
pub fn included(&self) -> Option<&Meta<Included<T, B, M>, M>> {
self.included.as_deref()
}
pub fn included_mut(&mut self) -> Option<&mut Meta<Included<T, B, M>, M>> {
self.included.as_deref_mut()
}
#[inline(always)]
pub fn set_included(&mut self, included: Option<IncludedEntry<T, B, M>>) {
self.included = included
}
#[inline(always)]
pub fn properties(&self) -> &Properties<T, B, M> {
&self.properties
}
#[inline(always)]
pub fn properties_mut(&mut self) -> &mut Properties<T, B, M> {
&mut self.properties
}
#[inline(always)]
pub fn reverse_properties(&self) -> Option<&Meta<ReverseProperties<T, B, M>, M>> {
self.reverse_properties.as_ref().map(Entry::as_value)
}
#[inline(always)]
pub fn reverse_properties_entry(&self) -> Option<&Entry<ReverseProperties<T, B, M>, M>> {
self.reverse_properties.as_ref()
}
#[inline(always)]
pub fn reverse_properties_mut(&mut self) -> Option<&mut Entry<ReverseProperties<T, B, M>, M>> {
self.reverse_properties.as_mut()
}
pub fn set_reverse_properties(
&mut self,
reverse_properties: Option<Entry<ReverseProperties<T, B, M>, M>>,
) {
self.reverse_properties = reverse_properties
}
#[inline]
pub fn is_unnamed_graph(&self) -> bool {
self.graph.is_some()
&& self.id.is_none()
&& self.types.is_none()
&& self.included.is_none()
&& self.properties.is_empty()
&& self.reverse_properties.is_none()
}
#[allow(clippy::result_large_err)]
#[inline(always)]
pub fn into_unnamed_graph(self) -> Result<Entry<Graph<T, B, M>, M>, Self> {
if self.is_unnamed_graph() {
Ok(self.graph.unwrap())
} else {
Err(self)
}
}
pub fn traverse(&self) -> Traverse<T, B, M> {
Traverse::new(Some(super::FragmentRef::Node(self)))
}
pub fn entries(&self) -> Entries<T, B, M> {
Entries {
id: self.id.as_ref(),
type_: self.types.as_ref(),
graph: self.graph.as_ref(),
included: self.included.as_ref(),
reverse: self.reverse_properties.as_ref(),
properties: self.properties.iter(),
}
}
}
impl<T: Eq + Hash, B: Eq + Hash, M> Node<T, B, M> {
#[inline(always)]
pub fn has_key(&self, key: &Term<T, B>) -> bool {
match key {
Term::Keyword(Keyword::Id) => self.id.is_some(),
Term::Keyword(Keyword::Type) => self.types.is_some(),
Term::Keyword(Keyword::Graph) => self.graph.is_some(),
Term::Keyword(Keyword::Included) => self.included.is_some(),
Term::Keyword(Keyword::Reverse) => self.reverse_properties.is_some(),
Term::Id(prop) => self.properties.contains(prop),
_ => false,
}
}
#[inline(always)]
pub fn get<'a, Q: ?Sized + Hash + hashbrown::Equivalent<Id<T, B>>>(
&self,
prop: &Q,
) -> Objects<T, B, M>
where
T: 'a,
{
self.properties.get(prop)
}
#[inline(always)]
pub fn get_any<'a, Q: ?Sized + Hash + hashbrown::Equivalent<Id<T, B>>>(
&self,
prop: &Q,
) -> Option<&IndexedObject<T, B, M>>
where
T: 'a,
{
self.properties.get_any(prop)
}
#[inline(always)]
pub fn insert(&mut self, prop: Meta<Id<T, B>, M>, value: IndexedObject<T, B, M>) {
self.properties.insert(prop, value)
}
#[inline(always)]
pub fn insert_all<Objects: Iterator<Item = IndexedObject<T, B, M>>>(
&mut self,
prop: Meta<Id<T, B>, M>,
values: Objects,
) {
self.properties.insert_all(prop, values)
}
pub fn reverse_properties_or_insert(
&mut self,
key_metadata: M,
props: Meta<ReverseProperties<T, B, M>, M>,
) -> &mut Entry<ReverseProperties<T, B, M>, M> {
self.reverse_properties
.get_or_insert_with(|| Entry::new(key_metadata, props))
}
pub fn reverse_properties_or_default(
&mut self,
key_metadata: M,
value_metadata: M,
) -> &mut Entry<ReverseProperties<T, B, M>, M> {
self.reverse_properties.get_or_insert_with(|| {
Entry::new(key_metadata, Meta(ReverseProperties::new(), value_metadata))
})
}
pub fn reverse_properties_or_insert_with(
&mut self,
f: impl FnOnce() -> Entry<ReverseProperties<T, B, M>, M>,
) -> &mut Entry<ReverseProperties<T, B, M>, M> {
self.reverse_properties.get_or_insert_with(f)
}
pub fn equivalent(&self, other: &Self) -> bool {
if self.id_entry().is_some() && other.id_entry().is_some() {
self.stripped() == other.stripped()
} else {
false
}
}
}
impl<T, B, M> Relabel<T, B, M> for Node<T, B, M> {
fn relabel_with<N: Vocabulary<Iri = T, BlankId = B>, G: rdf_types::MetaGenerator<N, M>>(
&mut self,
vocabulary: &mut N,
generator: &mut G,
relabeling: &mut hashbrown::HashMap<B, Meta<Subject<T, B>, M>>,
) where
M: Clone,
T: Clone + Eq + Hash,
B: Clone + Eq + Hash,
{
self.id = match self.id.take() {
Some(Entry {
key_metadata,
value: Meta(Id::Valid(Subject::Blank(b)), _),
}) => {
let value = relabeling
.entry(b)
.or_insert_with(|| generator.next(vocabulary))
.clone();
Some(Entry::new(key_metadata, value.cast()))
}
None => {
let value = generator.next(vocabulary);
Some(Entry::new(value.metadata().clone(), value.cast()))
}
id => id,
};
for ty in self.types_mut() {
if let Some(b) = ty.as_blank().cloned() {
*ty = relabeling
.entry(b)
.or_insert_with(|| generator.next(vocabulary))
.clone()
.cast();
}
}
if let Some(Meta(graph, _)) = self.graph_mut() {
*graph = std::mem::take(graph)
.into_iter()
.map(|mut o| {
o.relabel_with(vocabulary, generator, relabeling);
o
})
.collect();
}
if let Some(Meta(included, _)) = self.included_mut() {
*included = std::mem::take(included)
.into_iter()
.map(|mut n| {
n.relabel_with(vocabulary, generator, relabeling);
n
})
.collect();
}
for (_, objects) in self.properties_mut() {
for object in objects {
object.relabel_with(vocabulary, generator, relabeling);
}
}
if let Some(reverse_properties) = self.reverse_properties_mut() {
for (_, nodes) in reverse_properties.iter_mut() {
for node in nodes {
node.relabel_with(vocabulary, generator, relabeling);
}
}
}
}
}
impl<T: Eq + Hash, B: Eq + Hash, M: PartialEq> PartialEq for Node<T, B, M> {
fn eq(&self, other: &Self) -> bool {
self.id.eq(&other.id)
&& multiset::compare_unordered_opt(
self.types.as_ref().map(|t| t.as_slice()),
other.types.as_ref().map(|t| t.as_slice()),
) && self.graph.as_ref().map(Entry::as_value).map(Meta::value)
== other.graph.as_ref().map(Entry::as_value).map(Meta::value)
&& self.included.as_ref().map(Entry::as_value).map(Meta::value)
== other
.included
.as_ref()
.map(Entry::as_value)
.map(Meta::value)
&& self.properties.eq(&other.properties)
&& self.reverse_properties.eq(&other.reverse_properties)
}
}
impl<T: Eq + Hash, B: Eq + Hash, M> StrippedPartialEq for Node<T, B, M> {
fn stripped_eq(&self, other: &Self) -> bool {
self.id.stripped_eq(&other.id)
&& multiset::compare_stripped_unordered_opt(
self.types.as_ref().map(|t| t.as_slice()),
other.types.as_ref().map(|t| t.as_slice()),
) && self.graph.as_ref().map(Entry::as_value).map(Meta::value)
== other.graph.as_ref().map(Entry::as_value).map(Meta::value)
&& self.included.as_ref().map(Entry::as_value).map(Meta::value)
== other
.included
.as_ref()
.map(Entry::as_value)
.map(Meta::value)
&& self.properties.stripped_eq(&other.properties)
&& self
.reverse_properties
.stripped_eq(&other.reverse_properties)
}
}
impl<T: Eq + Hash, B: Eq + Hash, M> StrippedEq for Node<T, B, M> {}
impl<T, B, M> Indexed<Node<T, B, M>, M> {
pub fn entries(&self) -> IndexedEntries<T, B, M> {
IndexedEntries {
index: self.index(),
inner: self.inner().entries(),
}
}
}
impl<T: Eq + Hash, B: Eq + Hash, M> Indexed<Node<T, B, M>, M> {
pub fn equivalent(&self, other: &Self) -> bool {
self.index() == other.index() && self.inner().equivalent(other.inner())
}
}
#[derive(Derivative, PartialEq, Eq)]
#[derivative(Clone(bound = ""), Copy(bound = ""))]
pub enum EntryKeyRef<'a, T, B, M> {
Id,
Type,
Graph,
Included,
Reverse,
Property(Meta<&'a Id<T, B>, &'a M>),
}
impl<'a, T, B, M> EntryKeyRef<'a, T, B, M> {
pub fn into_keyword(self) -> Option<Keyword> {
match self {
Self::Id => Some(Keyword::Id),
Self::Type => Some(Keyword::Type),
Self::Graph => Some(Keyword::Graph),
Self::Included => Some(Keyword::Included),
Self::Reverse => Some(Keyword::Reverse),
Self::Property(_) => None,
}
}
pub fn as_keyword(&self) -> Option<Keyword> {
self.into_keyword()
}
pub fn into_str(self) -> &'a str
where
T: AsRef<str>,
B: AsRef<str>,
{
match self {
Self::Id => "@id",
Self::Type => "@type",
Self::Graph => "@graph",
Self::Included => "@included",
Self::Reverse => "@reverse",
Self::Property(p) => p.as_str(),
}
}
pub fn as_str(&self) -> &'a str
where
T: AsRef<str>,
B: AsRef<str>,
{
self.into_str()
}
}
impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>, M> IntoRefWithContext<'a, str, N>
for EntryKeyRef<'a, T, B, M>
{
fn into_ref_with(self, vocabulary: &'a N) -> &'a str {
match self {
EntryKeyRef::Id => "@id",
EntryKeyRef::Type => "@type",
EntryKeyRef::Graph => "@graph",
EntryKeyRef::Included => "@included",
EntryKeyRef::Reverse => "@reverse",
EntryKeyRef::Property(p) => p.0.with(vocabulary).as_str(),
}
}
}
#[derive(Derivative)]
#[derivative(Clone(bound = ""), Copy(bound = ""))]
pub enum EntryValueRef<'a, T, B, M> {
Id(Meta<&'a Id<T, B>, &'a M>),
Type(&'a TypeEntryValue<T, B, M>),
Graph(&'a HashSet<StrippedIndexedObject<T, B, M>>),
Included(&'a HashSet<StrippedIndexedNode<T, B, M>>),
Reverse(&'a ReverseProperties<T, B, M>),
Property(&'a [StrippedIndexedObject<T, B, M>]),
}
impl<'a, T, B, M> EntryValueRef<'a, T, B, M> {
pub fn is_json_array(&self) -> bool {
matches!(
self,
Self::Type(_) | Self::Graph(_) | Self::Included(_) | Self::Property(_)
)
}
pub fn is_json_object(&self) -> bool {
matches!(self, Self::Reverse(_))
}
fn sub_fragments(&self) -> SubFragments<'a, T, B, M> {
match self {
Self::Type(l) => SubFragments::Type(l.iter()),
Self::Graph(g) => SubFragments::Graph(g.iter()),
Self::Included(i) => SubFragments::Included(i.iter()),
Self::Reverse(r) => SubFragments::Reverse(r.iter()),
Self::Property(p) => SubFragments::Property(p.iter()),
_ => SubFragments::None,
}
}
}
#[derive(Derivative)]
#[derivative(Clone(bound = ""), Copy(bound = ""))]
pub enum EntryRef<'a, T, B, M> {
Id(&'a Entry<Id<T, B>, M>),
Type(&'a TypeEntry<T, B, M>),
Graph(&'a GraphEntry<T, B, M>),
Included(&'a IncludedEntry<T, B, M>),
Reverse(&'a Entry<ReverseProperties<T, B, M>, M>),
Property(
Meta<&'a Id<T, B>, &'a M>,
&'a [StrippedIndexedObject<T, B, M>],
),
}
impl<'a, T, B, M> EntryRef<'a, T, B, M> {
pub fn into_key(self) -> EntryKeyRef<'a, T, B, M> {
match self {
Self::Id(_) => EntryKeyRef::Id,
Self::Type(_) => EntryKeyRef::Type,
Self::Graph(_) => EntryKeyRef::Graph,
Self::Included(_) => EntryKeyRef::Included,
Self::Reverse(_) => EntryKeyRef::Reverse,
Self::Property(k, _) => EntryKeyRef::Property(k),
}
}
pub fn key(&self) -> EntryKeyRef<'a, T, B, M> {
self.into_key()
}
pub fn into_value(self) -> EntryValueRef<'a, T, B, M> {
match self {
Self::Id(v) => EntryValueRef::Id(Meta(&v.value, &v.key_metadata)),
Self::Type(v) => EntryValueRef::Type(&v.value),
Self::Graph(v) => EntryValueRef::Graph(v),
Self::Included(v) => EntryValueRef::Included(v),
Self::Reverse(v) => EntryValueRef::Reverse(v),
Self::Property(_, v) => EntryValueRef::Property(v),
}
}
pub fn value(&self) -> EntryValueRef<'a, T, B, M> {
self.into_value()
}
pub fn into_key_value(self) -> (EntryKeyRef<'a, T, B, M>, EntryValueRef<'a, T, B, M>) {
match self {
Self::Id(v) => (
EntryKeyRef::Id,
EntryValueRef::Id(Meta(&v.value, &v.key_metadata)),
),
Self::Type(v) => (EntryKeyRef::Type, EntryValueRef::Type(&v.value)),
Self::Graph(v) => (EntryKeyRef::Graph, EntryValueRef::Graph(v)),
Self::Included(v) => (EntryKeyRef::Included, EntryValueRef::Included(v)),
Self::Reverse(v) => (EntryKeyRef::Reverse, EntryValueRef::Reverse(v)),
Self::Property(k, v) => (EntryKeyRef::Property(k), EntryValueRef::Property(v)),
}
}
pub fn as_key_value(&self) -> (EntryKeyRef<'a, T, B, M>, EntryValueRef<'a, T, B, M>) {
match self {
Self::Id(v) => (
EntryKeyRef::Id,
EntryValueRef::Id(Meta(&v.value, &v.key_metadata)),
),
Self::Type(v) => (EntryKeyRef::Type, EntryValueRef::Type(&v.value)),
Self::Graph(v) => (EntryKeyRef::Graph, EntryValueRef::Graph(v)),
Self::Included(v) => (EntryKeyRef::Included, EntryValueRef::Included(v)),
Self::Reverse(v) => (EntryKeyRef::Reverse, EntryValueRef::Reverse(v)),
Self::Property(k, v) => (EntryKeyRef::Property(*k), EntryValueRef::Property(v)),
}
}
}
pub type TypeEntryValue<T, B, M> = Meta<Vec<Meta<Id<T, B>, M>>, M>;
pub type TypeEntry<T, B, M> = Entry<Vec<Meta<Id<T, B>, M>>, M>;
pub type GraphEntry<T, B, M> = Entry<Graph<T, B, M>, M>;
pub type IncludedEntry<T, B, M> = Entry<HashSet<StrippedIndexedNode<T, B, M>>, M>;
#[derive(Derivative)]
#[derivative(Clone(bound = ""))]
pub struct Entries<'a, T, B, M> {
id: Option<&'a Entry<Id<T, B>, M>>,
type_: Option<&'a TypeEntry<T, B, M>>,
graph: Option<&'a GraphEntry<T, B, M>>,
included: Option<&'a IncludedEntry<T, B, M>>,
reverse: Option<&'a Entry<ReverseProperties<T, B, M>, M>>,
properties: properties::Iter<'a, T, B, M>,
}
impl<'a, T, B, M> Iterator for Entries<'a, T, B, M> {
type Item = EntryRef<'a, T, B, M>;
fn size_hint(&self) -> (usize, Option<usize>) {
let mut len = self.properties.len();
if self.id.is_some() {
len += 1
}
if self.type_.is_some() {
len += 1
}
if self.graph.is_some() {
len += 1
}
if self.included.is_some() {
len += 1
}
if self.reverse.is_some() {
len += 1
}
(len, Some(len))
}
fn next(&mut self) -> Option<Self::Item> {
self.id.take().map(EntryRef::Id).or_else(|| {
self.type_.take().map(EntryRef::Type).or_else(|| {
self.graph.take().map(EntryRef::Graph).or_else(|| {
self.included.take().map(EntryRef::Included).or_else(|| {
self.reverse.take().map(EntryRef::Reverse).or_else(|| {
self.properties
.next()
.map(|(k, v)| EntryRef::Property(k, v))
})
})
})
})
})
}
}
impl<'a, T, B, M> ExactSizeIterator for Entries<'a, T, B, M> {}
#[derive(Derivative)]
#[derivative(Clone(bound = ""))]
pub struct IndexedEntries<'a, T, B, M> {
index: Option<&'a str>,
inner: Entries<'a, T, B, M>,
}
impl<'a, T, B, M> Iterator for IndexedEntries<'a, T, B, M> {
type Item = IndexedEntryRef<'a, T, B, M>;
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.inner.len() + usize::from(self.index.is_some());
(len, Some(len))
}
fn next(&mut self) -> Option<Self::Item> {
self.index
.take()
.map(IndexedEntryRef::Index)
.or_else(|| self.inner.next().map(IndexedEntryRef::Node))
}
}
impl<'a, T, B, M> ExactSizeIterator for IndexedEntries<'a, T, B, M> {}
#[derive(Derivative, PartialEq, Eq)]
#[derivative(Clone(bound = ""), Copy(bound = ""))]
pub enum IndexedEntryKeyRef<'a, T, B, M> {
Index,
Node(EntryKeyRef<'a, T, B, M>),
}
impl<'a, T, B, M> IndexedEntryKeyRef<'a, T, B, M> {
pub fn into_keyword(self) -> Option<Keyword> {
match self {
Self::Index => Some(Keyword::Index),
Self::Node(e) => e.into_keyword(),
}
}
pub fn as_keyword(&self) -> Option<Keyword> {
self.into_keyword()
}
pub fn into_str(self) -> &'a str
where
T: AsRef<str>,
B: AsRef<str>,
{
match self {
Self::Index => "@index",
Self::Node(e) => e.into_str(),
}
}
pub fn as_str(&self) -> &'a str
where
T: AsRef<str>,
B: AsRef<str>,
{
self.into_str()
}
}
impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>, M> IntoRefWithContext<'a, str, N>
for IndexedEntryKeyRef<'a, T, B, M>
{
fn into_ref_with(self, vocabulary: &'a N) -> &'a str {
match self {
IndexedEntryKeyRef::Index => "@index",
IndexedEntryKeyRef::Node(e) => e.into_with(vocabulary).into_str(),
}
}
}
#[derive(Derivative)]
#[derivative(Clone(bound = ""), Copy(bound = ""))]
pub enum IndexedEntryValueRef<'a, T, B, M> {
Index(&'a str),
Node(EntryValueRef<'a, T, B, M>),
}
#[derive(Derivative)]
#[derivative(Clone(bound = ""), Copy(bound = ""))]
pub enum IndexedEntryRef<'a, T, B, M> {
Index(&'a str),
Node(EntryRef<'a, T, B, M>),
}
impl<'a, T, B, M> IndexedEntryRef<'a, T, B, M> {
pub fn into_key(self) -> IndexedEntryKeyRef<'a, T, B, M> {
match self {
Self::Index(_) => IndexedEntryKeyRef::Index,
Self::Node(e) => IndexedEntryKeyRef::Node(e.key()),
}
}
pub fn key(&self) -> IndexedEntryKeyRef<'a, T, B, M> {
self.into_key()
}
pub fn into_value(self) -> IndexedEntryValueRef<'a, T, B, M> {
match self {
Self::Index(v) => IndexedEntryValueRef::Index(v),
Self::Node(e) => IndexedEntryValueRef::Node(e.value()),
}
}
pub fn value(&self) -> IndexedEntryValueRef<'a, T, B, M> {
self.into_value()
}
pub fn into_key_value(
self,
) -> (
IndexedEntryKeyRef<'a, T, B, M>,
IndexedEntryValueRef<'a, T, B, M>,
) {
match self {
Self::Index(v) => (IndexedEntryKeyRef::Index, IndexedEntryValueRef::Index(v)),
Self::Node(e) => {
let (k, v) = e.into_key_value();
(IndexedEntryKeyRef::Node(k), IndexedEntryValueRef::Node(v))
}
}
}
pub fn as_key_value(
&self,
) -> (
IndexedEntryKeyRef<'a, T, B, M>,
IndexedEntryValueRef<'a, T, B, M>,
) {
self.into_key_value()
}
}
pub enum FragmentRef<'a, T, B, M> {
Entry(EntryRef<'a, T, B, M>),
Key(EntryKeyRef<'a, T, B, M>),
Value(EntryValueRef<'a, T, B, M>),
TypeFragment(Meta<&'a Id<T, B>, &'a M>),
}
impl<'a, T, B, M> FragmentRef<'a, T, B, M> {
pub fn into_id(self) -> Option<Meta<&'a Id<T, B>, &'a M>> {
match self {
Self::Key(EntryKeyRef::Property(id)) => Some(id),
Self::Value(EntryValueRef::Id(id)) => Some(id),
Self::TypeFragment(ty) => Some(ty),
_ => None,
}
}
pub fn as_id(&self) -> Option<&'a Id<T, B>> {
match self {
Self::Key(EntryKeyRef::Property(id)) => Some(id),
Self::Value(EntryValueRef::Id(id)) => Some(id),
Self::TypeFragment(ty) => Some(ty),
_ => None,
}
}
pub fn is_json_array(&self) -> bool {
match self {
Self::Value(v) => v.is_json_array(),
_ => false,
}
}
pub fn is_json_object(&self) -> bool {
match self {
Self::Value(v) => v.is_json_object(),
_ => false,
}
}
pub fn sub_fragments(&self) -> SubFragments<'a, T, B, M> {
match self {
Self::Entry(e) => SubFragments::Entry(Some(e.key()), Some(e.value())),
Self::Value(v) => v.sub_fragments(),
_ => SubFragments::None,
}
}
}
pub enum SubFragments<'a, T, B, M> {
None,
Entry(
Option<EntryKeyRef<'a, T, B, M>>,
Option<EntryValueRef<'a, T, B, M>>,
),
Type(std::slice::Iter<'a, Meta<Id<T, B>, M>>),
Graph(std::collections::hash_set::Iter<'a, StrippedIndexedObject<T, B, M>>),
Included(std::collections::hash_set::Iter<'a, StrippedIndexedNode<T, B, M>>),
Reverse(reverse_properties::Iter<'a, T, B, M>),
Property(std::slice::Iter<'a, StrippedIndexedObject<T, B, M>>),
}
impl<'a, T, B, M> Iterator for SubFragments<'a, T, B, M> {
type Item = super::FragmentRef<'a, T, B, M>;
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::None => None,
Self::Entry(k, v) => k
.take()
.map(|k| super::FragmentRef::NodeFragment(FragmentRef::Key(k)))
.or_else(|| {
v.take()
.map(|v| super::FragmentRef::NodeFragment(FragmentRef::Value(v)))
}),
Self::Type(l) => l
.next_back()
.map(|t| super::FragmentRef::NodeFragment(FragmentRef::TypeFragment(t.borrow()))),
Self::Graph(g) => g.next().map(|o| super::FragmentRef::IndexedObject(o)),
Self::Included(i) => i.next().map(|n| super::FragmentRef::IndexedNode(n)),
Self::Reverse(r) => r
.next()
.map(|(_, n)| super::FragmentRef::IndexedNodeList(n)),
Self::Property(o) => o.next().map(|o| super::FragmentRef::IndexedObject(o)),
}
}
}
impl<T, B, M> object::Any<T, B, M> for Node<T, B, M> {
#[inline(always)]
fn as_ref(&self) -> object::Ref<T, B, M> {
object::Ref::Node(self)
}
}
impl<T, B, M> TryFrom<Object<T, B, M>> for Node<T, B, M> {
type Error = Object<T, B, M>;
#[inline(always)]
fn try_from(obj: Object<T, B, M>) -> Result<Node<T, B, M>, Object<T, B, M>> {
match obj {
Object::Node(node) => Ok(*node),
obj => Err(obj),
}
}
}
impl<T: Hash, B: Hash, M: Hash> Hash for Node<T, B, M> {
#[inline]
fn hash<H: Hasher>(&self, h: &mut H) {
self.id.hash(h);
utils::hash_set_opt(self.types.as_ref().map(Entry::as_value).map(Meta::value), h);
utils::hash_set_opt(self.graph.as_ref().map(Entry::as_value).map(Meta::value), h);
utils::hash_set_opt(
self.included.as_ref().map(Entry::as_value).map(Meta::value),
h,
);
self.properties.hash(h);
self.reverse_properties.hash(h)
}
}
impl<T: Hash, B: Hash, M> locspan::StrippedHash for Node<T, B, M> {
#[inline]
fn stripped_hash<H: Hasher>(&self, h: &mut H) {
self.id.stripped_hash(h);
utils::hash_set_stripped_opt(self.types.as_ref().map(Entry::as_value).map(Meta::value), h);
utils::hash_set_opt(self.graph.as_ref().map(Entry::as_value).map(Meta::value), h);
utils::hash_set_opt(
self.included.as_ref().map(Entry::as_value).map(Meta::value),
h,
);
self.properties.stripped_hash(h);
self.reverse_properties.stripped_hash(h)
}
}
pub struct Nodes<'a, T, B, M>(Option<std::slice::Iter<'a, Stripped<IndexedNode<T, B, M>>>>);
impl<'a, T, B, M> Nodes<'a, T, B, M> {
#[inline(always)]
pub(crate) fn new(inner: Option<std::slice::Iter<'a, Stripped<IndexedNode<T, B, M>>>>) -> Self {
Self(inner)
}
}
impl<'a, T, B, M> Iterator for Nodes<'a, T, B, M> {
type Item = &'a IndexedNode<T, B, M>;
#[inline(always)]
fn next(&mut self) -> Option<&'a IndexedNode<T, B, M>> {
match &mut self.0 {
None => None,
Some(it) => it.next().map(|n| &n.0),
}
}
}
impl<T: Eq + Hash, B: Eq + Hash, M> TryFromJsonObject<T, B, M> for Node<T, B, M> {
fn try_from_json_object_in(
vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>,
mut object: Meta<json_syntax::Object<M>, M>,
) -> Result<Meta<Self, M>, Meta<InvalidExpandedJson<M>, M>> {
let id = match object
.remove_unique("@id")
.map_err(InvalidExpandedJson::duplicate_key)?
{
Some(entry) => Some(Entry::new(
entry.key.into_metadata(),
Id::try_from_json_in(vocabulary, entry.value)?,
)),
None => None,
};
let types = match object
.remove_unique("@type")
.map_err(InvalidExpandedJson::duplicate_key)?
{
Some(entry) => Some(Entry::new(
entry.key.into_metadata(),
Vec::try_from_json_in(vocabulary, entry.value)?,
)),
None => None,
};
let graph = match object
.remove_unique("@graph")
.map_err(InvalidExpandedJson::duplicate_key)?
{
Some(entry) => Some(Entry::new(
entry.key.into_metadata(),
HashSet::try_from_json_in(vocabulary, entry.value)?,
)),
None => None,
};
let included = match object
.remove_unique("@included")
.map_err(InvalidExpandedJson::duplicate_key)?
{
Some(entry) => Some(Entry::new(
entry.key.into_metadata(),
HashSet::try_from_json_in(vocabulary, entry.value)?,
)),
None => None,
};
let reverse_properties = match object
.remove_unique("@reverse")
.map_err(InvalidExpandedJson::duplicate_key)?
{
Some(entry) => Some(Entry::new(
entry.key.into_metadata(),
ReverseProperties::try_from_json_in(vocabulary, entry.value)?,
)),
None => None,
};
let Meta(properties, meta) = Properties::try_from_json_object_in(vocabulary, object)?;
Ok(Meta(
Self {
id,
types,
graph,
included,
reverse_properties,
properties,
},
meta,
))
}
}
impl<T, B, M: Clone, N: Vocabulary<Iri = T, BlankId = B>> IntoJsonWithContextMeta<M, N>
for Node<T, B, M>
{
fn into_json_meta_with(self, meta: M, vocabulary: &N) -> Meta<json_syntax::Value<M>, M> {
let mut obj = json_syntax::Object::new();
if let Some(id) = self.id {
obj.insert(
Meta("@id".into(), id.key_metadata),
id.value.into_with(vocabulary).into_json(),
);
}
if let Some(types) = self.types {
if !types.is_empty() {
let value = types.value.into_with(vocabulary).into_json();
obj.insert(Meta("@type".into(), types.key_metadata), value);
}
}
if let Some(graph) = self.graph {
obj.insert(
Meta("@graph".into(), graph.key_metadata),
graph.value.into_with(vocabulary).into_json(),
);
}
if let Some(included) = self.included {
obj.insert(
Meta("@include".into(), included.key_metadata),
included.value.into_with(vocabulary).into_json(),
);
}
if let Some(reverse_properties) = self.reverse_properties {
obj.insert(
Meta("@reverse".into(), reverse_properties.key_metadata),
reverse_properties.value.into_with(vocabulary).into_json(),
);
}
for (Meta(prop, meta), objects) in self.properties {
obj.insert(
Meta(prop.with(vocabulary).to_string().into(), meta.clone()),
objects.into_json_meta_with(meta, vocabulary),
);
}
Meta(obj.into(), meta)
}
}