comnum_spec/blocks/schema/
json_schema.rs1use super::{ParamDefault, ParamInfo};
4use crate::blocks::BlockInfo;
5use serde_json::{Map, Value as Json, json};
6use std::borrow::Borrow;
7
8pub fn object_schema(params: &[ParamInfo], fixed: &[(&str, Json)]) -> Map<String, Json> {
12 let mut props = Map::new();
13 let mut required: Vec<Json> = Vec::new();
14 for (k, v) in fixed {
15 props.insert((*k).into(), v.clone());
16 required.push(json!(k));
17 }
18 for p in params {
19 props.insert(p.name.into(), p.json_schema());
20 if matches!(p.default, ParamDefault::Required) {
21 required.push(json!(p.name));
22 }
23 }
24 let mut s = Map::new();
25 s.insert("type".into(), json!("object"));
26 s.insert("properties".into(), Json::Object(props));
27 s.insert("required".into(), Json::Array(required));
28 s.insert("additionalProperties".into(), json!(false));
29 s
30}
31
32pub fn variants_schema(variants: &[(&'static str, Vec<ParamInfo>)]) -> Json {
36 let one_of: Vec<Json> = variants
37 .iter()
38 .map(|(kind, params)| {
39 let mut s = object_schema(params, &[("type", json!({"const": kind}))]);
40 s.insert("title".into(), json!(kind));
41 Json::Object(s)
42 })
43 .collect();
44 json!({"type": "object", "oneOf": one_of})
45}
46
47pub fn json_schema<B: Borrow<BlockInfo>>(registry: &[B]) -> Json {
51 let mut alternatives = Vec::new();
52 for b in registry.iter().map(Borrow::borrow) {
53 let mut s = object_schema(&b.params, &[("type", json!({"const": b.name}))]);
54 if let Some(Json::Object(props)) = s.get_mut("properties") {
55 props.insert("label".into(), json!({"type": "string", "description": "prefix of the recorded values"}));
56 }
57 let only_type = s.get("required").and_then(Json::as_array).is_some_and(|r| r.len() == 1);
58 s.insert("title".into(), json!(b.name));
59 s.insert("description".into(), json!(b.summary));
60 s.insert("x-needs".into(), json!(b.needs.iter().map(|f| f.name()).collect::<Vec<_>>()));
61 s.insert("x-gives".into(), json!(b.gives.iter().map(|f| f.name()).collect::<Vec<_>>()));
62 s.insert("x-starts".into(), json!(b.starts));
63 alternatives.push(Json::Object(s));
64 if only_type {
65 alternatives.push(json!({"const": b.name, "description": b.summary}));
66 }
67 }
68 json!({
69 "$schema": "https://json-schema.org/draft/2020-12/schema",
70 "title": "comnum link block",
71 "oneOf": alternatives,
72 })
73}