Skip to content

Commit

Permalink
#776: Allow repeat-expr and repeat-until keys without a repeat key
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingun committed Jul 13, 2024
1 parent 983060d commit c0b9841
Showing 1 changed file with 47 additions and 29 deletions.
76 changes: 47 additions & 29 deletions shared/src/main/scala/io/kaitai/struct/format/RepeatSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,53 @@ object RepeatSpec {
val repeatExpr = ParseUtils.getOptValueExpression(srcMap, "repeat-expr", path)
val repeatUntil = ParseUtils.getOptValueExpression(srcMap, "repeat-until", path)

repeat match {
case None =>
(NoRepeat, Set())
case Some("until") =>
val spec = repeatUntil match {
case Some(expr) => RepeatUntil(expr)
case None =>
throw KSYParseError.withText(
"`repeat: until` requires a `repeat-until` expression",
path ++ List("repeat")
)
}
(spec, Set("repeat-until"))
case Some("expr") =>
val spec = repeatExpr match {
case Some(expr) => RepeatExpr(expr)
case None =>
throw KSYParseError.withText(
"`repeat: expr` requires a `repeat-expr` expression",
path ++ List("repeat")
)
}
(spec, Set("repeat-expr"))
case Some("eos") =>
(RepeatEos, Set())
case Some(other) =>
throw KSYParseError.badDictValue(
Set("until", "expr", "eos"), other, path ++ List("repeat")
)
val allowed = Set("until", "expr", "eos")

(repeat, repeatExpr, repeatUntil) match {
// Only `repeat-x: ...` or nothing
case (None, None, None) => (NoRepeat, Set())
case (None, Some(count), None) => (RepeatExpr(count), Set("repeat-expr"))
case (None, None, Some(until)) => (RepeatUntil(until), Set("repeat-until"))

// Both `repeat: x` and `repeat-x: ...`
case (Some("eos"), None, None) => (RepeatEos, Set())
case (Some("expr"), Some(count), None) => (RepeatExpr(count), Set("repeat-expr"))
case (Some("until"), None, Some(until)) => (RepeatUntil(until), Set("repeat-until"))

case (Some(other), _, _) if !allowed.contains(other) => throw KSYParseError.badDictValue(
allowed, other,
path ++ List("repeat")
)

// Only `repeat: x`
case (Some("eos"), Some(_), Some(_)) |
(Some("expr"), Some(_), Some(_)) |
(Some("until"), Some(_), Some(_)) => throw KSYParseError.withText(
"either `repeat: eos`, or `repeat-expr`, or `repeat-until` must be specified",
path ++ List("repeat")
)
case (Some("expr"), None, None) => throw KSYParseError.withText(
"`repeat: expr` requires a `repeat-expr` key",
path ++ List("repeat")
)
case (Some("until"), None, None) => throw KSYParseError.withText(
"`repeat: until` requires a `repeat-until` key",
path ++ List("repeat")
)

// Incompatible combinations
case (Some(_), Some(_), _) => throw KSYParseError.withText(
"`repeat-expr` requires either a `repeat: expr` or absence of a `repeat` key",
path ++ List("repeat")
)
case (Some(_), _, Some(_)) => throw KSYParseError.withText(
"`repeat-until` requires either a `repeat: until` or absence of a `repeat` key",
path ++ List("repeat")
)
case (_, Some(_), Some(_)) => throw KSYParseError.withText(
"either `repeat-expr` or `repeat-until` must be specified",
path ++ List("repeat-expr")
)
}
}
}

0 comments on commit c0b9841

Please sign in to comment.