Skip to main content

harn_vm/schema/
mod.rs

1use crate::value::VmValue;
2use std::collections::BTreeMap;
3
4mod api;
5mod canonicalize;
6mod result;
7mod transform;
8mod type_check;
9mod validate;
10
11pub(crate) use api::{
12    schema_assert_param, schema_expect_value, schema_extend_value, schema_from_json_schema_value,
13    schema_from_openapi_schema_value, schema_is_value, schema_omit_value, schema_partial_value,
14    schema_pick_value, schema_result_value, schema_to_json_schema_value,
15    schema_to_openapi_schema_value,
16};
17pub(crate) use canonicalize::json_to_vm_value;
18
19fn vm_value_to_serde_json(value: &VmValue) -> serde_json::Value {
20    match value {
21        VmValue::Nil => serde_json::Value::Null,
22        VmValue::Bool(value) => serde_json::Value::Bool(*value),
23        VmValue::Int(value) => serde_json::json!(value),
24        VmValue::Float(value) => serde_json::json!(value),
25        VmValue::String(value) => serde_json::Value::String(value.to_string()),
26        VmValue::List(items) | VmValue::Set(items) => {
27            serde_json::Value::Array(items.iter().map(vm_value_to_serde_json).collect())
28        }
29        VmValue::Dict(items) => serde_json::Value::Object(
30            items
31                .iter()
32                .map(|(key, value)| (key.clone(), vm_value_to_serde_json(value)))
33                .collect(),
34        ),
35        _ => serde_json::Value::String(value.display()),
36    }
37}
38
39fn schema_bool(schema: &BTreeMap<String, VmValue>, key: &str) -> bool {
40    matches!(schema.get(key), Some(VmValue::Bool(true)))
41}
42
43fn schema_i64(schema: &BTreeMap<String, VmValue>, key: &str) -> Option<i64> {
44    match schema.get(key) {
45        Some(VmValue::Int(value)) => Some(*value),
46        _ => None,
47    }
48}
49
50fn schema_number(schema: &BTreeMap<String, VmValue>, key: &str) -> Option<f64> {
51    match schema.get(key) {
52        Some(VmValue::Int(value)) => Some(*value as f64),
53        Some(VmValue::Float(value)) => Some(*value),
54        _ => None,
55    }
56}
57
58fn location_label(path: &str) -> String {
59    if path.is_empty() {
60        "root".to_string()
61    } else {
62        path.to_string()
63    }
64}
65
66fn child_path(path: &str, key: &str) -> String {
67    if path.is_empty() {
68        key.to_string()
69    } else {
70        format!("{}.{}", path, key)
71    }
72}
73
74fn index_path(path: &str, index: usize) -> String {
75    if path.is_empty() {
76        format!("[{}]", index)
77    } else {
78        format!("{}[{}]", path, index)
79    }
80}
81
82#[cfg(test)]
83mod tests;