openapi_nexus/ir/types/schema.rs
1//! Schema types — the core of the IR's type system.
2
3use indexmap::IndexMap;
4use serde::Serialize;
5
6use super::type_expr::{IrTypeExpr, IrValidation};
7
8/// A named schema in the IR. Every schema has a name (its key in `IrSpec.schemas`),
9/// optional metadata, and a classified kind.
10#[derive(Debug, Clone, Serialize)]
11pub struct IrSchema {
12 pub name: String,
13 pub description: Option<String>,
14 pub deprecated: bool,
15 pub kind: IrSchemaKind,
16 /// Whether this schema originated from `components/schemas` (true) or was
17 /// promoted from an inline definition in operations/responses (false).
18 pub is_component: bool,
19}
20
21/// Pre-classified schema kind. The lowering pass determines this once;
22/// generators match on it directly instead of re-interpreting raw spec fields.
23#[derive(Debug, Clone, Serialize)]
24pub enum IrSchemaKind {
25 /// An object with named properties and optional additional properties.
26 Object(IrObject),
27 /// A typed enumeration.
28 Enum(IrEnum),
29 /// A discriminated union (oneOf with a discriminator field).
30 TaggedUnion(IrTaggedUnion),
31 /// An untagged union (oneOf/anyOf without a discriminator).
32 Union(IrUnion),
33 /// An intersection type (allOf).
34 Intersection(IrIntersection),
35 /// A type alias — wraps a single type expression.
36 Alias(IrTypeExpr),
37}
38
39// ---------------------------------------------------------------------------
40// Object
41// ---------------------------------------------------------------------------
42
43#[derive(Debug, Clone, Serialize)]
44pub struct IrObject {
45 pub properties: IndexMap<String, IrProperty>,
46 pub additional_properties: Option<IrTypeExpr>,
47}
48
49#[derive(Debug, Clone, Serialize)]
50pub struct IrProperty {
51 pub name: String,
52 pub type_expr: IrTypeExpr,
53 pub required: bool,
54 pub nullable: bool,
55 pub description: Option<String>,
56 pub default_value: Option<serde_json::Value>,
57 pub format: Option<String>,
58 pub validation: Option<IrValidation>,
59}
60
61// ---------------------------------------------------------------------------
62// Enum
63// ---------------------------------------------------------------------------
64
65#[derive(Debug, Clone, Serialize)]
66pub struct IrEnum {
67 pub value_type: IrEnumValueType,
68 pub values: Vec<IrEnumValue>,
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
72pub enum IrEnumValueType {
73 String,
74 Integer,
75 Number,
76 /// Mixed types (e.g. string + integer).
77 Mixed,
78}
79
80#[derive(Debug, Clone, Serialize)]
81pub struct IrEnumValue {
82 pub value: serde_json::Value,
83 pub description: Option<String>,
84}
85
86// ---------------------------------------------------------------------------
87// Tagged Union (discriminated)
88// ---------------------------------------------------------------------------
89
90#[derive(Debug, Clone, Serialize)]
91pub struct IrTaggedUnion {
92 pub discriminator_field: String,
93 pub tagging: TaggingStyle,
94 pub variants: Vec<IrTaggedVariant>,
95}
96
97#[derive(Debug, Clone, Serialize)]
98pub enum TaggingStyle {
99 /// Tag is a property inside the object itself (`allOf[$ref, { tag: enum }]`).
100 Internal,
101 /// Tag and content are separate fields.
102 Adjacent { content_field: String },
103 /// The key in a wrapping object determines the variant.
104 External,
105}
106
107#[derive(Debug, Clone, Serialize)]
108pub struct IrTaggedVariant {
109 pub discriminator_value: String,
110 pub content_type: IrTypeExpr,
111 pub description: Option<String>,
112}
113
114// ---------------------------------------------------------------------------
115// Union (untagged)
116// ---------------------------------------------------------------------------
117
118#[derive(Debug, Clone, Serialize)]
119pub struct IrUnion {
120 pub members: Vec<IrTypeExpr>,
121 /// Whether the union also includes null (e.g., `anyOf: [string, number, null]`).
122 pub nullable: bool,
123}
124
125// ---------------------------------------------------------------------------
126// Intersection (allOf)
127// ---------------------------------------------------------------------------
128
129#[derive(Debug, Clone, Serialize)]
130pub struct IrIntersection {
131 pub members: Vec<IrTypeExpr>,
132}