Skip to content

Commit

Permalink
WIP: Progress on type mapping and reverse mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
dnorman committed Feb 23, 2021
1 parent 7ef3f48 commit 3946adc
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 73 deletions.
2 changes: 2 additions & 0 deletions crates/data-adapters/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ pub enum Error {
NotFound,
CycleDetected,
Sanity,
InvariantViolation(&'static str),
SymbolResolution,
}

impl std::convert::From<Error> for std::io::Error {
Expand Down
170 changes: 103 additions & 67 deletions crates/data-adapters/src/json.rs
Original file line number Diff line number Diff line change
@@ -1,121 +1,136 @@
pub mod test;
pub mod typemap;

use std::marker::PhantomData;

use mindbase_artifact::body::{DataNode, SubGraph};
use mindbase_artifact::{
body::{DataNode, SubGraph, Type},
Artifact, ArtifactNodeType,
};
use mindbase_hypergraph::{
entity::{directed, vertex},
entity::{
directed, vertex,
EntityInner::{Directed, Undirected, Vertex},
},
traits::{GraphInterface, Symbol, Weight},
EntityId,
Entity, EntityId,
};
use serde_json::Value;

use crate::Error;

pub struct JsonAdapter<'a, G, W, T>
use self::typemap::JsonType;
pub use self::typemap::JsonTypeMap;

pub struct JsonAdapter<'a, G, T>
where
T: Clone,
{
graph: &'a G,
tm: TypeMap<T>,
_w: PhantomData<W>,
tm: JsonTypeMap<T>,
}

impl<'a, G, W, S> JsonAdapter<'a, G, W, S>
impl<'a, G, S> JsonAdapter<'a, G, S>
where
G: GraphInterface<W>,
W: Weight<Symbol = S> + From<S> + From<DataNode<S>> + From<SubGraph<S>>,
S: Symbol + Clone,
G: GraphInterface<Artifact<S>>,
// W: Weight<Symbol = S> + From<DataNode<S>> + From<SubGraph<S>> + From<Type<S>>,
S: Symbol + ArtifactNodeType + Clone,
{
pub fn new(graph: &'a G, typemap: TypeMap<S>) -> Self {
pub fn new(graph: &'a G, typemap: JsonTypeMap<S>) -> Self {
Self {
graph,
_w: PhantomData,
// a: PhantomData,
tm: typemap,
}
}
pub fn load<R: std::io::Read>(&self, reader: R) -> Result<EntityId, Error> {
pub fn load<R: std::io::Read>(&self, reader: R, filename: String) -> Result<EntityId, Error> {
let jv: Value = serde_json::from_reader(reader)?;

let root_element = self.input_recurse(jv)?;
let json_document = self.graph.insert(vertex(SubGraph {
graph_type: self.tm.Document.clone(),

let json_document = self.graph.insert(vertex(DataNode {
data_type: self.tm.to_sym(JsonType::Document),
data: Some(filename.into_bytes()),
}))?;

self.graph
.insert(directed(self.tm.RootElement.clone(), [json_document], [root_element]))?;
self.graph.insert(directed(
Type(self.tm.to_sym(JsonType::RootElement)),
[json_document],
[root_element],
))?;

Ok(json_document)
}
pub fn write<R: std::io::Write>(&self, writer: R, entity_id: EntityId) -> Result<(), Error> {
let mut cycleguard = CycleGuard::default();
self.output_recurse(&mut cycleguard, &entity_id, writer);
self.output_recurse(&mut cycleguard, &entity_id, writer)?;
Ok(())
}

fn input_recurse(&self, v: Value) -> Result<EntityId, Error> {
let tm = &self.tm;
Ok(match v {
Value::Null => self.graph.insert(vertex(DataNode {
data_type: self.tm.Null.clone(),
data_type: tm.to_sym(JsonType::Null),
data: None,
}))?,
Value::Bool(b) => self.graph.insert(vertex(DataNode {
data_type: self.tm.Bool.clone(),
data_type: tm.to_sym(JsonType::Bool),
data: Some(vec![b as u8]),
}))?,
Value::Number(n) => self.graph.insert(vertex(DataNode {
data_type: self.tm.Number.clone(),
data_type: tm.to_sym(JsonType::Number),
data: Some(n.as_i64().unwrap().to_ne_bytes().to_vec()),
}))?,
Value::String(s) => self.graph.insert(vertex(DataNode {
data_type: self.tm.String.clone(),
data_type: tm.to_sym(JsonType::String),
data: Some(s.as_bytes().to_vec()),
}))?,
Value::Array(values) => {
//First define the array node itself
let arr = self.graph.insert(vertex(DataNode {
data_type: self.tm.Array.clone(),
data: None,
}))?;
let arr = self.graph.insert(vertex(Type(tm.to_sym(JsonType::Array))))?;

// now recurse

let mut members: Vec<EntityId> = Vec::with_capacity(values.len());
for (i, value) in values.into_iter().enumerate() {
let member = self.input_recurse(value)?;

// TODO1 - how does this work with symbolic types?
self.graph.insert(directed(
DataNode {
data_type: self.tm.ArrayOffset.clone(),
data_type: self.tm.to_sym(JsonType::ArrayOffset),
data: Some(i.to_ne_bytes().to_vec()),
},
[arr],
[member],
))?;

if i == 0 {
self.graph.insert(directed(self.tm.ArrHead.clone(), [arr], [member]))?;
self.graph
.insert(directed(Type(tm.to_sym(JsonType::ArrHead)), [arr], [member]))?;
} else {
let prev = *members.last().unwrap();
self.graph.insert(directed(self.tm.ArrNextMember.clone(), [prev], [member]))?;
self.graph.insert(directed(self.tm.ArrPrevMember.clone(), [member], [prev]))?;
self.graph
.insert(directed(Type(tm.to_sym(JsonType::ArrNextMember)), [prev], [member]))?;
self.graph
.insert(directed(Type(tm.to_sym(JsonType::ArrPrevMember)), [member], [prev]))?;
};

members.push(member);
}
if let Some(tail) = members.last() {
self.graph.insert(directed(self.tm.ArrTail.clone(), [arr], [*tail]))?;
self.graph
.insert(directed(Type(tm.to_sym(JsonType::ArrTail)), [arr], [*tail]))?;
}

self.graph.insert(directed(self.tm.ArrayMember.clone(), [arr], members))?;
self.graph
.insert(directed(Type(tm.to_sym(JsonType::ArrayMember)), [arr], members))?;

arr
}
Value::Object(values) => {
//First define the array node itself
let obj = self.graph.insert(vertex(DataNode {
data_type: self.tm.Object.clone(),
data_type: tm.to_sym(JsonType::Object),
data: None,
}))?;
let mut properties: Vec<EntityId> = Vec::with_capacity(values.len());
Expand All @@ -128,7 +143,7 @@ where
// TODO1 - reconcile HyperedgeWeight with symbolic types
let prop = self.graph.insert(directed(
DataNode {
data_type: self.tm.ObjectProperty.clone(),
data_type: tm.to_sym(JsonType::ObjectProperty),
data: Some(key.bytes().collect()),
},
[obj],
Expand All @@ -139,9 +154,9 @@ where
properties.push(prop);
}
self.graph
.insert(directed(self.tm.ObjectMembers.clone(), [obj], members.clone()))?;
.insert(directed(Type(tm.to_sym(JsonType::ObjectMembers)), [obj], members))?;
self.graph
.insert(directed(self.tm.ObjectProperties.clone(), [obj], members))?;
.insert(directed(Type(tm.to_sym(JsonType::ObjectProperties)), [obj], members))?;

obj
}
Expand All @@ -150,43 +165,64 @@ where

fn output_recurse<R: std::io::Write>(
&self, cycleguard: &mut CycleGuard, entity_id: &EntityId, writer: R,
) -> Result<(), std::io::Error> {
) -> Result<(), Error> {
cycleguard.push(entity_id)?;

let entity = self.graph.get(entity_id)?;

// LEFT OFF HERE - TODO
// We need to be able to access the artifact here, while still preserving the ability to test without using fuzzy symbols
// match entity.weight {
// }
let artifact = entity.weight;

// The distinction between edge and vertex feels wrong.
// Maybe there should only be edges?

match artifact {
Artifact::Node(DataNode { data_type, data }) => {}
Artifact::SubGraph(SubGraph { graph_type }) => {}
Artifact::Type(Type(s)) => match self.tm.from_sym(s, self.graph)? {
JsonType::Document => {}
JsonType::Null => {}
JsonType::Bool => {}
JsonType::Number => {}
JsonType::String => {}
JsonType::Array => {}
JsonType::ArrayMember => {}
JsonType::ArrayOffset => {}
JsonType::ArrNextMember => {}
JsonType::ArrPrevMember => {}
JsonType::ArrHead => {}
JsonType::ArrTail => {}
JsonType::Object => {}
JsonType::ObjectProperty => {}
JsonType::ObjectProperties => {}
JsonType::ObjectMembers => {}
JsonType::RootElement => {}
},
_ => return Err(Error::InvariantViolation("Invalid artifact type for JSON")),
}

// Ok(match v {
// Value::Null => self.graph.insert(vertex(DataNode {
// data_type: self.tm.to_sym(JsonType::$),
// data: None,
// }))?,
// Value::Bool(b) => self.graph.insert(vertex(DataNode {
// data_type: self.tm.to_sym(JsonType::$),
// data: Some(vec![b as u8]),
// }))?,
// Value::Number(n) => self.graph.insert(vertex(DataNode {
// data_type: self.tm.to_sym(JsonType::$),
// data: Some(n.as_i64().unwrap().to_ne_bytes().to_vec()),
// }))?,
// Value::String(s) => self.graph.insert(vertex(DataNode {
// data_type: self.tm.to_sym(JsonType::$),
// data: Some(s.as_bytes().to_vec()),
// }))?

cycleguard.pop(entity_id);
unimplemented!()
}
}

#[allow(non_snake_case)]
pub struct TypeMap<T>
where
T: Clone,
{
Document: T,
Null: T,
Bool: T,
Number: T,
String: T,
Array: T,
ArrayMember: T,
ArrayOffset: T,
ArrNextMember: T,
ArrPrevMember: T,
ArrHead: T,
ArrTail: T,
Object: T,
ObjectProperty: T,
ObjectProperties: T,
ObjectMembers: T,
RootElement: T,
}

#[derive(Default)]
struct CycleGuard(Vec<EntityId>);

Expand Down
4 changes: 2 additions & 2 deletions crates/data-adapters/src/json/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ impl From<TestJSONType> for TestWeight<TestJSONType> {
}

impl TestJSONType {
pub fn typemap() -> crate::json::TypeMap<TestJSONType> {
crate::json::TypeMap {
pub fn typemap() -> crate::json::JsonTypeMap<TestJSONType> {
crate::json::JsonTypeMap {
Document: TestJSONType::Document,
Null: TestJSONType::Null,
Bool: TestJSONType::Bool,
Expand Down
Loading

0 comments on commit 3946adc

Please sign in to comment.