Add ByteBufUtils.writeUint{8,16,32,64}
[yangtools.git] / yang / yang-common-netty / src / main / java / org / opendaylight / yangtools / yang / common / netty / ByteBufUtils.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.common.netty;
9
10 import com.google.common.annotations.Beta;
11 import io.netty.buffer.ByteBuf;
12 import org.eclipse.jdt.annotation.NonNull;
13 import org.eclipse.jdt.annotation.Nullable;
14 import org.opendaylight.yangtools.yang.common.Uint16;
15 import org.opendaylight.yangtools.yang.common.Uint32;
16 import org.opendaylight.yangtools.yang.common.Uint64;
17 import org.opendaylight.yangtools.yang.common.Uint8;
18
19 /**
20  * Utility methods for interacting with {@link ByteBuf}s. These add a number of methods for reading and writing various
21  * data types from/to ByteBufs. Methods fall into these categories:
22  * <ul>
23  *   <li>{@code readUint*}, which extract the corresponding amount of data from a buffer and return an Uint type. These
24  *       are more efficient than going the {@code Uint8.valueOf(buf.readUnsignedByte())} route.</li>
25  *   <li>{@code writeUint*}, which write specified value into a buffer.</li>
26  *   <li>{@code writeMandatory*}, which write a property not statically known to be non-null. These methods throw
27  *       an {@link IllegalArgumentException} if the supplied value is null. Otherwise they will write it to provided
28  *       buffer.</li>
29  *   <li>{@code writeOptional*}, which write a value which can legally be null. In case the value is not null, it is
30  *       written to the provided buffer. If the value null, the method does nothing.</li>
31  *   <li>{@code writeOrZero*}, which write a value which can legally be null. In case the value is not null, it is
32  *       written to the provided buffer. If the value is null, a {code zero} value of corresponding width is written
33  *       instead.</li>
34  * </ul>
35  */
36 @Beta
37 public final class ByteBufUtils {
38     private ByteBufUtils() {
39
40     }
41
42     /**
43      * Read an {@link Uint8} from specified buffer.
44      *
45      * @param buf buffer
46      * @return A {@link Uint8}
47      * @throws NullPointerException if {@code buf} is null
48      * @throws IndexOutOfBoundsException if {@code buf} does not have enough data
49      */
50     public static @NonNull Uint8 readUint8(final ByteBuf buf) {
51         return Uint8.fromByteBits(buf.readByte());
52     }
53
54     /**
55      * Read a {@link Uint16} from specified buffer.
56      *
57      * @param buf buffer
58      * @return A {@link Uint16}
59      * @throws NullPointerException if {@code buf} is null
60      * @throws IndexOutOfBoundsException if {@code buf} does not have enough data
61      */
62     public static @NonNull Uint16 readUint16(final ByteBuf buf) {
63         return Uint16.fromShortBits(buf.readShort());
64     }
65
66     /**
67      * Read a {@link Uint32} from specified buffer.
68      *
69      * @param buf buffer
70      * @return A {@link Uint32}
71      * @throws NullPointerException if {@code buf} is null
72      * @throws IndexOutOfBoundsException if {@code buf} does not have enough data
73      */
74     public static @NonNull Uint32 readUint32(final ByteBuf buf) {
75         return Uint32.fromIntBits(buf.readInt());
76     }
77
78     /**
79      * Read a {@link Uint64} from specified buffer.
80      *
81      * @param buf buffer
82      * @return A {@link Uint64}
83      * @throws NullPointerException if {@code buf} is null
84      * @throws IndexOutOfBoundsException if {@code buf} does not have enough data
85      */
86     public static @NonNull Uint64 readUint64(final ByteBuf buf) {
87         return Uint64.fromLongBits(buf.readLong());
88     }
89
90     /**
91      * Write a {@link Uint8} to specified buffer.
92      *
93      * @param buf buffer
94      * @param value A {@link Uint8}
95      * @throws NullPointerException if any argument is null
96      */
97     public static void writeUint8(final ByteBuf buf, final Uint8 value) {
98         buf.writeByte(value.byteValue());
99     }
100
101     /**
102      * Write a {@link Uint16} to specified buffer.
103      *
104      * @param buf buffer
105      * @param value A {@link Uint16}
106      * @throws NullPointerException if any argument is null
107      */
108     public static void writeUint16(final ByteBuf buf, final Uint16 value) {
109         buf.writeShort(value.shortValue());
110     }
111
112     /**
113      * Write a {@link Uint32} to specified buffer.
114      *
115      * @param buf buffer
116      * @param value A {@link Uint32}
117      * @throws NullPointerException if any argument is null
118      */
119     public static void writeUint32(final ByteBuf buf, final Uint32 value) {
120         buf.writeInt(value.intValue());
121     }
122
123     /**
124      * Write a {@link Uint64} to specified buffer.
125      *
126      * @param buf buffer
127      * @param value A {@link Uint64}
128      * @throws NullPointerException if any argument is null
129      */
130     public static void writeUint64(final ByteBuf buf, final Uint64 value) {
131         buf.writeLong(value.longValue());
132     }
133
134     /**
135      * Write a {@link Uint8} to specified buffer. This method is provided for convenience, you may want to use
136      * {@link #writeUint8(ByteBuf, Uint8)} as it is more explicit.
137      *
138      * @param buf buffer
139      * @param value A {@link Uint8}
140      * @throws NullPointerException if any argument is null
141      */
142     public static void write(final ByteBuf buf, final Uint8 value) {
143         writeUint8(buf, value);
144     }
145
146     /**
147      * Write a {@link Uint16} to specified buffer. This method is provided for convenience, you may want to use
148      * {@link #writeUint16(ByteBuf, Uint16)} as it is more explicit.
149      *
150      * @param buf buffer
151      * @param value A {@link Uint16}
152      * @throws NullPointerException if any argument is null
153      */
154     public static void write(final ByteBuf buf, final Uint16 value) {
155         writeUint16(buf, value);
156     }
157
158     /**
159      * Write a {@link Uint32} to specified buffer. This method is provided for convenience, you may want to use
160      * {@link #writeUint32(ByteBuf, Uint32)} as it is more explicit.
161      *
162      * @param buf buffer
163      * @param value A {@link Uint32}
164      * @throws NullPointerException if any argument is null
165      */
166     public static void write(final ByteBuf buf, final Uint32 value) {
167         writeUint32(buf, value);
168     }
169
170     /**
171      * Write a {@link Uint64} to specified buffer. This method is provided for convenience, you may want to use
172      * {@link #writeUint64(ByteBuf, Uint64)} as it is more explicit.
173      *
174      * @param buf buffer
175      * @param value A {@link Uint64}
176      * @throws NullPointerException if any argument is null
177      */
178     public static void write(final ByteBuf buf, final Uint64 value) {
179         writeUint64(buf, value);
180     }
181
182     /**
183      * Write a {@link Byte} property to specified buffer. If the {@code value} is known to be non-null, prefer
184      * {@link ByteBuf#writeByte(int)} instead of this method.
185      *
186      * @param buf buffer
187      * @param value A {@link Byte}
188      * @param name Property name for error reporting purposes
189      * @throws NullPointerException if {@code buf} is null
190      * @throws IllegalArgumentException if {@code value} is null
191      */
192     public static void writeMandatory(final ByteBuf buf, final Byte value, final String name) {
193         buf.writeByte(nonNullArgument(value, name).byteValue());
194     }
195
196     /**
197      * Write a {@link Short} property to specified buffer. If the {@code value} is known to be non-null, prefer
198      * {@link ByteBuf#writeShort(int)} instead of this method.
199      *
200      * @param buf buffer
201      * @param value A {@link Short}
202      * @param name Property name for error reporting purposes
203      * @throws NullPointerException if {@code buf} is null
204      * @throws IllegalArgumentException if {@code value} is null
205      */
206     public static void writeMandatory(final ByteBuf buf, final Short value, final String name) {
207         buf.writeShort(nonNullArgument(value, name).shortValue());
208     }
209
210     /**
211      * Write a {@link Integer} property to specified buffer. If the {@code value} is known to be non-null, prefer
212      * {@link ByteBuf#writeInt(int)} instead of this method.
213      *
214      * @param buf buffer
215      * @param value A {@link Integer}
216      * @param name Property name for error reporting purposes
217      * @throws NullPointerException if {@code buf} is null
218      * @throws IllegalArgumentException if {@code value} is null
219      */
220     public static void writeMandatory(final ByteBuf buf, final Integer value, final String name) {
221         buf.writeInt(nonNullArgument(value, name));
222     }
223
224     /**
225      * Write a {@link Long} property to specified buffer. If the {@code value} is known to be non-null, prefer
226      * {@link ByteBuf#writeLong(long)} instead of this method.
227      *
228      * @param buf buffer
229      * @param value A {@link Long}
230      * @param name Property name for error reporting purposes
231      * @throws NullPointerException if {@code buf} is null
232      * @throws IllegalArgumentException if {@code value} is null
233      */
234     public static void writeMandatory(final ByteBuf buf, final Long value, final String name) {
235         buf.writeLong(nonNullArgument(value, name));
236     }
237
238     /**
239      * Write a {@link Uint8} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
240      * {@link #write(ByteBuf, Uint8)} instead of this method.
241      *
242      * @param buf buffer
243      * @param value A {@link Uint8}
244      * @param name Property name for error reporting purposes
245      * @throws NullPointerException if {@code buf} is null
246      * @throws IllegalArgumentException if {@code value} is null
247      */
248     public static void writeMandatory(final ByteBuf buf, final Uint8 value, final String name) {
249         write(buf, nonNullArgument(value, name));
250     }
251
252     /**
253      * Write a {@link Uint16} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
254      * {@link #write(ByteBuf, Uint16)} instead of this method.
255      *
256      * @param buf buffer
257      * @param value A {@link Uint16}
258      * @param name Property name for error reporting purposes
259      * @throws NullPointerException if {@code buf} is null
260      * @throws IllegalArgumentException if {@code value} is null
261      */
262     public static void writeMandatory(final ByteBuf buf, final Uint16 value, final String name) {
263         write(buf, nonNullArgument(value, name));
264     }
265
266     /**
267      * Write a {@link Uint32} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
268      * {@link #write(ByteBuf, Uint32)} instead of this method.
269      *
270      * @param buf buffer
271      * @param value A {@link Uint32}
272      * @param name Property name for error reporting purposes
273      * @throws NullPointerException if {@code buf} is null
274      * @throws IllegalArgumentException if {@code value} is null
275      */
276     public static void writeMandatory(final ByteBuf buf, final Uint32 value, final String name) {
277         write(buf, nonNullArgument(value, name));
278     }
279
280     /**
281      * Write a {@link Uint64} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
282      * {@link #write(ByteBuf, Uint64)} instead of this method.
283      *
284      * @param buf buffer
285      * @param value A {@link Uint64}
286      * @param name Property name for error reporting purposes
287      * @throws NullPointerException if {@code buf} is null
288      * @throws IllegalArgumentException if {@code value} is null
289      */
290     public static void writeMandatory(final ByteBuf buf, final Uint64 value, final String name) {
291         write(buf, nonNullArgument(value, name));
292     }
293
294     /**
295      * Write a {@link Byte} value to specified buffer if it is not null.
296      *
297      * @param buf buffer
298      * @param value A {@link Byte}
299      * @throws NullPointerException if {@code buf} is null
300      */
301     public static void writeOptional(final ByteBuf buf, final @Nullable Byte value) {
302         if (value != null) {
303             buf.writeByte(value.byteValue());
304         }
305     }
306
307     /**
308      * Write a {@link Byte} value to specified buffer if it is not null.
309      *
310      * @param buf buffer
311      * @param value A {@link Short}
312      * @throws NullPointerException if {@code buf} is null
313      */
314     public static void writeOptional(final ByteBuf buf, final @Nullable Short value) {
315         if (value != null) {
316             buf.writeShort(value.shortValue());
317         }
318     }
319
320     /**
321      * Write a {@link Integer} value to specified buffer if it is not null.
322      *
323      * @param buf buffer
324      * @param value A {@link Integer}
325      * @throws NullPointerException if {@code buf} is null
326      */
327     public static void writeOptional(final ByteBuf buf, final @Nullable Integer value) {
328         if (value != null) {
329             buf.writeInt(value);
330         }
331     }
332
333     /**
334      * Write a {@link Long} value to specified buffer if it is not null.
335      *
336      * @param buf buffer
337      * @param value A {@link Long}
338      * @throws NullPointerException if {@code buf} is null
339      */
340     public static void writeOptional(final ByteBuf buf, final @Nullable Long value) {
341         if (value != null) {
342             buf.writeLong(value);
343         }
344     }
345
346     /**
347      * Write a {@link Uint8} value to specified buffer if it is not null.
348      *
349      * @param buf buffer
350      * @param value A {@link Uint8}
351      * @throws NullPointerException if {@code buf} is null
352      */
353     public static void writeOptional(final ByteBuf buf, final @Nullable Uint8 value) {
354         if (value != null) {
355             write(buf, value);
356         }
357     }
358
359     /**
360      * Write a {@link Uint16} value to specified buffer if it is not null.
361      *
362      * @param buf buffer
363      * @param value A {@link Uint16}
364      * @throws NullPointerException if {@code buf} is null
365      */
366     public static void writeOptional(final ByteBuf buf, final @Nullable Uint16 value) {
367         if (value != null) {
368             write(buf, value);
369         }
370     }
371
372     /**
373      * Write a {@link Uint32} value to specified buffer if it is not null.
374      *
375      * @param buf buffer
376      * @param value A {@link Uint32}
377      * @throws NullPointerException if {@code buf} is null
378      */
379     public static void writeOptional(final ByteBuf buf, final @Nullable Uint32 value) {
380         if (value != null) {
381             write(buf, value);
382         }
383     }
384
385     /**
386      * Write a {@link Uint64} value to specified buffer if it is not null.
387      *
388      * @param buf buffer
389      * @param value A {@link Uint64}
390      * @throws NullPointerException if {@code buf} is null
391      */
392     public static void writeOptional(final ByteBuf buf, final @Nullable Uint64 value) {
393         if (value != null) {
394             write(buf, value);
395         }
396     }
397
398     /**
399      * Write a {@link Byte} value to specified buffer if it is not null, otherwise write one zero byte.
400      *
401      * @param buf buffer
402      * @param value A {@link Byte}
403      * @throws NullPointerException if {@code buf} is null
404      */
405     public static void writeOrZero(final ByteBuf buf, final @Nullable Byte value) {
406         buf.writeByte(value != null ? value.byteValue() : 0);
407     }
408
409     /**
410      * Write a {@link Short} value to specified buffer if it is not null, otherwise write two zero bytes.
411      *
412      * @param buf buffer
413      * @param value A {@link Short}
414      * @throws NullPointerException if {@code buf} is null
415      */
416     public static void writeOrZero(final ByteBuf buf, final @Nullable Short value) {
417         buf.writeShort(value != null ? value.shortValue() : (short) 0);
418     }
419
420     /**
421      * Write a {@link Integer} value to specified buffer if it is not null, otherwise write four zero bytes.
422      *
423      * @param buf buffer
424      * @param value A {@link Integer}
425      * @throws NullPointerException if {@code buf} is null
426      */
427     public static void writeOrZero(final ByteBuf buf, final @Nullable Integer value) {
428         buf.writeInt(value != null ? value : 0);
429     }
430
431     /**
432      * Write a {@link Byte} value to specified buffer if it is not null, otherwise write eight zero bytes.
433      *
434      * @param buf buffer
435      * @param value A {@link Byte}
436      * @throws NullPointerException if {@code buf} is null
437      */
438     public static void writeOrZero(final ByteBuf buf, final @Nullable Long value) {
439         buf.writeLong(value != null ? value : 0L);
440     }
441
442     /**
443      * Write a {@link Uint8} value to specified buffer if it is not null, otherwise write one zero byte.
444      *
445      * @param buf buffer
446      * @param value A {@link Uint8}
447      * @throws NullPointerException if {@code buf} is null
448      */
449     public static void writeOrZero(final ByteBuf buf, final @Nullable Uint8 value) {
450         buf.writeByte(value != null ? value.byteValue() : 0);
451     }
452
453     /**
454      * Write a {@link Uint16} value to specified buffer if it is not null, otherwise write two zero bytes.
455      *
456      * @param buf buffer
457      * @param value A {@link Uint16}
458      * @throws NullPointerException if {@code buf} is null
459      */
460     public static void writeOrZero(final ByteBuf buf, final @Nullable Uint16 value) {
461         buf.writeShort(value != null ? value.shortValue() : (short) 0);
462     }
463
464     /**
465      * Write a {@link Uint32} value to specified buffer if it is not null, otherwise write four zero bytes.
466      *
467      * @param buf buffer
468      * @param value A {@link Uint32}
469      * @throws NullPointerException if {@code buf} is null
470      */
471     public static void writeOrZero(final ByteBuf buf, final @Nullable Uint32 value) {
472         buf.writeInt(value != null ? value.intValue() : 0);
473     }
474
475     /**
476      * Write a {@link Uint64} value to specified buffer if it is not null, otherwise write eight zero bytes.
477      *
478      * @param buf buffer
479      * @param value A {@link Uint64}
480      * @throws NullPointerException if {@code buf} is null
481      */
482     public static void writeOrZero(final ByteBuf buf, final @Nullable Uint64 value) {
483         buf.writeLong(value != null ? value.longValue() : 0L);
484     }
485
486     private static <T> @NonNull T nonNullArgument(final @Nullable T obj, final String name) {
487         if (obj == null) {
488             throw new IllegalArgumentException(name + " is mandatory");
489         }
490         return obj;
491     }
492 }