Ensure P4Runtime byte strings are padded to their bit width

The P4Runtime server may send canonical byte strings (i.e.,
non-padded byte strings).
In ONOS we ensure, in the codecs, that all byte strings are
padded to match the model (P4Info) bit width. In this way,
we provide read-write symmetry inside ONOS.
ONOS always pads byte strings when sending messages to the
P4Runtime server.
This patch doesn't enforce read-write symmetry between
P4Runtime client and server on the wire.

N.B.: the current padding implementation works ONLY when
using non-negative integer.

Change-Id: I9f8e43de015bd0929dd543d7688c8e71bf5fe98d
diff --git a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/PacketMetadataCodec.java b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/PacketMetadataCodec.java
index 876f84c..ab29e62 100644
--- a/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/PacketMetadataCodec.java
+++ b/protocols/p4runtime/utils/src/main/java/org/onosproject/p4runtime/ctl/codec/PacketMetadataCodec.java
@@ -25,6 +25,7 @@
 import p4.config.v1.P4InfoOuterClass;
 import p4.v1.P4RuntimeOuterClass;
 
+import static org.onlab.util.ImmutableByteSequence.copyAndFit;
 import static org.onlab.util.ImmutableByteSequence.copyFrom;
 
 /**
@@ -54,18 +55,23 @@
             P4RuntimeOuterClass.PacketMetadata message,
             P4InfoOuterClass.Preamble ctrlPktMetaPreamble,
             PiPipeconf pipeconf, P4InfoBrowser browser)
-            throws P4InfoBrowser.NotFoundException {
-        final P4InfoOuterClass.ControllerPacketMetadata.Metadata packetMetadata =
+            throws P4InfoBrowser.NotFoundException, CodecException {
+        final P4InfoOuterClass.ControllerPacketMetadata.Metadata pktMeta =
                 browser.packetMetadatas(ctrlPktMetaPreamble.getId())
-                .getById(message.getMetadataId());
+                        .getById(message.getMetadataId());
         final ImmutableByteSequence value;
-        if (browser.isTypeString(packetMetadata.getTypeName())) {
+        if (browser.isTypeString(pktMeta.getTypeName())) {
             value = copyFrom(new String(message.getValue().toByteArray()));
         } else {
-            value = copyFrom(message.getValue().asReadOnlyByteBuffer());
+            try {
+                value = copyAndFit(message.getValue().asReadOnlyByteBuffer(),
+                                   pktMeta.getBitwidth());
+            } catch (ImmutableByteSequence.ByteSequenceTrimException e) {
+                throw new CodecException(e.getMessage());
+            }
         }
         return PiPacketMetadata.builder()
-                .withId(PiPacketMetadataId.of(packetMetadata.getName()))
+                .withId(PiPacketMetadataId.of(pktMeta.getName()))
                 .withValue(value)
                 .build();
     }