json_schema.rs

 1use schemars::schema::{ArrayValidation, InstanceType, RootSchema, Schema, SchemaObject};
 2use serde_json::Value;
 3
 4pub struct SettingsJsonSchemaParams<'a> {
 5    pub language_names: &'a [String],
 6    pub font_names: &'a [String],
 7}
 8
 9impl<'a> SettingsJsonSchemaParams<'a> {
10    pub fn font_family_schema(&self) -> Schema {
11        let available_fonts: Vec<_> = self.font_names.iter().cloned().map(Value::String).collect();
12
13        SchemaObject {
14            instance_type: Some(InstanceType::String.into()),
15            enum_values: Some(available_fonts),
16            ..Default::default()
17        }
18        .into()
19    }
20
21    pub fn font_fallback_schema(&self) -> Schema {
22        SchemaObject {
23            instance_type: Some(InstanceType::Array.into()),
24            array: Some(Box::new(ArrayValidation {
25                items: Some(schemars::schema::SingleOrVec::Single(Box::new(
26                    self.font_family_schema(),
27                ))),
28                unique_items: Some(true),
29                ..Default::default()
30            })),
31            ..Default::default()
32        }
33        .into()
34    }
35}
36
37type PropertyName<'a> = &'a str;
38type ReferencePath<'a> = &'a str;
39
40/// Modifies the provided [`RootSchema`] by adding references to all of the specified properties.
41///
42/// # Examples
43///
44/// ```
45/// # let root_schema = RootSchema::default();
46/// add_references_to_properties(&mut root_schema, &[
47///     ("property_a", "#/definitions/DefinitionA"),
48///     ("property_b", "#/definitions/DefinitionB"),
49/// ])
50/// ```
51pub fn add_references_to_properties(
52    root_schema: &mut RootSchema,
53    properties_with_references: &[(PropertyName, ReferencePath)],
54) {
55    for (property, definition) in properties_with_references {
56        let Some(schema) = root_schema.schema.object().properties.get_mut(*property) else {
57            log::warn!("property '{property}' not found in JSON schema");
58            continue;
59        };
60
61        match schema {
62            Schema::Object(schema) => {
63                schema.reference = Some(definition.to_string());
64            }
65            Schema::Bool(_) => {
66                // Boolean schemas can't have references.
67            }
68        }
69    }
70}