53c0c6c52fa7508d7dad92a79d267ee7bbea0720
[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 write(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 write(final ByteBuf buf, final Uint16 value) {
109         buf.writeShort(value.shortValue());
110     }
111
112     /**
113      * Write a {@link Uint32} from 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 write(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 write(final ByteBuf buf, final Uint64 value) {
131         buf.writeLong(value.longValue());
132     }
133
134     /**
135      * Write a {@link Byte} property to specified buffer. If the {@code value} is known to be non-null, prefer
136      * {@link ByteBuf#writeByte(int)} instead of this method.
137      *
138      * @param buf buffer
139      * @param value A {@link Byte}
140      * @param name Property name for error reporting purposes
141      * @throws NullPointerException if {@code buf} is null
142      * @throws IllegalArgumentException if {@code value} is null
143      */
144     public static void writeMandatory(final ByteBuf buf, final Byte value, final String name) {
145         buf.writeByte(nonNullArgument(value, name).byteValue());
146     }
147
148     /**
149      * Write a {@link Short} property to specified buffer. If the {@code value} is known to be non-null, prefer
150      * {@link ByteBuf#writeShort(int)} instead of this method.
151      *
152      * @param buf buffer
153      * @param value A {@link Short}
154      * @param name Property name for error reporting purposes
155      * @throws NullPointerException if {@code buf} is null
156      * @throws IllegalArgumentException if {@code value} is null
157      */
158     public static void writeMandatory(final ByteBuf buf, final Short value, final String name) {
159         buf.writeShort(nonNullArgument(value, name).shortValue());
160     }
161
162     /**
163      * Write a {@link Integer} property to specified buffer. If the {@code value} is known to be non-null, prefer
164      * {@link ByteBuf#writeInt(int)} instead of this method.
165      *
166      * @param buf buffer
167      * @param value A {@link Integer}
168      * @param name Property name for error reporting purposes
169      * @throws NullPointerException if {@code buf} is null
170      * @throws IllegalArgumentException if {@code value} is null
171      */
172     public static void writeMandatory(final ByteBuf buf, final Integer value, final String name) {
173         buf.writeInt(nonNullArgument(value, name).intValue());
174     }
175
176     /**
177      * Write a {@link Long} property to specified buffer. If the {@code value} is known to be non-null, prefer
178      * {@link ByteBuf#writeLong(long)} instead of this method.
179      *
180      * @param buf buffer
181      * @param value A {@link Long}
182      * @param name Property name for error reporting purposes
183      * @throws NullPointerException if {@code buf} is null
184      * @throws IllegalArgumentException if {@code value} is null
185      */
186     public static void writeMandatory(final ByteBuf buf, final Long value, final String name) {
187         buf.writeLong(nonNullArgument(value, name).longValue());
188     }
189
190     /**
191      * Write a {@link Uint8} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
192      * {@link #write(ByteBuf, Uint8)} instead of this method.
193      *
194      * @param buf buffer
195      * @param value A {@link Uint8}
196      * @param name Property name for error reporting purposes
197      * @throws NullPointerException if {@code buf} is null
198      * @throws IllegalArgumentException if {@code value} is null
199      */
200     public static void writeMandatory(final ByteBuf buf, final Uint8 value, final String name) {
201         write(buf, nonNullArgument(value, name));
202     }
203
204     /**
205      * Write a {@link Uint16} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
206      * {@link #write(ByteBuf, Uint16)} instead of this method.
207      *
208      * @param buf buffer
209      * @param value A {@link Uint16}
210      * @param name Property name for error reporting purposes
211      * @throws NullPointerException if {@code buf} is null
212      * @throws IllegalArgumentException if {@code value} is null
213      */
214     public static void writeMandatory(final ByteBuf buf, final Uint16 value, final String name) {
215         write(buf, nonNullArgument(value, name));
216     }
217
218     /**
219      * Write a {@link Uint32} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
220      * {@link #write(ByteBuf, Uint32)} instead of this method.
221      *
222      * @param buf buffer
223      * @param value A {@link Uint32}
224      * @param name Property name for error reporting purposes
225      * @throws NullPointerException if {@code buf} is null
226      * @throws IllegalArgumentException if {@code value} is null
227      */
228     public static void writeMandatory(final ByteBuf buf, final Uint32 value, final String name) {
229         write(buf, nonNullArgument(value, name));
230     }
231
232     /**
233      * Write a {@link Uint64} property to specified buffer. If the {@code value} is known to be non-null, prefer to use
234      * {@link #write(ByteBuf, Uint64)} instead of this method.
235      *
236      * @param buf buffer
237      * @param value A {@link Uint64}
238      * @param name Property name for error reporting purposes
239      * @throws NullPointerException if {@code buf} is null
240      * @throws IllegalArgumentException if {@code value} is null
241      */
242     public static void writeMandatory(final ByteBuf buf, final Uint64 value, final String name) {
243         write(buf, nonNullArgument(value, name));
244     }
245
246     /**
247      * Write a {@link Byte} value to specified buffer if it is not null.
248      *
249      * @param buf buffer
250      * @param value A {@link Byte}
251      * @throws NullPointerException if {@code buf} is null
252      */
253     public static void writeOptional(final ByteBuf buf, final @Nullable Byte value) {
254         if (value != null) {
255             buf.writeByte(value.byteValue());
256         }
257     }
258
259     /**
260      * Write a {@link Byte} value to specified buffer if it is not null.
261      *
262      * @param buf buffer
263      * @param value A {@link Short}
264      * @throws NullPointerException if {@code buf} is null
265      */
266     public static void writeOptional(final ByteBuf buf, final @Nullable Short value) {
267         if (value != null) {
268             buf.writeShort(value.shortValue());
269         }
270     }
271
272     /**
273      * Write a {@link Integer} value to specified buffer if it is not null.
274      *
275      * @param buf buffer
276      * @param value A {@link Integer}
277      * @throws NullPointerException if {@code buf} is null
278      */
279     public static void writeOptional(final ByteBuf buf, final @Nullable Integer value) {
280         if (value != null) {
281             buf.writeInt(value.intValue());
282         }
283     }
284
285     /**
286      * Write a {@link Long} value to specified buffer if it is not null.
287      *
288      * @param buf buffer
289      * @param value A {@link Long}
290      * @throws NullPointerException if {@code buf} is null
291      */
292     public static void writeOptional(final ByteBuf buf, final @Nullable Long value) {
293         if (value != null) {
294             buf.writeLong(value.longValue());
295         }
296     }
297
298     /**
299      * Write a {@link Uint8} value to specified buffer if it is not null.
300      *
301      * @param buf buffer
302      * @param value A {@link Uint8}
303      * @throws NullPointerException if {@code buf} is null
304      */
305     public static void writeOptional(final ByteBuf buf, final @Nullable Uint8 value) {
306         if (value != null) {
307             write(buf, value);
308         }
309     }
310
311     /**
312      * Write a {@link Uint16} value to specified buffer if it is not null.
313      *
314      * @param buf buffer
315      * @param value A {@link Uint16}
316      * @throws NullPointerException if {@code buf} is null
317      */
318     public static void writeOptional(final ByteBuf buf, final @Nullable Uint16 value) {
319         if (value != null) {
320             write(buf, value);
321         }
322     }
323
324     /**
325      * Write a {@link Uint32} value to specified buffer if it is not null.
326      *
327      * @param buf buffer
328      * @param value A {@link Uint32}
329      * @throws NullPointerException if {@code buf} is null
330      */
331     public static void writeOptional(final ByteBuf buf, final @Nullable Uint32 value) {
332         if (value != null) {
333             write(buf, value);
334         }
335     }
336
337     /**
338      * Write a {@link Uint64} value to specified buffer if it is not null.
339      *
340      * @param buf buffer
341      * @param value A {@link Uint64}
342      * @throws NullPointerException if {@code buf} is null
343      */
344     public static void writeOptional(final ByteBuf buf, final @Nullable Uint64 value) {
345         if (value != null) {
346             write(buf, value);
347         }
348     }
349
350     /**
351      * Write a {@link Byte} value to specified buffer if it is not null, otherwise write one zero byte.
352      *
353      * @param buf buffer
354      * @param value A {@link Byte}
355      * @throws NullPointerException if {@code buf} is null
356      */
357     public static void writeOrZero(final ByteBuf buf, final @Nullable Byte value) {
358         buf.writeByte(value != null ? value.byteValue() : 0);
359     }
360
361     /**
362      * Write a {@link Short} value to specified buffer if it is not null, otherwise write two zero bytes.
363      *
364      * @param buf buffer
365      * @param value A {@link Short}
366      * @throws NullPointerException if {@code buf} is null
367      */
368     public static void writeOrZero(final ByteBuf buf, final @Nullable Short value) {
369         buf.writeShort(value != null ? value.shortValue() : (short) 0);
370     }
371
372     /**
373      * Write a {@link Integer} value to specified buffer if it is not null, otherwise write four zero bytes.
374      *
375      * @param buf buffer
376      * @param value A {@link Integer}
377      * @throws NullPointerException if {@code buf} is null
378      */
379     public static void writeOrZero(final ByteBuf buf, final @Nullable Integer value) {
380         buf.writeInt(value != null ? value.intValue() : 0);
381     }
382
383     /**
384      * Write a {@link Byte} value to specified buffer if it is not null, otherwise write eight zero bytes.
385      *
386      * @param buf buffer
387      * @param value A {@link Byte}
388      * @throws NullPointerException if {@code buf} is null
389      */
390     public static void writeOrZero(final ByteBuf buf, final @Nullable Long value) {
391         buf.writeLong(value != null ? value.longValue() : 0L);
392     }
393
394     /**
395      * Write a {@link Uint8} value to specified buffer if it is not null, otherwise write one zero byte.
396      *
397      * @param buf buffer
398      * @param value A {@link Uint8}
399      * @throws NullPointerException if {@code buf} is null
400      */
401     public static void writeOrZero(final ByteBuf buf, final @Nullable Uint8 value) {
402         buf.writeByte(value != null ? value.byteValue() : 0);
403     }
404
405     /**
406      * Write a {@link Uint16} value to specified buffer if it is not null, otherwise write two zero bytes.
407      *
408      * @param buf buffer
409      * @param value A {@link Uint16}
410      * @throws NullPointerException if {@code buf} is null
411      */
412     public static void writeOrZero(final ByteBuf buf, final @Nullable Uint16 value) {
413         buf.writeShort(value != null ? value.shortValue() : (short) 0);
414     }
415
416     /**
417      * Write a {@link Uint32} value to specified buffer if it is not null, otherwise write four zero bytes.
418      *
419      * @param buf buffer
420      * @param value A {@link Uint32}
421      * @throws NullPointerException if {@code buf} is null
422      */
423     public static void writeOrZero(final ByteBuf buf, final @Nullable Uint32 value) {
424         buf.writeInt(value != null ? value.intValue() : 0);
425     }
426
427     /**
428      * Write a {@link Uint64} value to specified buffer if it is not null, otherwise write eight zero bytes.
429      *
430      * @param buf buffer
431      * @param value A {@link Uint64}
432      * @throws NullPointerException if {@code buf} is null
433      */
434     public static void writeOrZero(final ByteBuf buf, final @Nullable Uint64 value) {
435         buf.writeLong(value != null ? value.longValue() : 0L);
436     }
437
438     private static <T> @NonNull T nonNullArgument(final @Nullable T obj, final String name) {
439         if (obj == null) {
440             throw new IllegalArgumentException(name + " is mandatory");
441         }
442         return obj;
443     }
444 }