node/nodes: add skeleton types for graph nodes
This commit is contained in:
parent
cfb7c7bdbc
commit
5581c28129
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue