presolve_compiler/
runtime_form_registry.rs1use crate::{
3 FieldId, FormEntity, FormFieldBinding, FormFieldEntity, FormId, FormInstanceId, FormIrReport,
4 FormSerializationPlan, FormSubmissionPlan, ResetProducts, SerializationProducts,
5 SubmissionHost, SubmissionHostId, SubmissionProducts, ValidationRule, ValidationRuleId,
6};
7use std::collections::BTreeMap;
8pub const RUNTIME_FORM_REGISTRY_VERSION: u32 = 1;
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct RuntimeFormRecord {
11 pub form: FormId,
12 pub fields: Vec<FieldId>,
13 pub submission: Option<FormSubmissionPlan>,
14 pub serialization: Option<FormSerializationPlan>,
15}
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct RuntimeFormInstanceRecord {
18 pub instance: FormInstanceId,
19 pub form: FormId,
20 pub programs: usize,
21}
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct RuntimeFormRegistry {
24 pub version: u32,
25 pub forms: BTreeMap<FormId, RuntimeFormRecord>,
26 pub instances: BTreeMap<FormInstanceId, RuntimeFormInstanceRecord>,
27 pub bindings: Vec<FormFieldBinding>,
28 pub rules: BTreeMap<ValidationRuleId, ValidationRule>,
29 pub reset: ResetProducts,
30 pub hosts: BTreeMap<SubmissionHostId, SubmissionHost>,
31}
32#[must_use]
33#[allow(clippy::too_many_arguments)]
34pub fn build_runtime_form_registry(
35 forms: &BTreeMap<FormId, FormEntity>,
36 fields: &BTreeMap<FieldId, FormFieldEntity>,
37 bindings: &BTreeMap<crate::FieldBindingId, FormFieldBinding>,
38 rules: &BTreeMap<ValidationRuleId, ValidationRule>,
39 ir: &FormIrReport,
40 submissions: &SubmissionProducts,
41 serialization: &SerializationProducts,
42 reset: &ResetProducts,
43 hosts: &BTreeMap<SubmissionHostId, SubmissionHost>,
44) -> RuntimeFormRegistry {
45 let forms = forms
46 .values()
47 .map(|form| {
48 let mut ids = fields
49 .values()
50 .filter(|f| f.owner_form == form.id)
51 .collect::<Vec<_>>();
52 ids.sort_by_key(|f| f.declaration_order);
53 (
54 form.id.clone(),
55 RuntimeFormRecord {
56 form: form.id.clone(),
57 fields: ids.into_iter().map(|f| f.id.clone()).collect(),
58 submission: submissions
59 .plans
60 .get(&crate::SubmissionPlanId::for_form(&form.id))
61 .cloned(),
62 serialization: serialization
63 .plans
64 .get(&crate::SerializationPlanId::for_form(&form.id))
65 .cloned(),
66 },
67 )
68 })
69 .collect();
70 let instances = ir
71 .instances
72 .values()
73 .map(|instance| {
74 (
75 instance.id.clone(),
76 RuntimeFormInstanceRecord {
77 instance: instance.id.clone(),
78 form: instance.form.clone(),
79 programs: instance.input.len() + instance.blur.len() + 1,
80 },
81 )
82 })
83 .collect();
84 RuntimeFormRegistry {
85 version: RUNTIME_FORM_REGISTRY_VERSION,
86 forms,
87 instances,
88 bindings: bindings.values().cloned().collect(),
89 rules: rules.clone(),
90 reset: reset.clone(),
91 hosts: hosts.clone(),
92 }
93}
94#[cfg(test)]
95mod tests {
96 #[test]
97 fn is_versioned_and_instance_qualified() {
98 let parsed = presolve_parser::parse_file(
99 "src/X.tsx",
100 r#"@component("x")class X{@form()form!:Form;@field(this.form)value="";render(){return <input field={this.value}/>;}}"#,
101 );
102 let asm = crate::build_application_semantic_model(&parsed);
103 assert_eq!(asm.runtime_forms.version, 1);
104 assert!(asm
105 .runtime_forms
106 .instances
107 .values()
108 .all(|r| asm.runtime_forms.forms.contains_key(&r.form)));
109 }
110}