From cc2317db5bb85fd3796aec1f082a4fcd16f9cea5 Mon Sep 17 00:00:00 2001 From: Patrick Favre-Bulle Date: Tue, 31 Jul 2018 11:35:47 +0200 Subject: [PATCH 1/2] Add handling for UUID refs #9 --- CHANGELOG | 1 + src/main/java/at/favre/lib/bytes/Bytes.java | 42 ++++++++++++++++++- src/main/java/at/favre/lib/bytes/Util.java | 31 +++++++++++++- .../lib/bytes/BytesConstructorTests.java | 20 +++++++++ .../bytes/BytesToConvertOtherTypesTest.java | 17 +++++++- 5 files changed, 106 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2cec822..5da93fc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,6 +4,7 @@ * add `encodeCharsetToBytes()` feature #7 * add new `from(char[] charArray, Charset charset)` constructor with improved logic #8 + * add constructor/converter from/to UUID #9 ## v0.5.0 diff --git a/src/main/java/at/favre/lib/bytes/Bytes.java b/src/main/java/at/favre/lib/bytes/Bytes.java index 8abfe92..99b88e2 100644 --- a/src/main/java/at/favre/lib/bytes/Bytes.java +++ b/src/main/java/at/favre/lib/bytes/Bytes.java @@ -21,7 +21,11 @@ package at.favre.lib.bytes; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.File; +import java.io.InputStream; +import java.io.Serializable; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -31,7 +35,14 @@ import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.text.Normalizer; -import java.util.*; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.Random; +import java.util.UUID; /** * Bytes is wrapper class for an byte-array that allows a lot of convenience operations on it: @@ -471,6 +482,18 @@ public static Bytes from(char[] charArray, Charset charset) { return from(bytes); } + /** + * Convert UUID to a newly generated 16 byte long array representation. Puts the 8 byte most significant bits and + * 8 byte least significant bits into an byte array. + * + * @param uuid to convert to array + * @return new instance + */ + public static Bytes from(UUID uuid) { + Objects.requireNonNull(uuid); + return wrap(Util.getBytesFromUUID(uuid).array()); + } + /** * Parses a big endian binary string (e.g. 10010001) * @@ -1498,6 +1521,21 @@ public BigInteger toBigInteger() { } } + /** + * Creates a {@link UUID} instance of the internal byte array. This requires the internal array to be exactly 16 bytes. Takes the first + * 8 byte as mostSigBits and the last 8 byte as leastSigBits. There is no validation of version/type, just passes the raw bytes + * to a {@link UUID} constructor. + * + * @return newly created UUID + */ + public UUID toUUID() { + if (length() != 16) { + throw new IllegalStateException("creating UUID requires internal array to be exactly 16 bytes, was " + length()); + } + ByteBuffer byteBuffer = buffer(); + return new UUID(byteBuffer.getLong(), byteBuffer.getLong()); + } + /** * If the underlying byte array is exactly 1 byte / 8 bit long, returns signed two-complement * representation for a Java byte value. diff --git a/src/main/java/at/favre/lib/bytes/Util.java b/src/main/java/at/favre/lib/bytes/Util.java index d3a8c74..25d828b 100644 --- a/src/main/java/at/favre/lib/bytes/Util.java +++ b/src/main/java/at/favre/lib/bytes/Util.java @@ -21,10 +21,23 @@ package at.favre.lib.bytes; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.DataInput; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.file.Files; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Random; +import java.util.UUID; /** * Common Util methods to convert or modify byte arrays @@ -446,6 +459,20 @@ static boolean constantTimeEquals(byte[] obj, byte[] anotherArray) { return result == 0; } + /** + * Convert UUID to a newly generated 16 byte long array representation. Puts the 8 byte most significant bits and + * 8 byte least significant bits into an byte array. + * + * @param uuid to convert to array + * @return buffer containing the 16 bytes + */ + static ByteBuffer getBytesFromUUID(UUID uuid) { + ByteBuffer bb = ByteBuffer.allocate(16); + bb.putLong(uuid.getMostSignificantBits()); + bb.putLong(uuid.getLeastSignificantBits()); + return bb; + } + /* ================================================================================================= Copyright 2011 Twitter, Inc. diff --git a/src/test/java/at/favre/lib/bytes/BytesConstructorTests.java b/src/test/java/at/favre/lib/bytes/BytesConstructorTests.java index a0423c6..17d34db 100644 --- a/src/test/java/at/favre/lib/bytes/BytesConstructorTests.java +++ b/src/test/java/at/favre/lib/bytes/BytesConstructorTests.java @@ -38,6 +38,7 @@ import java.util.Arrays; import java.util.BitSet; import java.util.LinkedList; +import java.util.UUID; import static org.junit.Assert.*; @@ -423,4 +424,23 @@ public void fromObjectArray() { Bytes b = Bytes.from(objectArray); assertArrayEquals(new byte[]{0x01, 0x02, 0x03, 0x04}, b.array()); } + + @Test + public void fromUUID() { + testUUID(UUID.fromString("00000000-0000-0000-0000-000000000000")); + testUUID(UUID.fromString("123e4567-e89b-42d3-a456-556642440000")); + testUUID(UUID.fromString("e8e3db08-dc39-48ea-a3db-08dc3958eafb")); + testUUID(UUID.randomUUID()); + } + + private void testUUID(UUID uuid) { + Bytes b = Bytes.from(uuid); + assertEquals(16, b.length()); + assertEquals(uuid, b.toUUID()); + } + + @Test(expected = NullPointerException.class) + public void fromUUIDNullArgument() { + Bytes.from((UUID) null); + } } diff --git a/src/test/java/at/favre/lib/bytes/BytesToConvertOtherTypesTest.java b/src/test/java/at/favre/lib/bytes/BytesToConvertOtherTypesTest.java index 90bf1da..a48f8ba 100644 --- a/src/test/java/at/favre/lib/bytes/BytesToConvertOtherTypesTest.java +++ b/src/test/java/at/favre/lib/bytes/BytesToConvertOtherTypesTest.java @@ -219,4 +219,19 @@ public void toDouble() { } catch (IllegalStateException ignored) { } } -} \ No newline at end of file + + @Test(expected = IllegalStateException.class) + public void testToUUIDToLong() { + Bytes.random(17).toUUID(); + } + + @Test(expected = IllegalStateException.class) + public void testToUUIDToShort() { + Bytes.random(15).toUUID(); + } + + @Test(expected = IllegalStateException.class) + public void testToUUIDEmpty() { + Bytes.allocate(0).toUUID(); + } +} From bdc581662b67c022ef28eae0bd97932439a2436b Mon Sep 17 00:00:00 2001 From: Patrick Favre-Bulle Date: Tue, 31 Jul 2018 11:39:34 +0200 Subject: [PATCH 2/2] Update Readme refs #9 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0ca33dc..7134a49 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ to blindly paste code snippets from It's main features include: -* **Creation** from a wide variety of sources: multiple arrays, integers, [streams](https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html), random, strings, files, ... +* **Creation** from a wide variety of sources: multiple arrays, integers, [streams](https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html), random, strings, files, uuid, ... * **Transformation** with many built-in: append, [xor](https://en.wikipedia.org/wiki/Exclusive_or), [and](https://en.wikipedia.org/wiki/Logical_conjunction), [hash](https://en.wikipedia.org/wiki/Cryptographic_hash_function), [shifts](https://en.wikipedia.org/wiki/Bitwise_operation#Bit_shifts), shuffle, reverse, [checksum](https://en.wikipedia.org/wiki/Checksum), ... * **Validators** with the ability to arbitrarily combine multiple ones with logical expressions * **Parsing and Encoding** in most common binary-to-text-encodings: [hex](https://en.wikipedia.org/wiki/Hexadecimal), [base36](https://en.wikipedia.org/wiki/Base36), [base64](https://en.wikipedia.org/wiki/Base64), ... @@ -164,6 +164,7 @@ Bytes.from(myBitSet); //java.util.BitSet myBitSet = ... Bytes.from(bigInteger); //java.math.BigInteger Bytes.from(file); //reads bytes from any java.io.File Bytes.from(dataInput, 16); //reads bytes from any java.io.DataInput +Bytes.from(UUID.randomUUID()); //read 16 bytes from UUID ``` For parsing binary-text-encoded strings, see below.