Skip to content
This repository was archived by the owner on Jul 28, 2020. It is now read-only.

Commit 543ec37

Browse files
author
Nilan
committed
Inital commit.
0 parents  commit 543ec37

File tree

9 files changed

+378
-0
lines changed

9 files changed

+378
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.jar
2+
.idea
3+
build
4+
.gradle

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# cuid-java

build.gradle

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
group 'cool.graph.cuid-java'
2+
version '0.1.0-SNAPSHOT'
3+
4+
apply plugin: 'java'
5+
6+
repositories {
7+
mavenCentral()
8+
}
9+
10+
dependencies {
11+
testCompile group: 'junit', name: 'junit', version: '4.11'
12+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#Wed Jun 08 23:34:24 CEST 2016
2+
distributionBase=GRADLE_USER_HOME
3+
distributionPath=wrapper/dists
4+
zipStoreBase=GRADLE_USER_HOME
5+
zipStorePath=wrapper/dists
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-all.zip

gradlew

Lines changed: 160 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gradlew.bat

Lines changed: 90 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

settings.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
rootProject.name = 'cuid-java'
2+

src/main/java/Cuid.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import java.lang.management.ManagementFactory;
2+
import java.util.Date;
3+
4+
public class Cuid {
5+
private static final int BASE = 36;
6+
private static final int BLOCK_SIZE = 4;
7+
private static final int DISCRETE_VALUES = (int) Math.pow(BASE, BLOCK_SIZE);
8+
private static final String LETTER = "c";
9+
10+
private static final String FINGERPRINT;
11+
12+
static {
13+
FINGERPRINT = getFingerprint();
14+
}
15+
16+
private static int counter = 0;
17+
18+
private static String getHostInfo(String idFallback, String nameFallback) {
19+
String jvmName = ManagementFactory.getRuntimeMXBean().getName();
20+
final int index = jvmName.indexOf('@');
21+
if (index < 1) {
22+
return String.format("%s@%s", idFallback, nameFallback);
23+
}
24+
25+
return jvmName;
26+
}
27+
28+
private static String getFingerprint() {
29+
String hostInfo = getHostInfo(Long.toString(new Date().getTime()), "dummy-host");
30+
31+
String hostId = hostInfo.split("@")[0];
32+
String hostname = hostInfo.split("@")[1];
33+
34+
int acc = hostname.length() + BASE;
35+
for (int i = 0; i < hostname.length(); i++) {
36+
acc += acc + (int) hostname.charAt(i);
37+
}
38+
39+
String idBlock = pad(Long.toString(Long.parseLong(hostId), BASE), 2);
40+
String nameBlock = pad(Integer.toString(acc), 2);
41+
42+
return idBlock + nameBlock;
43+
}
44+
45+
private static String pad(String input, int size) {
46+
// courtesy of http://stackoverflow.com/a/4903603/1176596
47+
String repeatedZero = new String(new char[size]).replace("\0", "0");
48+
String padded = repeatedZero + input;
49+
return (padded).substring(padded.length() - size);
50+
}
51+
52+
private static String getRandomBlock() {
53+
return pad(Integer.toString((int) (Math.random() * DISCRETE_VALUES), BASE), BLOCK_SIZE);
54+
}
55+
56+
private static int safeCounter() {
57+
counter = counter < DISCRETE_VALUES ? counter : 0;
58+
return counter++;
59+
}
60+
61+
public static String createCuid() {
62+
String timestamp = Long.toString(new Date().getTime(), BASE);
63+
String counter = pad(Integer.toString(safeCounter(), BASE), BLOCK_SIZE);
64+
String random = getRandomBlock() + getRandomBlock();
65+
66+
return String.join("", LETTER, timestamp, counter, FINGERPRINT , random);
67+
}
68+
}

src/test/java/CuidTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import org.junit.Test;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import static org.junit.Assert.*;
7+
8+
public class CuidTest {
9+
@Test
10+
public void createCuid() throws Exception {
11+
// more sane tests?
12+
assertEquals(Cuid.createCuid().charAt(0), 'c');
13+
}
14+
15+
private boolean hasNoCollisions() {
16+
int iterations = 4200000;
17+
Map<String, String> cuids = new HashMap<>();
18+
19+
for (int i = 0; i < iterations; ++i) {
20+
String cuid = Cuid.createCuid();
21+
if (cuids.containsKey(cuid)) {
22+
return false;
23+
} else {
24+
cuids.put(cuid, cuid);
25+
}
26+
}
27+
28+
return true;
29+
}
30+
31+
@Test
32+
public void testForCollisions() {
33+
assertEquals(hasNoCollisions(), true);
34+
}
35+
}

0 commit comments

Comments
 (0)