use petgraph::graph::NodeIndex;
use crate::ir::{
graph::CookedGraph,
types::{GraphContainer, GraphInlineType, GraphSchemaType, GraphType},
};
use super::{TypeView, ViewNode};
#[derive(Debug)]
pub enum ContainerView<'a> {
Array(InnerView<'a>),
Map(InnerView<'a>),
Optional(InnerView<'a>),
}
impl<'a> ContainerView<'a> {
#[inline]
pub fn ty(&self) -> TypeView<'a> {
TypeView::new(self.cooked(), self.index())
}
}
impl<'a> ViewNode<'a> for ContainerView<'a> {
#[inline]
fn cooked(&self) -> &'a CookedGraph<'a> {
let (Self::Array(c) | Self::Map(c) | Self::Optional(c)) = self;
c.cooked
}
#[inline]
fn index(&self) -> NodeIndex<usize> {
let (Self::Array(c) | Self::Map(c) | Self::Optional(c)) = self;
c.container
}
}
#[derive(Debug)]
pub struct InnerView<'a> {
cooked: &'a CookedGraph<'a>,
container: NodeIndex<usize>,
inner: NodeIndex<usize>,
}
impl<'a> InnerView<'a> {
#[inline]
pub fn ty(&self) -> TypeView<'a> {
TypeView::new(self.cooked, self.inner)
}
#[inline]
pub fn description(&self) -> Option<&'a str> {
match self.cooked.graph[self.container] {
GraphType::Schema(GraphSchemaType::Container(_, container))
| GraphType::Inline(GraphInlineType::Container(_, container)) => {
container.inner().description
}
_ => None,
}
}
}
impl<'a> ContainerView<'a> {
#[inline]
pub(in crate::ir) fn new(
cooked: &'a CookedGraph<'a>,
index: NodeIndex<usize>,
container: GraphContainer<'a>,
) -> Self {
let inner = InnerView {
cooked,
container: index,
inner: container.inner().ty,
};
match container {
GraphContainer::Array(_) => Self::Array(inner),
GraphContainer::Map(_) => Self::Map(inner),
GraphContainer::Optional(_) => Self::Optional(inner),
}
}
#[inline]
pub fn dependencies(&self) -> impl Iterator<Item = TypeView<'a>> + use<'a> {
let (Self::Array(view) | Self::Map(view) | Self::Optional(view)) = self;
let inner = TypeView::new(view.cooked, view.inner);
let dependencies = inner.dependencies();
std::iter::once(inner).chain(dependencies)
}
}