diff --git a/crates/engine/src/schema/plastic.rs b/crates/engine/src/schema/plastic.rs index 24d16a2f47..232c4473b2 100644 --- a/crates/engine/src/schema/plastic.rs +++ b/crates/engine/src/schema/plastic.rs @@ -117,15 +117,27 @@ fn rule_name_schema(_: &mut SchemaGenerator) -> Schema { #[schemars(deny_unknown_fields, transform = bodies_required)] pub struct AssignRuleParams { /// The bodies, by name: 1 to 10 000. - // Optional in the type, required in the schema: left out or empty, the handler refuses the - // call with its own message. + // Optional in the type, required in the schema: left out, `null` or empty, the handler + // refuses the call with its own message, so the schema allows none of those. #[serde(default)] + #[schemars(schema_with = "bodies_schema")] pub bodies: Option, /// The rule, by name, as `plastic.rules` lists it. Empty or left out: the bodies have no /// rule of their own, so the active rule applies. pub rule: Option, } +/// `bodies` as `plastic.assign_rule` takes it: a name, or a list of 1 to 10 000 names. Not +/// `NameList`'s own schema, which allows the empty list the handler refuses. +fn bodies_schema(_: &mut SchemaGenerator) -> Schema { + json_schema!({ + "anyOf": [ + {"type": "string"}, + {"type": "array", "items": {"type": "string"}, "minItems": 1, "maxItems": crate::params::MAX_STRING_LIST} + ] + }) +} + /// List the plastic rules (the library's and the design's), the active rule and the rules /// assigned to bodies. No parameters. #[derive(Debug, Deserialize, JsonSchema)] diff --git a/crates/engine/src/schema/plastic_tests.rs b/crates/engine/src/schema/plastic_tests.rs index 9ba62e2227..d4e14f49b2 100644 --- a/crates/engine/src/schema/plastic_tests.rs +++ b/crates/engine/src/schema/plastic_tests.rs @@ -93,7 +93,7 @@ fn the_contracts_refuse_what_the_handlers_ignore() { /// #12313: the schemas take what the handlers read: a rule's name as text, its values as /// numbers or expressions, `active` and `delete` as true or false; bodies as a name or a list of -/// names, and the rule as text or `null`. +/// one or more names (not `null`), and the rule as text or `null`. #[test] fn the_schemas_take_what_the_handlers_read() { let manage = input_schema_for::(); @@ -119,6 +119,8 @@ fn the_schemas_take_what_the_handlers_read() { (json!({"bodies": ["Body1"], "rule": null}), true), (json!({}), false), (json!({"bodies": [5]}), false), + (json!({"bodies": null}), false), + (json!({"bodies": []}), false), (json!({"bodies": ["Body1"], "rule": 5}), false), ] { assert_eq!(conforms(assign, assign, &p), takes, "{p}");