Skip to content

RuleEdits

Namespace Nfty.Core.Editing in assembly Nfty.Core.

public static class RuleEdits

Authoring for a recipe's incompatibility rules: add, replace, remove. Pure — every method returns a NEW RecipeManifest and mutates nothing, the same shape LayerDepth and CookBookEdits use, so a caller can hold the previous manifest for undo without defensive copying.

Until this existed a rule could not be created or edited anywhere in the product — not in the GUI, not in the CLI. Every creation path wrote an empty rule list, and the only way a recipe got a rule was hand-editing the manifest JSON inside the archive.

A rule is addressed by INDEX, not by an id, because the manifest has no rule id and adding a required one would be a real schema migration for a field that buys nothing at generation time. The index is the position in RecipeManifest.Rules, which is stable for as long as the caller holds one manifest — which is exactly how long an edit lasts.

Methods

Add(RecipeManifest, IncompatibilityRule)

public static RecipeManifest Add(RecipeManifest recipe, IncompatibilityRule rule);

Appends a rule.

Parameters

  • recipe (RecipeManifest) - The recipe to add to.
  • rule (IncompatibilityRule) - The rule. Rejected if degenerate (see RuleEdits.Validate()) or if the recipe already carries the same one.

Returns. A new manifest with the rule appended.

Exceptions

  • ArgumentException - The rule is degenerate or a duplicate.

AreSame(IncompatibilityRule, IncompatibilityRule)

public static bool AreSame(IncompatibilityRule a, IncompatibilityRule b);

Whether two rules constrain the same thing. Targets compare as a SET: a rule's targets are evaluated as a conjunction, so listing them in a different order is the same rule written twice, and duplicate detection that missed that would be no detection at all.

Parameters

  • a (IncompatibilityRule) - One rule.
  • b (IncompatibilityRule) - The other.

Returns. True when they are the same constraint.

RemoveAt(RecipeManifest, int)

public static RecipeManifest RemoveAt(RecipeManifest recipe, int index);

Removes the rule at index.

Parameters

  • recipe (RecipeManifest) - The recipe to edit.
  • index (int) - Zero-based position in RecipeManifest.Rules.

Returns. A new manifest without it. Every later rule shifts down one, which is why a caller holding indexes across a removal must re-read them.

Exceptions

  • ArgumentOutOfRangeException - No rule at that index.

ReplaceAt(RecipeManifest, int, IncompatibilityRule)

public static RecipeManifest ReplaceAt(RecipeManifest recipe, int index, IncompatibilityRule rule);

Replaces the rule at index.

Parameters

  • recipe (RecipeManifest) - The recipe to edit.
  • index (int) - Zero-based position in RecipeManifest.Rules.
  • rule (IncompatibilityRule) - The replacement.

Returns. A new manifest with that one rule swapped, every other rule and its position untouched.

Exceptions

  • ArgumentOutOfRangeException - No rule at that index.
  • ArgumentException - The rule is degenerate, or duplicates a DIFFERENT rule in the same recipe — replacing a rule with itself is allowed, since that is what an edit that changes nothing looks like.

Validate(IncompatibilityRule)

public static void Validate(IncompatibilityRule rule);

Rejects a rule that cannot mean anything. This is the authoring half of a pair: Validator reports the same two shapes on a book that already has them, since before this class existed a rule could only be written by hand and a hand-written one can be anything. Refusing to WRITE one costs nothing; refusing to COOK one is justified because each silently changes the size of the DNA space.

Parameters

  • rule (IncompatibilityRule) - The rule to check.

Exceptions

  • ArgumentException - The rule is degenerate.