Add Hash ULID generator methods. #25
This commit is contained in:
parent
41c15148d3
commit
644ba86e2c
|
@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
Add Hash ULID generator methods. #25
|
||||
Add a MIN and MAX constants and methods. #26
|
||||
|
||||
## [5.2.0] - 2023-??-??
|
||||
|
|
|
@ -43,7 +43,7 @@ Add these lines to your `pom.xml`.
|
|||
<dependency>
|
||||
<groupId>com.github.f4b6a3</groupId>
|
||||
<artifactId>ulid-creator</artifactId>
|
||||
<version>5.1.0</version>
|
||||
<version>5.2.0</version>
|
||||
</dependency>
|
||||
```
|
||||
See more options in [maven.org](https://search.maven.org/artifact/com.github.f4b6a3/ulid-creator).
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-2022 Fabio Lima
|
||||
* Copyright (c) 2020-2023 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
|
||||
|
@ -24,11 +24,19 @@
|
|||
|
||||
package com.github.f4b6a3.ulid;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A class that generates ULIDs.
|
||||
* <p>
|
||||
* Both types of ULID can be easily created by this generator, i.e. monotonic
|
||||
* and non-monotonic.
|
||||
* <p>
|
||||
* In addition, a "non-standard" hash-based ULID can also be generated, in which
|
||||
* the random component is replaced with the first 10 bytes of an SHA-256 hash.
|
||||
*/
|
||||
public final class UlidCreator {
|
||||
|
||||
|
@ -37,6 +45,8 @@ public final class UlidCreator {
|
|||
|
||||
/**
|
||||
* Returns a ULID.
|
||||
* <p>
|
||||
* The random component is reset for each new ULID generated.
|
||||
*
|
||||
* @return a ULID
|
||||
*/
|
||||
|
@ -45,7 +55,9 @@ public final class UlidCreator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a ULID with a given time.
|
||||
* Returns a ULID.
|
||||
* <p>
|
||||
* The random component is reset for each new ULID generated.
|
||||
*
|
||||
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
||||
* @return a ULID
|
||||
|
@ -56,6 +68,9 @@ public final class UlidCreator {
|
|||
|
||||
/**
|
||||
* Returns a Monotonic ULID.
|
||||
* <p>
|
||||
* The random component is incremented for each new ULID generated in the same
|
||||
* millisecond.
|
||||
*
|
||||
* @return a ULID
|
||||
*/
|
||||
|
@ -64,7 +79,10 @@ public final class UlidCreator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a Monotonic ULID with a given time.
|
||||
* Returns a Monotonic ULID.
|
||||
* <p>
|
||||
* The random component is incremented for each new ULID generated in the same
|
||||
* millisecond.
|
||||
*
|
||||
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
||||
* @return a ULID
|
||||
|
@ -73,6 +91,68 @@ public final class UlidCreator {
|
|||
return MonotonicFactoryHolder.INSTANCE.create(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Hash ULID.
|
||||
* <p>
|
||||
* The random component is replaced with the first 10 bytes of an SHA-256 hash.
|
||||
* <p>
|
||||
* It always returns the same ULID for a specific pair of {@code time} and
|
||||
* {@code string}.
|
||||
* <p>
|
||||
* Usage example:
|
||||
*
|
||||
* <pre>{@code
|
||||
* long time = file.getCreatedAt();
|
||||
* String name = file.getFileName();
|
||||
* Ulid ulid = HashUlid.generate(time, name);
|
||||
* }</pre>
|
||||
*
|
||||
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
||||
* @param string a string to be hashed using SHA-256 algorithm.
|
||||
* @return a ULID
|
||||
* @since 5.2.0
|
||||
*/
|
||||
public static Ulid getHashUlid(final long time, String string) {
|
||||
byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
|
||||
return getHashUlid(time, bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Hash ULID.
|
||||
* <p>
|
||||
* The random component is replaced with the first 10 bytes of an SHA-256 hash.
|
||||
* <p>
|
||||
* It always returns the same ULID for a specific pair of {@code time} and
|
||||
* {@code bytes}.
|
||||
* <p>
|
||||
* Usage example:
|
||||
*
|
||||
* <pre>{@code
|
||||
* long time = file.getCreatedAt();
|
||||
* byte[] bytes = file.getFileBinary();
|
||||
* Ulid ulid = HashUlid.generate(time, bytes);
|
||||
* }</pre>
|
||||
*
|
||||
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
||||
* @param bytes a byte array to be hashed using SHA-256 algorithm.
|
||||
* @return a ULID
|
||||
* @since 5.2.0
|
||||
*/
|
||||
public static Ulid getHashUlid(final long time, byte[] bytes) {
|
||||
// Calculate the hash and take the first 10 bytes
|
||||
byte[] hash = hasher("SHA-256").digest(bytes);
|
||||
byte[] rand = Arrays.copyOf(hash, 10);
|
||||
return new Ulid(time, rand);
|
||||
}
|
||||
|
||||
private static MessageDigest hasher(final String algorithm) {
|
||||
try {
|
||||
return MessageDigest.getInstance(algorithm);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(String.format("%s not supported", algorithm));
|
||||
}
|
||||
}
|
||||
|
||||
private static class UlidFactoryHolder {
|
||||
static final UlidFactory INSTANCE = UlidFactory.newInstance();
|
||||
}
|
||||
|
|
|
@ -629,6 +629,32 @@ public class UlidTest extends UlidFactoryTest {
|
|||
checkCreationTime(list, startTime, endTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetHashUlid() throws NoSuchAlgorithmException {
|
||||
|
||||
Ulid prev = Ulid.MIN;
|
||||
for (int i = 0; i < DEFAULT_LOOP_MAX; i++) {
|
||||
|
||||
long time = (new Random()).nextLong() >>> 16;
|
||||
String string = UUID.randomUUID().toString();
|
||||
Ulid ulid = UlidCreator.getHashUlid(time, string);
|
||||
|
||||
assertNotNull(ulid);
|
||||
assertNotEquals(prev, ulid);
|
||||
assertNotEquals(Ulid.MIN, ulid);
|
||||
assertNotEquals(Ulid.MAX, ulid);
|
||||
assertEquals(time, ulid.getTime());
|
||||
assertEquals(Arrays.toString(ulid.getRandom()), Arrays.toString(ulid.getRandom()));
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
byte[] utf8 = string.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] hash = Arrays.copyOf(md.digest(utf8), 10);
|
||||
assertEquals(Arrays.toString(ulid.getRandom()), Arrays.toString(hash));
|
||||
|
||||
prev = ulid;
|
||||
}
|
||||
}
|
||||
|
||||
public static Ulid fromString(String string) {
|
||||
|
||||
long time = 0;
|
||||
|
|
Loading…
Reference in New Issue