Skip to content

Commit 634b64b

Browse files
committed
Move shuffle and sort to additional transformers
1 parent 1c80b15 commit 634b64b

File tree

7 files changed

+129
-132
lines changed

7 files changed

+129
-132
lines changed

README.md

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,25 @@ Bytes hash = Bytes.wrap(array).sha256();
201201
Bytes hash = Bytes.wrap(array).hash("MD5");
202202
```
203203

204-
**Checksum** can be calculated or automatically appended:
204+
Other transformers:
205+
206+
```java
207+
Bytes result = Bytes.wrap(array).sort(myComparator);
208+
Bytes result = Bytes.wrap(array).reverse();
209+
```
210+
211+
#### Additional Transformers
212+
213+
More transformers can be accessed through the `BytesTransformers`, which
214+
can be statically imported for a less verbose syntax:
205215

206216
```java
207217
import static at.favre.lib.bytes.BytesTransformers.*;
218+
```
219+
220+
**Checksum** can be calculated or automatically appended:
208221

222+
```java
209223
Bytes.wrap(array).transform(checksumAppendCrc32());
210224
Bytes.wrap(array).transform(checksumCrc32());
211225
Bytes.wrap(array).transform(checksum(new Adler32(), ChecksumTransformer.Mode.TRANSFORM, 4));
@@ -214,18 +228,21 @@ Bytes.wrap(array).transform(checksum(new Adler32(), ChecksumTransformer.Mode.TRA
214228
**GZip compression** is supported by [`GZIPInputStream`](https://docs.oracle.com/javase/7/docs/api/java/util/zip/GZIPInputStream.html):
215229

216230
```java
217-
import static at.favre.lib.bytes.BytesTransformers.*;
218-
219231
Bytes compressed = Bytes.wrap(array).transform(compressGzip());
220232
Bytes decompressed = compressed.transform(decompressGzip());
221233
```
222234

223-
Other transformers:
235+
**Sorting** of individual bytes with either [`Comparator`](https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html) or natural order:
236+
237+
```java
238+
Bytes.wrap(array).transform(sort());
239+
Bytes.wrap(array).transform(sort(byteComparator));
240+
```
241+
242+
**Shuffling** of individual bytes:
224243

225244
```java
226-
Bytes.wrap(array).shuffle();
227-
Bytes.wrap(array).sort(myComparator);
228-
Bytes.wrap(array).reverse();
245+
Bytes.wrap(array).transform(shuffle());
229246
```
230247

231248
### Parser and Encoder for Binary-Text-Encodings

src/main/java/at/favre/lib/bytes/Bytes.java

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -719,52 +719,6 @@ public Bytes reverse() {
719719
return transform(new BytesTransformer.ReverseTransformer());
720720
}
721721

722-
/**
723-
* Sorts the internal byte array according to given comparator.
724-
* <p>
725-
* See the considerations about possible in-place operation in {@link #transform(BytesTransformer)}.
726-
*
727-
* @param comparator to sort the bytes
728-
* @return sorted instance
729-
*/
730-
public Bytes sort(Comparator<Byte> comparator) {
731-
return transform(new BytesTransformer.SortTransformer(comparator));
732-
}
733-
734-
/**
735-
* Sorts the internal byte array with it's natural ordering
736-
* <p>
737-
* See the considerations about possible in-place operation in {@link #transform(BytesTransformer)}.
738-
*
739-
* @return sorted instance
740-
*/
741-
public Bytes sort() {
742-
return transform(new BytesTransformer.SortTransformer());
743-
}
744-
745-
/**
746-
* Shuffles the internal byte array
747-
* <p>
748-
* See the considerations about possible in-place operation in {@link #transform(BytesTransformer)}.
749-
*
750-
* @param random used to create entropy for the shuffle
751-
* @return a shuffled instance
752-
*/
753-
public Bytes shuffle(Random random) {
754-
return transform(new BytesTransformer.ShuffleTransformer(random));
755-
}
756-
757-
/**
758-
* Shuffles the internal byte array with a new {@link SecureRandom} instance.
759-
* <p>
760-
* See the considerations about possible in-place operation in {@link #transform(BytesTransformer)}.
761-
*
762-
* @return a shuffled instance
763-
*/
764-
public Bytes shuffle() {
765-
return transform(new BytesTransformer.ShuffleTransformer(new SecureRandom()));
766-
}
767-
768722
/**
769723
* Copies the specified array, truncating or padding with zeros (if necessary)
770724
* so the copy has the specified length. For all indices that are
@@ -782,7 +736,6 @@ public Bytes resize(int newByteLength) {
782736
return transform(new BytesTransformer.ResizeTransformer(newByteLength));
783737
}
784738

785-
786739
/**
787740
* Calculates sha256 on the underlying byte array and returns a byte instance containing the hash.
788741
*
@@ -794,17 +747,6 @@ public Bytes hashSha256() {
794747
return hash(BytesTransformer.MessageDigestTransformer.ALGORITHM_SHA_256);
795748
}
796749

797-
/**
798-
* Calculates sha512 on the underlying byte array and returns a byte instance containing the hash.
799-
*
800-
* @return sha512 hash (64 bytes) of internal byte array
801-
* @throws IllegalArgumentException if the message digest algorithm can not be found in the security providers
802-
* @see <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithms">Secure Hash Algorithms</a>
803-
*/
804-
public Bytes hashSha512() {
805-
return hash(BytesTransformer.MessageDigestTransformer.ALGORITHM_SHA_512);
806-
}
807-
808750
/**
809751
* Calculates hash with provided algorithm on the underlying byte array and returns a byte instance
810752
* containing the hash.

src/main/java/at/favre/lib/bytes/BytesTransformer.java

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import java.math.BigInteger;
2525
import java.security.MessageDigest;
2626
import java.security.NoSuchAlgorithmException;
27-
import java.util.*;
27+
import java.util.Objects;
2828

2929
/**
3030
* Interface for transforming {@link Bytes}
@@ -175,54 +175,6 @@ public byte[] transform(byte[] currentArray, boolean inPlace) {
175175
}
176176
}
177177

178-
/**
179-
* Sorts the internal byte array with given {@link java.util.Comparator}
180-
*/
181-
final class SortTransformer implements BytesTransformer {
182-
private final Comparator<Byte> comparator;
183-
184-
SortTransformer() {
185-
this(null);
186-
}
187-
188-
SortTransformer(Comparator<Byte> comparator) {
189-
this.comparator = comparator;
190-
}
191-
192-
@Override
193-
public byte[] transform(byte[] currentArray, boolean inPlace) {
194-
if (comparator == null) {
195-
byte[] out = inPlace ? currentArray : Bytes.from(currentArray).array();
196-
Arrays.sort(out);
197-
return out;
198-
} else {
199-
//no in-place implementation with comparator
200-
List<Byte> list = Bytes.wrap(currentArray).toList();
201-
Collections.sort(list, comparator);
202-
return Bytes.from(list).array();
203-
}
204-
}
205-
}
206-
207-
/**
208-
* Shuffles the internal byte array
209-
*/
210-
final class ShuffleTransformer implements BytesTransformer {
211-
private final Random random;
212-
213-
ShuffleTransformer(Random random) {
214-
Objects.requireNonNull(random, "passed random must not be null");
215-
this.random = random;
216-
}
217-
218-
@Override
219-
public byte[] transform(byte[] currentArray, boolean inPlace) {
220-
byte[] out = inPlace ? currentArray : Bytes.from(currentArray).array();
221-
Util.shuffle(out, random);
222-
return out;
223-
}
224-
}
225-
226178
/**
227179
* Creates a new instance with a copy of the internal byte array and all other attributes.
228180
*/

src/main/java/at/favre/lib/bytes/BytesTransformers.java

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
import java.io.ByteArrayInputStream;
44
import java.io.ByteArrayOutputStream;
5-
import java.util.Objects;
5+
import java.security.SecureRandom;
6+
import java.util.*;
67
import java.util.zip.CRC32;
78
import java.util.zip.Checksum;
89
import java.util.zip.GZIPInputStream;
@@ -16,6 +17,45 @@ public final class BytesTransformers {
1617
private BytesTransformers() {
1718
}
1819

20+
/**
21+
* Create a {@link BytesTransformer} which shuffles the individual bytes in an array
22+
* with an {@link SecureRandom} instance.
23+
*
24+
* @return transformer
25+
*/
26+
public static BytesTransformer shuffle() {
27+
return new ShuffleTransformer(new SecureRandom());
28+
}
29+
30+
/**
31+
* Create a {@link BytesTransformer} which shuffles the individual bytes in an array
32+
*
33+
* @param random to use for entropy
34+
* @return transformer
35+
*/
36+
public static BytesTransformer shuffle(Random random) {
37+
return new ShuffleTransformer(random);
38+
}
39+
40+
/**
41+
* Create a {@link BytesTransformer} which sorts the internal byte array with it's natural ordering.
42+
*
43+
* @return transformer
44+
*/
45+
public static BytesTransformer sort() {
46+
return new SortTransformer();
47+
}
48+
49+
/**
50+
* Create a {@link BytesTransformer} which sorts the internal byte array according to given comparator.
51+
*
52+
* @param comparator to sort the bytes
53+
* @return transformer
54+
*/
55+
public static BytesTransformer sort(Comparator<Byte> comparator) {
56+
return new SortTransformer(comparator);
57+
}
58+
1959
/**
2060
* Create a {@link BytesTransformer} which appends 4 byte Crc32 checksum to given bytes
2161
*
@@ -69,6 +109,54 @@ public static BytesTransformer decompressGzip() {
69109
return new GzipCompressor(false);
70110
}
71111

112+
/**
113+
* Shuffles the internal byte array
114+
*/
115+
final static class ShuffleTransformer implements BytesTransformer {
116+
private final Random random;
117+
118+
ShuffleTransformer(Random random) {
119+
Objects.requireNonNull(random, "passed random must not be null");
120+
this.random = random;
121+
}
122+
123+
@Override
124+
public byte[] transform(byte[] currentArray, boolean inPlace) {
125+
byte[] out = inPlace ? currentArray : Bytes.from(currentArray).array();
126+
Util.shuffle(out, random);
127+
return out;
128+
}
129+
}
130+
131+
/**
132+
* Sorts the internal byte array with given {@link java.util.Comparator}
133+
*/
134+
final static class SortTransformer implements BytesTransformer {
135+
private final Comparator<Byte> comparator;
136+
137+
SortTransformer() {
138+
this(null);
139+
}
140+
141+
SortTransformer(Comparator<Byte> comparator) {
142+
this.comparator = comparator;
143+
}
144+
145+
@Override
146+
public byte[] transform(byte[] currentArray, boolean inPlace) {
147+
if (comparator == null) {
148+
byte[] out = inPlace ? currentArray : Bytes.from(currentArray).array();
149+
Arrays.sort(out);
150+
return out;
151+
} else {
152+
//no in-place implementation with comparator
153+
List<Byte> list = Bytes.wrap(currentArray).toList();
154+
Collections.sort(list, comparator);
155+
return Bytes.from(list).array();
156+
}
157+
}
158+
}
159+
72160
/**
73161
* Adds or converts to arbitrary checksum
74162
*/
@@ -88,7 +176,7 @@ enum Mode {
88176
private final Mode mode;
89177
private final int checksumLengthByte;
90178

91-
public ChecksumTransformer(Checksum checksum, Mode mode, int checksumLengthByte) {
179+
ChecksumTransformer(Checksum checksum, Mode mode, int checksumLengthByte) {
92180
if (checksumLengthByte <= 0 || checksumLengthByte > 8)
93181
throw new IllegalArgumentException("checksumlength must be between 1 and 8 bytes");
94182

@@ -117,7 +205,7 @@ public byte[] transform(byte[] currentArray, boolean inPlace) {
117205
final static class GzipCompressor implements BytesTransformer {
118206
private final boolean compress;
119207

120-
public GzipCompressor(boolean compress) {
208+
GzipCompressor(boolean compress) {
121209
this.compress = compress;
122210
}
123211

src/test/java/at/favre/lib/bytes/BytesMiscTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,15 +219,14 @@ public void readOnlyShouldKeepProperty() throws Exception {
219219
assertTrue(b.reverse().isReadOnly());
220220
assertTrue(b.resize(7).isReadOnly());
221221
assertTrue(b.resize(6).isReadOnly());
222-
assertTrue(b.sort().isReadOnly());
223-
assertTrue(b.shuffle().isReadOnly());
224222
assertTrue(b.not().isReadOnly());
225223
assertTrue(b.leftShift(1).isReadOnly());
226224
assertTrue(b.rightShift(1).isReadOnly());
227225
assertTrue(b.and(Bytes.random(b.length())).isReadOnly());
228226
assertTrue(b.or(Bytes.random(b.length())).isReadOnly());
229227
assertTrue(b.xor(Bytes.random(b.length())).isReadOnly());
230228
assertTrue(b.append(3).isReadOnly());
229+
assertTrue(b.hashSha256().isReadOnly());
231230
}
232231

233232
@Test

src/test/java/at/favre/lib/bytes/BytesTransformTest.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -208,23 +208,23 @@ public void copy() throws Exception {
208208
}
209209

210210
@Test
211-
public void shuffle() throws Exception {
212-
assertArrayNotEquals(example_bytes_twentyfour, Bytes.from(example_bytes_twentyfour).shuffle().array());
213-
assertArrayNotEquals(example_bytes_twentyfour, Bytes.from(example_bytes_twentyfour).shuffle(new SecureRandom()).array());
214-
assertArrayNotEquals(new byte[24], Bytes.from(example_bytes_twentyfour).shuffle(new SecureRandom()).array());
211+
public void shuffleTest() throws Exception {
212+
assertArrayNotEquals(example_bytes_twentyfour, Bytes.from(example_bytes_twentyfour).transform(shuffle()).array());
213+
assertArrayNotEquals(example_bytes_twentyfour, Bytes.from(example_bytes_twentyfour).transform(shuffle(new SecureRandom())).array());
214+
assertArrayNotEquals(new byte[24], Bytes.from(example_bytes_twentyfour).transform(shuffle(new SecureRandom())).array());
215215
}
216216

217217
@Test
218-
public void sort() throws Exception {
218+
public void sortTest() throws Exception {
219219
byte[] sorted = new byte[]{0, 1, 2, 3, 4, 5, 6};
220-
assertArrayEquals(sorted, Bytes.from(sorted).shuffle().sort().array());
221-
assertArrayEquals(sorted, Bytes.from(new byte[]{6, 0, 3, 4, 1, 5, 2}).sort().array());
222-
assertArrayEquals(Bytes.from(sorted).reverse().array(), Bytes.from(new byte[]{6, 0, 3, 4, 1, 5, 2}).sort(new Comparator<Byte>() {
220+
assertArrayEquals(sorted, Bytes.from(sorted).transform(shuffle()).transform(sort()).array());
221+
assertArrayEquals(sorted, Bytes.from(new byte[]{6, 0, 3, 4, 1, 5, 2}).transform(sort()).array());
222+
assertArrayEquals(Bytes.from(sorted).reverse().array(), Bytes.from(new byte[]{6, 0, 3, 4, 1, 5, 2}).transform(sort(new Comparator<Byte>() {
223223
@Override
224224
public int compare(Byte o1, Byte o2) {
225225
return o2.compareTo(o1);
226226
}
227-
}).array());
227+
})).array());
228228
}
229229

230230
@Test
@@ -274,8 +274,8 @@ public void bitSwitchOutOfBounds() throws Exception {
274274
public void hash() throws Exception {
275275
assertEquals(Bytes.parseHex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), Bytes.from("").hashSha256());
276276
assertEquals(Bytes.parseHex("e362eea626386c93a54c9b82e6b896c0350fbff0ee12f284660253aac0908cfb"), Bytes.from("ö9h%6Ghh1\"").hashSha256());
277-
assertEquals(Bytes.parseHex("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"), Bytes.from("").hashSha512());
278-
assertEquals(Bytes.parseHex("106747C3DDC117091BEF8D21AEBAA8D314656D3AE1135AB36F4C0B07A264127CF625FE616751BEC66B43032B904E2D3B6C21BF14E078F6BB775A72503F48111D"), Bytes.from("ö9h%6Ghh1\"").hashSha512());
277+
assertEquals(Bytes.parseHex("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"), Bytes.from("").hash("SHA-512"));
278+
assertEquals(Bytes.parseHex("106747C3DDC117091BEF8D21AEBAA8D314656D3AE1135AB36F4C0B07A264127CF625FE616751BEC66B43032B904E2D3B6C21BF14E078F6BB775A72503F48111D"), Bytes.from("ö9h%6Ghh1\"").hash("SHA-512"));
279279
assertEquals(Bytes.parseHex("d41d8cd98f00b204e9800998ecf8427e"), Bytes.from("").hash("MD5"));
280280
assertEquals(Bytes.parseHex("ff38205f1cb22f588d8bc9ae21f22092"), Bytes.from("ö9h%6Ghh1\"").hash("MD5"));
281281
}

0 commit comments

Comments
 (0)