Skip to content

Commit 8792049

Browse files
committed
Partially implement validation for valid key
Fixed (4): ``` [info] - attr_bad_valid_expr *** FAILED *** [info] [] [info] did not equal [info] [attr_bad_valid_expr.ksy: /seq/0/valid/expr: [info] error: invalid type: expected boolean, got Int1Type(true) [info] ] (SimpleMatchers.scala:34) [info] - expr_field_unknown_valid_eq_long *** FAILED *** [info] [] [info] did not equal [info] [expr_field_unknown_valid_eq_long.ksy: /seq/0/valid/eq: [info] error: unable to access 'bar' in expr_field_unknown_valid_eq_long context [info] ] (SimpleMatchers.scala:34) [info] - expr_field_unknown_valid_expr *** FAILED *** [info] [] [info] did not equal [info] [expr_field_unknown_valid_expr.ksy: /seq/0/valid/expr: [info] error: unable to access 'bar' in expr_field_unknown_valid_expr context [info] ] (SimpleMatchers.scala:34) [info] - expr_field_unknown_valid_range *** FAILED *** [info] [] [info] did not equal [info] [expr_field_unknown_valid_range.ksy: /seq/0/valid/min: [info] error: unable to access 'bar' in expr_field_unknown_valid_range context [info] [info] expr_field_unknown_valid_range.ksy: /seq/0/valid/max: [info] error: unable to access 'qux' in expr_field_unknown_valid_range context [info] ] (SimpleMatchers.scala:34) ``` Changed error message (4, must correct model to distinguish between `valid` and `valid.eq`): ``` [info] - attr_bad_valid_eq_long *** FAILED *** [info] [attr_bad_valid_eq_long.ksy: /seq/0/valid/eq: [info] error: invalid type: expected Int1Type(false), got CalcStrType [info] ] [info] did not equal [info] [attr_bad_valid_eq_long.ksy: /seq/0/valid/eq: [info] error: can't compare Int1Type(false) and CalcStrType [info] ] (SimpleMatchers.scala:34) [info] - attr_bad_valid_eq_short *** FAILED *** [info] [attr_bad_valid_eq_short.ksy: /seq/0/valid/eq: [info] error: invalid type: expected Int1Type(false), got CalcStrType [info] ] [info] did not equal [info] [attr_bad_valid_eq_short.ksy: /seq/0/valid: [info] error: can't compare Int1Type(false) and CalcStrType [info] ] (SimpleMatchers.scala:34) [info] - attr_bad_valid_repeat_eq_short *** FAILED *** [info] [attr_bad_valid_repeat_eq_short.ksy: /seq/0/valid/eq: [info] error: invalid type: expected IntMultiType(true,Width4,Some(LittleEndian)), got ArrayTypeInStream(CalcIntType) [info] ] [info] did not equal [info] [attr_bad_valid_repeat_eq_short.ksy: /seq/0/valid: [info] error: can't compare IntMultiType(true,Width4,Some(LittleEndian)) and ArrayTypeInStream(CalcIntType) [info] ] (SimpleMatchers.scala:34) [info] - expr_field_unknown_valid_eq_short *** FAILED *** [info] [expr_field_unknown_valid_eq_short.ksy: /seq/0/valid/eq: [info] error: unable to access 'bar' in expr_field_unknown_valid_eq_short context [info] ] [info] did not equal [info] [expr_field_unknown_valid_eq_short.ksy: /seq/0/valid: [info] error: unable to access 'bar' in expr_field_unknown_valid_eq_short context [info] ] (SimpleMatchers.scala:34) ``` Changed error message (3, expected must be corrected or false-positives): ``` [info] - attr_bad_valid_any_of *** FAILED *** [info] [attr_bad_valid_any_of.ksy: /seq/0/valid/any-of/0: [info] error: invalid type: expected Int1Type(false), got Int1Type(true) [info] [info] attr_bad_valid_any_of.ksy: /seq/0/valid/any-of/1: [info] error: invalid type: expected Int1Type(false), got Int1Type(true) [info] [info] attr_bad_valid_any_of.ksy: /seq/0/valid/any-of/2: [info] error: invalid type: expected Int1Type(false), got CalcBooleanType [info] [info] attr_bad_valid_any_of.ksy: /seq/0/valid/any-of/3: [info] error: invalid type: expected Int1Type(false), got Int1Type(true) [info] ] [info] did not equal [info] [attr_bad_valid_any_of.ksy: /seq/0/valid/any-of/2: [info] error: can't compare Int1Type(false) and CalcBooleanType [info] ] (SimpleMatchers.scala:34) [info] - attr_bad_valid_range *** FAILED *** [info] [attr_bad_valid_range.ksy: /seq/0/valid/min: [info] error: invalid type: expected Int1Type(false), got CalcBooleanType [info] [info] attr_bad_valid_range.ksy: /seq/0/valid/max: [info] error: invalid type: expected Int1Type(false), got CalcStrType [info] ] [info] did not equal [info] [attr_bad_valid_range.ksy: /seq/0/valid/min: [info] error: can't compare Int1Type(false) and CalcBooleanType [info] [info] attr_bad_valid_range.ksy: /seq/0/valid/max: [info] error: can't compare Int1Type(false) and CalcStrType [info] ] (SimpleMatchers.scala:34) [info] - expr_field_unknown_valid_any_of *** FAILED *** [info] [expr_field_unknown_valid_any_of.ksy: /seq/0/valid/any-of/0: [info] error: invalid type: expected Int1Type(false), got Int1Type(true) [info] [info] expr_field_unknown_valid_any_of.ksy: /seq/0/valid/any-of/1: [info] error: unable to access 'bar' in expr_field_unknown_valid_any_of context [info] [info] expr_field_unknown_valid_any_of.ksy: /seq/0/valid/any-of/2: [info] error: invalid type: expected Int1Type(false), got Int1Type(true) [info] [info] expr_field_unknown_valid_any_of.ksy: /seq/0/valid/any-of/3: [info] error: unable to access 'qux' in expr_field_unknown_valid_any_of context [info] ] [info] did not equal [info] [expr_field_unknown_valid_any_of.ksy: /seq/0/valid/any-of/1: [info] error: unable to access 'bar' in expr_field_unknown_valid_any_of context [info] [info] expr_field_unknown_valid_any_of.ksy: /seq/0/valid/any-of/3: [info] error: unable to access 'qux' in expr_field_unknown_valid_any_of context [info] ] (SimpleMatchers.scala:34) ```
1 parent 049b464 commit 8792049

1 file changed

Lines changed: 48 additions & 2 deletions

File tree

shared/src/main/scala/io/kaitai/struct/precompile/TypeValidator.scala

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,12 @@ class TypeValidator(specs: ClassSpecs) extends PrecompileStep {
8282

8383
val problemsDataType = validateDataType(attr.dataType, path)
8484

85-
List(problemsIf, problemsRepeat, problemsDataType).flatten
85+
val problemsValid: Iterable[CompilationProblem] = attr.valid match {
86+
case Some(valid) => validateValidClause(valid, attr.dataType, attr.path :+ "valid")
87+
case None => None // all good
88+
}
89+
90+
List(problemsIf, problemsRepeat, problemsDataType, problemsValid).flatten
8691
}
8792

8893
def validateParseInstance(pis: ParseInstanceSpec): Iterable[CompilationProblem] = {
@@ -100,7 +105,12 @@ class TypeValidator(specs: ClassSpecs) extends PrecompileStep {
100105
case None => None // all good
101106
}
102107

103-
List(problemsAttr, problemsIo, problemsPos).flatten
108+
val problemsValid: Iterable[CompilationProblem] = pis.valid match {
109+
case Some(valid) => validateValidClause(valid, pis.dataType, pis.path :+ "valid")
110+
case None => None // all good
111+
}
112+
113+
List(problemsAttr, problemsIo, problemsPos, problemsValid).flatten
104114
}
105115

106116
def validateValueInstance(vis: ValueInstanceSpec): Option[CompilationProblem] = {
@@ -204,6 +214,42 @@ class TypeValidator(specs: ClassSpecs) extends PrecompileStep {
204214
}
205215
}
206216

217+
/**
218+
* @param valid The `valid` clause of Kaitai Struct attribute or parse instance definition
219+
* @param attrType The type of attribute, used to check compatibility of valid expressions to that type
220+
* @param path Path where `valid` key is defined
221+
*/
222+
private def validateValidClause(
223+
valid: ValidationSpec,
224+
attrType: DataType,
225+
path: List[String]
226+
): Iterable[CompilationProblem] = {
227+
// TODO: This is not user-face message
228+
val expected = attrType.toString
229+
valid match {
230+
// TODO: Need to distinguish between `valid`, `valid.eq` and `contents`
231+
case ValidationEq(value) =>
232+
checkAssertObject(value, attrType, expected, path, "eq")
233+
case ValidationMin(min) =>
234+
checkAssertObject(min, attrType, expected, path, "min")
235+
case ValidationMax(max) =>
236+
checkAssertObject(max, attrType, expected, path, "max")
237+
case ValidationRange(min, max) => {
238+
checkAssertObject(min, attrType, expected, path, "min") ++
239+
checkAssertObject(max, attrType, expected, path, "max")
240+
}
241+
case ValidationAnyOf(values) => {
242+
val itemPath = path :+ "any-of"
243+
values.zipWithIndex.flatMap { case (value, i) =>
244+
checkAssertObject(value, attrType, expected, itemPath, i.toString)
245+
}
246+
}
247+
case ValidationInEnum() => List()
248+
case ValidationExpr(checkExpr) =>
249+
checkAssert[BooleanType](checkExpr, "boolean", path, "expr")
250+
}
251+
}
252+
207253
/**
208254
* Checks that expression's type conforms to a given datatype, otherwise
209255
* throw a human-readable exception, with some pointers that would help

0 commit comments

Comments
 (0)