node/nodes: add skeleton types for graph nodes

This commit is contained in:
Paul Stemmet 2022-04-10 14:26:18 +00:00
parent cfb7c7bdbc
commit 5581c28129
Signed by: Paul Stemmet
GPG Key ID: EDEA539F594E7E75
6 changed files with 653 additions and 0 deletions

View File

@ -6,3 +6,7 @@
//! This module contains the basis for storing arbitrary
//! YAML documents as an in memory graph.
use crate::event::types::Slice;
mod nodes;

61
src/node/nodes/alias.rs Normal file
View File

@ -0,0 +1,61 @@
/*
* This Source Code Form is subject to the terms of the
* Mozilla Public License, v. 2.0. If a copy of the MPL
* was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
use crate::node::nodes::{NodeIndex, NodeSpecific};
pub(in crate::node) struct AliasNode
{
parent: NodeIndex,
id: NodeIndex,
points_to: NodeIndex,
}
impl AliasNode
{
pub fn new(id: NodeIndex, parent: NodeIndex, points_to: NodeIndex) -> Self
{
Self::with_parent(id, parent, points_to)
}
pub fn new_with_data(
parent: NodeIndex,
points_to: NodeIndex,
) -> impl FnOnce(NodeIndex) -> AliasNode
{
move |id| Self::new(id, parent, points_to)
}
pub fn id(&self) -> NodeIndex
{
self.id
}
pub fn parent(&self) -> Option<NodeIndex>
{
Some(self.parent)
}
fn with_parent(id: NodeIndex, parent: NodeIndex, points_to: NodeIndex) -> Self
{
Self {
parent,
id,
points_to,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(in crate::node) struct AliasData;
impl AliasData
{
pub fn opaque(self) -> NodeSpecific
{
self.into()
}
}

72
src/node/nodes/mapping.rs Normal file
View File

@ -0,0 +1,72 @@
/*
* This Source Code Form is subject to the terms of the
* Mozilla Public License, v. 2.0. If a copy of the MPL
* was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
use std::collections::HashMap;
use crate::node::nodes::{NodeIndex, NodeSpecific};
pub(in crate::node) type Children = HashMap<NodeIndex, Option<NodeIndex>>;
pub(in crate::node) struct MappingNode
{
parent: Option<NodeIndex>,
id: NodeIndex,
children: Children,
}
impl MappingNode
{
pub fn root(id: NodeIndex) -> Self
{
Self::with_parent(id, None)
}
pub fn new(id: NodeIndex, parent: NodeIndex) -> Self
{
Self::with_parent(id, Some(parent))
}
pub fn root_with() -> impl FnOnce(NodeIndex) -> MappingNode
{
move |id| Self::root(id)
}
pub fn new_with(parent: NodeIndex) -> impl FnOnce(NodeIndex) -> MappingNode
{
move |id| Self::new(id, parent)
}
pub fn children(&self) -> &Children
{
&self.children
}
pub fn children_mut(&mut self) -> &mut Children
{
&mut self.children
}
fn with_parent(id: NodeIndex, parent: Option<NodeIndex>) -> Self
{
Self {
parent,
id,
children: Default::default(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(in crate::node) struct MappingData;
impl MappingData
{
pub fn opaque(self) -> NodeSpecific
{
self.into()
}
}

253
src/node/nodes/mod.rs Normal file
View File

@ -0,0 +1,253 @@
/*
* This Source Code Form is subject to the terms of the
* Mozilla Public License, v. 2.0. If a copy of the MPL
* was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
use slotmap::new_key_type;
use crate::node::{
nodes::{
alias::{AliasData, AliasNode},
mapping::{MappingData, MappingNode},
scalar::{ScalarData, ScalarNode},
sequence::{SequenceData, SequenceNode},
},
Slice,
};
pub(in crate::node) mod alias;
pub(in crate::node) mod mapping;
pub(in crate::node) mod scalar;
pub(in crate::node) mod sequence;
new_key_type! {
/// Identifier used for locating [Node]s in a graph.
///
/// An invariant of this type is that one should never use
/// [NodeIndex]s as indexes into graphs that did not generate
/// the [NodeIndex]. Behavior is safe and cannot cause UB,
/// but is unspecified, and never what you want.
pub(in crate::node) struct NodeIndex;
}
/// Possible nodes one can encounter while traversing a
/// graph.
///
/// Importantly, only `LeafNode`s contain data, all other
/// variants deal with the structure of the graph and can be
/// considered internal nodes.
pub(in crate::node) enum Node<'de>
{
/// Data container, storing a single scalar node
Leaf(ScalarNode<'de>),
/// Mapping node, storing key value node pairs
Map(MappingNode),
/// List node, storing a sequence of nodes
List(SequenceNode),
/// Alias node pointing to a previously seen node
Alias(AliasNode),
}
impl<'de> Node<'de>
{
/// Wrap the new scalar node produced by f
pub fn scalar<F>(f: F) -> impl FnOnce(NodeIndex) -> Node<'de>
where
F: FnOnce(NodeIndex) -> ScalarNode<'de>,
{
|id| Node::Leaf(f(id))
}
/// Wrap the new mapping node produced by f
pub fn mapping<F>(f: F) -> impl FnOnce(NodeIndex) -> Node<'de>
where
F: FnOnce(NodeIndex) -> MappingNode,
{
|id| Node::Map(f(id))
}
/// Wrap the new sequence node produced by f
pub fn sequence<F>(f: F) -> impl FnOnce(NodeIndex) -> Node<'de>
where
F: FnOnce(NodeIndex) -> SequenceNode,
{
|id| Node::List(f(id))
}
/// Wrap the new alias node produced by f
pub fn alias<F>(f: F) -> impl FnOnce(NodeIndex) -> Node<'de>
where
F: FnOnce(NodeIndex) -> AliasNode,
{
|id| Node::Alias(f(id))
}
}
#[derive(Debug, Clone)]
pub(in crate::node) struct NodeData<'de>
{
anchor: Option<Slice<'de>>,
tag: Option<Tag<'de>>,
context: NodeContext,
mark: NodeMark,
node_specific: NodeSpecific,
}
impl<'de> NodeData<'de>
{
pub fn new(
anchor: Option<Slice<'de>>,
tag: Option<Tag<'de>>,
context: NodeContext,
mark: NodeMark,
ns: NodeSpecific,
) -> Self
{
Self {
anchor,
tag,
context,
mark,
node_specific: ns,
}
}
pub fn anchor(&self) -> Option<&Slice<'de>>
{
self.anchor.as_ref()
}
pub fn tag(&self) -> Option<&Tag<'de>>
{
self.tag.as_ref()
}
pub fn context(&self) -> NodeContext
{
self.context
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(in crate::node) struct Tag<'de>
{
handle: Slice<'de>,
prefix: Slice<'de>,
suffix: Slice<'de>,
}
impl<'de> Tag<'de>
{
pub fn new(handle: Slice<'de>, prefix: Slice<'de>, suffix: Slice<'de>) -> Self
{
Self {
handle,
prefix,
suffix,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(in crate::node) enum NodeContext
{
Block,
Flow,
}
impl NodeContext
{
pub const fn is_block(self) -> bool
{
matches!(self, Self::Block)
}
pub const fn is_flow(self) -> bool
{
!self.is_block()
}
}
impl Default for NodeContext
{
fn default() -> Self
{
Self::Block
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(in crate::node) struct NodeMark
{
start: usize,
end: usize,
}
impl NodeMark
{
pub const fn new(start: usize, end: usize) -> Self
{
Self { start, end }
}
pub const fn start(&self) -> usize
{
self.start
}
pub const fn end(&self) -> usize
{
self.end
}
}
impl From<(usize, usize)> for NodeMark
{
fn from((start, end): (usize, usize)) -> Self
{
Self::new(start, end)
}
}
#[derive(Debug, Clone)]
pub(in crate::node) enum NodeSpecific
{
Mapping(MappingData),
Sequence(SequenceData),
Alias(AliasData),
Scalar(ScalarData),
}
impl From<ScalarData> for NodeSpecific
{
fn from(data: ScalarData) -> Self
{
Self::Scalar(data)
}
}
impl From<AliasData> for NodeSpecific
{
fn from(data: AliasData) -> Self
{
Self::Alias(data)
}
}
impl From<MappingData> for NodeSpecific
{
fn from(data: MappingData) -> Self
{
Self::Mapping(data)
}
}
impl From<SequenceData> for NodeSpecific
{
fn from(data: SequenceData) -> Self
{
Self::Sequence(data)
}
}

183
src/node/nodes/scalar.rs Normal file
View File

@ -0,0 +1,183 @@
/*
* This Source Code Form is subject to the terms of the
* Mozilla Public License, v. 2.0. If a copy of the MPL
* was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
use crate::{
node::nodes::{NodeContext, NodeData, NodeIndex, NodeMark, NodeSpecific, Tag},
token::{ScalarStyle, Slice},
};
pub(in crate::node) struct ScalarNode<'de>
{
parent: Option<NodeIndex>,
id: NodeIndex,
scalar: Slice<'de>,
}
impl<'de> ScalarNode<'de>
{
pub fn root(id: NodeIndex, data: Slice<'de>) -> Self
{
Self::with_parent(id, data, None)
}
pub fn new(id: NodeIndex, parent: NodeIndex, data: Slice<'de>) -> Self
{
Self::with_parent(id, data, Some(parent))
}
pub fn root_with_data(data: Slice<'de>) -> impl FnOnce(NodeIndex) -> ScalarNode<'de>
{
move |id| Self::root(id, data)
}
pub fn new_with_data(
parent: NodeIndex,
data: Slice<'de>,
) -> impl FnOnce(NodeIndex) -> ScalarNode<'de>
{
move |id| Self::new(id, parent, data)
}
pub fn id(&self) -> NodeIndex
{
self.id
}
pub fn parent(&self) -> Option<NodeIndex>
{
self.parent
}
fn with_parent(id: NodeIndex, scalar: Slice<'de>, parent: Option<NodeIndex>) -> Self
{
Self { parent, id, scalar }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(in crate::node) struct ScalarData
{
style: ScalarStyle,
}
impl ScalarData
{
pub const fn new(style: ScalarStyle) -> Self
{
Self { style }
}
pub fn opaque(self) -> NodeSpecific
{
self.into()
}
}
#[derive(Debug, Clone, Copy)]
#[repr(transparent)]
pub(in crate::node) struct ScalarDataRef<'a, 'de>
{
data: &'a NodeData<'de>,
}
impl<'a, 'de> ScalarDataRef<'a, 'de>
{
fn new(data: &'a NodeData<'de>) -> Self
{
Self { data }
}
pub const fn anchor(&self) -> Option<&Slice<'de>>
{
self.data.anchor.as_ref()
}
pub const fn tag(&self) -> Option<&Tag<'de>>
{
self.data.tag.as_ref()
}
pub const fn context(&self) -> &NodeContext
{
&self.data.context
}
pub const fn mark(&self) -> &NodeMark
{
&self.data.mark
}
pub fn style(&self) -> &ScalarStyle
{
&self.scalar().style
}
fn scalar(&self) -> &ScalarData
{
use NodeSpecific::Scalar;
match self.data.node_specific
{
Scalar(ref s) => s,
_ => unreachable!(),
}
}
}
#[derive(Debug)]
#[repr(transparent)]
pub(in crate::node) struct ScalarDataMut<'a, 'de>
{
data: &'a mut NodeData<'de>,
}
impl<'a, 'de> ScalarDataMut<'a, 'de>
{
fn new(data: &'a mut NodeData<'de>) -> Self
{
let mut this = Self { data };
let _assert = this.scalar();
this
}
pub fn anchor(&mut self) -> Option<&mut Slice<'de>>
{
self.data.anchor.as_mut()
}
pub fn tag(&mut self) -> Option<&mut Tag<'de>>
{
self.data.tag.as_mut()
}
pub fn context(&mut self) -> &mut NodeContext
{
&mut self.data.context
}
pub fn mark(&mut self) -> &mut NodeMark
{
&mut self.data.mark
}
pub fn style(&mut self) -> &mut ScalarStyle
{
&mut self.scalar().style
}
fn scalar(&mut self) -> &mut ScalarData
{
use NodeSpecific::Scalar;
match self.data.node_specific
{
Scalar(ref mut s) => s,
_ => unreachable!(),
}
}
}

View File

@ -0,0 +1,80 @@
/*
* This Source Code Form is subject to the terms of the
* Mozilla Public License, v. 2.0. If a copy of the MPL
* was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
use crate::node::nodes::{NodeIndex, NodeSpecific};
pub(in crate::node) type Children = Vec<NodeIndex>;
pub(in crate::node) struct SequenceNode
{
parent: Option<NodeIndex>,
id: NodeIndex,
children: Children,
}
impl SequenceNode
{
pub fn root(id: NodeIndex) -> Self
{
Self::with_parent(id, None)
}
pub fn new(id: NodeIndex, parent: NodeIndex) -> Self
{
Self::with_parent(id, Some(parent))
}
pub fn root_with() -> impl FnOnce(NodeIndex) -> SequenceNode
{
move |id| Self::root(id)
}
pub fn new_with(parent: NodeIndex) -> impl FnOnce(NodeIndex) -> SequenceNode
{
move |id| Self::new(id, parent)
}
pub fn id(&self) -> NodeIndex
{
self.id
}
pub fn parent(&self) -> Option<NodeIndex>
{
self.parent
}
pub fn children(&self) -> &Children
{
&self.children
}
pub fn children_mut(&mut self) -> &mut Children
{
&mut self.children
}
fn with_parent(id: NodeIndex, parent: Option<NodeIndex>) -> Self
{
Self {
parent,
id,
children: Default::default(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(in crate::node) struct SequenceData;
impl SequenceData
{
pub fn opaque(self) -> NodeSpecific
{
self.into()
}
}