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