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")

Reply via email to