Move supporting types to other modules
This commit is contained in:
parent
ae04935f2a
commit
5045e9881c
42
serialization/src/compound_literal_subjects.rs
Normal file
42
serialization/src/compound_literal_subjects.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use crate::rdf::subject_string;
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use json_ld::ValidId as Subject;
|
||||
use rdf_types::Vocabulary;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct CompoundLiteralSubjects {
|
||||
graphs: IndexMap<String, CompoundMap>,
|
||||
}
|
||||
|
||||
impl CompoundLiteralSubjects {
|
||||
pub(crate) fn graph_entry(
|
||||
&mut self,
|
||||
graph: String,
|
||||
) -> indexmap::map::Entry<'_, String, CompoundMap> {
|
||||
self.graphs.entry(graph)
|
||||
}
|
||||
|
||||
pub(crate) fn graph(&self, graph: &str) -> Option<&CompoundMap> {
|
||||
self.graphs.get(graph)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct CompoundMap {
|
||||
subjects: IndexSet<String>,
|
||||
}
|
||||
|
||||
impl CompoundMap {
|
||||
pub(crate) fn insert<N>(&mut self, subject: &Subject<N::Iri, N::BlankId>, vocabulary: &N)
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let subject = subject_string(subject, vocabulary);
|
||||
|
||||
self.subjects.insert(subject);
|
||||
}
|
||||
|
||||
pub(crate) fn iter(&self) -> indexmap::set::Iter<'_, String> {
|
||||
self.subjects.iter()
|
||||
}
|
||||
}
|
144
serialization/src/graph_map.rs
Normal file
144
serialization/src/graph_map.rs
Normal file
|
@ -0,0 +1,144 @@
|
|||
use crate::{
|
||||
json_value::{JsonValue, Map},
|
||||
object_entry::ObjectEntry,
|
||||
rdf::{subject_string, QuadSubject},
|
||||
referenced_once::ReferencedValue,
|
||||
subject_entry::SubjectEntry,
|
||||
};
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use rdf_types::Vocabulary;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct GraphMap {
|
||||
graphs: IndexMap<String, Rc<RefCell<GraphEntry>>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct GraphEntry {
|
||||
// short for
|
||||
// {graph_name} -> Map
|
||||
// @id -> {graph_name}
|
||||
graphs: IndexSet<String>,
|
||||
|
||||
// short for
|
||||
// {subject} -> Map
|
||||
// @id -> {subject}
|
||||
// @type -> Array
|
||||
// {object}
|
||||
// {predicate} -> Array
|
||||
// {object}
|
||||
subjects: IndexMap<String, Rc<RefCell<SubjectEntry>>>,
|
||||
|
||||
// short for
|
||||
// {object} -> Map
|
||||
// @id -> {object}
|
||||
|
||||
// short for
|
||||
// {object} -> Map
|
||||
// @id -> {object}
|
||||
objects: IndexMap<String, Rc<RefCell<ObjectEntry>>>,
|
||||
|
||||
// short for
|
||||
// nil -> Map
|
||||
// usages -> Array
|
||||
// node -> Map (SubjectEntry)
|
||||
// property -> {predicate}
|
||||
// value -> {object}
|
||||
usages: Rc<RefCell<Option<Vec<ReferencedValue>>>>,
|
||||
}
|
||||
|
||||
impl GraphMap {
|
||||
pub(crate) fn insert(&mut self, graph_name: String, graph_entry: Rc<RefCell<GraphEntry>>) {
|
||||
self.graphs.insert(graph_name, graph_entry);
|
||||
}
|
||||
|
||||
pub(crate) fn entry(
|
||||
&mut self,
|
||||
graph_name: String,
|
||||
) -> indexmap::map::Entry<'_, String, Rc<RefCell<GraphEntry>>> {
|
||||
self.graphs.entry(graph_name)
|
||||
}
|
||||
|
||||
pub(crate) fn iter(&self) -> indexmap::map::Iter<'_, String, Rc<RefCell<GraphEntry>>> {
|
||||
self.graphs.iter()
|
||||
}
|
||||
|
||||
pub(crate) fn get(&self, graph: &str) -> Option<&Rc<RefCell<GraphEntry>>> {
|
||||
self.graphs.get(graph)
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphEntry {
|
||||
pub(crate) fn contains_graph(&self, graph_name: &str) -> bool {
|
||||
self.graphs.contains(graph_name)
|
||||
}
|
||||
|
||||
pub(crate) fn insert_graph(&mut self, graph_name: String) {
|
||||
self.graphs.insert(graph_name);
|
||||
}
|
||||
|
||||
pub(crate) fn subject_entry<'a, N>(
|
||||
&'a mut self,
|
||||
subject: &QuadSubject<N>,
|
||||
vocabulary: &N,
|
||||
) -> indexmap::map::Entry<'a, String, Rc<RefCell<SubjectEntry>>>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
self.subjects.entry(subject_string(subject, vocabulary))
|
||||
}
|
||||
|
||||
pub(crate) fn remove_subject(&mut self, subject: &str) -> Option<Rc<RefCell<SubjectEntry>>> {
|
||||
self.subjects.remove(subject)
|
||||
}
|
||||
|
||||
pub(crate) fn object_entry<'a, N>(
|
||||
&'a mut self,
|
||||
object: &QuadSubject<N>,
|
||||
vocabulary: &N,
|
||||
) -> indexmap::map::Entry<'a, String, Rc<RefCell<ObjectEntry>>>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
self.objects.entry(subject_string(object, vocabulary))
|
||||
}
|
||||
|
||||
pub(crate) fn remove(&mut self, item: &str) {
|
||||
self.subjects.remove(item);
|
||||
self.objects.remove(item);
|
||||
}
|
||||
|
||||
pub(crate) fn usages_entry(&mut self) -> &Rc<RefCell<Option<Vec<ReferencedValue>>>> {
|
||||
*self.usages.borrow_mut() = Some(Vec::new());
|
||||
&self.usages
|
||||
}
|
||||
|
||||
pub(crate) fn usages(&self) -> &Rc<RefCell<Option<Vec<ReferencedValue>>>> {
|
||||
&self.usages
|
||||
}
|
||||
|
||||
pub(crate) fn to_vec(&self) -> Vec<(String, JsonValue)> {
|
||||
let mut vec: Vec<(String, JsonValue)> = self
|
||||
.graphs
|
||||
.iter()
|
||||
.map(|graph| {
|
||||
let mut map = Map::new();
|
||||
map.insert("@id".into(), graph.as_str().into());
|
||||
(graph.into(), map.into())
|
||||
})
|
||||
.collect();
|
||||
|
||||
vec.extend(self.subjects.iter().map(|(subject, subject_entry)| {
|
||||
(subject.clone(), subject_entry.borrow().to_json_value())
|
||||
}));
|
||||
|
||||
vec.extend(
|
||||
self.objects.iter().map(|(object, object_entry)| {
|
||||
(object.clone(), object_entry.borrow().to_json_value())
|
||||
}),
|
||||
);
|
||||
|
||||
vec
|
||||
}
|
||||
}
|
52
serialization/src/input_dataset.rs
Normal file
52
serialization/src/input_dataset.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use crate::rdf::{NormalizingQuad, QuadSubject, QuadValue};
|
||||
use rdf_types::{Triple, Vocabulary};
|
||||
use std::{collections::HashMap, hash::Hash};
|
||||
|
||||
type SerializingTriple<N> = Triple<QuadSubject<N>, QuadSubject<N>, QuadValue<N>>;
|
||||
|
||||
pub(crate) struct InputDataset<N>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
graphs: HashMap<Option<QuadSubject<N>>, Vec<SerializingTriple<N>>>,
|
||||
}
|
||||
|
||||
impl<N> Default for InputDataset<N>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
graphs: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> InputDataset<N>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
pub(crate) fn new(input_dataset: Vec<NormalizingQuad<N>>) -> Self
|
||||
where
|
||||
N::Iri: Hash + Eq,
|
||||
N::BlankId: Hash + Eq,
|
||||
{
|
||||
input_dataset
|
||||
.into_iter()
|
||||
.fold(Self::default(), |mut this, quad| {
|
||||
let (subject, predicate, object, graph) = quad.into_parts();
|
||||
|
||||
let triple = Triple(subject, predicate, object);
|
||||
|
||||
this.graphs.entry(graph).or_default().push(triple);
|
||||
|
||||
this
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn graphs(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (Option<&'_ QuadSubject<N>>, &'_ [SerializingTriple<N>])> {
|
||||
self.graphs.iter().map(|(k, v)| (k.as_ref(), v.as_slice()))
|
||||
}
|
||||
}
|
225
serialization/src/json_value.rs
Normal file
225
serialization/src/json_value.rs
Normal file
|
@ -0,0 +1,225 @@
|
|||
use crate::rdf::{get_subject, subject_str, QuadSubject};
|
||||
use indexmap::IndexMap;
|
||||
use locspan::Meta;
|
||||
use rdf_types::Vocabulary;
|
||||
use std::{
|
||||
cell::{RefCell, RefMut},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
pub(crate) fn subject_json<N>(id: &QuadSubject<N>, vocabulary: &N) -> JsonValue
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let subject = get_subject(id, vocabulary);
|
||||
let s = subject_str(&subject);
|
||||
s.into()
|
||||
}
|
||||
|
||||
pub(crate) type Map = IndexMap<String, JsonValue>;
|
||||
pub(crate) type Array = Vec<JsonValue>;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct JsonValue {
|
||||
value: JsonValueKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
enum JsonValueKind {
|
||||
Map(Rc<RefCell<Map>>),
|
||||
Array(Rc<RefCell<Array>>),
|
||||
String(json_syntax::String),
|
||||
Number(json_syntax::NumberBuf),
|
||||
Boolean(bool),
|
||||
Null,
|
||||
}
|
||||
|
||||
impl JsonValue {
|
||||
pub(crate) fn matches_string(&self, s: &str) -> bool {
|
||||
self.get_string().map(|string| string == s).unwrap_or(false)
|
||||
}
|
||||
|
||||
pub(crate) fn get_string(&self) -> Option<&str> {
|
||||
match self.value {
|
||||
JsonValueKind::String(ref s) => Some(s.as_str()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_array_mut(&self) -> Option<RefMut<'_, Array>> {
|
||||
match self.value {
|
||||
JsonValueKind::Array(ref array) => Some(array.borrow_mut()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_map_mut(&self) -> Option<RefMut<'_, Map>> {
|
||||
match self.value {
|
||||
JsonValueKind::Map(ref map) => Some(map.borrow_mut()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_map(&self) -> Option<Rc<RefCell<Map>>> {
|
||||
match self.value {
|
||||
JsonValueKind::Map(ref map) => Some(map.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Map> for JsonValue {
|
||||
fn from(value: Map) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Map(Rc::new(RefCell::new(value))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rc<RefCell<Map>>> for JsonValue {
|
||||
fn from(value: Rc<RefCell<Map>>) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Map(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Array> for JsonValue {
|
||||
fn from(value: Array) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Array(Rc::new(RefCell::new(value))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rc<RefCell<Array>>> for JsonValue {
|
||||
fn from(value: Rc<RefCell<Array>>) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Array(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for JsonValue {
|
||||
fn from(value: &'a str) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::String(value.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<json_syntax::String> for JsonValue {
|
||||
fn from(value: json_syntax::String) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::String(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<json_syntax::NumberBuf> for JsonValue {
|
||||
fn from(value: json_syntax::NumberBuf) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Number(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for JsonValue {
|
||||
fn from(value: bool) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Boolean(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<()> for JsonValue {
|
||||
fn from(_: ()) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> From<Meta<json_syntax::Value<M>, M>> for JsonValue {
|
||||
fn from(Meta(value, _): Meta<json_syntax::Value<M>, M>) -> Self {
|
||||
match value {
|
||||
json_syntax::Value::Null => ().into(),
|
||||
json_syntax::Value::Boolean(boolean) => boolean.into(),
|
||||
json_syntax::Value::Number(num) => num.into(),
|
||||
json_ld_syntax::Value::String(string) => string.into(),
|
||||
json_ld_syntax::Value::Array(array) => array.into(),
|
||||
json_ld_syntax::Value::Object(object) => object.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct WithMeta<M>(pub(crate) JsonValue, pub(crate) M);
|
||||
|
||||
impl<M> From<WithMeta<M>> for Meta<json_syntax::Value<M>, M>
|
||||
where
|
||||
M: Clone,
|
||||
{
|
||||
fn from(WithMeta(value, meta): WithMeta<M>) -> Self {
|
||||
let value = match value.value {
|
||||
JsonValueKind::Null => json_syntax::Value::Null,
|
||||
JsonValueKind::Boolean(boolean) => json_syntax::Value::Boolean(boolean),
|
||||
JsonValueKind::Number(number) => json_syntax::Value::Number(number),
|
||||
JsonValueKind::String(string) => json_syntax::Value::String(string),
|
||||
JsonValueKind::Array(array) => json_syntax::Value::Array(
|
||||
array
|
||||
.borrow()
|
||||
.iter()
|
||||
.map(|value| WithMeta(value.clone(), meta.clone()).into())
|
||||
.collect(),
|
||||
),
|
||||
JsonValueKind::Map(map) => json_syntax::Value::Object(map.borrow().iter().fold(
|
||||
json_syntax::Object::new(),
|
||||
|mut object, (k, v)| {
|
||||
object.insert(
|
||||
Meta(k.as_str().into(), meta.clone()),
|
||||
WithMeta(v.clone(), meta.clone()).into(),
|
||||
);
|
||||
object
|
||||
},
|
||||
)),
|
||||
};
|
||||
|
||||
Meta(value, meta)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> From<json_syntax::Array<M>> for JsonValue {
|
||||
fn from(values: json_syntax::Array<M>) -> Self {
|
||||
let array = values
|
||||
.into_iter()
|
||||
.map(|value| value.into())
|
||||
.collect::<Vec<JsonValue>>();
|
||||
array.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> From<json_syntax::Object<M>> for JsonValue {
|
||||
fn from(value: json_syntax::Object<M>) -> Self {
|
||||
let mut map = Map::new();
|
||||
|
||||
for json_syntax::object::Entry { key, value } in value.into_iter() {
|
||||
if let Some(entry) = map.remove(key.0.as_str()) {
|
||||
let entry_clone = entry.clone();
|
||||
|
||||
let entry = if let Some(mut array) = entry.get_array_mut() {
|
||||
array.push(value.into());
|
||||
drop(array);
|
||||
entry_clone
|
||||
} else {
|
||||
vec![entry_clone, value.into()].into()
|
||||
};
|
||||
|
||||
map.insert(key.0.to_string(), entry);
|
||||
} else {
|
||||
map.insert(key.0.to_string(), value.into());
|
||||
}
|
||||
}
|
||||
|
||||
map.into()
|
||||
}
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
use indexmap::{IndexMap, IndexSet};
|
||||
use iref::Iri;
|
||||
use json_ld::{
|
||||
rdf::{
|
||||
RdfDirection, RDF_DIRECTION, RDF_FIRST, RDF_JSON, RDF_NIL, RDF_REST, RDF_TYPE, RDF_VALUE,
|
||||
|
@ -9,762 +7,41 @@ use json_ld::{
|
|||
};
|
||||
use json_ld_syntax::Parse;
|
||||
use locspan::Meta;
|
||||
use rdf_types::{BlankId, BlankIdVocabulary, IriVocabulary, Quad, Triple, Vocabulary};
|
||||
use rdf_types::Vocabulary;
|
||||
use smallvec::SmallVec;
|
||||
use static_iref::iri;
|
||||
use std::{
|
||||
cell::{RefCell, RefMut},
|
||||
collections::HashMap,
|
||||
hash::Hash,
|
||||
rc::Rc,
|
||||
use std::{cell::RefCell, hash::Hash, rc::Rc};
|
||||
|
||||
mod compound_literal_subjects;
|
||||
mod graph_map;
|
||||
mod input_dataset;
|
||||
mod json_value;
|
||||
mod object_entry;
|
||||
mod rdf;
|
||||
mod referenced_once;
|
||||
mod subject_entry;
|
||||
|
||||
use compound_literal_subjects::CompoundLiteralSubjects;
|
||||
use graph_map::{GraphEntry, GraphMap};
|
||||
use input_dataset::InputDataset;
|
||||
use json_value::{subject_json, Array, JsonValue, Map, WithMeta};
|
||||
use object_entry::ObjectEntry;
|
||||
use rdf::{
|
||||
expect_iri, get_iri, subject_matches, subject_string, NormalizingQuad, QuadValue, RDF_LANGUAGE,
|
||||
RDF_LIST,
|
||||
};
|
||||
|
||||
const RDF_LANGUAGE: Iri<'static> = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#language");
|
||||
const RDF_LIST: Iri<'static> = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#list");
|
||||
|
||||
type QuadSubject<N> = Subject<<N as IriVocabulary>::Iri, <N as BlankIdVocabulary>::BlankId>;
|
||||
type QuadValue<N> =
|
||||
json_ld::rdf::Value<<N as IriVocabulary>::Iri, <N as BlankIdVocabulary>::BlankId>;
|
||||
type NormalizingQuad<N> = Quad<QuadSubject<N>, QuadSubject<N>, QuadValue<N>, QuadSubject<N>>;
|
||||
|
||||
type SerializingTriple<N> = Triple<QuadSubject<N>, QuadSubject<N>, QuadValue<N>>;
|
||||
|
||||
struct InputDataset<N>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
graphs: HashMap<Option<QuadSubject<N>>, Vec<SerializingTriple<N>>>,
|
||||
}
|
||||
|
||||
impl<N> Default for InputDataset<N>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
graphs: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> InputDataset<N>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
fn new(input_dataset: Vec<NormalizingQuad<N>>) -> Self
|
||||
where
|
||||
N::Iri: Hash + Eq,
|
||||
N::BlankId: Hash + Eq,
|
||||
{
|
||||
input_dataset
|
||||
.into_iter()
|
||||
.fold(Self::default(), |mut this, quad| {
|
||||
let (subject, predicate, object, graph) = quad.into_parts();
|
||||
|
||||
let triple = Triple(subject, predicate, object);
|
||||
|
||||
this.graphs.entry(graph).or_default().push(triple);
|
||||
|
||||
this
|
||||
})
|
||||
}
|
||||
|
||||
fn graphs(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (Option<&'_ QuadSubject<N>>, &'_ [SerializingTriple<N>])> {
|
||||
self.graphs.iter().map(|(k, v)| (k.as_ref(), v.as_slice()))
|
||||
}
|
||||
}
|
||||
|
||||
fn expect_iri<N>(id: &N::Iri, iri: Iri<'_>, vocabulary: &N) -> bool
|
||||
where
|
||||
N: Vocabulary,
|
||||
N::Iri: Eq,
|
||||
{
|
||||
vocabulary.get(iri).map(|iri| iri == *id).unwrap_or(false) || get_iri(id, vocabulary) == iri
|
||||
}
|
||||
|
||||
fn get_iri<'a, N>(id: &'a N::Iri, vocabulary: &'a N) -> Iri<'a>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
vocabulary.iri(id).expect("Id in vocabulary")
|
||||
}
|
||||
|
||||
fn get_subject<'a, N>(id: &'a QuadSubject<N>, vocabulary: &'a N) -> Subject<Iri<'a>, &'a BlankId>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
match id {
|
||||
Subject::Iri(iri) => Subject::Iri(vocabulary.iri(iri).expect("Id in vocabulary")),
|
||||
Subject::Blank(blank) => {
|
||||
Subject::Blank(vocabulary.blank_id(blank).expect("Id in vocabulary"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn subject_str<'a>(subject: &'a Subject<Iri<'a>, &'a BlankId>) -> &'a str {
|
||||
match subject {
|
||||
Subject::Iri(ref iri) => iri.as_str(),
|
||||
Subject::Blank(blank) => blank.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
fn subject_matches<N>(subject: &Subject<N::Iri, N::BlankId>, iri: Iri<'_>, vocabulary: &N) -> bool
|
||||
where
|
||||
N: Vocabulary,
|
||||
N::Iri: Eq,
|
||||
{
|
||||
match subject {
|
||||
Subject::Iri(id) => expect_iri(id, iri, vocabulary),
|
||||
Subject::Blank(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn subject_string<N>(id: &Subject<N::Iri, N::BlankId>, vocabulary: &N) -> String
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let subject = get_subject(id, vocabulary);
|
||||
let s = subject_str(&subject);
|
||||
s.to_string()
|
||||
}
|
||||
|
||||
fn subject_json<N>(id: &Subject<N::Iri, N::BlankId>, vocabulary: &N) -> JsonValue
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let subject = get_subject(id, vocabulary);
|
||||
let s = subject_str(&subject);
|
||||
s.into()
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
struct JsonValue {
|
||||
value: JsonValueKind,
|
||||
}
|
||||
|
||||
impl JsonValue {
|
||||
fn matches_string(&self, s: &str) -> bool {
|
||||
self.get_string().map(|string| string == s).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn get_string(&self) -> Option<&str> {
|
||||
match self.value {
|
||||
JsonValueKind::String(ref s) => Some(s.as_str()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_array_mut(&self) -> Option<RefMut<'_, Array>> {
|
||||
match self.value {
|
||||
JsonValueKind::Array(ref array) => Some(array.borrow_mut()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_map_mut(&self) -> Option<RefMut<'_, Map>> {
|
||||
match self.value {
|
||||
JsonValueKind::Map(ref map) => Some(map.borrow_mut()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_map(&self) -> Option<Rc<RefCell<Map>>> {
|
||||
match self.value {
|
||||
JsonValueKind::Map(ref map) => Some(map.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Map = IndexMap<String, JsonValue>;
|
||||
type Array = Vec<JsonValue>;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
enum JsonValueKind {
|
||||
Map(Rc<RefCell<Map>>),
|
||||
Array(Rc<RefCell<Array>>),
|
||||
String(json_syntax::String),
|
||||
Number(json_syntax::NumberBuf),
|
||||
Boolean(bool),
|
||||
Null,
|
||||
}
|
||||
|
||||
impl From<Map> for JsonValue {
|
||||
fn from(value: Map) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Map(Rc::new(RefCell::new(value))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rc<RefCell<Map>>> for JsonValue {
|
||||
fn from(value: Rc<RefCell<Map>>) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Map(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Array> for JsonValue {
|
||||
fn from(value: Array) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Array(Rc::new(RefCell::new(value))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rc<RefCell<Array>>> for JsonValue {
|
||||
fn from(value: Rc<RefCell<Array>>) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Array(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for JsonValue {
|
||||
fn from(value: &'a str) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::String(value.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<json_syntax::String> for JsonValue {
|
||||
fn from(value: json_syntax::String) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::String(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<json_syntax::NumberBuf> for JsonValue {
|
||||
fn from(value: json_syntax::NumberBuf) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Number(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for JsonValue {
|
||||
fn from(value: bool) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Boolean(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<()> for JsonValue {
|
||||
fn from(_: ()) -> Self {
|
||||
JsonValue {
|
||||
value: JsonValueKind::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> From<Meta<json_syntax::Value<M>, M>> for JsonValue {
|
||||
fn from(Meta(value, _): Meta<json_syntax::Value<M>, M>) -> Self {
|
||||
match value {
|
||||
json_syntax::Value::Null => ().into(),
|
||||
json_syntax::Value::Boolean(boolean) => boolean.into(),
|
||||
json_syntax::Value::Number(num) => num.into(),
|
||||
json_ld_syntax::Value::String(string) => string.into(),
|
||||
json_ld_syntax::Value::Array(array) => array.into(),
|
||||
json_ld_syntax::Value::Object(object) => object.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WithMeta<M>(JsonValue, M);
|
||||
|
||||
impl<M> From<WithMeta<M>> for Meta<json_syntax::Value<M>, M>
|
||||
where
|
||||
M: Clone,
|
||||
{
|
||||
fn from(WithMeta(value, meta): WithMeta<M>) -> Self {
|
||||
let value = match value.value {
|
||||
JsonValueKind::Null => json_syntax::Value::Null,
|
||||
JsonValueKind::Boolean(boolean) => json_syntax::Value::Boolean(boolean),
|
||||
JsonValueKind::Number(number) => json_syntax::Value::Number(number),
|
||||
JsonValueKind::String(string) => json_syntax::Value::String(string),
|
||||
JsonValueKind::Array(array) => json_syntax::Value::Array(
|
||||
array
|
||||
.borrow()
|
||||
.iter()
|
||||
.map(|value| WithMeta(value.clone(), meta.clone()).into())
|
||||
.collect(),
|
||||
),
|
||||
JsonValueKind::Map(map) => json_syntax::Value::Object(map.borrow().iter().fold(
|
||||
json_syntax::Object::new(),
|
||||
|mut object, (k, v)| {
|
||||
object.insert(
|
||||
Meta(k.as_str().into(), meta.clone()),
|
||||
WithMeta(v.clone(), meta.clone()).into(),
|
||||
);
|
||||
object
|
||||
},
|
||||
)),
|
||||
};
|
||||
|
||||
Meta(value, meta)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> From<json_syntax::Array<M>> for JsonValue {
|
||||
fn from(values: json_syntax::Array<M>) -> Self {
|
||||
let array = values
|
||||
.into_iter()
|
||||
.map(|value| value.into())
|
||||
.collect::<Vec<JsonValue>>();
|
||||
array.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> From<json_syntax::Object<M>> for JsonValue {
|
||||
fn from(value: json_syntax::Object<M>) -> Self {
|
||||
let mut map = Map::new();
|
||||
|
||||
for json_syntax::object::Entry { key, value } in value.into_iter() {
|
||||
if let Some(entry) = map.remove(key.0.as_str()) {
|
||||
let entry_clone = entry.clone();
|
||||
|
||||
let entry = if let Some(mut array) = entry.get_array_mut() {
|
||||
array.push(value.into());
|
||||
drop(array);
|
||||
entry_clone
|
||||
} else {
|
||||
vec![entry_clone, value.into()].into()
|
||||
};
|
||||
|
||||
map.insert(key.0.to_string(), entry);
|
||||
} else {
|
||||
map.insert(key.0.to_string(), value.into());
|
||||
}
|
||||
}
|
||||
|
||||
map.into()
|
||||
}
|
||||
}
|
||||
use referenced_once::{ReferencedOnce, ReferencedValue};
|
||||
use subject_entry::SubjectEntry;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InvalidJson;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct ReferencedOnce {
|
||||
value: HashMap<String, ReferencedEntry>,
|
||||
}
|
||||
|
||||
impl ReferencedOnce {
|
||||
fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn get_mut<'a>(&'a mut self, object: &str) -> Option<&'a mut ReferencedEntry> {
|
||||
self.value.get_mut(object)
|
||||
}
|
||||
|
||||
fn get_value(&self, object: &str) -> Option<&ReferencedValue> {
|
||||
self.value.get(object).and_then(|entry| match entry {
|
||||
ReferencedEntry::False => None,
|
||||
ReferencedEntry::Value(value) => Some(value),
|
||||
})
|
||||
}
|
||||
|
||||
fn contains_key(&self, object: &str) -> bool {
|
||||
self.get_value(object).is_some()
|
||||
}
|
||||
|
||||
fn insert(&mut self, object: String, referenced_value: ReferencedValue) {
|
||||
self.value
|
||||
.insert(object, ReferencedEntry::Value(referenced_value));
|
||||
impl std::fmt::Display for InvalidJson {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Invalid Json")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ReferencedEntry {
|
||||
False,
|
||||
Value(ReferencedValue),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct ReferencedValue {
|
||||
node: Rc<RefCell<SubjectEntry>>,
|
||||
property: String,
|
||||
value: Rc<RefCell<Map>>,
|
||||
}
|
||||
|
||||
impl ReferencedEntry {
|
||||
fn set_false(&mut self) {
|
||||
*self = Self::False;
|
||||
}
|
||||
}
|
||||
|
||||
impl ReferencedValue {
|
||||
fn new<N>(
|
||||
node: Rc<RefCell<SubjectEntry>>,
|
||||
property: &Subject<N::Iri, N::BlankId>,
|
||||
value: Rc<RefCell<Map>>,
|
||||
vocabulary: &N,
|
||||
) -> Self
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let property = get_subject(property, vocabulary);
|
||||
let property = subject_str(&property).to_string();
|
||||
|
||||
Self {
|
||||
node,
|
||||
property,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct GraphMap {
|
||||
graphs: IndexMap<String, Rc<RefCell<GraphEntry>>>,
|
||||
}
|
||||
|
||||
impl GraphMap {
|
||||
fn insert(&mut self, graph_name: String, graph_entry: Rc<RefCell<GraphEntry>>) {
|
||||
self.graphs.insert(graph_name, graph_entry);
|
||||
}
|
||||
|
||||
fn entry(
|
||||
&mut self,
|
||||
graph_name: String,
|
||||
) -> indexmap::map::Entry<'_, String, Rc<RefCell<GraphEntry>>> {
|
||||
self.graphs.entry(graph_name)
|
||||
}
|
||||
|
||||
fn iter(&self) -> indexmap::map::Iter<'_, String, Rc<RefCell<GraphEntry>>> {
|
||||
self.graphs.iter()
|
||||
}
|
||||
|
||||
fn get(&self, graph: &str) -> Option<&Rc<RefCell<GraphEntry>>> {
|
||||
self.graphs.get(graph)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct GraphEntry {
|
||||
// short for
|
||||
// {graph_name} -> Map
|
||||
// @id -> {graph_name}
|
||||
graphs: IndexSet<String>,
|
||||
|
||||
// short for
|
||||
// {subject} -> Map
|
||||
// @id -> {subject}
|
||||
// @type -> Array
|
||||
// {object}
|
||||
// {predicate} -> Array
|
||||
// {object}
|
||||
subjects: IndexMap<String, Rc<RefCell<SubjectEntry>>>,
|
||||
|
||||
// short for
|
||||
// {object} -> Map
|
||||
// @id -> {object}
|
||||
|
||||
// short for
|
||||
// {object} -> Map
|
||||
// @id -> {object}
|
||||
objects: IndexMap<String, Rc<RefCell<ObjectEntry>>>,
|
||||
|
||||
// short for
|
||||
// nil -> Map
|
||||
// usages -> Array
|
||||
// node -> Map (SubjectEntry)
|
||||
// property -> {predicate}
|
||||
// value -> {object}
|
||||
usages: Rc<RefCell<Option<Vec<ReferencedValue>>>>,
|
||||
}
|
||||
|
||||
impl GraphEntry {
|
||||
fn contains_graph(&self, graph_name: &str) -> bool {
|
||||
self.graphs.contains(graph_name)
|
||||
}
|
||||
|
||||
fn insert_graph(&mut self, graph_name: String) {
|
||||
self.graphs.insert(graph_name);
|
||||
}
|
||||
|
||||
fn subject_entry<'a, N>(
|
||||
&'a mut self,
|
||||
subject: &Subject<N::Iri, N::BlankId>,
|
||||
vocabulary: &N,
|
||||
) -> indexmap::map::Entry<'a, String, Rc<RefCell<SubjectEntry>>>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
self.subjects.entry(subject_string(subject, vocabulary))
|
||||
}
|
||||
|
||||
fn remove_subject(&mut self, subject: &str) -> Option<Rc<RefCell<SubjectEntry>>> {
|
||||
self.subjects.remove(subject)
|
||||
}
|
||||
|
||||
fn object_entry<'a, N>(
|
||||
&'a mut self,
|
||||
object: &Subject<N::Iri, N::BlankId>,
|
||||
vocabulary: &N,
|
||||
) -> indexmap::map::Entry<'a, String, Rc<RefCell<ObjectEntry>>>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
self.objects.entry(subject_string(object, vocabulary))
|
||||
}
|
||||
|
||||
fn remove(&mut self, item: &str) {
|
||||
self.subjects.remove(item);
|
||||
self.objects.remove(item);
|
||||
}
|
||||
|
||||
fn usages_entry(&mut self) -> &Rc<RefCell<Option<Vec<ReferencedValue>>>> {
|
||||
*self.usages.borrow_mut() = Some(Vec::new());
|
||||
&self.usages
|
||||
}
|
||||
|
||||
fn usages(&self) -> &Rc<RefCell<Option<Vec<ReferencedValue>>>> {
|
||||
&self.usages
|
||||
}
|
||||
|
||||
fn to_vec(&self) -> Vec<(String, JsonValue)> {
|
||||
let mut vec: Vec<(String, JsonValue)> = self
|
||||
.graphs
|
||||
.iter()
|
||||
.map(|graph| {
|
||||
let mut map = Map::new();
|
||||
map.insert("@id".into(), graph.as_str().into());
|
||||
(graph.into(), map.into())
|
||||
})
|
||||
.collect();
|
||||
|
||||
vec.extend(self.subjects.iter().map(|(subject, subject_entry)| {
|
||||
(subject.clone(), subject_entry.borrow().to_json_value())
|
||||
}));
|
||||
|
||||
vec.extend(
|
||||
self.objects.iter().map(|(object, object_entry)| {
|
||||
(object.clone(), object_entry.borrow().to_json_value())
|
||||
}),
|
||||
);
|
||||
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SubjectEntry {
|
||||
// @id -> {subject}
|
||||
id: json_syntax::String,
|
||||
// @type -> Array
|
||||
// {object} (if type)
|
||||
ty: Option<Vec<json_syntax::String>>,
|
||||
// {predicate} -> Array
|
||||
// {object} (value)
|
||||
predicate_values: IndexMap<String, Vec<Rc<RefCell<Map>>>>,
|
||||
}
|
||||
|
||||
impl SubjectEntry {
|
||||
fn new<N>(subject: &Subject<N::Iri, N::BlankId>, vocabulary: &N) -> Self
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let subject = get_subject(subject, vocabulary);
|
||||
let subject_str = subject_str(&subject);
|
||||
|
||||
SubjectEntry {
|
||||
id: subject_str.into(),
|
||||
ty: None,
|
||||
predicate_values: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn contains_type<N>(&self, rhs: &Subject<N::Iri, N::BlankId>, vocabulary: &N) -> bool
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let rhs = get_subject(rhs, vocabulary);
|
||||
let rhs_str = subject_str(&rhs);
|
||||
|
||||
if let Some(ty) = &self.ty {
|
||||
ty.iter().any(|lhs| lhs.as_str() == rhs_str)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_type<N>(&mut self, ty: &Subject<N::Iri, N::BlankId>, vocabulary: &N)
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let ty = get_subject(ty, vocabulary);
|
||||
let ty_str = subject_str(&ty);
|
||||
|
||||
if let Some(ty) = &mut self.ty {
|
||||
ty.push(ty_str.into());
|
||||
} else {
|
||||
self.ty = Some(vec![ty_str.into()]);
|
||||
}
|
||||
}
|
||||
|
||||
fn predicate_entry<'a, N>(
|
||||
&'a mut self,
|
||||
predicate: &Subject<N::Iri, N::BlankId>,
|
||||
vocabulary: &N,
|
||||
) -> indexmap::map::Entry<'a, String, Vec<Rc<RefCell<Map>>>>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
self.predicate_values
|
||||
.entry(subject_string(predicate, vocabulary))
|
||||
}
|
||||
|
||||
fn contains_predicate_value<N>(
|
||||
&self,
|
||||
predicate: &Subject<N::Iri, N::BlankId>,
|
||||
vocabulary: &N,
|
||||
rhs: &Rc<RefCell<Map>>,
|
||||
) -> bool
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let predicate = get_subject(predicate, vocabulary);
|
||||
let predicate_str = subject_str(&predicate);
|
||||
|
||||
let Some(values) = self.predicate_values.get(predicate_str) else { return false; };
|
||||
|
||||
values.iter().any(|lhs| *lhs.borrow() == *rhs.borrow())
|
||||
}
|
||||
|
||||
fn insert_predicate_value<N>(
|
||||
&mut self,
|
||||
predicate: &Subject<N::Iri, N::BlankId>,
|
||||
vocabulary: &N,
|
||||
value: Rc<RefCell<Map>>,
|
||||
) where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let predicate = get_subject(predicate, vocabulary);
|
||||
let predicate_str = subject_str(&predicate);
|
||||
|
||||
let Some(values) = self.predicate_values.get_mut(predicate_str) else { return; };
|
||||
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
fn predicate_value(&self, predicate: &str) -> Option<&Vec<Rc<RefCell<Map>>>> {
|
||||
self.predicate_values.get(predicate)
|
||||
}
|
||||
|
||||
fn is_blank_node(&self) -> bool {
|
||||
self.id.starts_with("_:")
|
||||
}
|
||||
|
||||
fn id(&self) -> &str {
|
||||
self.id.as_str()
|
||||
}
|
||||
|
||||
fn ty(&self) -> Option<&[json_syntax::String]> {
|
||||
self.ty.as_deref()
|
||||
}
|
||||
|
||||
fn predicate_len(&self) -> usize {
|
||||
self.predicate_values.len()
|
||||
}
|
||||
|
||||
fn to_json_value(&self) -> JsonValue {
|
||||
let mut map = Map::new();
|
||||
|
||||
map.insert("@id".into(), self.id.clone().into());
|
||||
|
||||
if let Some(ty) = &self.ty {
|
||||
map.insert(
|
||||
"@type".into(),
|
||||
ty.iter()
|
||||
.map(|ty| ty.as_str().into())
|
||||
.collect::<Vec<JsonValue>>()
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
for (predicate, values) in &self.predicate_values {
|
||||
map.insert(
|
||||
predicate.into(),
|
||||
values
|
||||
.iter()
|
||||
.map(|value| value.clone().into())
|
||||
.collect::<Vec<JsonValue>>()
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
map.into()
|
||||
}
|
||||
}
|
||||
|
||||
struct ObjectEntry {
|
||||
// short for
|
||||
// @id -> rdf:nil
|
||||
id: json_syntax::String,
|
||||
}
|
||||
|
||||
impl ObjectEntry {
|
||||
fn new<N>(object: &Subject<N::Iri, N::BlankId>, vocabulary: &N) -> Self
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let object = get_subject(object, vocabulary);
|
||||
let object_str = subject_str(&object);
|
||||
|
||||
ObjectEntry {
|
||||
id: object_str.into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_json_value(&self) -> JsonValue {
|
||||
let mut map = Map::new();
|
||||
map.insert("@id".into(), self.id.clone().into());
|
||||
map.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct CompoundLiteralSubjects {
|
||||
graphs: IndexMap<String, CompoundMap>,
|
||||
}
|
||||
|
||||
impl CompoundLiteralSubjects {
|
||||
fn graph_entry(&mut self, graph: String) -> indexmap::map::Entry<'_, String, CompoundMap> {
|
||||
self.graphs.entry(graph)
|
||||
}
|
||||
|
||||
fn graph(&self, graph: &str) -> Option<&CompoundMap> {
|
||||
self.graphs.get(graph)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct CompoundMap {
|
||||
subjects: IndexSet<String>,
|
||||
}
|
||||
|
||||
impl CompoundMap {
|
||||
fn insert<N>(&mut self, subject: &Subject<N::Iri, N::BlankId>, vocabulary: &N)
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let subject = subject_string(subject, vocabulary);
|
||||
|
||||
self.subjects.insert(subject);
|
||||
}
|
||||
|
||||
fn iter(&self) -> indexmap::set::Iter<'_, String> {
|
||||
self.subjects.iter()
|
||||
}
|
||||
}
|
||||
impl std::error::Error for InvalidJson {}
|
||||
|
||||
pub fn rdf_to_json_ld<N, M>(
|
||||
rdf_dataset: Vec<NormalizingQuad<N>>,
|
||||
|
|
31
serialization/src/object_entry.rs
Normal file
31
serialization/src/object_entry.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use crate::{
|
||||
json_value::{JsonValue, Map},
|
||||
rdf::{get_subject, subject_str, QuadSubject},
|
||||
};
|
||||
use rdf_types::Vocabulary;
|
||||
|
||||
pub(crate) struct ObjectEntry {
|
||||
// short for
|
||||
// @id -> rdf:nil
|
||||
id: json_syntax::String,
|
||||
}
|
||||
|
||||
impl ObjectEntry {
|
||||
pub(crate) fn new<N>(object: &QuadSubject<N>, vocabulary: &N) -> Self
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let object = get_subject(object, vocabulary);
|
||||
let object_str = subject_str(&object);
|
||||
|
||||
ObjectEntry {
|
||||
id: object_str.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_json_value(&self) -> JsonValue {
|
||||
let mut map = Map::new();
|
||||
map.insert("@id".into(), self.id.clone().into());
|
||||
map.into()
|
||||
}
|
||||
}
|
74
serialization/src/rdf.rs
Normal file
74
serialization/src/rdf.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
use iref::Iri;
|
||||
use json_ld::ValidId as Subject;
|
||||
use rdf_types::{BlankId, BlankIdVocabulary, IriVocabulary, Quad, Vocabulary};
|
||||
use static_iref::iri;
|
||||
|
||||
pub(crate) const RDF_LANGUAGE: Iri<'static> =
|
||||
iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#language");
|
||||
pub(crate) const RDF_LIST: Iri<'static> = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#list");
|
||||
|
||||
pub(crate) type QuadSubject<N> =
|
||||
Subject<<N as IriVocabulary>::Iri, <N as BlankIdVocabulary>::BlankId>;
|
||||
|
||||
pub(crate) type QuadValue<N> =
|
||||
json_ld::rdf::Value<<N as IriVocabulary>::Iri, <N as BlankIdVocabulary>::BlankId>;
|
||||
|
||||
pub(crate) type NormalizingQuad<N> =
|
||||
Quad<QuadSubject<N>, QuadSubject<N>, QuadValue<N>, QuadSubject<N>>;
|
||||
|
||||
pub(crate) fn expect_iri<N>(id: &N::Iri, iri: Iri<'_>, vocabulary: &N) -> bool
|
||||
where
|
||||
N: Vocabulary,
|
||||
N::Iri: Eq,
|
||||
{
|
||||
vocabulary.get(iri).map(|iri| iri == *id).unwrap_or(false) || get_iri(id, vocabulary) == iri
|
||||
}
|
||||
|
||||
pub(crate) fn get_iri<'a, N>(id: &'a N::Iri, vocabulary: &'a N) -> Iri<'a>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
vocabulary.iri(id).expect("Id in vocabulary")
|
||||
}
|
||||
|
||||
pub(crate) fn get_subject<'a, N>(
|
||||
id: &'a QuadSubject<N>,
|
||||
vocabulary: &'a N,
|
||||
) -> Subject<Iri<'a>, &'a BlankId>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
match id {
|
||||
Subject::Iri(iri) => Subject::Iri(vocabulary.iri(iri).expect("Id in vocabulary")),
|
||||
Subject::Blank(blank) => {
|
||||
Subject::Blank(vocabulary.blank_id(blank).expect("Id in vocabulary"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn subject_str<'a>(subject: &'a Subject<Iri<'a>, &'a BlankId>) -> &'a str {
|
||||
match subject {
|
||||
Subject::Iri(ref iri) => iri.as_str(),
|
||||
Subject::Blank(blank) => blank.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn subject_matches<N>(subject: &QuadSubject<N>, iri: Iri<'_>, vocabulary: &N) -> bool
|
||||
where
|
||||
N: Vocabulary,
|
||||
N::Iri: Eq,
|
||||
{
|
||||
match subject {
|
||||
Subject::Iri(id) => expect_iri(id, iri, vocabulary),
|
||||
Subject::Blank(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn subject_string<N>(id: &QuadSubject<N>, vocabulary: &N) -> String
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let subject = get_subject(id, vocabulary);
|
||||
let s = subject_str(&subject);
|
||||
s.to_string()
|
||||
}
|
78
serialization/src/referenced_once.rs
Normal file
78
serialization/src/referenced_once.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use crate::{
|
||||
json_value::Map,
|
||||
rdf::{get_subject, subject_str, QuadSubject},
|
||||
subject_entry::SubjectEntry,
|
||||
};
|
||||
use rdf_types::Vocabulary;
|
||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct ReferencedOnce {
|
||||
value: HashMap<String, ReferencedEntry>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum ReferencedEntry {
|
||||
False,
|
||||
Value(ReferencedValue),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ReferencedValue {
|
||||
pub(crate) node: Rc<RefCell<SubjectEntry>>,
|
||||
pub(crate) property: String,
|
||||
pub(crate) value: Rc<RefCell<Map>>,
|
||||
}
|
||||
|
||||
impl ReferencedOnce {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut<'a>(&'a mut self, object: &str) -> Option<&'a mut ReferencedEntry> {
|
||||
self.value.get_mut(object)
|
||||
}
|
||||
|
||||
pub(crate) fn get_value(&self, object: &str) -> Option<&ReferencedValue> {
|
||||
self.value.get(object).and_then(|entry| match entry {
|
||||
ReferencedEntry::False => None,
|
||||
ReferencedEntry::Value(value) => Some(value),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn contains_key(&self, object: &str) -> bool {
|
||||
self.get_value(object).is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn insert(&mut self, object: String, referenced_value: ReferencedValue) {
|
||||
self.value
|
||||
.insert(object, ReferencedEntry::Value(referenced_value));
|
||||
}
|
||||
}
|
||||
|
||||
impl ReferencedEntry {
|
||||
pub(crate) fn set_false(&mut self) {
|
||||
*self = Self::False;
|
||||
}
|
||||
}
|
||||
|
||||
impl ReferencedValue {
|
||||
pub(crate) fn new<N>(
|
||||
node: Rc<RefCell<SubjectEntry>>,
|
||||
property: &QuadSubject<N>,
|
||||
value: Rc<RefCell<Map>>,
|
||||
vocabulary: &N,
|
||||
) -> Self
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let property = get_subject(property, vocabulary);
|
||||
let property = subject_str(&property).to_string();
|
||||
|
||||
Self {
|
||||
node,
|
||||
property,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
157
serialization/src/subject_entry.rs
Normal file
157
serialization/src/subject_entry.rs
Normal file
|
@ -0,0 +1,157 @@
|
|||
use crate::{
|
||||
json_value::{JsonValue, Map},
|
||||
rdf::{get_subject, subject_str, subject_string, QuadSubject},
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
use rdf_types::Vocabulary;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct SubjectEntry {
|
||||
// @id -> {subject}
|
||||
id: json_syntax::String,
|
||||
// @type -> Array
|
||||
// {object} (if type)
|
||||
ty: Option<Vec<json_syntax::String>>,
|
||||
// {predicate} -> Array
|
||||
// {object} (value)
|
||||
predicate_values: IndexMap<String, Vec<Rc<RefCell<Map>>>>,
|
||||
}
|
||||
|
||||
impl SubjectEntry {
|
||||
pub(crate) fn new<N>(subject: &QuadSubject<N>, vocabulary: &N) -> Self
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let subject = get_subject(subject, vocabulary);
|
||||
let subject_str = subject_str(&subject);
|
||||
|
||||
SubjectEntry {
|
||||
id: subject_str.into(),
|
||||
ty: None,
|
||||
predicate_values: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn contains_type<N>(&self, rhs: &QuadSubject<N>, vocabulary: &N) -> bool
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let rhs = get_subject(rhs, vocabulary);
|
||||
let rhs_str = subject_str(&rhs);
|
||||
|
||||
if let Some(ty) = &self.ty {
|
||||
ty.iter().any(|lhs| lhs.as_str() == rhs_str)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn insert_type<N>(&mut self, ty: &QuadSubject<N>, vocabulary: &N)
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let ty = get_subject(ty, vocabulary);
|
||||
let ty_str = subject_str(&ty);
|
||||
|
||||
if let Some(ty) = &mut self.ty {
|
||||
ty.push(ty_str.into());
|
||||
} else {
|
||||
self.ty = Some(vec![ty_str.into()]);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn predicate_entry<'a, N>(
|
||||
&'a mut self,
|
||||
predicate: &QuadSubject<N>,
|
||||
vocabulary: &N,
|
||||
) -> indexmap::map::Entry<'a, String, Vec<Rc<RefCell<Map>>>>
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
self.predicate_values
|
||||
.entry(subject_string(predicate, vocabulary))
|
||||
}
|
||||
|
||||
pub(crate) fn contains_predicate_value<N>(
|
||||
&self,
|
||||
predicate: &QuadSubject<N>,
|
||||
vocabulary: &N,
|
||||
rhs: &Rc<RefCell<Map>>,
|
||||
) -> bool
|
||||
where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let predicate = get_subject(predicate, vocabulary);
|
||||
let predicate_str = subject_str(&predicate);
|
||||
|
||||
let Some(values) = self.predicate_values.get(predicate_str) else { return false; };
|
||||
|
||||
values.iter().any(|lhs| *lhs.borrow() == *rhs.borrow())
|
||||
}
|
||||
|
||||
pub(crate) fn insert_predicate_value<N>(
|
||||
&mut self,
|
||||
predicate: &QuadSubject<N>,
|
||||
vocabulary: &N,
|
||||
value: Rc<RefCell<Map>>,
|
||||
) where
|
||||
N: Vocabulary,
|
||||
{
|
||||
let predicate = get_subject(predicate, vocabulary);
|
||||
let predicate_str = subject_str(&predicate);
|
||||
|
||||
let Some(values) = self.predicate_values.get_mut(predicate_str) else { return; };
|
||||
|
||||
values.push(value);
|
||||
}
|
||||
|
||||
pub(crate) fn predicate_value(&self, predicate: &str) -> Option<&Vec<Rc<RefCell<Map>>>> {
|
||||
self.predicate_values.get(predicate)
|
||||
}
|
||||
|
||||
pub(crate) fn is_blank_node(&self) -> bool {
|
||||
self.id.starts_with("_:")
|
||||
}
|
||||
|
||||
pub(crate) fn id(&self) -> &str {
|
||||
self.id.as_str()
|
||||
}
|
||||
|
||||
pub(crate) fn ty(&self) -> Option<&[json_syntax::String]> {
|
||||
self.ty.as_deref()
|
||||
}
|
||||
|
||||
pub(crate) fn predicate_len(&self) -> usize {
|
||||
self.predicate_values.len()
|
||||
}
|
||||
|
||||
pub(crate) fn to_json_value(&self) -> JsonValue {
|
||||
let mut map = Map::new();
|
||||
|
||||
map.insert("@id".into(), self.id.clone().into());
|
||||
|
||||
if let Some(ty) = &self.ty {
|
||||
map.insert(
|
||||
"@type".into(),
|
||||
ty.iter()
|
||||
.map(|ty| ty.as_str().into())
|
||||
.collect::<Vec<JsonValue>>()
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
for (predicate, values) in &self.predicate_values {
|
||||
map.insert(
|
||||
predicate.into(),
|
||||
values
|
||||
.iter()
|
||||
.map(|value| value.clone().into())
|
||||
.collect::<Vec<JsonValue>>()
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
map.into()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue