Add yang-common-netty 22/86022/5
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 27 Nov 2019 10:07:31 +0000 (11:07 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 10 Dec 2019 22:09:08 +0000 (23:09 +0100)
This adds common utilities for dealing with Uint8 types with ByteBufs,
along with some convenience nullness-handling methods.

JIRA: YANGTOOLS-1047
Change-Id: Idf5bef51db30c5397d440e2648fe9c417735aae2
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
artifacts/pom.xml
docs/pom.xml
features/features-yangtools/pom.xml
features/odl-yangtools-netty/pom.xml [new file with mode: 0644]
features/odl-yangtools-netty/src/main/feature/feature.xml [new file with mode: 0644]
features/pom.xml
yang/pom.xml
yang/yang-common-netty/pom.xml [new file with mode: 0644]
yang/yang-common-netty/src/main/java/org/opendaylight/yangtools/yang/common/netty/ByteBufUtils.java [new file with mode: 0644]
yang/yang-common-netty/src/test/java/org/opendaylight/yangtools/yang/common/netty/ByteBufUtilsNullnessTest.java [new file with mode: 0644]
yang/yang-common-netty/src/test/java/org/opendaylight/yangtools/yang/common/netty/ByteBufUtilsTest.java [new file with mode: 0644]

index b8e572392648fe8cb6b3b0261c2aff23cfebecd1..63fdbfe29a61a97c6bd61f659794862c8510bd03 100644 (file)
                 <version>4.0.3-SNAPSHOT</version>
             </dependency>
 
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-common-netty</artifactId>
+                <version>4.0.3-SNAPSHOT</version>
+            </dependency>
+
             <!-- Test utilities, not packaged in features -->
             <dependency>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <type>xml</type>
                 <classifier>features</classifier>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>odl-yangtools-netty</artifactId>
+                <version>4.0.3-SNAPSHOT</version>
+                <type>xml</type>
+                <classifier>features</classifier>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>odl-yangtools-xpath-api</artifactId>
index 5a016ef15b080241407a2ad4b2548ca0aa62956a..7b79d12d26117311ac46bd4f3844209f268eb27f 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-common</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common-netty</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-data-api</artifactId>
index 3c7036048425c9e0643755366ecb96b611fdddca..e9369d77f158f281310e34691a29438c3cc232a5 100644 (file)
             <classifier>features</classifier>
             <type>xml</type>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>odl-yangtools-netty</artifactId>
+            <classifier>features</classifier>
+            <type>xml</type>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>odl-yangtools-parser-api</artifactId>
diff --git a/features/odl-yangtools-netty/pom.xml b/features/odl-yangtools-netty/pom.xml
new file mode 100644 (file)
index 0000000..b72a0e3
--- /dev/null
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.opendaylight.odlparent</groupId>
+        <artifactId>single-feature-parent</artifactId>
+        <version>6.0.3</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.opendaylight.yangtools</groupId>
+    <artifactId>odl-yangtools-netty</artifactId>
+    <version>4.0.3-SNAPSHOT</version>
+    <packaging>feature</packaging>
+    <name>OpenDaylight :: Yangtools :: Netty integration</name>
+    <description>YANG Tools/netty-buffer utilities</description>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yangtools-artifacts</artifactId>
+                <version>${project.version}</version>
+                <scope>import</scope>
+                <type>pom</type>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.odlparent</groupId>
+            <artifactId>odl-netty-4</artifactId>
+            <type>xml</type>
+            <classifier>features</classifier>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>odl-yangtools-common</artifactId>
+            <type>xml</type>
+            <classifier>features</classifier>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common-netty</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/features/odl-yangtools-netty/src/main/feature/feature.xml b/features/odl-yangtools-netty/src/main/feature/feature.xml
new file mode 100644 (file)
index 0000000..6c3d767
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="odl-yangtools-netty">
+    <feature name="odl-yangtools-netty">
+        <feature version="[6,7)">odl-netty-4</feature>
+    </feature>
+</features>
index ad63f695fe69f4ea6bcbbfa984d4e3d0733ab5b8..c9764f4426ea5222d11115c97a2aa5581466d7e9 100644 (file)
@@ -29,6 +29,7 @@
         <module>odl-yangtools-data-api</module>
         <module>odl-yangtools-data</module>
         <module>odl-yangtools-export</module>
+        <module>odl-yangtools-netty</module>
         <module>odl-yangtools-parser-api</module>
         <module>odl-yangtools-parser</module>
         <module>odl-yangtools-util</module>
index 6f1c2f1fd44e787a97a8965b04a19da9d146173c..c9dc65f9fdb2584f2e0b16db6cdbbb629543c521 100644 (file)
@@ -24,6 +24,7 @@
 
     <modules>
         <module>yang-common</module>
+        <module>yang-common-netty</module>
         <module>yang-data-api</module>
         <module>yang-data-xpath-api</module>
         <module>yang-data-jaxen</module>
diff --git a/yang/yang-common-netty/pom.xml b/yang/yang-common-netty/pom.xml
new file mode 100644 (file)
index 0000000..a684a3e
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>bundle-parent</artifactId>
+        <version>4.0.3-SNAPSHOT</version>
+        <relativePath>../../bundle-parent</relativePath>
+    </parent>
+
+    <artifactId>yang-common-netty</artifactId>
+    <packaging>bundle</packaging>
+    <name>${project.artifactId}</name>
+    <description>Netty utilities for Common YANG definitions</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-buffer</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Automatic-Module-Name>org.opendaylight.yangtools.yang.common.netty</Automatic-Module-Name>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/yang/yang-common-netty/src/main/java/org/opendaylight/yangtools/yang/common/netty/ByteBufUtils.java b/yang/yang-common-netty/src/main/java/org/opendaylight/yangtools/yang/common/netty/ByteBufUtils.java
new file mode 100644 (file)
index 0000000..9569e40
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.common.netty;
+
+import com.google.common.annotations.Beta;
+import io.netty.buffer.ByteBuf;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.Uint16;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
+import org.opendaylight.yangtools.yang.common.Uint8;
+
+/**
+ * Utility methods for interacting with {@link ByteBuf}s. These add a number of methods for reading and writing various
+ * data types from/to ByteBufs. Methods fall into these categories:
+ * <ul>
+ *   <li>{@code readUint*}, which extract the corresponding amount of data from a buffer and return an Uint type. These
+ *       are more efficient than going the {@code Uint8.valueOf(buf.readUnsignedByte())} route.</li>
+ *   <li>{@code writeUint*}, which write specified value into a buffer.</li>
+ *   <li>{@code writeMandatory*}, which write a property not statically known to be non-null. These methods throw
+ *       an {@link IllegalArgumentException} if the supplied value is null. Otherwise they will write it to provided
+ *       buffer.</li>
+ *   <li>{@code writeOptional*}, which write a value which can legally be null. In case the value is not null, it is
+ *       written to the provided buffer. If the value null, the method does nothing.</li>
+ *   <li>{@code writeOrZero*}, which write a value which can legally be null. In case the value is not null, it is
+ *       written to the provided buffer. If the value is null, a {code zero} value of corresponding width is written
+ *       instead.</li>
+ * </ul>
+ */
+@Beta
+public final class ByteBufUtils {
+    private ByteBufUtils() {
+
+    }
+
+    /**
+     * Read an {@link Uint8} from specified buffer.
+     *
+     * @param buf buffer
+     * @return A {@link Uint8}
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IndexOutOfBoundsException if {@code buf} does not have enough data
+     */
+    public static @NonNull Uint8 readUint8(final ByteBuf buf) {
+        return Uint8.fromByteBits(buf.readByte());
+    }
+
+    /**
+     * Read a {@link Uint16} from specified buffer.
+     *
+     * @param buf buffer
+     * @return A {@link Uint16}
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IndexOutOfBoundsException if {@code buf} does not have enough data
+     */
+    public static @NonNull Uint16 readUint16(final ByteBuf buf) {
+        return Uint16.fromShortBits(buf.readShort());
+    }
+
+    /**
+     * Read a {@link Uint32} from specified buffer.
+     *
+     * @param buf buffer
+     * @return A {@link Uint32}
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IndexOutOfBoundsException if {@code buf} does not have enough data
+     */
+    public static @NonNull Uint32 readUint32(final ByteBuf buf) {
+        return Uint32.fromIntBits(buf.readInt());
+    }
+
+    /**
+     * Read a {@link Uint64} from specified buffer.
+     *
+     * @param buf buffer
+     * @return A {@link Uint64}
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IndexOutOfBoundsException if {@code buf} does not have enough data
+     */
+    public static @NonNull Uint64 readUint64(final ByteBuf buf) {
+        return Uint64.fromLongBits(buf.readLong());
+    }
+
+    /**
+     * Write a {@link Uint8} to specified buffer.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint8}
+     * @throws NullPointerException if any argument is null
+     */
+    public static void write(final ByteBuf buf, final Uint8 value) {
+        buf.writeByte(value.byteValue());
+    }
+
+    /**
+     * Write a {@link Uint16} to specified buffer.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint16}
+     * @throws NullPointerException if any argument is null
+     */
+    public static void write(final ByteBuf buf, final Uint16 value) {
+        buf.writeShort(value.shortValue());
+    }
+
+    /**
+     * Write a {@link Uint32} from specified buffer.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint32}
+     * @throws NullPointerException if any argument is null
+     */
+    public static void write(final ByteBuf buf, final Uint32 value) {
+        buf.writeInt(value.intValue());
+    }
+
+    /**
+     * Write a {@link Uint64} to specified buffer.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint64}
+     * @throws NullPointerException if any argument is null
+     */
+    public static void write(final ByteBuf buf, final Uint64 value) {
+        buf.writeLong(value.longValue());
+    }
+
+    /**
+     * Write a {@link Byte} property to specified buffer. If the {@code value} is known to be non-null, prefer
+     * {@link ByteBuf#writeByte(int)} instead of this method.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @param name Property name for error reporting purposes
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IllegalArgumentException if {@code value} is null
+     */
+    public static void writeMandatory(final ByteBuf buf, final Byte value, final String name) {
+        buf.writeByte(nonNullArgument(value, name).byteValue());
+    }
+
+    /**
+     * Write a {@link Short} property to specified buffer. If the {@code value} is known to be non-null, prefer
+     * {@link ByteBuf#writeShort(int)} instead of this method.
+     *
+     * @param buf buffer
+     * @param value A {@link Short}
+     * @param name Property name for error reporting purposes
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IllegalArgumentException if {@code value} is null
+     */
+    public static void writeMandatory(final ByteBuf buf, final Short value, final String name) {
+        buf.writeShort(nonNullArgument(value, name).shortValue());
+    }
+
+    /**
+     * Write a {@link Integer} property to specified buffer. If the {@code value} is known to be non-null, prefer
+     * {@link ByteBuf#writeInt(int)} instead of this method.
+     *
+     * @param buf buffer
+     * @param value A {@link Integer}
+     * @param name Property name for error reporting purposes
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IllegalArgumentException if {@code value} is null
+     */
+    public static void writeMandatory(final ByteBuf buf, final Integer value, final String name) {
+        buf.writeInt(nonNullArgument(value, name).intValue());
+    }
+
+    /**
+     * Write a {@link Long} property to specified buffer. If the {@code value} is known to be non-null, prefer
+     * {@link ByteBuf#writeLong(long)} instead of this method.
+     *
+     * @param buf buffer
+     * @param value A {@link Long}
+     * @param name Property name for error reporting purposes
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IllegalArgumentException if {@code value} is null
+     */
+    public static void writeMandatory(final ByteBuf buf, final Long value, final String name) {
+        buf.writeLong(nonNullArgument(value, name).longValue());
+    }
+
+    /**
+     * Write a {@link Uint8} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
+     * {@link #write(ByteBuf, Uint8)} instead of this method.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint8}
+     * @param name Property name for error reporting purposes
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IllegalArgumentException if {@code value} is null
+     */
+    public static void writeMandatory(final ByteBuf buf, final Uint8 value, final String name) {
+        write(buf, nonNullArgument(value, name));
+    }
+
+    /**
+     * Write a {@link Uint16} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
+     * {@link #write(ByteBuf, Uint16)} instead of this method.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint16}
+     * @param name Property name for error reporting purposes
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IllegalArgumentException if {@code value} is null
+     */
+    public static void writeMandatory(final ByteBuf buf, final Uint16 value, final String name) {
+        write(buf, nonNullArgument(value, name));
+    }
+
+    /**
+     * Write a {@link Uint32} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
+     * {@link #write(ByteBuf, Uint32)} instead of this method.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint32}
+     * @param name Property name for error reporting purposes
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IllegalArgumentException if {@code value} is null
+     */
+    public static void writeMandatory(final ByteBuf buf, final Uint32 value, final String name) {
+        write(buf, nonNullArgument(value, name));
+    }
+
+    /**
+     * Write a {@link Uint64} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
+     * {@link #write(ByteBuf, Uint64)} instead of this method.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint64}
+     * @param name Property name for error reporting purposes
+     * @throws NullPointerException if {@code buf} is null
+     * @throws IllegalArgumentException if {@code value} is null
+     */
+    public static void writeMandatory(final ByteBuf buf, final Uint64 value, final String name) {
+        write(buf, nonNullArgument(value, name));
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOptional(final ByteBuf buf, final @Nullable Byte value) {
+        if (value != null) {
+            buf.writeByte(value.byteValue());
+        }
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null.
+     *
+     * @param buf buffer
+     * @param value A {@link Short}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOptional(final ByteBuf buf, final @Nullable Short value) {
+        if (value != null) {
+            buf.writeShort(value.shortValue());
+        }
+    }
+
+    /**
+     * Write a {@link Integer} value to specified buffer if it is not null.
+     *
+     * @param buf buffer
+     * @param value A {@link Integer}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOptional(final ByteBuf buf, final @Nullable Integer value) {
+        if (value != null) {
+            buf.writeInt(value.intValue());
+        }
+    }
+
+    /**
+     * Write a {@link Long} value to specified buffer if it is not null.
+     *
+     * @param buf buffer
+     * @param value A {@link Long}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOptional(final ByteBuf buf, final @Nullable Long value) {
+        if (value != null) {
+            buf.writeLong(value.longValue());
+        }
+    }
+
+    /**
+     * Write a {@link Uint8} value to specified buffer if it is not null.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint8}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOptional(final ByteBuf buf, final @Nullable Uint8 value) {
+        if (value != null) {
+            write(buf, value);
+        }
+    }
+
+    /**
+     * Write a {@link Uint16} value to specified buffer if it is not null.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint16}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOptional(final ByteBuf buf, final @Nullable Uint16 value) {
+        if (value != null) {
+            write(buf, value);
+        }
+    }
+
+    /**
+     * Write a {@link Uint32} value to specified buffer if it is not null.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint32}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOptional(final ByteBuf buf, final @Nullable Uint32 value) {
+        if (value != null) {
+            write(buf, value);
+        }
+    }
+
+    /**
+     * Write a {@link Uint64} value to specified buffer if it is not null.
+     *
+     * @param buf buffer
+     * @param value A {@link Uint64}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOptional(final ByteBuf buf, final @Nullable Uint64 value) {
+        if (value != null) {
+            write(buf, value);
+        }
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null, otherwise write one zero byte.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOrZero(final ByteBuf buf, final @Nullable Byte value) {
+        buf.writeByte(value != null ? value.byteValue() : 0);
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null, otherwise write two zero bytes.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOrZero(final ByteBuf buf, final @Nullable Short value) {
+        buf.writeShort(value != null ? value.shortValue() : (short) 0);
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null, otherwise write four zero bytes.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOrZero(final ByteBuf buf, final @Nullable Integer value) {
+        buf.writeInt(value != null ? value.intValue() : 0);
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null, otherwise write eight zero bytes.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOrZero(final ByteBuf buf, final @Nullable Long value) {
+        buf.writeLong(value != null ? value.longValue() : 0L);
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null, otherwise write one zero byte.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOrZero(final ByteBuf buf, final @Nullable Uint8 value) {
+        buf.writeByte(value != null ? value.byteValue() : 0);
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null, otherwise write two zero bytes.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOrZero(final ByteBuf buf, final @Nullable Uint16 value) {
+        buf.writeShort(value != null ? value.shortValue() : (short) 0);
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null, otherwise write four zero bytes.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOrZero(final ByteBuf buf, final @Nullable Uint32 value) {
+        buf.writeInt(value != null ? value.intValue() : 0);
+    }
+
+    /**
+     * Write a {@link Byte} value to specified buffer if it is not null, otherwise write eight zero bytes.
+     *
+     * @param buf buffer
+     * @param value A {@link Byte}
+     * @throws NullPointerException if {@code buf} is null
+     */
+    public static void writeOrZero(final ByteBuf buf, final @Nullable Uint64 value) {
+        buf.writeLong(value != null ? value.longValue() : 0L);
+    }
+
+    private static <T> @NonNull T nonNullArgument(final @Nullable T obj, final String name) {
+        if (obj == null) {
+            throw new IllegalArgumentException(name + " is mandatory");
+        }
+        return obj;
+    }
+}
diff --git a/yang/yang-common-netty/src/test/java/org/opendaylight/yangtools/yang/common/netty/ByteBufUtilsNullnessTest.java b/yang/yang-common-netty/src/test/java/org/opendaylight/yangtools/yang/common/netty/ByteBufUtilsNullnessTest.java
new file mode 100644 (file)
index 0000000..0f0c843
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.common.netty;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.Uint16;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
+import org.opendaylight.yangtools.yang.common.Uint8;
+
+public class ByteBufUtilsNullnessTest {
+    private ByteBuf buf;
+
+    @Before
+    public void before() {
+        buf = Unpooled.buffer();
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testReadUint8() {
+        ByteBufUtils.readUint8(null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testReadUint16() {
+        ByteBufUtils.readUint16(null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testReadUint32() {
+        ByteBufUtils.readUint8(null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testReadUint64() {
+        ByteBufUtils.readUint64(null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteNullBuf8() {
+        ByteBufUtils.write(null, Uint8.ONE);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteNullBuf16() {
+        ByteBufUtils.write(null, Uint16.ONE);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteNullBuf32() {
+        ByteBufUtils.write(null, Uint32.ONE);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteNullBuf64() {
+        ByteBufUtils.write(null, Uint64.ONE);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteNull8() {
+        ByteBufUtils.write(buf, (Uint8) null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteNull16() {
+        ByteBufUtils.write(buf, (Uint16) null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteNull32() {
+        ByteBufUtils.write(buf, (Uint32) null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteNull64() {
+        ByteBufUtils.write(null, (Uint64) null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteMandatoryByte() {
+        ByteBufUtils.writeMandatory(buf, (Byte) null, "name");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteMandatoryShort() {
+        ByteBufUtils.writeMandatory(buf, (Short) null, "name");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteMandatoryInt() {
+        ByteBufUtils.writeMandatory(buf, (Integer) null, "name");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteMandatoryLong() {
+        ByteBufUtils.writeMandatory(buf, (Long) null, "name");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteMandatoryUint8() {
+        ByteBufUtils.writeMandatory(buf, (Uint8) null, "name");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteMandatoryUint16() {
+        ByteBufUtils.writeMandatory(buf, (Uint16) null, "name");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteMandatoryUint32() {
+        ByteBufUtils.writeMandatory(buf, (Uint32) null, "name");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteMandatoryUint64() {
+        ByteBufUtils.writeMandatory(buf, (Uint64) null, "name");
+    }
+
+
+}
diff --git a/yang/yang-common-netty/src/test/java/org/opendaylight/yangtools/yang/common/netty/ByteBufUtilsTest.java b/yang/yang-common-netty/src/test/java/org/opendaylight/yangtools/yang/common/netty/ByteBufUtilsTest.java
new file mode 100644 (file)
index 0000000..08bb977
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.common.netty;
+
+import static org.junit.Assert.assertEquals;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.Uint16;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
+import org.opendaylight.yangtools.yang.common.Uint8;
+
+public class ByteBufUtilsTest {
+    @Test
+    public void testWriteByte() {
+        test(Byte.MAX_VALUE);
+        test(Byte.MIN_VALUE);
+    }
+
+    @Test
+    public void testWriteShort() {
+        test(Short.MAX_VALUE);
+        test(Short.MIN_VALUE);
+    }
+
+    @Test
+    public void testWriteInt() {
+        test(Integer.MAX_VALUE);
+        test(Integer.MIN_VALUE);
+    }
+
+    @Test
+    public void testWriteLong() {
+        test(Long.MAX_VALUE);
+        test(Long.MIN_VALUE);
+    }
+
+    @Test
+    public void testWrite8() {
+        testUint(Uint8.ONE);
+        testUint(Uint8.TWO);
+        testUint(Uint8.TEN);
+        testUint(Uint8.MAX_VALUE);
+    }
+
+    @Test
+    public void testWrite16() {
+        testUint(Uint16.ONE);
+        testUint(Uint16.TWO);
+        testUint(Uint16.TEN);
+        testUint(Uint16.MAX_VALUE);
+    }
+
+    @Test
+    public void testWrite32() {
+        testUint(Uint32.ONE);
+        testUint(Uint32.TWO);
+        testUint(Uint32.TEN);
+        testUint(Uint32.MAX_VALUE);
+    }
+
+    @Test
+    public void testWrite64() {
+        testUint(Uint64.ONE);
+        testUint(Uint64.TWO);
+        testUint(Uint64.TEN);
+        testUint(Uint64.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteOptionalByte() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOptional(buf, (Byte) null);
+        assertEquals(0, buf.readableBytes());
+
+        ByteBufUtils.writeOptional(buf, Byte.MAX_VALUE);
+        assertEquals(1, buf.readableBytes());
+    }
+
+    @Test
+    public void testWriteOptionalShort() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOptional(buf, (Short) null);
+        assertEquals(0, buf.readableBytes());
+
+        ByteBufUtils.writeOptional(buf, Short.MAX_VALUE);
+        assertEquals(2, buf.readableBytes());
+    }
+
+    @Test
+    public void testWriteOptionalInt() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOptional(buf, (Integer) null);
+        assertEquals(0, buf.readableBytes());
+
+        ByteBufUtils.writeOptional(buf, Integer.MAX_VALUE);
+        assertEquals(4, buf.readableBytes());
+    }
+
+    @Test
+    public void testWriteOptionalLong() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOptional(buf, (Long) null);
+        assertEquals(0, buf.readableBytes());
+
+        ByteBufUtils.writeOptional(buf, Long.MAX_VALUE);
+        assertEquals(8, buf.readableBytes());
+    }
+
+    @Test
+    public void testWriteOptional8() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOptional(buf, (Uint8) null);
+        assertEquals(0, buf.readableBytes());
+
+        ByteBufUtils.writeOptional(buf, Uint8.MAX_VALUE);
+        assertUint(buf, Uint8.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteOptional16() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOptional(buf, (Uint16) null);
+        assertEquals(0, buf.readableBytes());
+
+        ByteBufUtils.writeOptional(buf, Uint16.MAX_VALUE);
+        assertUint(buf, Uint16.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteOptional32() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOptional(buf, (Uint32) null);
+        assertEquals(0, buf.readableBytes());
+
+        ByteBufUtils.writeOptional(buf, Uint32.MAX_VALUE);
+        assertUint(buf, Uint32.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteOptional64() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOptional(buf, (Uint64) null);
+        assertEquals(0, buf.readableBytes());
+
+        ByteBufUtils.writeOptional(buf, Uint64.MAX_VALUE);
+        assertUint(buf, Uint64.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteZeroByte() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOrZero(buf, (Byte) null);
+        assertByte(buf, 0);
+
+        ByteBufUtils.writeOrZero(buf, Byte.MAX_VALUE);
+        assertByte(buf, Byte.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteZeroShort() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOrZero(buf, (Short) null);
+        assertShort(buf, 0);
+
+        ByteBufUtils.writeOrZero(buf, Short.MAX_VALUE);
+        assertShort(buf, Short.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteZeroInt() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOrZero(buf, (Integer) null);
+        assertInt(buf, 0);
+
+        ByteBufUtils.writeOrZero(buf, Integer.MAX_VALUE);
+        assertInt(buf, Integer.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteZeroLong() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOrZero(buf, (Long) null);
+        assertLong(buf, 0);
+
+        ByteBufUtils.writeOrZero(buf, Long.MAX_VALUE);
+        assertLong(buf, Long.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteZero8() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOrZero(buf, (Uint8) null);
+        assertUint(buf, Uint8.ZERO);
+
+        ByteBufUtils.writeOrZero(buf, Uint8.MAX_VALUE);
+        assertUint(buf, Uint8.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteZero16() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOrZero(buf, (Uint16) null);
+        assertUint(buf, Uint16.ZERO);
+
+        ByteBufUtils.writeOrZero(buf, Uint16.MAX_VALUE);
+        assertUint(buf, Uint16.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteZero32() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOrZero(buf, (Uint32) null);
+        assertUint(buf, Uint32.ZERO);
+
+        ByteBufUtils.writeOrZero(buf, Uint32.MAX_VALUE);
+        assertUint(buf, Uint32.MAX_VALUE);
+    }
+
+    @Test
+    public void testWriteZero64() {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeOrZero(buf, (Uint64) null);
+        assertUint(buf, Uint64.ZERO);
+
+        ByteBufUtils.writeOrZero(buf, Uint64.MAX_VALUE);
+        assertUint(buf, Uint64.MAX_VALUE);
+    }
+
+    private static void test(final Byte value) {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeMandatory(buf, value, "foo");
+        assertByte(buf, value);
+    }
+
+    private static void test(final Short value) {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeMandatory(buf, value, "foo");
+        assertShort(buf, value);
+    }
+
+    private static void test(final Integer value) {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeMandatory(buf, value, "foo");
+        assertInt(buf, value);
+    }
+
+    private static void test(final Long value) {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeMandatory(buf, value, "foo");
+        assertLong(buf, value);
+    }
+
+    private static void testUint(final Uint8 value) {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeMandatory(buf, value, "foo");
+        assertUint(buf, value);
+    }
+
+    private static void testUint(final Uint16 value) {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeMandatory(buf, value, "foo");
+        assertUint(buf, value);
+    }
+
+    private static void testUint(final Uint32 value) {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeMandatory(buf, value, "foo");
+        assertUint(buf, value);
+    }
+
+    private static void testUint(final Uint64 value) {
+        final ByteBuf buf = Unpooled.buffer();
+        ByteBufUtils.writeMandatory(buf, value, "foo");
+        assertUint(buf, value);
+    }
+
+    private static void assertByte(final ByteBuf buf, final int value) {
+        assertEquals(1, buf.readableBytes());
+        assertEquals(value, buf.readByte());
+    }
+
+    private static void assertShort(final ByteBuf buf, final int value) {
+        assertEquals(2, buf.readableBytes());
+        assertEquals(value, buf.readShort());
+    }
+
+    private static void assertInt(final ByteBuf buf, final int value) {
+        assertEquals(4, buf.readableBytes());
+        assertEquals(value, buf.readInt());
+    }
+
+    private static void assertLong(final ByteBuf buf, final long value) {
+        assertEquals(8, buf.readableBytes());
+        assertEquals(value, buf.readLong());
+    }
+
+    private static void assertUint(final ByteBuf buf, final Uint8 value) {
+        assertEquals(1, buf.readableBytes());
+        assertEquals(value, ByteBufUtils.readUint8(buf));
+    }
+
+    private static void assertUint(final ByteBuf buf, final Uint16 value) {
+        assertEquals(2, buf.readableBytes());
+        assertEquals(value, ByteBufUtils.readUint16(buf));
+    }
+
+    private static void assertUint(final ByteBuf buf, final Uint32 value) {
+        assertEquals(4, buf.readableBytes());
+        assertEquals(value, ByteBufUtils.readUint32(buf));
+    }
+
+    private static void assertUint(final ByteBuf buf, final Uint64 value) {
+        assertEquals(8, buf.readableBytes());
+        assertEquals(value, ByteBufUtils.readUint64(buf));
+    }
+}