ploidy_core/ir/views/
struct_.rs

1use petgraph::graph::NodeIndex;
2
3use crate::ir::{
4    graph::{IrGraph, IrGraphNode},
5    types::{IrStruct, IrStructField, IrStructFieldName},
6};
7
8use super::{ViewNode, ir::IrTypeView};
9
10/// A graph-aware view of an [`IrStruct`].
11#[derive(Debug)]
12pub struct IrStructView<'a> {
13    graph: &'a IrGraph<'a>,
14    index: NodeIndex,
15    ty: &'a IrStruct<'a>,
16}
17
18impl<'a> IrStructView<'a> {
19    pub(in crate::ir) fn new(
20        graph: &'a IrGraph<'a>,
21        index: NodeIndex,
22        ty: &'a IrStruct<'a>,
23    ) -> Self {
24        Self { graph, index, ty }
25    }
26
27    #[inline]
28    pub fn description(&self) -> Option<&'a str> {
29        self.ty.description
30    }
31
32    /// Returns an iterator over this struct's fields.
33    #[inline]
34    pub fn fields(&self) -> impl Iterator<Item = IrStructFieldView<'_, 'a>> {
35        self.ty.fields.iter().map(move |field| IrStructFieldView {
36            parent: self,
37            field,
38        })
39    }
40}
41
42impl<'a> ViewNode<'a> for IrStructView<'a> {
43    #[inline]
44    fn graph(&self) -> &'a IrGraph<'a> {
45        self.graph
46    }
47
48    #[inline]
49    fn index(&self) -> NodeIndex {
50        self.index
51    }
52}
53
54/// A graph-aware view of an [`IrStructField`].
55#[derive(Debug)]
56pub struct IrStructFieldView<'view, 'a> {
57    parent: &'view IrStructView<'a>,
58    field: &'a IrStructField<'a>,
59}
60
61impl<'view, 'a> IrStructFieldView<'view, 'a> {
62    #[inline]
63    pub fn name(&self) -> IrStructFieldName<'a> {
64        self.field.name
65    }
66
67    /// Returns a view of the inner type that this type wraps.
68    #[inline]
69    pub fn ty(&self) -> IrTypeView<'a> {
70        let node = IrGraphNode::from_ref(self.parent.graph.spec, self.field.ty.as_ref());
71        IrTypeView::new(self.parent.graph, self.parent.graph.indices[&node])
72    }
73
74    #[inline]
75    pub fn required(&self) -> bool {
76        self.field.required
77    }
78
79    #[inline]
80    pub fn description(&self) -> Option<&'a str> {
81        self.field.description
82    }
83
84    #[inline]
85    pub fn discriminator(&self) -> bool {
86        self.field.discriminator
87    }
88
89    #[inline]
90    pub fn flattened(&self) -> bool {
91        self.field.flattened
92    }
93
94    /// Returns `true` if this field needs indirection to break a cycle.
95    pub fn needs_indirection(&self) -> bool {
96        let node = IrGraphNode::from_ref(self.parent.graph.spec, self.field.ty.as_ref());
97        let index = self.parent.graph.indices[&node];
98        self.parent
99            .graph
100            .circular_refs
101            .contains(&(self.parent.index, index))
102    }
103}