Use Uint64 for 'length' argument 55/95055/1
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 7 Feb 2021 10:20:21 +0000 (11:20 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 7 Feb 2021 10:32:00 +0000 (11:32 +0100)
RFC6020/7950 place an upper bound on the integral size of length
argument -- explictly calling out that an implementation does not
have to support size beyond unsigned 64bit.

Take advantage of this to lower our memory footprint, by using our
yang.common.Uint64 class instead of java.math.BigInteger. Also
use Uint64.intern() to minimize the number of actual instances we
create.

JIRA: YANGTOOLS-1206
Change-Id: Id112279eb9632d06a80e444d16bd5c825e4ba4ff
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/length/LengthStatementSupport.java

index a423c1866d58b47d5a566fdcf0832ab136495dc8..befd0af8486da45b0e1249bf1deb3819738dc06b 100644 (file)
@@ -9,11 +9,11 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.length;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
-import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
@@ -110,10 +110,18 @@ public final class LengthStatementSupport
             return UnresolvedNumber.min();
         }
 
+        // As per RFC6020/RFC7950 section 9.4.4:
+        //
+        //   An implementation is not required to support a length value larger than 18446744073709551615.
+        //
+        // We could support bigger precision at the cost of additional memory and/or potential ValueRange upper/lower
+        // bound inconsistency. We also take advantage of Uint64's interning facilities.
         try {
-            return new BigInteger(value);
-        } catch (final NumberFormatException e) {
-            throw new SourceException(ctx, e, "Value %s is not a valid integer", value);
+            return Uint64.valueOf(value).intern();
+        } catch (NumberFormatException e) {
+            throw new SourceException(ctx, e, "Value %s is not a valid unsigned integer", value);
+        } catch (IllegalArgumentException e) {
+            throw new SourceException(ctx, e, "Value %s exceeds maximum supported value %s", value, Uint64.MAX_VALUE);
         }
     }
 }
\ No newline at end of file