///|
/// Expand only when every referenced variable is bound. This opt-in policy is
/// useful for fixed SDK operations; ordinary RFC 6570 expansion allows missing
/// variables and remains available through `Template::expand`.
pub fn Template::expand_required(
  self : Template,
  bindings : Array[(String, Value)],
  reject_unused~ : Bool = false,
  max_output~ : Int32 = 1048576,
  max_bindings~ : Int32 = 4096,
  max_value_length~ : Int32 = 1048576,
  max_items~ : Int32 = 4096,
) -> Result[String, ExpandError] {
  if max_bindings < 0 || bindings.length() > max_bindings {
    return Err(TooManyBindings)
  }
  let required : Map[String, Bool] = Map([])
  for name in self.variables {
    required[name] = true
  }
  let supplied : Map[String, Bool] = Map([])
  for binding in bindings {
    let (name, _) = binding
    if supplied.contains(name) {
      return Err(DuplicateVariable(name))
    }
    supplied[name] = true
    if reject_unused && !required.contains(name) {
      return Err(UnusedVariable(name))
    }
  }
  for name in self.variables {
    if !supplied.contains(name) {
      return Err(MissingVariable(name))
    }
  }
  self.expand(
    bindings,
    max_output~,
    max_bindings~,
    max_value_length~,
    max_items~,
  )
}