Skip to main content

rustev_contract/
parameter.rs

1//! Template-only shapes (spec 034, 3.1 to 3.4). Core checks declaration
2//! bounds, locks and site compatibility before substituting JSON values.
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6pub const MAX_PARAMETERS: usize = 256;
7pub const MAX_VARIANTS: usize = 16;
8pub const MAX_REFERENCE_SITES: usize = 4096;
9pub const MIN_TEXT_BYTES: usize = 1;
10pub const MAX_TEXT_BYTES: usize = 65_536;
11pub const MIN_ITEMS: usize = 1;
12pub const MAX_ITEMS: usize = 4096;
13pub const MIN_ENUM_OPTIONS: usize = 1;
14pub const MAX_ENUM_OPTIONS: usize = 256;
15pub const MIN_RECORD_FIELDS: usize = 1;
16pub const MAX_RECORD_FIELDS: usize = 64;
17
18/// The ASCII name grammar of spec 034, 3.1.3.
19pub fn is_parameter_name(s: &str) -> bool {
20    (1..=64).contains(&s.len())
21        && s.as_bytes()[0].is_ascii_lowercase()
22        && s.bytes()
23            .all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'_')
24}
25/// Variant names use the same grammar (spec 034, 3.1.3).
26pub fn is_variant_name(s: &str) -> bool {
27    is_parameter_name(s)
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
31#[serde(deny_unknown_fields)]
32pub struct ParameterDecl {
33    pub name: String,
34    #[serde(rename = "type")]
35    pub ty: ParamType,
36    pub lock: Lock,
37    pub bounds: Bounds,
38    pub default: ParamDefault,
39}
40
41/// Exact external tags from spec 034, 3.2.1.
42#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
43#[serde(rename_all = "snake_case", deny_unknown_fields)]
44pub enum ParamType {
45    Bool,
46    Integer,
47    Decimal,
48    Timestamp,
49    DurationMs,
50    Text {
51        max_bytes: usize,
52    },
53    Enum {
54        options: Vec<String>,
55    },
56    List {
57        item: Box<ParamType>,
58        max_items: usize,
59    },
60    Set {
61        item: Box<ParamType>,
62        max_items: usize,
63    },
64    Record {
65        fields: Vec<ParamField>,
66    },
67}
68#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
69#[serde(deny_unknown_fields)]
70pub struct ParamField {
71    pub name: String,
72    #[serde(rename = "type")]
73    pub ty: ParamType,
74}
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
76#[serde(rename_all = "snake_case", deny_unknown_fields)]
77pub enum Lock {
78    Fixed,
79    Bounded,
80    Free,
81}
82
83/// Bounds shapes (spec 034, 3.2.1). `unique_items` defaults to false and
84/// is always written, including false, in canonical bytes.
85#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
86#[serde(rename_all = "snake_case", deny_unknown_fields)]
87pub enum Bounds {
88    None,
89    Range([Value; 2]),
90    OneOf(Vec<Value>),
91    List {
92        item: Box<Bounds>,
93        min_items: usize,
94        max_items: usize,
95        #[serde(default)]
96        unique_items: bool,
97    },
98    Set {
99        min_items: usize,
100        max_items: usize,
101        must_include: Vec<Value>,
102    },
103    Record {
104        fields: Vec<BoundField>,
105    },
106}
107#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
108#[serde(deny_unknown_fields)]
109pub struct BoundField {
110    pub name: String,
111    pub bounds: Bounds,
112}
113#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
114#[serde(rename_all = "snake_case", deny_unknown_fields)]
115pub enum ParamDefault {
116    None,
117    Value(Value),
118}
119
120/// Exactly one member (spec 034, 3.3.1).
121#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
122#[serde(deny_unknown_fields)]
123pub struct ParamRef {
124    pub param: String,
125}
126/// Optional-item control (spec 034, 3.4.3).
127#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
128#[serde(untagged)]
129pub enum Enabled {
130    Bool(bool),
131    Param(ParamRef),
132}