1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.Byte;
13 
14 import hunt.Nullable;
15 import hunt.Number;
16 
17 import std.conv;
18 
19 /**
20  *
21  * The {@code Byte} class wraps a value of primitive type {@code byte}
22  * in an object.  An object of type {@code Byte} contains a single
23  * field whose type is {@code byte}.
24  *
25  * <p>In addition, this class provides several methods for converting
26  * a {@code byte} to a {@code string} and a {@code string} to a {@code
27  * byte}, as well as other constants and methods useful when dealing
28  * with a {@code byte}.
29  *
30  * @author  Nakul Saraiya
31  * @author  Joseph D. Darcy
32  * @see     java.lang.Number
33  * @since   JDK1.1
34  */
35 class Byte : AbstractNumber!(byte) {
36 
37     /**
38      * A constant holding the minimum value a {@code byte} can
39      * have, -2<sup>7</sup>.
40      */
41     static  byte   MIN_VALUE = -128;
42 
43     /**
44      * A constant holding the maximum value a {@code byte} can
45      * have, 2<sup>7</sup>-1.
46      */
47     static  byte   MAX_VALUE = 127;
48 
49     /**
50      * The {@code Class} instance representing the primitive type
51      * {@code byte}.
52      */
53     //@SuppressWarnings("unchecked")
54     // static  Class<Byte>     TYPE = (Class<Byte>) Class.getPrimitiveClass("byte");
55 
56     /**
57      * Returns a new {@code string} object representing the
58      * specified {@code byte}. The radix is assumed to be 10.
59      *
60      * @param b the {@code byte} to be converted
61      * @return the string representation of the specified {@code byte}
62      * @see java.lang.Integer#toString(int)
63      */
64     // static string toString(byte b) {
65     //     return Integer.toString((int)b, 10);
66     // }
67 
68     // private static class ByteCache {
69     //     private ByteCache(){}
70 
71     //     static  Byte cache[] = new Byte[-(-128) + 127 + 1];
72 
73     //     static {
74     //         for(int i = 0; i < cache.length; i++)
75     //             cache[i] = new Byte((byte)(i - 128));
76     //     }
77     // }
78 
79     /**
80      * Returns a {@code Byte} instance representing the specified
81      * {@code byte} value.
82      * If a new {@code Byte} instance is not required, this method
83      * should generally be used in preference to the constructor
84      * {@link #Byte(byte)}, as this method is likely to yield
85      * significantly better space and time performance since
86      * all byte values are cached.
87      *
88      * @param  b a byte value.
89      * @return a {@code Byte} instance representing {@code b}.
90      * @since  1.5
91      */
92     // static Byte valueOf(byte b) {
93     //      int offset = 128;
94     //     return ByteCache.cache[(int)b + offset];
95     // }
96 
97     /**
98      * Parses the string argument as a signed {@code byte} in the
99      * radix specified by the second argument. The characters in the
100      * string must all be digits, of the specified radix (as
101      * determined by whether {@link java.lang.Character#digit(char,
102      * int)} returns a nonnegative value) except that the first
103      * character may be an ASCII minus sign {@code '-'}
104      * ({@code '\u005Cu002D'}) to indicate a negative value or an
105      * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to
106      * indicate a positive value.  The resulting {@code byte} value is
107      * returned.
108      *
109      * <p>An exception of type {@code NumberFormatException} is
110      * thrown if any of the following situations occurs:
111      * <ul>
112      * <li> The first argument is {@code null} or is a string of
113      * length zero.
114      *
115      * <li> The radix is either smaller than {@link
116      * java.lang.Character#MIN_RADIX} or larger than {@link
117      * java.lang.Character#MAX_RADIX}.
118      *
119      * <li> Any character of the string is not a digit of the
120      * specified radix, except that the first character may be a minus
121      * sign {@code '-'} ({@code '\u005Cu002D'}) or plus sign
122      * {@code '+'} ({@code '\u005Cu002B'}) provided that the
123      * string is longer than length 1.
124      *
125      * <li> The value represented by the string is not a value of type
126      * {@code byte}.
127      * </ul>
128      *
129      * @param s         the {@code string} containing the
130      *                  {@code byte}
131      *                  representation to be parsed
132      * @param radix     the radix to be used while parsing {@code s}
133      * @return          the {@code byte} value represented by the string
134      *                   argument in the specified radix
135      * @throws          NumberFormatException If the string does
136      *                  not contain a parsable {@code byte}.
137      */
138     // static byte parseByte(string s, int radix)
139     //     throws NumberFormatException {
140     //     int i = Integer.parseInt(s, radix);
141     //     if (i < MIN_VALUE || i > MAX_VALUE)
142     //         throw new NumberFormatException(
143     //             "Value out of range. Value:\"" ~ s ~ "\" Radix:" ~ radix);
144     //     return (byte)i;
145     // }
146 
147     /**
148      * Parses the string argument as a signed decimal {@code
149      * byte}. The characters in the string must all be decimal digits,
150      * except that the first character may be an ASCII minus sign
151      * {@code '-'} ({@code '\u005Cu002D'}) to indicate a negative
152      * value or an ASCII plus sign {@code '+'}
153      * ({@code '\u005Cu002B'}) to indicate a positive value. The
154      * resulting {@code byte} value is returned, exactly as if the
155      * argument and the radix 10 were given as arguments to the {@link
156      * #parseByte(java.lang.string, int)} method.
157      *
158      * @param s         a {@code string} containing the
159      *                  {@code byte} representation to be parsed
160      * @return          the {@code byte} value represented by the
161      *                  argument in decimal
162      * @throws          NumberFormatException if the string does not
163      *                  contain a parsable {@code byte}.
164      */
165     // static byte parseByte(string s) throws NumberFormatException {
166     //     return parseByte(s, 10);
167     // }
168 
169     /**
170      * Returns a {@code Byte} object holding the value
171      * extracted from the specified {@code string} when parsed
172      * with the radix given by the second argument. The first argument
173      * is interpreted as representing a signed {@code byte} in
174      * the radix specified by the second argument, exactly as if the
175      * argument were given to the {@link #parseByte(java.lang.string,
176      * int)} method. The result is a {@code Byte} object that
177      * represents the {@code byte} value specified by the string.
178      *
179      * <p> In other words, this method returns a {@code Byte} object
180      * equal to the value of:
181      *
182      * <blockquote>
183      * {@code new Byte(Byte.parseByte(s, radix))}
184      * </blockquote>
185      *
186      * @param s         the string to be parsed
187      * @param radix     the radix to be used in interpreting {@code s}
188      * @return          a {@code Byte} object holding the value
189      *                  represented by the string argument in the
190      *                  specified radix.
191      * @throws          NumberFormatException If the {@code string} does
192      *                  not contain a parsable {@code byte}.
193      */
194     // static Byte valueOf(string s, int radix)
195     //     throws NumberFormatException {
196     //     return valueOf(parseByte(s, radix));
197     // }
198 
199     /**
200      * Returns a {@code Byte} object holding the value
201      * given by the specified {@code string}. The argument is
202      * interpreted as representing a signed decimal {@code byte},
203      * exactly as if the argument were given to the {@link
204      * #parseByte(java.lang.string)} method. The result is a
205      * {@code Byte} object that represents the {@code byte}
206      * value specified by the string.
207      *
208      * <p> In other words, this method returns a {@code Byte} object
209      * equal to the value of:
210      *
211      * <blockquote>
212      * {@code new Byte(Byte.parseByte(s))}
213      * </blockquote>
214      *
215      * @param s         the string to be parsed
216      * @return          a {@code Byte} object holding the value
217      *                  represented by the string argument
218      * @throws          NumberFormatException If the {@code string} does
219      *                  not contain a parsable {@code byte}.
220      */
221     // static Byte valueOf(string s) throws NumberFormatException {
222     //     return valueOf(s, 10);
223     // }
224 
225     /**
226      * Decodes a {@code string} into a {@code Byte}.
227      * Accepts decimal, hexadecimal, and octal numbers given by
228      * the following grammar:
229      *
230      * <blockquote>
231      * <dl>
232      * <dt><i>DecodableString:</i>
233      * <dd><i>Sign<sub>opt</sub> DecimalNumeral</i>
234      * <dd><i>Sign<sub>opt</sub></i> {@code 0x} <i>HexDigits</i>
235      * <dd><i>Sign<sub>opt</sub></i> {@code 0X} <i>HexDigits</i>
236      * <dd><i>Sign<sub>opt</sub></i> {@code #} <i>HexDigits</i>
237      * <dd><i>Sign<sub>opt</sub></i> {@code 0} <i>OctalDigits</i>
238      *
239      * <dt><i>Sign:</i>
240      * <dd>{@code -}
241      * <dd>{@code +}
242      * </dl>
243      * </blockquote>
244      *
245      * <i>DecimalNumeral</i>, <i>HexDigits</i>, and <i>OctalDigits</i>
246      * are as defined in section 3.10.1 of
247      * <cite>The Java&trade; Language Specification</cite>,
248      * except that underscores are not accepted between digits.
249      *
250      * <p>The sequence of characters following an optional
251      * sign and/or radix specifier ("{@code 0x}", "{@code 0X}",
252      * "{@code #}", or leading zero) is parsed as by the {@code
253      * Byte.parseByte} method with the indicated radix (10, 16, or 8).
254      * This sequence of characters must represent a positive value or
255      * a {@link NumberFormatException} will be thrown.  The result is
256      * negated if first character of the specified {@code string} is
257      * the minus sign.  No whitespace characters are permitted in the
258      * {@code string}.
259      *
260      * @param     nm the {@code string} to decode.
261      * @return   a {@code Byte} object holding the {@code byte}
262      *          value represented by {@code nm}
263      * @throws  NumberFormatException  if the {@code string} does not
264      *            contain a parsable {@code byte}.
265      * @see java.lang.Byte#parseByte(java.lang.string, int)
266      */
267     // static Byte decode(string nm) throws NumberFormatException {
268     //     int i = Integer.decode(nm);
269     //     if (i < MIN_VALUE || i > MAX_VALUE)
270     //         throw new NumberFormatException(
271     //                 "Value " ~ i ~ " out of range from input " ~ nm);
272     //     return valueOf((byte)i);
273     // }
274 
275     /**
276      * The value of the {@code Byte}.
277      *
278      * @serial
279      */
280     // private  byte value;
281 
282     /**
283      * Constructs a newly allocated {@code Byte} object that
284      * represents the specified {@code byte} value.
285      *
286      * @param value     the value to be represented by the
287      *                  {@code Byte}.
288      */
289     this(byte value) {
290         super(value);
291     }
292 
293     this(int value) {
294         super(cast(byte)value);
295     }
296     
297     /**
298      * Constructs a newly allocated {@code Byte} object that
299      * represents the {@code byte} value indicated by the
300      * {@code string} parameter. The string is converted to a
301      * {@code byte} value in exactly the manner used by the
302      * {@code parseByte} method for radix 10.
303      *
304      * @param s         the {@code string} to be converted to a
305      *                  {@code Byte}
306      * @throws           NumberFormatException If the {@code string}
307      *                  does not contain a parsable {@code byte}.
308      * @see        java.lang.Byte#parseByte(java.lang.string, int)
309      */
310     // Byte(string s) throws NumberFormatException {
311     //     this.value = parseByte(s, 10);
312     // }
313 
314     /**
315      * Returns a {@code string} object representing this
316      * {@code Byte}'s value.  The value is converted to signed
317      * decimal representation and returned as a string, exactly as if
318      * the {@code byte} value were given as an argument to the
319      * {@link java.lang.Byte#toString(byte)} method.
320      *
321      * @return  a string representation of the value of this object in
322      *          base&nbsp;10.
323      */
324     // string toString() {
325     //     return Integer.toString((int)value);
326     // }
327 
328     /**
329      * Returns a hash code for this {@code Byte}; equal to the result
330      * of invoking {@code intValue()}.
331      *
332      * @return a hash code value for this {@code Byte}
333      */
334     // @Override
335     // int hashCode() {
336     //     return Byte.hashCode(value);
337     // }
338 
339     /**
340      * Returns a hash code for a {@code byte} value; compatible with
341      * {@code Byte.hashCode()}.
342      *
343      * @param value the value to hash
344      * @return a hash code value for a {@code byte} value.
345      * @since 1.8
346      */
347     override size_t toHash() @trusted nothrow {
348         return cast(size_t)value;
349     }
350 
351     /**
352      * Converts the argument to an {@code int} by an unsigned
353      * conversion.  In an unsigned conversion to an {@code int}, the
354      * high-order 24 bits of the {@code int} are zero and the
355      * low-order 8 bits are equal to the bits of the {@code byte} argument.
356      *
357      * Consequently, zero and positive {@code byte} values are mapped
358      * to a numerically equal {@code int} value and negative {@code
359      * byte} values are mapped to an {@code int} value equal to the
360      * input plus 2<sup>8</sup>.
361      *
362      * @param  x the value to convert to an unsigned {@code int}
363      * @return the argument converted to {@code int} by an unsigned
364      *         conversion
365      * @since 1.8
366      */
367     static int toUnsignedInt(byte x) {
368         return (cast(int) x) & 0xff;
369     }
370 
371     /**
372      * Converts the argument to a {@code long} by an unsigned
373      * conversion.  In an unsigned conversion to a {@code long}, the
374      * high-order 56 bits of the {@code long} are zero and the
375      * low-order 8 bits are equal to the bits of the {@code byte} argument.
376      *
377      * Consequently, zero and positive {@code byte} values are mapped
378      * to a numerically equal {@code long} value and negative {@code
379      * byte} values are mapped to a {@code long} value equal to the
380      * input plus 2<sup>8</sup>.
381      *
382      * @param  x the value to convert to an unsigned {@code long}
383      * @return the argument converted to {@code long} by an unsigned
384      *         conversion
385      * @since 1.8
386      */
387     static long toUnsignedLong(byte x) {
388         return (cast(long) x) & 0xffL;
389     }
390 
391 
392     /**
393      * The number of bits used to represent a {@code byte} value in two's
394      * complement binary form.
395      *
396      * @since 1.5
397      */
398     static enum int SIZE = 8;
399 
400     /**
401      * The number of bytes used to represent a {@code byte} value in two's
402      * complement binary form.
403      *
404      * @since 1.8
405      */
406     static enum int BYTES = byte.sizeof;
407 
408     static byte parseByte(string s)  {
409         auto i = to!int(s);
410         if (i < MIN_VALUE || i > MAX_VALUE)
411         {
412             throw new Exception(
413                     "Value " ~s ~ " out of range from input ");
414         }
415 
416          return cast(byte)i;
417     }
418 
419 }
420 
421 
422 class Bytes : Nullable!(byte[]) {
423 
424     this(byte[] bs) {
425         _value = bs.dup;
426     }
427 
428 }