Improve PotassiumPathArgument encoding 27/106027/2
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 18 May 2023 09:12:23 +0000 (11:12 +0200)
committerRobert Varga <nite@hq.sk>
Thu, 18 May 2023 10:36:52 +0000 (10:36 +0000)
As it turns out we have only three different PathArgument types, which
means we can shift one bit towards encoding of size. This allows us to
encode up to 12 path arguments directly.

JIRA: YANGTOOLS-568
Change-Id: Ic3cd1c4e349e5f2d3c2e66a069ab5b0033c16d5c
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
codec/yang-data-codec-binfmt/src/main/java/org/opendaylight/yangtools/yang/data/codec/binfmt/PotassiumDataOutput.java
codec/yang-data-codec-binfmt/src/main/java/org/opendaylight/yangtools/yang/data/codec/binfmt/PotassiumPathArgument.java
codec/yang-data-codec-binfmt/src/test/java/org/opendaylight/yangtools/yang/data/codec/binfmt/NipSerializationTest.java

index dbc4c3c61b42180921f89b9a67622e086ee26348..3c30ff84622b5bb93a473ccebec8accee989e03f 100644 (file)
@@ -230,7 +230,7 @@ final class PotassiumDataOutput extends AbstractNormalizedNodeDataOutput {
 
     private void writeNodeIdentifierWithPredicates(final NodeIdentifierWithPredicates identifier) throws IOException {
         final int size = identifier.size();
-        if (size < 5) {
+        if (size < 13) {
             writePathArgumentQName(identifier.getNodeType(),
                 (byte) (PotassiumPathArgument.NODE_IDENTIFIER_WITH_PREDICATES
                         | size << PotassiumPathArgument.SIZE_SHIFT));
index 9a0dac5bf8361c4b2d8806c82058ad14b37fee70..32365ee56d1cd47ab5b05689ccf1a321ad4bd090 100644 (file)
@@ -8,12 +8,12 @@
 package org.opendaylight.yangtools.yang.data.codec.binfmt;
 
 /**
- * Path Argument types used in Potassium encoding. These are encoded as a single byte, three bits of which are reserved
+ * Path Argument types used in Potassium encoding. These are encoded as a single byte, two bits of which are reserved
  * for PathArgument type itself:
  * <pre>
  *   7 6 5 4 3 2 1 0
  *  +-+-+-+-+-+-+-+-+
- *  |         | Type|
+ *  |           |Typ|
  *  +-+-+-+-+-+-+-+-+
  * </pre>
  * There are three type defined:
@@ -22,14 +22,16 @@ package org.opendaylight.yangtools.yang.data.codec.binfmt;
  *     <pre>
  *       7 6 5 4 3 2 1 0
  *      +-+-+-+-+-+-+-+-+
- *      |0 0 0| Q |0 0 1|
+ *      |0 0 0 0| Q |0 1|
  *      +-+-+-+-+-+-+-+-+
  *     </pre>
+ *     Here {@code Q} refers to one of the four possible QName encodings: {@link #QNAME_DEF}, {@link #QNAME_REF_1B},
+ *     {@link #QNAME_REF_2B} or {@link #QNAME_REF_4B}.
  *   <li>{@link #NODE_IDENTIFIER_WITH_PREDICATES}, which encodes a QName same way NodeIdentifier does:
  *     <pre>
  *       7 6 5 4 3 2 1 0
  *      +-+-+-+-+-+-+-+-+
- *      | Size| Q |0 1 0|
+ *      | Size  | Q |1 0|
  *      +-+-+-+-+-+-+-+-+
  *      </pre>
  *      but additionally encodes number of predicates contained using {@link #SIZE_0} through {@link #SIZE_4}. If that
@@ -44,7 +46,7 @@ package org.opendaylight.yangtools.yang.data.codec.binfmt;
  *     <pre>
  *       7 6 5 4 3 2 1 0
  *      +-+-+-+-+-+-+-+-+
- *      |0 0 0| Q |0 1 1|
+ *      |0 0 0 0| Q |1 1|
  *      +-+-+-+-+-+-+-+-+
  *     </pre>
  *     but is additionally followed by a single encoded value, as per {@link PotassiumValue}.
@@ -53,40 +55,27 @@ package org.opendaylight.yangtools.yang.data.codec.binfmt;
  * </ul>
  */
 final class PotassiumPathArgument {
-    // 3 bits reserved for type...
+    // 2 bits reserved for type...
+    // 0x00 reserved
     static final byte NODE_IDENTIFIER                 = 0x01;
     static final byte NODE_IDENTIFIER_WITH_PREDICATES = 0x02;
     static final byte NODE_WITH_VALUE                 = 0x03;
-
-    // ... leaving five values currently unused
-    // FIXME: this means we can use just two bits for type encoding
-    // 0x00 reserved
-    // 0x04 reserved
-    // 0x05 reserved
-    // 0x06 reserved
-    // 0x07 reserved
-
-    static final byte TYPE_MASK                       = 0x07;
+    static final byte TYPE_MASK                       = NODE_WITH_VALUE;
 
     // For normal path path arguments we can either define a QName reference or follow a 1-4 byte reference.
     static final byte QNAME_DEF                       = 0x00;
-    static final byte QNAME_REF_1B                    = 0x08; // Unsigned
-    static final byte QNAME_REF_2B                    = 0x10; // Unsigned
-    static final byte QNAME_REF_4B                    = 0x18; // Signed
+    static final byte QNAME_REF_1B                    = 0x04; // Unsigned
+    static final byte QNAME_REF_2B                    = 0x08; // Unsigned
+    static final byte QNAME_REF_4B                    = 0x0C; // Signed
     static final byte QNAME_MASK                      = QNAME_REF_4B;
 
-    // For NodeIdentifierWithPredicates we also carry the number of subsequent path arguments. The case of 0-4 arguments
-    // is indicated directly, otherwise there is 1-4 bytes carrying the reference.
-    static final byte SIZE_0                          = 0x00;
-    static final byte SIZE_1                          = 0x20;
-    static final byte SIZE_2                          = 0x40;
-    static final byte SIZE_3                          = 0x60;
-    static final byte SIZE_4                          = (byte) 0x80;
+    // For NodeIdentifierWithPredicates we also carry the number of subsequent path arguments. The case of 0-12
+    // arguments is indicated directly, otherwise there is 1-4 bytes carrying the reference.
     static final byte SIZE_1B                         = (byte) 0xA0;
     static final byte SIZE_2B                         = (byte) 0xC0;
     static final byte SIZE_4B                         = (byte) 0xE0;
-    static final byte SIZE_MASK                       = SIZE_4B;
-    static final byte SIZE_SHIFT                      = 5;
+    static final byte SIZE_MASK                       = (byte) 0xF0;
+    static final byte SIZE_SHIFT                      = 4;
 
     private PotassiumPathArgument() {
 
index a6047e894a53ddd155b218f1527554484ed99d4a..ffc83714d4792d87bd4e09fb0beb515e3e56b626 100644 (file)
@@ -27,7 +27,7 @@ public class NipSerializationTest extends AbstractSerializationTest {
     @Parameters(name = "{0}")
     public static Iterable<Object[]> data() {
         return Collections.singletonList(
-            new Object[] { NormalizedNodeStreamVersion.POTASSIUM, 95, 107, 156, 3_409, 982_867, 1_443_164 });
+            new Object[] { NormalizedNodeStreamVersion.POTASSIUM, 95, 107, 155, 252, 3_409, 982_867, 1_443_164 });
     }
 
     @Parameter(1)
@@ -37,10 +37,12 @@ public class NipSerializationTest extends AbstractSerializationTest {
     @Parameter(3)
     public int size5;
     @Parameter(4)
-    public int size256;
+    public int size13;
     @Parameter(5)
-    public int size65792;
+    public int size256;
     @Parameter(6)
+    public int size65792;
+    @Parameter(7)
     public int twiceSize65792;
 
     @Test
@@ -58,6 +60,11 @@ public class NipSerializationTest extends AbstractSerializationTest {
         assertEquals(createIdentifier(5), size5);
     }
 
+    @Test
+    public void test13() {
+        assertEquals(createIdentifier(13), size13);
+    }
+
     @Test
     public void test256() {
         assertEquals(createIdentifier(256), size256);