1mod base_schema;
4#[cfg(feature = "bench-support")]
5pub mod bench_support;
6mod condition_encoding;
7mod emission_plan;
8mod emission_policy;
9mod emission_report;
10mod foreign_schema;
11mod merge;
12mod overlay_lowering;
13mod path_resolver;
14mod path_schema;
15mod program_wrapper;
16mod provider_definitions;
17mod provider_requirement_synthesis;
18mod provider_schema;
19mod quoted_serialization;
20pub mod required_inference;
21mod requirement_domain;
22mod resolve_policy;
23mod schema_model;
24mod schema_node;
25mod schema_tree;
26mod values_yaml;
27
28use std::collections::{BTreeMap, BTreeSet};
29
30use helm_schema_core::{ContractSchemaSignals, ResourceSchemaOracle};
31use serde_json::Value;
32use serde_yaml::Value as YamlValue;
33
34pub(crate) use emission_plan::CompletionPass;
35use emission_plan::LoweredEmissionPlan;
36pub use emission_policy::{
37 ConditionalAnchors, EmissionClassKind, EmissionOrigin, EmissionPolicy, EmissionPolicyDelta,
38 EmissionSelection, InvalidEmissionPolicy, POLICY_VOCABULARY_VERSION, ResolvedEmissionPolicy,
39 SchemaProfile,
40};
41pub use emission_report::{
42 CanonicalizationCounts, CarrierCounts, EmissionReport, FactCounts, InsertionAbstentionCounts,
43 MandatoryOutcomes,
44};
45
46#[derive(Debug, Clone, PartialEq)]
48pub struct PreparedValuesDocuments {
49 composed: YamlValue,
50 dependency: YamlValue,
51 dependency_refill: YamlValue,
52}
53
54impl PreparedValuesDocuments {
55 #[must_use]
57 pub fn new(composed: YamlValue, dependency: YamlValue, dependency_refill: YamlValue) -> Self {
58 Self {
59 composed,
60 dependency,
61 dependency_refill,
62 }
63 }
64}
65
66#[derive(Clone, Copy)]
73pub struct ValuesSchemaInput<'a> {
74 pub contract_schema_signals: &'a ContractSchemaSignals,
76 pub provider: &'a dyn ResourceSchemaOracle,
78 pub values_documents: Option<&'a PreparedValuesDocuments>,
95 pub shadowed_input_paths: Option<&'a BTreeSet<String>>,
99 pub values_descriptions: Option<&'a BTreeMap<String, String>>,
101 pub emission_policy: EmissionPolicy,
103}
104
105impl<'a> ValuesSchemaInput<'a> {
106 pub fn new(
108 contract_schema_signals: &'a ContractSchemaSignals,
109 provider: &'a dyn ResourceSchemaOracle,
110 ) -> Self {
111 Self {
112 contract_schema_signals,
113 provider,
114 values_documents: None,
115 shadowed_input_paths: None,
116 values_descriptions: None,
117 emission_policy: SchemaProfile::Full.resolved_policy().policy(),
118 }
119 }
120
121 #[must_use]
123 pub fn with_values_documents(mut self, values_documents: &'a PreparedValuesDocuments) -> Self {
124 self.values_documents = Some(values_documents);
125 self
126 }
127
128 #[must_use]
130 pub fn with_shadowed_input_paths(mut self, shadowed_input_paths: &'a BTreeSet<String>) -> Self {
131 self.shadowed_input_paths = Some(shadowed_input_paths);
132 self
133 }
134
135 #[must_use]
137 pub fn with_values_descriptions(
138 mut self,
139 values_descriptions: &'a BTreeMap<String, String>,
140 ) -> Self {
141 self.values_descriptions = Some(values_descriptions);
142 self
143 }
144
145 #[must_use]
147 pub fn with_profile(mut self, profile: SchemaProfile) -> Self {
148 self.emission_policy = profile.resolved_policy().policy();
149 self
150 }
151
152 #[must_use]
154 pub fn with_emission_policy(mut self, policy: EmissionPolicy) -> Self {
155 self.emission_policy = policy;
156 self
157 }
158}
159
160#[tracing::instrument(skip_all)]
168pub fn generate_values_schema(input: ValuesSchemaInput<'_>) -> Value {
169 generate_values_schema_with_report(input).0
170}
171
172#[tracing::instrument(skip_all)]
177pub fn generate_values_schema_with_report(input: ValuesSchemaInput<'_>) -> (Value, EmissionReport) {
178 generate_values_schema_through(&input, CompletionPass::Descriptions)
179}
180
181fn generate_values_schema_through(
182 input: &ValuesSchemaInput<'_>,
183 completion_pass: CompletionPass,
184) -> (Value, EmissionReport) {
185 let plan = LoweredEmissionPlan::build(input);
186 let projected = plan.project(input.emission_policy);
187 let completed = plan.complete(projected, completion_pass);
188 (completed.schema, completed.emission_report)
189}
190
191pub(crate) fn runtime_iterable_schema(allow_integer: bool) -> serde_json::Value {
198 let mut types = vec!["array", "object"];
199 if allow_integer {
200 types.push("integer");
201 }
202 types.push("null");
203 crate::schema_model::type_union_schema(types)
204}
205
206pub(crate) use helm_schema_core::split_value_path;
207
208fn common_prefix_len(left: &[String], right: &[String]) -> usize {
209 left.iter()
210 .zip(right.iter())
211 .take_while(|(left, right)| left == right)
212 .count()
213}
214
215#[cfg(test)]
216#[path = "tests/mod.rs"]
217mod tests;