Skip to main content

sim_shape/
options.rs

1//! Shape-backed validation for option maps.
2//!
3//! Option surfaces often start as runtime key/value pairs and then fan out into
4//! local typed readers. This module provides the shared structural check for the
5//! map shape before a consumer performs domain-specific parsing.
6
7use std::sync::Arc;
8
9use sim_kernel::{Cx, Expr, Result, Symbol};
10
11use crate::{Shape, ShapeMatch, TableExtraPolicy, TableFieldSpec, TableShape};
12
13/// One option field constraint for [`check_option_map`].
14pub struct OptionFieldSpec {
15    /// Symbol key to look up in the option map.
16    pub key: Symbol,
17    /// Shape that must accept the option value when present.
18    pub shape: Arc<dyn Shape>,
19    /// Whether this option must be present.
20    pub required: bool,
21}
22
23impl OptionFieldSpec {
24    /// Build a required option field.
25    pub fn required(key: Symbol, shape: Arc<dyn Shape>) -> Self {
26        Self {
27            key,
28            shape,
29            required: true,
30        }
31    }
32
33    /// Build an optional option field.
34    pub fn optional(key: Symbol, shape: Arc<dyn Shape>) -> Self {
35        Self {
36            key,
37            shape,
38            required: false,
39        }
40    }
41}
42
43/// Check an option-map expression against field specs and an extra-key policy.
44///
45/// This is intentionally a thin wrapper around [`TableShape`]: it gives option
46/// parsers a domain-named entry point while preserving the same match scoring,
47/// captures, and diagnostics as the table grammar.
48pub fn check_option_map(
49    cx: &mut Cx,
50    expr: &Expr,
51    fields: Vec<OptionFieldSpec>,
52    extra: TableExtraPolicy,
53) -> Result<ShapeMatch> {
54    let fields = fields
55        .into_iter()
56        .map(|field| TableFieldSpec {
57            key: field.key,
58            shape: field.shape,
59            required: field.required,
60        })
61        .collect();
62    TableShape::new(fields, extra).check_expr(cx, expr)
63}