Skip to main content

cratestack_core/schema/
model.rs

1//! Model / mixin / type / enum / field IR nodes parsed out of a
2//! `.cstack` file. Every IR node carries [`SourceSpan`] back-pointers
3//! so consumers (parser, LSP, generators) can map errors to source
4//! positions.
5
6use serde::{Deserialize, Serialize};
7
8use super::SourceSpan;
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11pub struct Model {
12    pub docs: Vec<String>,
13    pub name: String,
14    pub name_span: SourceSpan,
15    pub fields: Vec<Field>,
16    pub attributes: Vec<Attribute>,
17    pub span: SourceSpan,
18}
19
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21pub struct MixinDecl {
22    pub docs: Vec<String>,
23    pub name: String,
24    pub name_span: SourceSpan,
25    pub fields: Vec<Field>,
26    pub span: SourceSpan,
27}
28
29#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
30pub struct TypeDecl {
31    pub docs: Vec<String>,
32    pub name: String,
33    pub name_span: SourceSpan,
34    pub fields: Vec<Field>,
35    pub span: SourceSpan,
36}
37
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
39pub struct EnumDecl {
40    pub docs: Vec<String>,
41    pub name: String,
42    pub name_span: SourceSpan,
43    pub variants: Vec<EnumVariant>,
44    pub span: SourceSpan,
45}
46
47#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
48pub struct EnumVariant {
49    pub docs: Vec<String>,
50    pub name: String,
51    pub span: SourceSpan,
52}
53
54#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
55pub struct Field {
56    pub docs: Vec<String>,
57    pub name: String,
58    pub name_span: SourceSpan,
59    pub ty: TypeRef,
60    pub attributes: Vec<Attribute>,
61    pub span: SourceSpan,
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
65pub struct TypeRef {
66    pub name: String,
67    pub name_span: SourceSpan,
68    pub arity: TypeArity,
69    pub generic_args: Vec<TypeRef>,
70    /// Compile-time integer literal arguments to a parametric scalar
71    /// type, e.g. the `1536` in `Vector(1536)`. Empty for every type
72    /// that isn't parametric — currently only `Vector(n)` populates
73    /// this (see `docs/design/extensions.md` §6). `#[serde(default)]`
74    /// keeps deserialization of migration snapshots written before
75    /// this field existed working unchanged.
76    #[serde(default)]
77    pub int_args: Vec<u32>,
78}
79
80impl TypeRef {
81    pub fn is_page(&self) -> bool {
82        self.name == "Page"
83    }
84
85    pub fn page_item(&self) -> Option<&TypeRef> {
86        if self.is_page() {
87            self.generic_args.first()
88        } else {
89            None
90        }
91    }
92
93    pub fn is_page_input(&self) -> bool {
94        self.name == "PageInput"
95    }
96
97    pub fn is_find_many(&self) -> bool {
98        self.name == "FindMany"
99    }
100
101    pub fn find_many_item(&self) -> Option<&TypeRef> {
102        if self.is_find_many() {
103            self.generic_args.first()
104        } else {
105            None
106        }
107    }
108
109    pub fn is_vector(&self) -> bool {
110        self.name == "Vector"
111    }
112
113    /// The `n` in `Vector(n)`, if this is a well-formed vector type
114    /// reference (exactly one integer argument). Validation
115    /// (`cratestack-parser`) is responsible for rejecting any other
116    /// shape before this is relied upon by codegen.
117    pub fn vector_dim(&self) -> Option<u32> {
118        if self.is_vector() {
119            self.int_args.first().copied()
120        } else {
121            None
122        }
123    }
124}
125
126#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
127pub enum TypeArity {
128    Required,
129    Optional,
130    List,
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
134pub struct Attribute {
135    pub raw: String,
136    pub span: SourceSpan,
137}