pub mod apply;
pub(crate) mod coerce;
pub mod diff;
pub mod elements;
pub mod inference;
pub mod meta_graph;
pub mod meta_schema;
pub(crate) mod nested;
pub mod node;
pub mod parse;
pub mod patch;
pub mod types;
pub mod validation;
pub mod visualize;
pub use apply::*;
pub use diff::*;
pub use elements::*;
pub use inference::*;
pub use meta_schema::*;
pub use node::*;
pub use patch::*;
pub use types::*;
pub(crate) use validation::*;
pub use visualize::*;
use indexmap::IndexMap;
use crate::value::ElementProperty;
pub const SCHEMA_FORMAT_URL: &str = "https://graphersal.dev/schema/v1";
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct GraphSchema {
pub mode: SchemaMode,
pub meta: Option<ElementProperty>,
pub vertices: IndexMap<String, VertexSchema>,
pub edges: IndexMap<String, EdgeSchema>,
}
impl GraphSchema {
pub fn new() -> Self {
Self::default()
}
pub fn with_mode(mut self, mode: SchemaMode) -> Self {
self.mode = mode;
self
}
pub fn with_meta(mut self, meta: ElementProperty) -> Self {
self.meta = Some(match meta {
object @ ElementProperty::Object(_) => object,
other => {
let mut map = crate::value::PropertyMap::default();
map.insert("value", other);
ElementProperty::Object(Box::new(map))
}
});
self
}
pub fn with_vertex(mut self, label: impl Into<String>, schema: PropertySchema) -> Self {
self.vertices
.insert(label.into(), VertexSchema::new(schema));
self
}
pub fn with_edge(mut self, label: impl Into<String>, edge: EdgeSchema) -> Self {
self.edges.insert(label.into(), edge);
self
}
pub fn is_empty(&self) -> bool {
self.mode == SchemaMode::None
&& self.meta.is_none()
&& self.vertices.is_empty()
&& self.edges.is_empty()
}
pub(crate) fn label_root(
&self,
kind: crate::graph::GraphNodeType,
label: &str,
) -> Option<&PropertySchema> {
match kind {
crate::graph::GraphNodeType::Vertex => self.vertices.get(label).map(|v| &v.schema),
crate::graph::GraphNodeType::Edge => self.edges.get(label).map(|e| &e.schema),
}
}
pub(crate) fn declared_property(
&self,
kind: crate::graph::GraphNodeType,
labels: &[compact_str::CompactString],
key: &str,
) -> Option<&PropertySchema> {
labels
.iter()
.find_map(|label| self.label_root(kind, label.as_str())?.properties.get(key))
}
}
#[cfg(feature = "serde")]
mod serde_impl {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::GraphSchema;
use crate::value::ElementProperty;
impl Serialize for GraphSchema {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.to_value().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for GraphSchema {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = ElementProperty::deserialize(deserializer)?;
GraphSchema::from_value(&value).map_err(serde::de::Error::custom)
}
}
}