This is an automated email from the ASF dual-hosted git repository.
slawrence pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git
The following commit(s) were added to refs/heads/main by this push:
new 6b0e56e8c Fix check for explicit length within length facet range
6b0e56e8c is described below
commit 6b0e56e8c9af894a852779fea2fb4ba486b0963f
Author: Steve Lawrence <[email protected]>
AuthorDate: Tue Sep 17 15:25:44 2024 -0400
Fix check for explicit length within length facet range
When we check if an explicit dfdl:length is within range of the
minLength/maxLength/length facets, we do not take into account units or
character encoding, which can lead to incorrect and confusing warnings.
This modifies the check to use the existing LengthInBitsEv to calculate
the length in bits of an element (which uses lengthUnits), and uses
CharsetEv for string types to correctly convert the explicit bit length
to infoset length, where possible
DAFFODIL-2888
---
.../core/grammar/ElementBaseGrammarMixin.scala | 68 +++++++++++++---------
.../text_number_props/TextNumberPropsUnparse.tdml | 25 +++++++-
.../TestTextNumberPropsUnparse.scala | 1 +
3 files changed, 62 insertions(+), 32 deletions(-)
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala
index b56c5610b..fffbe2139 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ElementBaseGrammarMixin.scala
@@ -1611,37 +1611,47 @@ trait ElementBaseGrammarMixin
)
case _ => // ok
}
+
/*
- * When lengthKind is explicit and length is a constant, it is a warning if
- * the type is a type that respects minLength and maxLength, and the
constant length
- * is not in range.
+ * Warn if a type respects minLength/maxLength/length facets and we can
calculate that the
+ * infoset length will be out of range of the facet values. Note that we
can only do this in
+ * specific cases, like when the length and encoding properties are
constant and the
+ * encoding is fixed width characters.
*/
- val isTypeUsingLengthOrMinMaxLengthFacets = typeDef.typeNode match {
- case s: NodeInfo.String.Kind => true
- case s: NodeInfo.HexBinary.Kind => true
- case _ => false
- }
- if (
- (lengthKind eq LengthKind.Explicit) &&
- isTypeUsingLengthOrMinMaxLengthFacets &&
- optLengthConstant.isDefined
- ) {
- val len = optLengthConstant.get
- lazy val maxLengthLong = maxLength.longValueExact
- lazy val minLengthLong = minLength.longValueExact
- def warn(m: String, value: Long): Unit = SDW(
- WarnID.FacetExplicitLengthOutOfRange,
- "Explicit dfdl:length of %s is out of range for facet %s='%s'.",
- len,
- m,
- value
- )
- if (hasLength && len != minLengthLong && len != maxLengthLong)
- warn("length", minLengthLong)
- else if (hasMinLength || hasMaxLength) {
- if (maxLengthLong != -1 && len > maxLengthLong) warn("maxLength",
maxLengthLong)
- Assert.invariant(minLengthLong >= 0)
- if (minLengthLong > 0 && len < minLengthLong) warn("minLength",
minLengthLong)
+ if ((lengthKind eq LengthKind.Explicit) && (hasLength || hasMinLength ||
hasMaxLength)) {
+ val optInfosetLen = elementLengthInBitsEv.optConstant.flatMap {
maybeKnownLenInBits =>
+ if (maybeKnownLenInBits.isDefined) {
+ val len = maybeKnownLenInBits.get
+ typeDef.typeNode match {
+ case _: NodeInfo.String.Kind => {
+ charsetEv.optConstant.flatMap { charset =>
+ if (charset.maybeFixedWidth.isDefined)
+ Some(len / charset.maybeFixedWidth.get)
+ else
+ None
+ }
+ }
+ case _: NodeInfo.HexBinary.Kind => Some(len / 8)
+ case _ => None
+ }
+ } else None
+ }
+ optInfosetLen.foreach { len =>
+ def warn(facet: String, value: Long): Unit = SDW(
+ WarnID.FacetExplicitLengthOutOfRange,
+ "Calculated infoset length (%s) is out of range for facet %s='%s'.",
+ len,
+ facet,
+ value
+ )
+ lazy val maxLengthLong = maxLength.longValueExact
+ lazy val minLengthLong = minLength.longValueExact
+ if (hasLength && (len != minLengthLong || len != maxLengthLong))
+ warn("length", minLengthLong)
+ if (hasMaxLength && (maxLengthLong != -1 && len > maxLengthLong))
+ warn("maxLength", maxLengthLong)
+ if (hasMinLength && (len < minLengthLong))
+ warn("minLength", minLengthLong)
}
}
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section13/text_number_props/TextNumberPropsUnparse.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section13/text_number_props/TextNumberPropsUnparse.tdml
index da2cadfba..a9b0730f3 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section13/text_number_props/TextNumberPropsUnparse.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section13/text_number_props/TextNumberPropsUnparse.tdml
@@ -126,6 +126,8 @@
<xs:element name="e12_dfdlLength2" type="ex:stLen10"
dfdl:lengthKind="explicit" dfdl:length="{ 2 }" dfdl:textStringPadCharacter="#"
dfdl:textPadKind="padChar" dfdl:textTrimKind="padChar"
dfdl:textStringJustification="left" />
+ <xs:element name="e12bits" type="ex:st3to10" dfdl:lengthKind="explicit"
dfdl:length="{ 8 }" dfdl:lengthUnits="bits" dfdl:textStringJustification="left"
/>
+
<xs:element name="e13" dfdl:lengthKind="implicit">
<xs:complexType>
<xs:sequence dfdl:separator="," >
@@ -417,7 +419,7 @@
</tdml:infoset>
<tdml:warnings>
<tdml:warning>Schema Definition Warning</tdml:warning>
- <tdml:warning>Explicit dfdl:length</tdml:warning>
+ <tdml:warning>Calculated infoset length</tdml:warning>
<tdml:warning>out of range</tdml:warning>
<tdml:warning>facet minLength</tdml:warning>
</tdml:warnings>
@@ -442,7 +444,7 @@
</tdml:infoset>
<tdml:warnings>
<tdml:warning>Schema Definition Warning</tdml:warning>
- <tdml:warning>Explicit dfdl:length</tdml:warning>
+ <tdml:warning>Calculated infoset length</tdml:warning>
<tdml:warning>out of range</tdml:warning>
<tdml:warning>facet minLength</tdml:warning>
</tdml:warnings>
@@ -459,13 +461,30 @@
</tdml:infoset>
<tdml:warnings>
<tdml:warning>Schema Definition Warning</tdml:warning>
- <tdml:warning>Explicit dfdl:length</tdml:warning>
+ <tdml:warning>Calculated infoset length</tdml:warning>
<tdml:warning>out of range</tdml:warning>
<tdml:warning>facet length</tdml:warning>
</tdml:warnings>
<tdml:document>O#</tdml:document>
</tdml:unparserTestCase>
+ <tdml:unparserTestCase name="unparsePaddedString12"
model="delimitedStringsPadding" root="e12bits"
+ description="ensure minLength facet results in a
warning taking lengthUnits into account"
+ roundTrip="false">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e12bits xmlns:ex="http://example.com">0</ex:e12bits>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:warnings>
+ <tdml:warning>Schema Definition Warning</tdml:warning>
+ <tdml:warning>Calculated infoset length</tdml:warning>
+ <tdml:warning>out of range</tdml:warning>
+ <tdml:warning>facet minLength</tdml:warning>
+ </tdml:warnings>
+ <tdml:document>0</tdml:document>
+ </tdml:unparserTestCase>
+
<!--
Test Name: unparseDelimitedPaddedString11
Schema: delimitedStringsPadding
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section13/text_number_props/TestTextNumberPropsUnparse.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section13/text_number_props/TestTextNumberPropsUnparse.scala
index ff83769f5..956d91252 100644
---
a/daffodil-test/src/test/scala/org/apache/daffodil/section13/text_number_props/TestTextNumberPropsUnparse.scala
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section13/text_number_props/TestTextNumberPropsUnparse.scala
@@ -77,6 +77,7 @@ class TestTextNumberPropsUnparse {
@Test def test_unparsePaddedString10(): Unit = {
runner.runOneTest("unparsePaddedString10") }
@Test def test_unparsePaddedString11(): Unit = {
runner.runOneTest("unparsePaddedString11") }
+ @Test def test_unparsePaddedString12(): Unit = {
runner.runOneTest("unparsePaddedString12") }
@Test def test_unparsePaddedStringTruncate01(): Unit = {
runner.runOneTest("unparsePaddedStringTruncate01")