Migrate RFC references to rfc-editor.org
[yangtools.git] / common / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / Uint16.java
1 /*
2  * Copyright (c) 2015 Pantheon Technologies 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;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.collect.Interner;
14 import com.google.common.collect.Interners;
15 import java.io.Serial;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.yangtools.concepts.Either;
20
21 /**
22  * Dedicated type for YANG's 'type uint16' type.
23  *
24  * @author Robert Varga
25  */
26 @Beta
27 @NonNullByDefault
28 public class Uint16 extends Number implements CanonicalValue<Uint16> {
29     public static final class Support extends AbstractCanonicalValueSupport<Uint16> {
30         public Support() {
31             super(Uint16.class);
32         }
33
34         @Override
35         public Either<Uint16, CanonicalValueViolation> fromString(final String str) {
36             try {
37                 return Either.ofFirst(Uint16.valueOf(str));
38             } catch (IllegalArgumentException e) {
39                 return CanonicalValueViolation.variantOf(e);
40             }
41         }
42     }
43
44     private static final CanonicalValueSupport<Uint16> SUPPORT = new Support();
45     @Serial
46     private static final long serialVersionUID = 1L;
47     private static final int MAX_VALUE_INT = 65535;
48     private static final String MAX_VALUE_STR = "65535";
49
50     private static final String CACHE_SIZE_PROPERTY = "org.opendaylight.yangtools.yang.common.Uint16.cache.size";
51     private static final int DEFAULT_CACHE_SIZE = 256;
52
53     /**
54      * Tunable cache for values. By default it holds {@value #DEFAULT_CACHE_SIZE} entries. This can be
55      * changed via {@value #CACHE_SIZE_PROPERTY} system property.
56      */
57     private static final int CACHE_SIZE;
58
59     static {
60         final int p = Integer.getInteger(CACHE_SIZE_PROPERTY, DEFAULT_CACHE_SIZE);
61         CACHE_SIZE = p >= 0 ? Math.min(p, MAX_VALUE_INT + 1) : DEFAULT_CACHE_SIZE;
62     }
63
64     private static final @NonNull Uint16[] CACHE;
65
66     static {
67         final Uint16[] c = new Uint16[CACHE_SIZE];
68         for (int i = 0; i < c.length; ++i) {
69             c[i] = new Uint16((short) i);
70         }
71         CACHE = c;
72     }
73
74     private static final Interner<Uint16> INTERNER = Interners.newWeakInterner();
75
76     /**
77      * Value of {@code 0}.
78      */
79     public static final Uint16 ZERO = valueOf(0).intern();
80     /**
81      * Value of {@code 1}.
82      */
83     public static final Uint16 ONE = valueOf(1).intern();
84     /**
85      * Value of {@code 2}.
86      */
87     public static final Uint16 TWO = valueOf(2).intern();
88     /**
89      * Value of {@code 10}.
90      */
91     public static final Uint16 TEN = valueOf(10).intern();
92     /**
93      * Value of {@code 65535}.
94      */
95     public static final Uint16 MAX_VALUE = valueOf(MAX_VALUE_INT).intern();
96
97     private final short value;
98
99     private Uint16(final short value) {
100         this.value = value;
101     }
102
103     protected Uint16(final Uint16 other) {
104         this(other.value);
105     }
106
107     private static Uint16 instanceFor(final short value) {
108         final int slot = Short.toUnsignedInt(value);
109         return slot < CACHE.length ? CACHE[slot] : new Uint16(value);
110     }
111
112     /**
113      * Returns an {@code Uint16} corresponding to a given bit representation. The argument is interpreted as an
114      * unsigned 16-bit value.
115      *
116      * @param bits unsigned bit representation
117      * @return A Uint16 instance
118      */
119     public static Uint16 fromShortBits(final short bits) {
120         return instanceFor(bits);
121     }
122
123     /**
124      * Returns an {@code Uint16} corresponding to a given {@code byteVal}. The inverse operation is
125      * {@link #byteValue()}.
126      *
127      * @param byteVal byte value
128      * @return A Uint16 instance
129      * @throws IllegalArgumentException if byteVal is less than zero
130      */
131     public static Uint16 valueOf(final byte byteVal) {
132         UintConversions.checkNonNegative(byteVal, MAX_VALUE_STR);
133         return instanceFor(byteVal);
134     }
135
136     /**
137      * Returns an {@code Uint16} corresponding to a given {@code shortVal}. The inverse operation is
138      * {@link #shortValue()}.
139      *
140      * @param shortVal short value
141      * @return A Uint16 instance
142      * @throws IllegalArgumentException if shortVal is less than zero.
143      */
144     public static Uint16 valueOf(final short shortVal) {
145         UintConversions.checkNonNegative(shortVal, MAX_VALUE_STR);
146         return instanceFor(shortVal);
147     }
148
149     /**
150      * Returns an {@code Uint16} corresponding to a given {@code intVal}. The inverse operation is {@link #intValue()}.
151      *
152      * @param intVal int value
153      * @return A Uint16 instance
154      * @throws IllegalArgumentException if intVal is less than zero or greater than 65535.
155      */
156     public static Uint16 valueOf(final int intVal) {
157         UintConversions.checkRange(intVal, MAX_VALUE_INT);
158         return instanceFor((short)intVal);
159     }
160
161     /**
162      * Returns an {@code Uint16} corresponding to a given {@code longVal}. The inverse operation is
163      * {@link #longValue()}.
164      *
165      * @param longVal long value
166      * @return A Uint16 instance
167      * @throws IllegalArgumentException if intVal is less than zero or greater than 65535.
168      */
169     public static Uint16 valueOf(final long longVal) {
170         UintConversions.checkRange(longVal, MAX_VALUE_INT);
171         return instanceFor((short)longVal);
172     }
173
174     /**
175      * Returns an {@code Uint16} corresponding to a given {@code uint}.
176      *
177      * @param uint Uint8 value
178      * @return A Uint16 instance
179      * @throws NullPointerException if uint is null
180      */
181     public static Uint16 valueOf(final Uint8 uint) {
182         return instanceFor(uint.shortValue());
183     }
184
185     /**
186      * Returns an {@code Uint8} corresponding to a given {@code uint}.
187      *
188      * @param uint Uint32 value
189      * @return A Uint16 instance
190      * @throws NullPointerException if uint is null
191      * @throws IllegalArgumentException if uint is greater than 65535.
192      */
193     public static Uint16 valueOf(final Uint32 uint) {
194         return valueOf(uint.longValue());
195     }
196
197     /**
198      * Returns an {@code Uint8} corresponding to a given {@code uint}.
199      *
200      * @param uint Uint64 value
201      * @return A Uint16 instance
202      * @throws NullPointerException if uint is null
203      * @throws IllegalArgumentException if uint is greater than 65535.
204      */
205     public static Uint16 valueOf(final Uint64 uint) {
206         return valueOf(uint.longValue());
207     }
208
209     /**
210      * Returns an {@code Uint16} holding the value of the specified {@code String}, parsed as an unsigned {@code int}
211      * value.
212      *
213      * @param string String to parse
214      * @return A Uint16 instance
215      * @throws NullPointerException if string is null
216      * @throws IllegalArgumentException if the parsed value is less than zero or greater than 65535
217      * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int} value.
218      */
219     public static Uint16 valueOf(final String string) {
220         return valueOf(string, 10);
221     }
222
223     /**
224      * Returns an {@code Uint16} holding the value of the specified {@code String}, parsed as an unsigned {@code int}
225      * value.
226      *
227      * @param string String to parse
228      * @param radix Radix to use
229      * @return A Uint16 instance
230      * @throws NullPointerException if string is null
231      * @throws IllegalArgumentException if the parsed value is less than zero or greater than 65535
232      * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int} value, or if the
233      *                               {@code radix} is outside of allowed range.
234      */
235     public static Uint16 valueOf(final String string, final int radix) {
236         return valueOf(Integer.parseInt(requireNonNull(string), radix));
237     }
238
239     /**
240      * Returns an {@code Uint16} corresponding to a given {@code byteVal} if it is representable. If the value is
241      * negative {@link #ZERO} will be returned.
242      *
243      * @param byteVal byte value
244      * @return A Uint16 instance
245      */
246     public static Uint16 saturatedOf(final byte byteVal) {
247         return byteVal <= 0 ? Uint16.ZERO : instanceFor(byteVal);
248     }
249
250     /**
251      * Returns an {@code Uint16} corresponding to a given {@code shortVal} if it is representable. If the value is
252      * negative {@link #ZERO} will be returned.
253      *
254      * @param shortVal short value
255      * @return A Uint16 instance
256      */
257     public static Uint16 saturatedOf(final short shortVal) {
258         return shortVal <= 0 ? Uint16.ZERO : instanceFor(shortVal);
259     }
260
261     /**
262      * Returns an {@code Uint16} corresponding to a given {@code intVal} if it is representable. If the value is
263      * negative {@link #ZERO} will be returned. If the value is greater than 65535, {@link #MAX_VALUE} will be returned.
264      *
265      * @param intVal int value
266      * @return A Uint16 instance
267      */
268     public static Uint16 saturatedOf(final int intVal) {
269         if (intVal <= 0) {
270             return Uint16.ZERO;
271         }
272         if (intVal >= MAX_VALUE_INT) {
273             return Uint16.MAX_VALUE;
274         }
275         return instanceFor((short) intVal);
276     }
277
278     /**
279      * Returns an {@code Uint16} corresponding to a given {@code longVal} if it is representable. If the value is
280      * negative {@link #ZERO} will be returned. If the value is greater than 65535, {@link #MAX_VALUE} will be returned.
281      *
282      * @param longVal long value
283      * @return A Uint16 instance
284      */
285     public static Uint16 saturatedOf(final long longVal) {
286         if (longVal <= 0) {
287             return Uint16.ZERO;
288         }
289         if (longVal >= MAX_VALUE_INT) {
290             return Uint16.MAX_VALUE;
291         }
292         return instanceFor((short) longVal);
293     }
294
295     /**
296      * {@inheritDoc}
297      *
298      * <p>
299      * The inverse operation is {@link #fromShortBits(short)}. In case this value is greater than
300      * {@link Short#MAX_VALUE}, the returned value will be equal to {@code this - 2^16}.
301      */
302     @Override
303     public final short shortValue() {
304         return value;
305     }
306
307     @Override
308     public final int intValue() {
309         return Short.toUnsignedInt(value);
310     }
311
312     @Override
313     public final long longValue() {
314         return Short.toUnsignedLong(value);
315     }
316
317     @Override
318     public final float floatValue() {
319         return intValue();
320     }
321
322     @Override
323     public final double doubleValue() {
324         return intValue();
325     }
326
327     @Override
328     @SuppressWarnings("checkstyle:parameterName")
329     public final int compareTo(final Uint16 o) {
330         return Short.compareUnsigned(value, o.value);
331     }
332
333     @Override
334     public final String toCanonicalString() {
335         return Integer.toString(intValue());
336     }
337
338     @Override
339     public final CanonicalValueSupport<Uint16> support() {
340         return SUPPORT;
341     }
342
343     /**
344      * Return an interned (shared) instance equivalent to this object. This may return the same object.
345      *
346      * @return A shared instance.
347      */
348     public final Uint16 intern() {
349         return intValue() < CACHE_SIZE ? this : INTERNER.intern(this);
350     }
351
352     /**
353      * Convert this value to an {@code int}.
354      *
355      * @return An int
356      */
357     public final int toJava() {
358         return intValue();
359     }
360
361     /**
362      * Convert this value to a {@code Uint8}.
363      *
364      * @return A Uint8
365      * @throws IllegalArgumentException if this value is greater than 255.
366      */
367     public final Uint8 toUint8() {
368         return Uint8.valueOf(toJava());
369     }
370
371     /**
372      * Convert this value to a {@code Uint32}.
373      *
374      * @return A Uint32
375      */
376     public final Uint32 toUint32() {
377         return Uint32.fromIntBits(intValue());
378     }
379
380     /**
381      * Convert this value to a {@code Uint64}.
382      *
383      * @return A Uint64
384      */
385     public final Uint64 toUint64() {
386         return Uint64.fromLongBits(longValue());
387     }
388
389     public final Uint8 toSaturatedUint8() {
390         return Uint8.saturatedOf(toJava());
391     }
392
393     @Override
394     public final int hashCode() {
395         return Short.hashCode(value);
396     }
397
398     @Override
399     public final boolean equals(final @Nullable Object obj) {
400         return this == obj || obj instanceof Uint16 other && value == other.value;
401     }
402
403     /**
404      * A slightly faster version of {@link #equals(Object)}.
405      *
406      * @param obj Uint16 object
407      * @return  {@code true} if this object is the same as the obj argument; {@code false} otherwise.
408      */
409     public final boolean equals(final @Nullable Uint16 obj) {
410         return this == obj || obj != null && value == obj.value;
411     }
412
413     @Override
414     public final String toString() {
415         return toCanonicalString();
416     }
417
418     @Serial
419     private Object readResolve() {
420         return instanceFor(value);
421     }
422 }