Version 4.0.0 #15
Now you call `UlidFactory.newInstance()` and it's variants to get a new `UlidFactory`. List of changes: - Added `UlidFactory.newInstance()` - Added `UlidFactory.newInstance(Random)` - Added `UlidFactory.newInstance(Supplier<byte[]>)` - Added `UlidFactory.newMonotonicInstance()` - Added `UlidFactory.newMonotonicInstance(Random)` - Added `UlidFactory.newMonotonicInstance(Supplier<byte[]>)` - Added benchmark code to compare ULID with UUID - Removed `DefaultFactory` - Removed `MonotonicFactory` - Removed `Ulid.toUpperCase()` - Removed `RandomGenerator`
This commit is contained in:
parent
8a68ad617e
commit
27a4f60cb5
26
CHANGELOG.md
26
CHANGELOG.md
|
@ -4,9 +4,28 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## Added
|
Nothing unreleased.
|
||||||
|
|
||||||
- Add benchmark code to compare ULID with UUID
|
## [4.0.0] - 2021-08-08
|
||||||
|
|
||||||
|
Now you call `UlidFactory.newInstance()` and it's variants to get a new `UlidFactory`.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `UlidFactory.newInstance()`
|
||||||
|
- Added `UlidFactory.newInstance(Random)`
|
||||||
|
- Added `UlidFactory.newInstance(Supplier<byte[]>)`
|
||||||
|
- Added `UlidFactory.newMonotonicInstance()`
|
||||||
|
- Added `UlidFactory.newMonotonicInstance(Random)`
|
||||||
|
- Added `UlidFactory.newMonotonicInstance(Supplier<byte[]>)`
|
||||||
|
- Added benchmark code to compare ULID with UUID
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Removed `DefaultFactory`
|
||||||
|
- Removed `MonotonicFactory`
|
||||||
|
- Removed `Ulid.toUpperCase()`
|
||||||
|
- Removed `RandomGenerator`
|
||||||
|
|
||||||
## [3.2.0] - 2021-07-17
|
## [3.2.0] - 2021-07-17
|
||||||
|
|
||||||
|
@ -243,7 +262,8 @@ Project created as an alternative Java implementation of [ULID spec](https://git
|
||||||
- Added `LICENSE`
|
- Added `LICENSE`
|
||||||
- Added test cases
|
- Added test cases
|
||||||
|
|
||||||
[unreleased]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.2.0...HEAD
|
[unreleased]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-4.0.0...HEAD
|
||||||
|
[4.0.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.2.0...ulid-creator-4.0.0
|
||||||
[3.2.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.1.1...ulid-creator-3.2.0
|
[3.2.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.1.1...ulid-creator-3.2.0
|
||||||
[3.1.1]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.1.0...ulid-creator-3.1.1
|
[3.1.1]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.1.0...ulid-creator-3.1.1
|
||||||
[3.1.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.0.1...ulid-creator-3.1.0
|
[3.1.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.0.1...ulid-creator-3.1.0
|
||||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Fabio Lima
|
Copyright (c) 2020-2021 Fabio Lima
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
30
README.md
30
README.md
|
@ -35,7 +35,7 @@ Add these lines to your `pom.xml`.
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.f4b6a3</groupId>
|
<groupId>com.github.f4b6a3</groupId>
|
||||||
<artifactId>ulid-creator</artifactId>
|
<artifactId>ulid-creator</artifactId>
|
||||||
<version>3.2.0</version>
|
<version>4.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
See more options in [maven.org](https://search.maven.org/artifact/com.github.f4b6a3/ulid-creator).
|
See more options in [maven.org](https://search.maven.org/artifact/com.github.f4b6a3/ulid-creator).
|
||||||
|
@ -44,7 +44,7 @@ Module name: `com.github.f4b6a3.ulid`.
|
||||||
|
|
||||||
### ULID
|
### ULID
|
||||||
|
|
||||||
The ULID is a 128 bit long identifier. The first 48 bits represent the count of milliseconds since Unix Epoch, 1970-01-01. The remaining 80 bits are generated by a secure random number generator.
|
The ULID is a 128 bit long identifier. The first 48 bits represent the number of milliseconds since Unix Epoch, 1970-01-01. The remaining 80 bits are generated by a secure random number generator.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Generate a ULID
|
// Generate a ULID
|
||||||
|
@ -83,7 +83,7 @@ Sequence of ULIDs:
|
||||||
|
|
||||||
### Monotonic ULID
|
### Monotonic ULID
|
||||||
|
|
||||||
The Monotonic ULID is a 128 bit long identifier. The first 48 bits represent the count of milliseconds since Unix Epoch, 1970-01-01. The remaining 80 bits are generated by a secure random number generator.
|
The Monotonic ULID is a 128 bit long identifier. The first 48 bits represent the number of milliseconds since Unix Epoch, 1970-01-01. The remaining 80 bits are generated by a secure random number generator.
|
||||||
|
|
||||||
The random component is incremented by 1 whenever the current millisecond is equal to the previous one. But when the current millisecond is different, the random component changes to another random value.
|
The random component is incremented by 1 whenever the current millisecond is equal to the previous one. But when the current millisecond is different, the random component changes to another random value.
|
||||||
|
|
||||||
|
@ -197,22 +197,20 @@ byte[] random = Ulid.getRandom("0123456789ABCDEFGHJKMNPQRS"); // 10 bytes (80 bi
|
||||||
Use a `UlidFactory` with `java.util.Random`:
|
Use a `UlidFactory` with `java.util.Random`:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// use a `Random` instance
|
// use a `java.util.Random` instance for fast generation
|
||||||
UlidFactory factory = new DefaultFactory(new Random());
|
UlidFactory factory = UlidFactory.newInstance(new Random());
|
||||||
Ulid ulid = factory.create();
|
Ulid ulid = factory.create();
|
||||||
```
|
```
|
||||||
|
|
||||||
Use a `UlidFactory` with a random generator of your choice:
|
Use a `UlidFactory` with a random generator of your choice:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// use a method of any RNG with this signature: `void nextBytes(byte[])`
|
// use a random supplier that returns an array of 10 bytes
|
||||||
import com.github.niceguy.random.AwesomeRandom; // a hypothetical RNG
|
AwesomeRandom awesomeRandom = new AwesomeRandom(); // a hypothetical RNG
|
||||||
UlidFactory factory = new DefaultFactory(new AwesomeRandom()::nextBytes);
|
UlidFactory factory = UlidFactory.newInstance(() -> awesomeRandom.nextBytes(Ulid.RANDOM_BYTES));
|
||||||
Ulid ulid = factory.create();
|
Ulid ulid = factory.create();
|
||||||
```
|
```
|
||||||
|
|
||||||
(*) as long as it provides a void method like `nextBytes(byte[])`.
|
|
||||||
|
|
||||||
Benchmark
|
Benchmark
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
|
@ -222,12 +220,12 @@ This section shows benchmarks comparing `UlidCreator` to `java.util.UUID`.
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
THROUGHPUT (operations/msec) Mode Cnt Score Error Units
|
THROUGHPUT (operations/msec) Mode Cnt Score Error Units
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
UUID_randomUUID thrpt 5 2051,918 ± 24,797 ops/ms
|
UUID_randomUUID thrpt 5 2060,570 ± 37,242 ops/ms
|
||||||
UUID_randomUUID_toString thrpt 5 1176,382 ± 32,709 ops/ms
|
UUID_randomUUID_toString thrpt 5 1177,386 ± 39,803 ops/ms
|
||||||
UlidCreator_getUlid thrpt 5 2738,998 ± 51,092 ops/ms
|
UlidCreator_getUlid thrpt 5 2740,609 ± 86,350 ops/ms
|
||||||
UlidCreator_getUlid_toString thrpt 5 2548,178 ± 25,484 ops/ms
|
UlidCreator_getUlid_toString thrpt 5 2526,284 ± 56,726 ops/ms
|
||||||
UlidCreator_getMonotonicUlid thrpt 5 19807,920 ± 410,996 ops/ms
|
UlidCreator_getMonotonicUlid thrpt 5 19373,150 ± 192,402 ops/ms
|
||||||
UlidCreator_getMonotonicUlid_toString thrpt 5 13178,389 ± 147,323 ops/ms
|
UlidCreator_getMonotonicUlid_toString thrpt 5 13269,201 ± 254,953 ops/ms
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
Total time: 00:08:01
|
Total time: 00:08:01
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
To execute the benchmark, run the script `./benchmark/run.sh`.
|
To execute the benchmark, run the script `./benchmark/run.sh`.
|
||||||
|
|
||||||
Sorry, there is no `run.bat` file for Windows.
|
Sorry, there is no `run.bat` file for Windows at this time.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020 Fabio Lima
|
* Copyright (c) 2020-2021 Fabio Lima
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -48,13 +48,13 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
private final long msb; // most significant bits
|
private final long msb; // most significant bits
|
||||||
private final long lsb; // least significant bits
|
private final long lsb; // least significant bits
|
||||||
|
|
||||||
public static final int ULID_LENGTH = 26;
|
public static final int ULID_CHARS = 26;
|
||||||
public static final int TIME_LENGTH = 10;
|
public static final int TIME_CHARS = 10;
|
||||||
public static final int RANDOM_LENGTH = 16;
|
public static final int RANDOM_CHARS = 16;
|
||||||
|
|
||||||
public static final int ULID_BYTES_LENGTH = 16;
|
public static final int ULID_BYTES = 16;
|
||||||
public static final int TIME_BYTES_LENGTH = 6;
|
public static final int TIME_BYTES = 6;
|
||||||
public static final int RANDOM_BYTES_LENGTH = 10;
|
public static final int RANDOM_BYTES = 10;
|
||||||
|
|
||||||
private static final char[] ALPHABET_UPPERCASE = //
|
private static final char[] ALPHABET_UPPERCASE = //
|
||||||
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', //
|
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', //
|
||||||
|
@ -180,7 +180,7 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
throw new IllegalArgumentException("Invalid time value"); // time overflow!
|
throw new IllegalArgumentException("Invalid time value"); // time overflow!
|
||||||
}
|
}
|
||||||
// The random component has 80 bits (10 bytes).
|
// The random component has 80 bits (10 bytes).
|
||||||
if (random == null || random.length != RANDOM_BYTES_LENGTH) {
|
if (random == null || random.length != RANDOM_BYTES) {
|
||||||
throw new IllegalArgumentException("Invalid random bytes"); // null or wrong length!
|
throw new IllegalArgumentException("Invalid random bytes"); // null or wrong length!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
*/
|
*/
|
||||||
public static Ulid from(byte[] bytes) {
|
public static Ulid from(byte[] bytes) {
|
||||||
|
|
||||||
if (bytes == null || bytes.length != ULID_BYTES_LENGTH) {
|
if (bytes == null || bytes.length != ULID_BYTES) {
|
||||||
throw new IllegalArgumentException("Invalid ULID bytes"); // null or wrong length!
|
throw new IllegalArgumentException("Invalid ULID bytes"); // null or wrong length!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
*/
|
*/
|
||||||
public byte[] toBytes() {
|
public byte[] toBytes() {
|
||||||
|
|
||||||
final byte[] bytes = new byte[ULID_BYTES_LENGTH];
|
final byte[] bytes = new byte[ULID_BYTES];
|
||||||
|
|
||||||
bytes[0x0] = (byte) (msb >>> 56);
|
bytes[0x0] = (byte) (msb >>> 56);
|
||||||
bytes[0x1] = (byte) (msb >>> 48);
|
bytes[0x1] = (byte) (msb >>> 48);
|
||||||
|
@ -351,11 +351,15 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
* The output string is 26 characters long and contains only characters from
|
* The output string is 26 characters long and contains only characters from
|
||||||
* Crockford's base 32 alphabet.
|
* Crockford's base 32 alphabet.
|
||||||
*
|
*
|
||||||
|
* For lower case string, use the shorthand {@code Ulid#toLowerCase()}, instead
|
||||||
|
* of {@code Ulid#toString()#toLowerCase()}.
|
||||||
|
*
|
||||||
* See: https://www.crockford.com/base32.html
|
* See: https://www.crockford.com/base32.html
|
||||||
*
|
*
|
||||||
* @return a string
|
* @return a ULID string
|
||||||
*/
|
*/
|
||||||
public String toUpperCase() {
|
@Override
|
||||||
|
public String toString() {
|
||||||
return toString(ALPHABET_UPPERCASE);
|
return toString(ALPHABET_UPPERCASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,7 +490,7 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
*/
|
*/
|
||||||
public byte[] getRandom() {
|
public byte[] getRandom() {
|
||||||
|
|
||||||
final byte[] bytes = new byte[RANDOM_BYTES_LENGTH];
|
final byte[] bytes = new byte[RANDOM_BYTES];
|
||||||
|
|
||||||
bytes[0x0] = (byte) (msb >>> 8);
|
bytes[0x0] = (byte) (msb >>> 8);
|
||||||
bytes[0x1] = (byte) (msb);
|
bytes[0x1] = (byte) (msb);
|
||||||
|
@ -536,7 +540,7 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
random1 |= ALPHABET_VALUES[chars[0x18]] << 5;
|
random1 |= ALPHABET_VALUES[chars[0x18]] << 5;
|
||||||
random1 |= ALPHABET_VALUES[chars[0x19]];
|
random1 |= ALPHABET_VALUES[chars[0x19]];
|
||||||
|
|
||||||
final byte[] bytes = new byte[RANDOM_BYTES_LENGTH];
|
final byte[] bytes = new byte[RANDOM_BYTES];
|
||||||
|
|
||||||
bytes[0x0] = (byte) (random0 >>> 32);
|
bytes[0x0] = (byte) (random0 >>> 32);
|
||||||
bytes[0x1] = (byte) (random0 >>> 24);
|
bytes[0x1] = (byte) (random0 >>> 24);
|
||||||
|
@ -617,24 +621,6 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
return string != null && isValidCharArray(string.toCharArray());
|
return string != null && isValidCharArray(string.toCharArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the ULID into a canonical string in upper case.
|
|
||||||
*
|
|
||||||
* The output string is 26 characters long and contains only characters from
|
|
||||||
* Crockford's base 32 alphabet.
|
|
||||||
*
|
|
||||||
* For lower case string, use the shorthand {@code Ulid#toLowerCase()}, instead
|
|
||||||
* of {@code Ulid#toString()#toLowerCase()}.
|
|
||||||
*
|
|
||||||
* See: https://www.crockford.com/base32.html
|
|
||||||
*
|
|
||||||
* @return a ULID string
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
|
@ -675,7 +661,7 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
|
|
||||||
protected String toString(char[] alphabet) {
|
protected String toString(char[] alphabet) {
|
||||||
|
|
||||||
final char[] chars = new char[ULID_LENGTH];
|
final char[] chars = new char[ULID_CHARS];
|
||||||
|
|
||||||
long time = this.msb >>> 16;
|
long time = this.msb >>> 16;
|
||||||
long random0 = ((this.msb & 0xffffL) << 24) | (this.lsb >>> 40);
|
long random0 = ((this.msb & 0xffffL) << 24) | (this.lsb >>> 40);
|
||||||
|
@ -734,7 +720,7 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
*/
|
*/
|
||||||
protected static boolean isValidCharArray(final char[] chars) {
|
protected static boolean isValidCharArray(final char[] chars) {
|
||||||
|
|
||||||
if (chars == null || chars.length != ULID_LENGTH) {
|
if (chars == null || chars.length != ULID_CHARS) {
|
||||||
return false; // null or wrong size!
|
return false; // null or wrong size!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020 Fabio Lima
|
* Copyright (c) 2020-2021 Fabio Lima
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -24,16 +24,12 @@
|
||||||
|
|
||||||
package com.github.f4b6a3.ulid;
|
package com.github.f4b6a3.ulid;
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.factory.DefaultFactory;
|
|
||||||
import com.github.f4b6a3.ulid.factory.MonotonicFactory;
|
|
||||||
import com.github.f4b6a3.ulid.factory.UlidFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Facade to the ULID factories.
|
* A class for generating ULIDs.
|
||||||
*
|
*
|
||||||
* The ULID has two components:
|
* The ULID has two components:
|
||||||
*
|
*
|
||||||
* - Time component: a part of 48 bits that represent the amount of milliseconds
|
* - Time component: a part of 48 bits that represent the number of milliseconds
|
||||||
* since Unix Epoch, 1970-01-01.
|
* since Unix Epoch, 1970-01-01.
|
||||||
*
|
*
|
||||||
* - Random component: a byte array of 80 bits that has a random value generated
|
* - Random component: a byte array of 80 bits that has a random value generated
|
||||||
|
@ -54,27 +50,28 @@ public final class UlidCreator {
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
*/
|
*/
|
||||||
public static Ulid getUlid() {
|
public static Ulid getUlid() {
|
||||||
return DefaultFactoryHolder.INSTANCE.create();
|
return UlidFactoryHolder.INSTANCE.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a ULID with a specific time.
|
* Returns a ULID with a given time.
|
||||||
*
|
*
|
||||||
* @param time a specific time
|
* The time must be the number of milliseconds since 1970-01-01 (Unix epoch).
|
||||||
|
*
|
||||||
|
* @param time a given time
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
*/
|
*/
|
||||||
public static Ulid getUlid(final long time) {
|
public static Ulid getUlid(final long time) {
|
||||||
return DefaultFactoryHolder.INSTANCE.create(time);
|
return UlidFactoryHolder.INSTANCE.create(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Monotonic ULID.
|
* Returns a Monotonic ULID.
|
||||||
*
|
*
|
||||||
* The random component is reset to a new value every time the millisecond
|
* The random component is reset to a new value whenever the time changes.
|
||||||
* changes.
|
|
||||||
*
|
*
|
||||||
* If more than one ULID is generated within the same millisecond, the random
|
* If more than one ULID is generated within the same time, the random component
|
||||||
* component is incremented by one.
|
* is incremented by one.
|
||||||
*
|
*
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
*/
|
*/
|
||||||
|
@ -83,20 +80,27 @@ public final class UlidCreator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Monotonic ULID with a specific time.
|
* Returns a Monotonic ULID with a given time.
|
||||||
*
|
*
|
||||||
* @param time a specific time
|
* The time must be the number of milliseconds since 1970-01-01 (Unix epoch).
|
||||||
|
*
|
||||||
|
* The random component is reset to a new value whenever the time changes.
|
||||||
|
*
|
||||||
|
* If more than one ULID is generated within the same time, the random component
|
||||||
|
* is incremented by one.
|
||||||
|
*
|
||||||
|
* @param time a given time
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
*/
|
*/
|
||||||
public static Ulid getMonotonicUlid(final long time) {
|
public static Ulid getMonotonicUlid(final long time) {
|
||||||
return MonotonicFactoryHolder.INSTANCE.create(time);
|
return MonotonicFactoryHolder.INSTANCE.create(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DefaultFactoryHolder {
|
private static class UlidFactoryHolder {
|
||||||
static final UlidFactory INSTANCE = new DefaultFactory();
|
static final UlidFactory INSTANCE = UlidFactory.newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MonotonicFactoryHolder {
|
private static class MonotonicFactoryHolder {
|
||||||
static final UlidFactory INSTANCE = new MonotonicFactory();
|
static final UlidFactory INSTANCE = UlidFactory.newMonotonicInstance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2021 Fabio Lima
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.github.f4b6a3.ulid;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.function.LongFunction;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory that generates ULIDs.
|
||||||
|
*
|
||||||
|
* If the factory is not monotonic, the random component always changes.
|
||||||
|
*
|
||||||
|
* If the factory is monotonic, the random component changes whenever the
|
||||||
|
* millisecond changes. If more than one ULID is generated within the same
|
||||||
|
* millisecond, the random component is incremented by one.
|
||||||
|
*
|
||||||
|
* The maximum ULIDs that can be generated per millisecond is 2^80.
|
||||||
|
*/
|
||||||
|
public final class UlidFactory {
|
||||||
|
|
||||||
|
private final LongFunction<Ulid> ulidFunction;
|
||||||
|
|
||||||
|
public UlidFactory() {
|
||||||
|
this.ulidFunction = new UlidFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
private UlidFactory(LongFunction<Ulid> ulidFunction) {
|
||||||
|
this.ulidFunction = ulidFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new factory.
|
||||||
|
*
|
||||||
|
* It is equivalent to {@code new UlidFactory()}.
|
||||||
|
*
|
||||||
|
* @return {@link UlidFactory}
|
||||||
|
*/
|
||||||
|
public static UlidFactory newInstance() {
|
||||||
|
return new UlidFactory(new UlidFunction());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new factory.
|
||||||
|
*
|
||||||
|
* @param random a {@link Random} generator
|
||||||
|
* @return {@link UlidFactory}
|
||||||
|
*/
|
||||||
|
public static UlidFactory newInstance(Random random) {
|
||||||
|
return new UlidFactory(new UlidFunction(random));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new factory.
|
||||||
|
*
|
||||||
|
* The given random supplier must return an array of 10 bytes.
|
||||||
|
*
|
||||||
|
* @param randomSupplier a random supplier that returns 10 bytes
|
||||||
|
* @return {@link UlidFactory}
|
||||||
|
*/
|
||||||
|
public static UlidFactory newInstance(Supplier<byte[]> randomSupplier) {
|
||||||
|
return new UlidFactory(new UlidFunction(randomSupplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new monotonic factory.
|
||||||
|
*
|
||||||
|
* @return {@link UlidFactory}
|
||||||
|
*/
|
||||||
|
public static UlidFactory newMonotonicInstance() {
|
||||||
|
return new UlidFactory(new MonotonicFunction());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new monotonic factory.
|
||||||
|
*
|
||||||
|
* @param random a {@link Random} generator
|
||||||
|
* @return {@link UlidFactory}
|
||||||
|
*/
|
||||||
|
public static UlidFactory newMonotonicInstance(Random random) {
|
||||||
|
return new UlidFactory(new MonotonicFunction(random));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new monotonic factory.
|
||||||
|
*
|
||||||
|
* The given random supplier must return an array of 10 bytes.
|
||||||
|
*
|
||||||
|
* @param randomSupplier a random supplier that returns 10 bytes
|
||||||
|
* @return {@link UlidFactory}
|
||||||
|
*/
|
||||||
|
public static UlidFactory newMonotonicInstance(Supplier<byte[]> randomSupplier) {
|
||||||
|
return new UlidFactory(new MonotonicFunction(randomSupplier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a UUID.
|
||||||
|
*
|
||||||
|
* @return a ULID
|
||||||
|
*/
|
||||||
|
public Ulid create() {
|
||||||
|
return create(System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a UUID with a specific time.
|
||||||
|
*
|
||||||
|
* The time must be the number of milliseconds since 1970-01-01 (Unix epoch).
|
||||||
|
*
|
||||||
|
* @param time a given time
|
||||||
|
* @return a ULID
|
||||||
|
*/
|
||||||
|
public Ulid create(final long time) {
|
||||||
|
return this.ulidFunction.apply(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that creates ULIDs.
|
||||||
|
*/
|
||||||
|
protected static final class UlidFunction implements LongFunction<Ulid> {
|
||||||
|
|
||||||
|
// it must return an array of 10 bytes
|
||||||
|
private Supplier<byte[]> randomSupplier;
|
||||||
|
|
||||||
|
public UlidFunction() {
|
||||||
|
this(new SecureRandom());
|
||||||
|
}
|
||||||
|
|
||||||
|
public UlidFunction(Random random) {
|
||||||
|
this(getRandomSupplier(random));
|
||||||
|
}
|
||||||
|
|
||||||
|
public UlidFunction(Supplier<byte[]> randomSupplier) {
|
||||||
|
this.randomSupplier = randomSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Ulid apply(final long time) {
|
||||||
|
return new Ulid(time, this.randomSupplier.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that creates Monotonic ULIDs.
|
||||||
|
*/
|
||||||
|
protected static final class MonotonicFunction implements LongFunction<Ulid> {
|
||||||
|
|
||||||
|
private long lastTime = -1;
|
||||||
|
private Ulid lastUlid = null;
|
||||||
|
|
||||||
|
// it must return an array of 10 bytes
|
||||||
|
private Supplier<byte[]> randomSupplier;
|
||||||
|
|
||||||
|
public MonotonicFunction() {
|
||||||
|
this(new SecureRandom());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonotonicFunction(Random random) {
|
||||||
|
this(getRandomSupplier(random));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonotonicFunction(Supplier<byte[]> randomSupplier) {
|
||||||
|
this.randomSupplier = randomSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized Ulid apply(final long time) {
|
||||||
|
|
||||||
|
if (time == this.lastTime) {
|
||||||
|
this.lastUlid = lastUlid.increment();
|
||||||
|
} else {
|
||||||
|
this.lastUlid = new Ulid(time, this.randomSupplier.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastTime = time;
|
||||||
|
return new Ulid(this.lastUlid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It instantiates a supplier that returns an array of 10 bytes.
|
||||||
|
*
|
||||||
|
* @param random a {@link Random} generator
|
||||||
|
* @return a random supplier that returns 10 bytes
|
||||||
|
*/
|
||||||
|
protected static Supplier<byte[]> getRandomSupplier(Random random) {
|
||||||
|
return () -> {
|
||||||
|
byte[] payload = new byte[Ulid.RANDOM_BYTES];
|
||||||
|
random.nextBytes(payload);
|
||||||
|
return payload;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2020 Fabio Lima
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.github.f4b6a3.ulid.factory;
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.Ulid;
|
|
||||||
import com.github.f4b6a3.ulid.random.RandomGenerator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory that generates ULIDs.
|
|
||||||
*
|
|
||||||
* The random component is always reset to a new random value.
|
|
||||||
*
|
|
||||||
* The maximum ULIDs that can be generated per millisecond is 2^80.
|
|
||||||
*/
|
|
||||||
public class DefaultFactory extends UlidFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the default {@link java.security.SecureRandom}.
|
|
||||||
*/
|
|
||||||
public DefaultFactory() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use a random generator that inherits from {@link Random}.
|
|
||||||
*
|
|
||||||
* @param random a {@link Random} instance
|
|
||||||
*/
|
|
||||||
public DefaultFactory(Random random) {
|
|
||||||
this(random::nextBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use a random generator that inherits from {@link RandomGenerator}.
|
|
||||||
*
|
|
||||||
* @param randomGenerator a {@link RandomGenerator} instance
|
|
||||||
*/
|
|
||||||
public DefaultFactory(RandomGenerator randomGenerator) {
|
|
||||||
super(randomGenerator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a ULID.
|
|
||||||
*
|
|
||||||
* @param time a specific time
|
|
||||||
* @return a ULID
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Ulid create(final long time) {
|
|
||||||
final byte[] random = new byte[Ulid.RANDOM_BYTES_LENGTH];
|
|
||||||
this.randomGenerator.nextBytes(random);
|
|
||||||
return new Ulid(time, random);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2020 Fabio Lima
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.github.f4b6a3.ulid.factory;
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.Ulid;
|
|
||||||
import com.github.f4b6a3.ulid.random.RandomGenerator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory that generates Monotonic ULIDs.
|
|
||||||
*
|
|
||||||
* The random component is reset to a new value every time the millisecond
|
|
||||||
* changes.
|
|
||||||
*
|
|
||||||
* If more than one ULID is generated within the same millisecond, the random
|
|
||||||
* component is incremented by one.
|
|
||||||
*
|
|
||||||
* The maximum ULIDs that can be generated per millisecond is 2^80.
|
|
||||||
*/
|
|
||||||
public final class MonotonicFactory extends UlidFactory {
|
|
||||||
|
|
||||||
private long lastTime = -1;
|
|
||||||
private Ulid lastUlid = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the default {@link java.security.SecureRandom}.
|
|
||||||
*/
|
|
||||||
public MonotonicFactory() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use a random generator that inherits from {@link Random}.
|
|
||||||
*
|
|
||||||
* @param random a {@link Random} instance
|
|
||||||
*/
|
|
||||||
public MonotonicFactory(Random random) {
|
|
||||||
this(random::nextBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use a random generator that inherits from {@link RandomGenerator}.
|
|
||||||
*
|
|
||||||
* @param randomGenerator a {@link RandomGenerator} instance
|
|
||||||
*/
|
|
||||||
public MonotonicFactory(RandomGenerator randomGenerator) {
|
|
||||||
super(randomGenerator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a ULID.
|
|
||||||
*
|
|
||||||
* @param time a specific time
|
|
||||||
* @return a ULID
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public synchronized Ulid create(final long time) {
|
|
||||||
|
|
||||||
if (time == this.lastTime) {
|
|
||||||
this.lastUlid = lastUlid.increment();
|
|
||||||
} else {
|
|
||||||
final byte[] random = new byte[Ulid.RANDOM_BYTES_LENGTH];
|
|
||||||
this.randomGenerator.nextBytes(random);
|
|
||||||
this.lastUlid = new Ulid(time, random);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.lastTime = time;
|
|
||||||
return new Ulid(this.lastUlid);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2020 Fabio Lima
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.github.f4b6a3.ulid.factory;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.Ulid;
|
|
||||||
import com.github.f4b6a3.ulid.random.RandomGenerator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An abstract factory for generating ULIDs.
|
|
||||||
*
|
|
||||||
* The only method that must be implemented is {@link UlidFactory#create(long)}.
|
|
||||||
*/
|
|
||||||
public abstract class UlidFactory {
|
|
||||||
|
|
||||||
protected RandomGenerator randomGenerator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the default {@link java.security.SecureRandom}.
|
|
||||||
*/
|
|
||||||
public UlidFactory() {
|
|
||||||
this(new SecureRandom()::nextBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use a random generator that inherits from {@link RandomGenerator}.
|
|
||||||
*
|
|
||||||
* @param randomGenerator a {@link RandomGenerator} instance
|
|
||||||
*/
|
|
||||||
public UlidFactory(RandomGenerator randomGenerator) {
|
|
||||||
this.randomGenerator = randomGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a UUID.
|
|
||||||
*
|
|
||||||
* @return a ULID
|
|
||||||
*/
|
|
||||||
public Ulid create() {
|
|
||||||
return create(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a UUID with a specific time.
|
|
||||||
*
|
|
||||||
* This method must be implemented by all subclasses.
|
|
||||||
*
|
|
||||||
* @param time a specific time
|
|
||||||
* @return a ULID
|
|
||||||
*/
|
|
||||||
public abstract Ulid create(final long time);
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2018-2020 Fabio Lima
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.github.f4b6a3.ulid.random;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface RandomGenerator {
|
|
||||||
void nextBytes(byte[] bytes);
|
|
||||||
}
|
|
|
@ -50,7 +50,7 @@ public class UlidTest {
|
||||||
long time = msb >>> 16;
|
long time = msb >>> 16;
|
||||||
|
|
||||||
// get the random bytes
|
// get the random bytes
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(Ulid.RANDOM_BYTES_LENGTH);
|
ByteBuffer buffer = ByteBuffer.allocate(Ulid.RANDOM_BYTES);
|
||||||
buffer.put((byte) ((msb >>> 8) & 0xff));
|
buffer.put((byte) ((msb >>> 8) & 0xff));
|
||||||
buffer.put((byte) (msb & 0xff));
|
buffer.put((byte) (msb & 0xff));
|
||||||
buffer.putLong(lsb);
|
buffer.putLong(lsb);
|
||||||
|
@ -63,7 +63,7 @@ public class UlidTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long time = 0x0000ffffffffffffL + 1; // greater than 2^48-1
|
long time = 0x0000ffffffffffffL + 1; // greater than 2^48-1
|
||||||
byte[] bytes = new byte[Ulid.RANDOM_BYTES_LENGTH];
|
byte[] bytes = new byte[Ulid.RANDOM_BYTES];
|
||||||
new Ulid(time, bytes);
|
new Ulid(time, bytes);
|
||||||
fail("Should throw an exception");
|
fail("Should throw an exception");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
@ -72,7 +72,7 @@ public class UlidTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long time = 0x8000000000000000L; // negative number
|
long time = 0x8000000000000000L; // negative number
|
||||||
byte[] bytes = new byte[Ulid.RANDOM_BYTES_LENGTH];
|
byte[] bytes = new byte[Ulid.RANDOM_BYTES];
|
||||||
new Ulid(time, bytes);
|
new Ulid(time, bytes);
|
||||||
fail("Should throw an exception");
|
fail("Should throw an exception");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
@ -90,7 +90,7 @@ public class UlidTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long time = 0x0000000000000000L;
|
long time = 0x0000000000000000L;
|
||||||
byte[] bytes = new byte[Ulid.RANDOM_BYTES_LENGTH + 1]; // random component with invalid size
|
byte[] bytes = new byte[Ulid.RANDOM_BYTES + 1]; // random component with invalid size
|
||||||
new Ulid(time, bytes);
|
new Ulid(time, bytes);
|
||||||
fail("Should throw an exception");
|
fail("Should throw an exception");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
@ -131,12 +131,12 @@ public class UlidTest {
|
||||||
Ulid ulid0 = new Ulid(msb, lsb);
|
Ulid ulid0 = new Ulid(msb, lsb);
|
||||||
|
|
||||||
String string1 = toString(ulid0);
|
String string1 = toString(ulid0);
|
||||||
String string2 = ulid0.toUpperCase(); // <- test Ulid.toUpperCase()
|
String string2 = ulid0.toString(); // <- test Ulid.toString()
|
||||||
assertEquals(string1, string2);
|
assertEquals(string1, string2);
|
||||||
|
|
||||||
// RFC-4122 UUID v4
|
// RFC-4122 UUID v4
|
||||||
UUID uuid0 = new UUID(msb, lsb);
|
UUID uuid0 = new UUID(msb, lsb);
|
||||||
String string3 = ulid0.toRfc4122().toUpperCase(); // <- test Ulid.toRfc4122().toUpperCase()
|
String string3 = ulid0.toRfc4122().toString(); // <- test Ulid.toRfc4122().toString()
|
||||||
Ulid ulid3 = fromString(string3);
|
Ulid ulid3 = fromString(string3);
|
||||||
UUID uuid3 = new UUID(ulid3.getMostSignificantBits(), ulid3.getLeastSignificantBits());
|
UUID uuid3 = new UUID(ulid3.getMostSignificantBits(), ulid3.getLeastSignificantBits());
|
||||||
assertEquals(4, uuid3.version()); // check version
|
assertEquals(4, uuid3.version()); // check version
|
||||||
|
@ -218,11 +218,11 @@ public class UlidTest {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
for (int i = 0; i < DEFAULT_LOOP_MAX; i++) {
|
for (int i = 0; i < DEFAULT_LOOP_MAX; i++) {
|
||||||
|
|
||||||
byte[] bytes0 = new byte[Ulid.ULID_BYTES_LENGTH];
|
byte[] bytes0 = new byte[Ulid.ULID_BYTES];
|
||||||
random.nextBytes(bytes0);
|
random.nextBytes(bytes0);
|
||||||
|
|
||||||
Ulid ulid0 = Ulid.from(bytes0); // <- test Ulid.from(UUID)
|
Ulid ulid0 = Ulid.from(bytes0); // <- test Ulid.from(UUID)
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(Ulid.ULID_BYTES_LENGTH);
|
ByteBuffer buffer = ByteBuffer.allocate(Ulid.ULID_BYTES);
|
||||||
buffer.putLong(ulid0.getMostSignificantBits());
|
buffer.putLong(ulid0.getMostSignificantBits());
|
||||||
buffer.putLong(ulid0.getLeastSignificantBits());
|
buffer.putLong(ulid0.getLeastSignificantBits());
|
||||||
byte[] bytes1 = buffer.array();
|
byte[] bytes1 = buffer.array();
|
||||||
|
@ -241,7 +241,7 @@ public class UlidTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] bytes = new byte[Ulid.ULID_BYTES_LENGTH + 1];
|
byte[] bytes = new byte[Ulid.ULID_BYTES + 1];
|
||||||
Ulid.from(bytes);
|
Ulid.from(bytes);
|
||||||
fail("Should throw an exception");
|
fail("Should throw an exception");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
@ -281,7 +281,7 @@ public class UlidTest {
|
||||||
public void testGetTimeAndGetRandom() {
|
public void testGetTimeAndGetRandom() {
|
||||||
|
|
||||||
long time = 0;
|
long time = 0;
|
||||||
byte[] bytes = new byte[Ulid.RANDOM_BYTES_LENGTH];
|
byte[] bytes = new byte[Ulid.RANDOM_BYTES];
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
|
|
|
@ -3,9 +3,6 @@ package com.github.f4b6a3.ulid;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.factory.MonotonicFactory;
|
|
||||||
import com.github.f4b6a3.ulid.factory.UlidFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* This test starts many threads that keep requesting thousands of ULIDs to a
|
* This test starts many threads that keep requesting thousands of ULIDs to a
|
||||||
|
@ -119,7 +116,7 @@ public class UniquenessTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void execute(boolean verbose, int threadCount, int requestCount) {
|
public static void execute(boolean verbose, int threadCount, int requestCount) {
|
||||||
UlidFactory factory = new MonotonicFactory(new Random());
|
UlidFactory factory = UlidFactory.newMonotonicInstance(new Random());
|
||||||
UniquenessTest test = new UniquenessTest(threadCount, requestCount, factory, verbose);
|
UniquenessTest test = new UniquenessTest(threadCount, requestCount, factory, verbose);
|
||||||
test.start();
|
test.start();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
package com.github.f4b6a3.ulid.bench;
|
|
||||||
|
|
||||||
// Add theese dependencies to pom.xml:
|
|
||||||
//
|
|
||||||
// <dependency>
|
|
||||||
// <groupId>org.openjdk.jmh</groupId>
|
|
||||||
// <artifactId>jmh-core</artifactId>
|
|
||||||
// <version>1.23</version>
|
|
||||||
// </dependency>
|
|
||||||
// <dependency>
|
|
||||||
// <groupId>org.openjdk.jmh</groupId>
|
|
||||||
// <artifactId>jmh-generator-annprocess</artifactId>
|
|
||||||
// <version>1.23</version>
|
|
||||||
// </dependency>
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import org.openjdk.jmh.annotations.Benchmark;
|
|
||||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
|
||||||
import org.openjdk.jmh.annotations.Measurement;
|
|
||||||
import org.openjdk.jmh.annotations.Mode;
|
|
||||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
|
||||||
import org.openjdk.jmh.annotations.Scope;
|
|
||||||
import org.openjdk.jmh.annotations.State;
|
|
||||||
import org.openjdk.jmh.annotations.Threads;
|
|
||||||
import org.openjdk.jmh.annotations.Warmup;
|
|
||||||
import org.openjdk.jmh.runner.Runner;
|
|
||||||
import org.openjdk.jmh.runner.RunnerException;
|
|
||||||
import org.openjdk.jmh.runner.options.Options;
|
|
||||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.Ulid;
|
|
||||||
import com.github.f4b6a3.ulid.UlidCreator;
|
|
||||||
|
|
||||||
@Threads(1)
|
|
||||||
@State(Scope.Thread)
|
|
||||||
@Warmup(iterations = 5)
|
|
||||||
@Measurement(iterations = 5)
|
|
||||||
public class Benchmarks {
|
|
||||||
|
|
||||||
@Benchmark
|
|
||||||
@BenchmarkMode(Mode.Throughput)
|
|
||||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
|
||||||
public UUID getUuid() {
|
|
||||||
return UUID.randomUUID();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
|
||||||
@BenchmarkMode(Mode.Throughput)
|
|
||||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
|
||||||
public String getUuidString() {
|
|
||||||
return UUID.randomUUID().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
|
||||||
@BenchmarkMode(Mode.Throughput)
|
|
||||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
|
||||||
public Ulid getUlid() {
|
|
||||||
return UlidCreator.getUlid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
|
||||||
@BenchmarkMode(Mode.Throughput)
|
|
||||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
|
||||||
public String getUlidString() {
|
|
||||||
return UlidCreator.getUlid().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
|
||||||
@BenchmarkMode(Mode.Throughput)
|
|
||||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
|
||||||
public Ulid getMonotonicUlid() {
|
|
||||||
return UlidCreator.getMonotonicUlid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
|
||||||
@BenchmarkMode(Mode.Throughput)
|
|
||||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
|
||||||
public String getMonotonicUlidString() {
|
|
||||||
return UlidCreator.getMonotonicUlid().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws RunnerException {
|
|
||||||
Options opt = new OptionsBuilder().include(Benchmarks.class.getSimpleName()).forks(1).build();
|
|
||||||
new Runner(opt).run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -4,7 +4,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.Ulid;
|
import com.github.f4b6a3.ulid.Ulid;
|
||||||
import com.github.f4b6a3.ulid.UlidCreator;
|
import com.github.f4b6a3.ulid.UlidCreator;
|
||||||
import com.github.f4b6a3.ulid.factory.UlidFactory;
|
import com.github.f4b6a3.ulid.UlidFactory;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ public class DefaultFactoryTest extends UlidFactoryTest {
|
||||||
|
|
||||||
// Instantiate and start many threads
|
// Instantiate and start many threads
|
||||||
for (int i = 0; i < THREAD_TOTAL; i++) {
|
for (int i = 0; i < THREAD_TOTAL; i++) {
|
||||||
UlidFactory factory = new DefaultFactory(new Random());
|
UlidFactory factory = UlidFactory.newInstance(new Random());
|
||||||
threads[i] = new TestThread(factory, DEFAULT_LOOP_MAX);
|
threads[i] = new TestThread(factory, DEFAULT_LOOP_MAX);
|
||||||
threads[i].start();
|
threads[i].start();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.Ulid;
|
import com.github.f4b6a3.ulid.Ulid;
|
||||||
import com.github.f4b6a3.ulid.UlidCreator;
|
import com.github.f4b6a3.ulid.UlidCreator;
|
||||||
import com.github.f4b6a3.ulid.factory.UlidFactory;
|
import com.github.f4b6a3.ulid.UlidFactory;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ public class MonotonicFactoryTest extends UlidFactoryTest {
|
||||||
|
|
||||||
// Instantiate and start many threads
|
// Instantiate and start many threads
|
||||||
for (int i = 0; i < THREAD_TOTAL; i++) {
|
for (int i = 0; i < THREAD_TOTAL; i++) {
|
||||||
UlidFactory factory = new MonotonicFactory(new Random());
|
UlidFactory factory = UlidFactory.newMonotonicInstance(new Random());
|
||||||
threads[i] = new TestThread(factory, DEFAULT_LOOP_MAX);
|
threads[i] = new TestThread(factory, DEFAULT_LOOP_MAX);
|
||||||
threads[i].start();
|
threads[i].start();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.github.f4b6a3.ulid.factory.UlidFactory;
|
import com.github.f4b6a3.ulid.UlidFactory;
|
||||||
|
|
||||||
public abstract class UlidFactoryTest {
|
public abstract class UlidFactoryTest {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue