Compare commits
No commits in common. "main" and "0.2.0" have entirely different histories.
13 changed files with 49 additions and 394 deletions
8
.forgejo/workflows/build.yaml
Normal file
8
.forgejo/workflows/build.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
on: [push]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: alpine:3.19
|
||||||
|
steps:
|
||||||
|
- run: echo Verifying builds
|
|
@ -1,67 +0,0 @@
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
library_snapshot:
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: registry.garrity.co:8443/gs/ci-scala:latest
|
|
||||||
name: 'Build and Test Library Snapshot'
|
|
||||||
env:
|
|
||||||
GS_MAVEN_USER: ${{ vars.GS_MAVEN_USER }}
|
|
||||||
GS_MAVEN_TOKEN: ${{ secrets.GS_MAVEN_TOKEN }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
name: 'Checkout Repository'
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: 'Pre-Commit'
|
|
||||||
run: |
|
|
||||||
pre-commit install
|
|
||||||
pre-commit run --all-files
|
|
||||||
- name: 'Prepare Versioned Build'
|
|
||||||
run: |
|
|
||||||
latest_git_tag="$(git describe --tags --abbrev=0 || echo 'No Tags')"
|
|
||||||
latest_commit_message="$(git show -s --format=%s HEAD)"
|
|
||||||
if [[ "$latest_commit_message" == *"(major)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="major"
|
|
||||||
elif [[ "$latest_commit_message" == *"(minor)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="minor"
|
|
||||||
elif [[ "$latest_commit_message" == *"(patch)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="patch"
|
|
||||||
elif [[ "$latest_commit_message" == *"(docs)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="norelease"
|
|
||||||
elif [[ "$latest_commit_message" == *"(norelease)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="norelease"
|
|
||||||
else
|
|
||||||
export GS_RELEASE_TYPE="norelease"
|
|
||||||
fi
|
|
||||||
echo "GS_RELEASE_TYPE=$GS_RELEASE_TYPE" >> $GITHUB_ENV
|
|
||||||
echo "Previous Git Tag: $latest_git_tag"
|
|
||||||
echo "Latest Commit: $latest_commit_message ($GS_RELEASE_TYPE) (SNAPSHOT)"
|
|
||||||
if [ "$GS_RELEASE_TYPE" = "norelease" ]; then
|
|
||||||
sbtn -Dsnapshot=true -Drelease="patch" semVerInfo
|
|
||||||
else
|
|
||||||
sbtn -Dsnapshot=true -Drelease="$GS_RELEASE_TYPE" semVerInfo
|
|
||||||
fi
|
|
||||||
- name: 'Unit Tests and Code Coverage'
|
|
||||||
run: |
|
|
||||||
sbtn clean
|
|
||||||
sbtn coverage
|
|
||||||
sbtn test
|
|
||||||
sbtn coverageReport
|
|
||||||
- name: 'Publish Snapshot'
|
|
||||||
run: |
|
|
||||||
echo "Testing env var propagation = ${{ env.GS_RELEASE_TYPE }}"
|
|
||||||
if [ "${{ env.GS_RELEASE_TYPE }}" = "norelease" ]; then
|
|
||||||
echo "Skipping publish due to GS_RELEASE_TYPE=norelease"
|
|
||||||
else
|
|
||||||
sbtn coverageOff
|
|
||||||
sbtn clean
|
|
||||||
sbtn publish
|
|
||||||
fi
|
|
|
@ -1,84 +0,0 @@
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
library_release:
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: registry.garrity.co:8443/gs/ci-scala:latest
|
|
||||||
name: 'Build and Release Library'
|
|
||||||
env:
|
|
||||||
GS_MAVEN_USER: ${{ vars.GS_MAVEN_USER }}
|
|
||||||
GS_MAVEN_TOKEN: ${{ secrets.GS_MAVEN_TOKEN }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
name: 'Checkout Repository'
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: 'Pre-Commit'
|
|
||||||
run: |
|
|
||||||
pre-commit install
|
|
||||||
pre-commit run --all-files
|
|
||||||
- name: 'Prepare Versioned Build'
|
|
||||||
run: |
|
|
||||||
latest_git_tag="$(git describe --tags --abbrev=0 || echo 'No Tags')"
|
|
||||||
latest_commit_message="$(git show -s --format=%s HEAD)"
|
|
||||||
if [[ "$latest_commit_message" == *"(major)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="major"
|
|
||||||
elif [[ "$latest_commit_message" == *"(minor)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="minor"
|
|
||||||
elif [[ "$latest_commit_message" == *"(patch)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="patch"
|
|
||||||
elif [[ "$latest_commit_message" == *"(docs)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="norelease"
|
|
||||||
elif [[ "$latest_commit_message" == *"(norelease)"* ]]; then
|
|
||||||
export GS_RELEASE_TYPE="norelease"
|
|
||||||
else
|
|
||||||
export GS_RELEASE_TYPE="norelease"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "GS_RELEASE_TYPE=$GS_RELEASE_TYPE" >> $GITHUB_ENV
|
|
||||||
echo "Previous Git Tag: $latest_git_tag"
|
|
||||||
echo "Latest Commit: $latest_commit_message"
|
|
||||||
echo "Selected Release Type: '$GS_RELEASE_TYPE'"
|
|
||||||
|
|
||||||
if [ "$GS_RELEASE_TYPE" = "norelease" ]; then
|
|
||||||
echo "Skipping all versioning for 'norelease' commit."
|
|
||||||
else
|
|
||||||
sbtn -Drelease="$GS_RELEASE_TYPE" semVerInfo
|
|
||||||
fi
|
|
||||||
- name: 'Unit Tests and Code Coverage'
|
|
||||||
run: |
|
|
||||||
if [ "${{ env.GS_RELEASE_TYPE }}" = "norelease" ]; then
|
|
||||||
echo "Skipping build/test for 'norelease' commit."
|
|
||||||
else
|
|
||||||
sbtn clean
|
|
||||||
sbtn coverage
|
|
||||||
sbtn test
|
|
||||||
sbtn coverageReport
|
|
||||||
fi
|
|
||||||
- name: 'Publish Release'
|
|
||||||
run: |
|
|
||||||
if [ "${{ env.GS_RELEASE_TYPE }}" = "norelease" ]; then
|
|
||||||
echo "Skipping publish for 'norelease' commit."
|
|
||||||
else
|
|
||||||
sbtn coverageOff
|
|
||||||
sbtn clean
|
|
||||||
sbtn semVerWriteVersionToFile
|
|
||||||
sbtn publish
|
|
||||||
fi
|
|
||||||
- name: 'Create Git Tag'
|
|
||||||
run: |
|
|
||||||
if [ "${{ env.GS_RELEASE_TYPE }}" = "norelease" ]; then
|
|
||||||
echo "Skipping Git tag for 'norelease' commit."
|
|
||||||
else
|
|
||||||
selected_version="$(cat .version)"
|
|
||||||
git tag "$selected_version"
|
|
||||||
git push origin "$selected_version"
|
|
||||||
fi
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,4 +2,3 @@ target/
|
||||||
project/target/
|
project/target/
|
||||||
project/project/
|
project/project/
|
||||||
modules/core/target/
|
modules/core/target/
|
||||||
.version
|
|
||||||
|
|
|
@ -5,13 +5,7 @@ repos:
|
||||||
hooks:
|
hooks:
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: fix-byte-order-marker
|
|
||||||
- id: mixed-line-ending
|
|
||||||
args: ['--fix=lf']
|
|
||||||
description: Enforces using only 'LF' line endings.
|
|
||||||
- id: trailing-whitespace
|
|
||||||
- id: check-yaml
|
|
||||||
- repo: https://git.garrity.co/garrity-software/gs-pre-commit-scala
|
- repo: https://git.garrity.co/garrity-software/gs-pre-commit-scala
|
||||||
rev: v1.0.0
|
rev: v0.1.3
|
||||||
hooks:
|
hooks:
|
||||||
- id: scalafmt
|
- id: scalafmt
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// See: https://github.com/scalameta/scalafmt/tags for the latest tags.
|
// See: https://github.com/scalameta/scalafmt/tags for the latest tags.
|
||||||
version = 3.9.4
|
version = 3.7.11
|
||||||
runner.dialect = scala3
|
runner.dialect = scala3
|
||||||
maxColumn = 80
|
maxColumn = 80
|
||||||
|
|
||||||
|
|
29
README.md
29
README.md
|
@ -1,23 +1,15 @@
|
||||||
# gs-uuid
|
# gs-uuid
|
||||||
|
|
||||||
[GS Open Source](https://garrity.co/oss.html) |
|
|
||||||
[License (Apache 2.0)](./LICENSE)
|
[License (Apache 2.0)](./LICENSE)
|
||||||
|
|
||||||
UUIDs for Scala 3 with generation based on JUG, and serialization based on code
|
UUID's for Scala 3 with generation based on JUG, and serialization based on code
|
||||||
from Jackson Databind. The only dependency is JUG, whereas the relevant Jackson
|
from Jackson Databind. The only dependency is JUG, whereas the relevant Jackson
|
||||||
code is copied to this implementation (and slightly modified).
|
code is copied to this implementation (and slightly modified).
|
||||||
|
|
||||||
This project uses the Apache 2.0 License due to the use of Jackson Databind
|
|
||||||
code.
|
|
||||||
|
|
||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
- [Dependency](#dependency)
|
|
||||||
- [Donate](#donate)
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Dependency
|
|
||||||
|
|
||||||
This artifact is available in the Garrity Software Maven repository.
|
This artifact is available in the Garrity Software Maven repository.
|
||||||
|
|
||||||
```scala
|
```scala
|
||||||
|
@ -25,22 +17,5 @@ externalResolvers +=
|
||||||
"Garrity Software Releases" at "https://maven.garrity.co/releases"
|
"Garrity Software Releases" at "https://maven.garrity.co/releases"
|
||||||
|
|
||||||
val GsUuid: ModuleID =
|
val GsUuid: ModuleID =
|
||||||
"gs" %% "gs-uuid-v0" % "$VERSION"
|
"gs" %% "gs-uuid-v0" % "0.1.0"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Type
|
|
||||||
|
|
||||||
```scala
|
|
||||||
import gs.uuid.v0.UUID
|
|
||||||
|
|
||||||
given UUID.Generator = UUID.Generator.version7()
|
|
||||||
|
|
||||||
val id = UUID.generate()
|
|
||||||
|
|
||||||
println(id.str()) // 292c9bc70d0f4d998053d7b2f72cd9b7
|
|
||||||
```
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
|
|
||||||
Enjoy this project or want to help me achieve my [goals](https://garrity.co)?
|
|
||||||
Consider [Donating to Pat on Ko-fi](https://ko-fi.com/gspfm).
|
|
||||||
|
|
17
build.sbt
17
build.sbt
|
@ -1,26 +1,17 @@
|
||||||
val scala3: String = "3.6.4"
|
val scala3: String = "3.3.1"
|
||||||
|
|
||||||
ThisBuild / scalaVersion := scala3
|
ThisBuild / scalaVersion := scala3
|
||||||
ThisBuild / versionScheme := Some("semver-spec")
|
ThisBuild / versionScheme := Some("semver-spec")
|
||||||
ThisBuild / gsProjectName := "gs-uuid"
|
ThisBuild / gsProjectName := "gs-uuid"
|
||||||
|
|
||||||
ThisBuild / licenses := Seq(
|
|
||||||
"Apache 2.0" -> url(
|
|
||||||
"https://git.garrity.co/garrity-software/gs-uuid/src/branch/main/LICENSE"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
val sharedSettings = Seq(
|
val sharedSettings = Seq(
|
||||||
scalaVersion := scala3,
|
scalaVersion := scala3,
|
||||||
version := semVerSelected.value,
|
version := semVerSelected.value
|
||||||
coverageFailOnMinimum := true,
|
|
||||||
coverageMinimumStmtTotal := 100,
|
|
||||||
coverageMinimumBranchTotal := 100
|
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val testSettings = Seq(
|
lazy val testSettings = Seq(
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"org.scalameta" %% "munit" % "1.1.0" % Test
|
"org.scalameta" %% "munit" % "1.0.0-M10" % Test
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,6 +22,6 @@ lazy val `gs-uuid` = project
|
||||||
.settings(name := s"${gsProjectName.value}-v${semVerMajor.value}")
|
.settings(name := s"${gsProjectName.value}-v${semVerMajor.value}")
|
||||||
.settings(
|
.settings(
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"com.fasterxml.uuid" % "java-uuid-generator" % "5.1.0"
|
"com.fasterxml.uuid" % "java-uuid-generator" % "4.1.1"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
sbt.version=1.10.11
|
sbt.version=1.9.8
|
||||||
|
|
|
@ -1,33 +1,10 @@
|
||||||
def selectCredentials(): Credentials =
|
credentials += Credentials(Path.userHome / ".sbt" / ".credentials")
|
||||||
if ((Path.userHome / ".sbt" / ".credentials").exists())
|
|
||||||
Credentials(Path.userHome / ".sbt" / ".credentials")
|
|
||||||
else
|
|
||||||
Credentials.apply(
|
|
||||||
realm = "Reposilite",
|
|
||||||
host = "maven.garrity.co",
|
|
||||||
userName = sys.env
|
|
||||||
.get("GS_MAVEN_USER")
|
|
||||||
.getOrElse(
|
|
||||||
throw new RuntimeException(
|
|
||||||
"You must either provide ~/.sbt/.credentials or specify the GS_MAVEN_USER environment variable."
|
|
||||||
)
|
|
||||||
),
|
|
||||||
passwd = sys.env
|
|
||||||
.get("GS_MAVEN_TOKEN")
|
|
||||||
.getOrElse(
|
|
||||||
throw new RuntimeException(
|
|
||||||
"You must either provide ~/.sbt/.credentials or specify the GS_MAVEN_TOKEN environment variable."
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
credentials += selectCredentials()
|
|
||||||
|
|
||||||
externalResolvers := Seq(
|
externalResolvers := Seq(
|
||||||
"Garrity Software Mirror" at "https://maven.garrity.co/releases",
|
"Garrity Software Mirror" at "https://maven.garrity.co/releases",
|
||||||
"Garrity Software Releases" at "https://maven.garrity.co/gs"
|
"Garrity Software Releases" at "https://maven.garrity.co/gs"
|
||||||
)
|
)
|
||||||
|
|
||||||
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.1.0")
|
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.8")
|
||||||
addSbtPlugin("gs" % "sbt-garrity-software" % "0.5.0")
|
addSbtPlugin("gs" % "sbt-garrity-software" % "0.2.0")
|
||||||
addSbtPlugin("gs" % "sbt-gs-semver" % "0.3.0")
|
addSbtPlugin("gs" % "sbt-gs-semver" % "0.2.0")
|
||||||
|
|
|
@ -5,9 +5,9 @@ import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UUID serialization and deserialization. This is a direct copy of Jackson
|
* UUID serialization and deserialization. This is a direct copy of Jackson
|
||||||
* Databind (under the Apache 2.0 license at time of writing) with extremely
|
* Databind (also under the Apache 2.0 license at time of writing) with
|
||||||
* minor modifications to remove dashes from the output and to likewise support
|
* extremely minor modifications to remove dashes from the output and to
|
||||||
* parsing with/without dashes.
|
* likewise support parsing with/without dashes.
|
||||||
*/
|
*/
|
||||||
public final class UUIDFormat {
|
public final class UUIDFormat {
|
||||||
private UUIDFormat() {}
|
private UUIDFormat() {}
|
||||||
|
@ -33,7 +33,7 @@ public final class UUIDFormat {
|
||||||
* @param uuid The UUID to render.
|
* @param uuid The UUID to render.
|
||||||
* @return Hexadecimal representation of the UUID.
|
* @return Hexadecimal representation of the UUID.
|
||||||
*/
|
*/
|
||||||
public static String toHexWithoutDashes(final UUID uuid) {
|
public static String toHex(final UUID uuid) {
|
||||||
final char[] ch = new char[32];
|
final char[] ch = new char[32];
|
||||||
|
|
||||||
// Example:
|
// Example:
|
||||||
|
@ -64,34 +64,6 @@ public final class UUIDFormat {
|
||||||
return new String(ch, 0, 32);
|
return new String(ch, 0, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Render the given UUID as a 36-character string using lowercase
|
|
||||||
* hexadecimal with dashes.</p>
|
|
||||||
*
|
|
||||||
* @param uuid The UUID to render.
|
|
||||||
* @return Hexadecimal representation of the UUID.
|
|
||||||
*/
|
|
||||||
public static String toHexWithDashes(final UUID uuid) {
|
|
||||||
final char[] ch = new char[36];
|
|
||||||
|
|
||||||
final long msb = uuid.getMostSignificantBits();
|
|
||||||
_appendInt((int) (msb >> 32), ch, 0);
|
|
||||||
ch[8] = '-';
|
|
||||||
int i = (int) msb;
|
|
||||||
_appendShort(i >>> 16, ch, 9);
|
|
||||||
ch[13] = '-';
|
|
||||||
_appendShort(i, ch, 14);
|
|
||||||
ch[18] = '-';
|
|
||||||
|
|
||||||
final long lsb = uuid.getLeastSignificantBits();
|
|
||||||
_appendShort((int) (lsb >>> 48), ch, 19);
|
|
||||||
ch[23] = '-';
|
|
||||||
_appendShort((int) (lsb >>> 32), ch, 24);
|
|
||||||
_appendInt((int) lsb, ch, 28);
|
|
||||||
|
|
||||||
return new String(ch, 0, 36);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Render the given UUID as a 16-byte array.</p>
|
* <p>Render the given UUID as a 16-byte array.</p>
|
||||||
*
|
*
|
||||||
|
|
|
@ -2,8 +2,7 @@ package gs.uuid.v0
|
||||||
|
|
||||||
import com.fasterxml.uuid.Generators
|
import com.fasterxml.uuid.Generators
|
||||||
|
|
||||||
/** Alias for the `java.util.UUID` type, which represents a 128-bit (16-byte)
|
/** Alias for the `java.util.UUID` type, which represents a 128-bit value.
|
||||||
* value.
|
|
||||||
*
|
*
|
||||||
* ## ID Generation
|
* ## ID Generation
|
||||||
*
|
*
|
||||||
|
@ -17,17 +16,19 @@ import com.fasterxml.uuid.Generators
|
||||||
*
|
*
|
||||||
* ## Serialization
|
* ## Serialization
|
||||||
*
|
*
|
||||||
* This library supports the following representations:
|
* This library uses a custom variant of the JDK 17 implementation that removes
|
||||||
|
* dashes from the output and is likewise capable of parsing those values.
|
||||||
*
|
*
|
||||||
* - Hexadecimal string without dashes
|
* {{{
|
||||||
* - Byte array
|
* val example: UUID = UUID(java.util.UUID.randomUUID())
|
||||||
*
|
* val serialized = example.str() // or example.withoutDashes()
|
||||||
* Serialization code is based on Jackson Databind (Apache 2.0).
|
* // example value = 899efa6f40ed45189efa6f40ed9518ed
|
||||||
|
* }}}
|
||||||
*/
|
*/
|
||||||
opaque type UUID = java.util.UUID
|
opaque type UUID = java.util.UUID
|
||||||
|
|
||||||
object UUID:
|
object UUID:
|
||||||
/** Express any `java.util.UUID` as a GS UUID.
|
/** Express any `java.util.UUID` as a Meager UUID.
|
||||||
*
|
*
|
||||||
* @param uuid
|
* @param uuid
|
||||||
* The input UUID.
|
* The input UUID.
|
||||||
|
@ -36,21 +37,6 @@ object UUID:
|
||||||
*/
|
*/
|
||||||
def apply(uuid: java.util.UUID): UUID = uuid
|
def apply(uuid: java.util.UUID): UUID = uuid
|
||||||
|
|
||||||
/** Parse a byte array as a [[UUID]].
|
|
||||||
*
|
|
||||||
* See `toBytes()` for the inverse of this function.
|
|
||||||
*
|
|
||||||
* @param bytes
|
|
||||||
* The array of bytes to parse.
|
|
||||||
* @return
|
|
||||||
* The new [[UUID]], or `None` if the bytes do not represent a valid UUID.
|
|
||||||
*/
|
|
||||||
def fromBytes(bytes: Array[Byte]): Option[UUID] =
|
|
||||||
scala.util
|
|
||||||
.Try(UUIDFormat.fromBytes(bytes))
|
|
||||||
.map(uuid => Some(apply(uuid)))
|
|
||||||
.getOrElse(None)
|
|
||||||
|
|
||||||
given CanEqual[UUID, UUID] = CanEqual.derived
|
given CanEqual[UUID, UUID] = CanEqual.derived
|
||||||
|
|
||||||
/** Generate a new UUID.
|
/** Generate a new UUID.
|
||||||
|
@ -66,16 +52,6 @@ object UUID:
|
||||||
G: Generator
|
G: Generator
|
||||||
): UUID = G.next()
|
): UUID = G.next()
|
||||||
|
|
||||||
/** @return
|
|
||||||
* New v4 UUID (Random).
|
|
||||||
*/
|
|
||||||
def v4(): UUID = Generator.version4.next()
|
|
||||||
|
|
||||||
/** @return
|
|
||||||
* New v7 UUID (Epoch + Counter + Random).
|
|
||||||
*/
|
|
||||||
def v7(): UUID = Generator.version7.next()
|
|
||||||
|
|
||||||
/** Parse the given string as a UUID.
|
/** Parse the given string as a UUID.
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
|
@ -86,14 +62,6 @@ object UUID:
|
||||||
*/
|
*/
|
||||||
def parse(str: String): Option[UUID] = fromString(str)
|
def parse(str: String): Option[UUID] = fromString(str)
|
||||||
|
|
||||||
/** Parse the given string as a UUID.
|
|
||||||
*
|
|
||||||
* @param str
|
|
||||||
* The UUID, which is expected to be in a hexadecimal format with no
|
|
||||||
* dashes.
|
|
||||||
* @return
|
|
||||||
* The parsed UUID value, or `None` if the value does not represent a UUID.
|
|
||||||
*/
|
|
||||||
def fromString(str: String): Option[UUID] =
|
def fromString(str: String): Option[UUID] =
|
||||||
scala.util
|
scala.util
|
||||||
.Try(UUIDFormat.fromHex(str))
|
.Try(UUIDFormat.fromHex(str))
|
||||||
|
@ -101,48 +69,16 @@ object UUID:
|
||||||
.getOrElse(None)
|
.getOrElse(None)
|
||||||
|
|
||||||
extension (uid: UUID)
|
extension (uid: UUID)
|
||||||
/** @return
|
def toUUID: java.util.UUID = uid
|
||||||
* The underlying `java.util.UUID`.
|
|
||||||
*/
|
|
||||||
def toUUID(): java.util.UUID = uid
|
|
||||||
|
|
||||||
/** @return
|
def str(): String = withoutDashes()
|
||||||
* The byte array representation of this UUID.
|
|
||||||
*/
|
|
||||||
def toBytes(): Array[Byte] = UUIDFormat.toBytes(uid)
|
|
||||||
|
|
||||||
/** Serialize this UUID.
|
def withoutDashes(): String = UUIDFormat.toHex(uid)
|
||||||
*
|
|
||||||
* @param dashes
|
|
||||||
* Whether to use dashes in the output (default = false).
|
|
||||||
* @return
|
|
||||||
* Hexadecimal string representation of this UUID.
|
|
||||||
*/
|
|
||||||
def str(dashes: Boolean = false): String = withoutDashes()
|
|
||||||
|
|
||||||
/** @return
|
|
||||||
* Hexadecimal string representation of this UUID, without dashes.
|
|
||||||
*/
|
|
||||||
def withoutDashes(): String = UUIDFormat.toHexWithoutDashes(uid)
|
|
||||||
|
|
||||||
/** @return
|
|
||||||
* Hexadecimal string representation of this UUID, with dashes.
|
|
||||||
*/
|
|
||||||
def withDashes(): String = UUIDFormat.toHexWithDashes(uid)
|
|
||||||
|
|
||||||
/** @return
|
|
||||||
* The least significant bits of this UUID.
|
|
||||||
*/
|
|
||||||
def lsb(): Long = uid.getLeastSignificantBits()
|
def lsb(): Long = uid.getLeastSignificantBits()
|
||||||
|
|
||||||
/** @return
|
|
||||||
* The most significant bits of this UUID.
|
|
||||||
*/
|
|
||||||
def msb(): Long = uid.getMostSignificantBits()
|
def msb(): Long = uid.getMostSignificantBits()
|
||||||
|
|
||||||
/** @return
|
|
||||||
* `true` if this UUID is `0`, `false` otherwise.
|
|
||||||
*/
|
|
||||||
def isZero(): Boolean = lsb() == 0L && msb() == 0L
|
def isZero(): Boolean = lsb() == 0L && msb() == 0L
|
||||||
|
|
||||||
/** Type class for UUID generation.
|
/** Type class for UUID generation.
|
||||||
|
@ -155,11 +91,11 @@ object UUID:
|
||||||
object Generator:
|
object Generator:
|
||||||
/** Instantiate a new Type 4 generator.
|
/** Instantiate a new Type 4 generator.
|
||||||
*/
|
*/
|
||||||
lazy val version4: Generator = new Version4
|
def version4: Generator = new Version4
|
||||||
|
|
||||||
/** Instantiate a new Type 7 generator.
|
/** Instantiate a new Type 7 generator.
|
||||||
*/
|
*/
|
||||||
lazy val version7: Generator = new Version7
|
def version7: Generator = new Version7
|
||||||
|
|
||||||
/** Type 4 (Random) implementation of a UUID generator.
|
/** Type 4 (Random) implementation of a UUID generator.
|
||||||
*/
|
*/
|
||||||
|
@ -167,8 +103,8 @@ object UUID:
|
||||||
private val gen = Generators.randomBasedGenerator()
|
private val gen = Generators.randomBasedGenerator()
|
||||||
override def next(): UUID = gen.generate()
|
override def next(): UUID = gen.generate()
|
||||||
|
|
||||||
/** Type 7 (Unix Epoch Time + Counter + Random) implementation of a UUID
|
/** Type 7 (Unix Epoch Time + Random) implementation of a UUID generator.
|
||||||
* generator. Consider using this rather than Type 1 or Type 6.
|
* Consider using this rather than Type 1 or Type 6.
|
||||||
*
|
*
|
||||||
* This type is defined in [IETF New UUID Formats
|
* This type is defined in [IETF New UUID Formats
|
||||||
* Draft](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html#name-uuid-version-7)
|
* Draft](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html#name-uuid-version-7)
|
||||||
|
|
|
@ -11,16 +11,7 @@ class UUIDTests extends munit.FunSuite:
|
||||||
val base = v4.next()
|
val base = v4.next()
|
||||||
val str = base.str()
|
val str = base.str()
|
||||||
val parsed = UUID.parse(str)
|
val parsed = UUID.parse(str)
|
||||||
assertEquals(parsed, Some(base))
|
assert(parsed == Some(base))
|
||||||
}
|
|
||||||
|
|
||||||
test(
|
|
||||||
"should instantiate a type 4 UUID, serialize it, and parse the result (helper function)"
|
|
||||||
) {
|
|
||||||
val base = UUID.v4()
|
|
||||||
val str = base.str()
|
|
||||||
val parsed = UUID.parse(str)
|
|
||||||
assertEquals(parsed, Some(base))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
test(
|
||||||
|
@ -29,16 +20,7 @@ class UUIDTests extends munit.FunSuite:
|
||||||
val base = v7.next()
|
val base = v7.next()
|
||||||
val str = base.str()
|
val str = base.str()
|
||||||
val parsed = UUID.parse(str)
|
val parsed = UUID.parse(str)
|
||||||
assertEquals(parsed, Some(base))
|
assert(parsed == Some(base))
|
||||||
}
|
|
||||||
|
|
||||||
test(
|
|
||||||
"should instantiate a type 7 UUID, serialize it, and parse the result (helper function)"
|
|
||||||
) {
|
|
||||||
val base = UUID.v7()
|
|
||||||
val str = base.str()
|
|
||||||
val parsed = UUID.parse(str)
|
|
||||||
assertEquals(parsed, Some(base))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("should instantiate from any java.util.UUID") {
|
test("should instantiate from any java.util.UUID") {
|
||||||
|
@ -46,39 +28,18 @@ class UUIDTests extends munit.FunSuite:
|
||||||
val base = UUID(raw)
|
val base = UUID(raw)
|
||||||
val str = base.str()
|
val str = base.str()
|
||||||
val parsed = UUID.fromString(str)
|
val parsed = UUID.fromString(str)
|
||||||
assertEquals(parsed, Some(base))
|
assert(parsed == Some(base))
|
||||||
assertEquals(parsed.map(_.toUUID()), Some(raw))
|
assert(parsed.map(_.toUUID) == Some(raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
test("should successfully parse a UUID with dashes") {
|
test("should successfully parse a UUID with dashes") {
|
||||||
val raw = java.util.UUID.randomUUID()
|
|
||||||
val base = UUID(raw)
|
|
||||||
assertEquals(UUID.parse(base.withDashes()), Some(base))
|
|
||||||
}
|
|
||||||
|
|
||||||
test(
|
|
||||||
"should successfully parse a UUID with dashes, generated with this library"
|
|
||||||
) {
|
|
||||||
val base = java.util.UUID.randomUUID()
|
val base = java.util.UUID.randomUUID()
|
||||||
assertEquals(UUID.parse(base.toString()), Some(UUID(base)))
|
assert(UUID.parse(base.toString()) == Some(UUID(base)))
|
||||||
}
|
}
|
||||||
|
|
||||||
test("should fail to parse a non-hex string") {
|
test("should fail to parse a non-hex string") {
|
||||||
val input = "ghijklmnoped45189efa6f40ed9518ed"
|
val input = "ghijklmnoped45189efa6f40ed9518ed"
|
||||||
assertEquals(UUID.parse(input), None)
|
assert(UUID.parse(input) == None)
|
||||||
}
|
|
||||||
|
|
||||||
test("should round trip to/from a byte array") {
|
|
||||||
given UUID.Generator = v7
|
|
||||||
val base = UUID.generate()
|
|
||||||
val bytes = base.toBytes()
|
|
||||||
val parsed = UUID.fromBytes(bytes)
|
|
||||||
assertEquals(parsed, Some(base))
|
|
||||||
}
|
|
||||||
|
|
||||||
test("should fail to parse an invalid byte array") {
|
|
||||||
val bytes = Array[Byte](1)
|
|
||||||
assertEquals(UUID.fromBytes(bytes), None)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("should generate using an available type class instance") {
|
test("should generate using an available type class instance") {
|
||||||
|
@ -86,14 +47,7 @@ class UUIDTests extends munit.FunSuite:
|
||||||
val base = doGen
|
val base = doGen
|
||||||
val str = base.str()
|
val str = base.str()
|
||||||
val parsed = UUID.parse(str)
|
val parsed = UUID.parse(str)
|
||||||
assertEquals(parsed, Some(base))
|
assert(parsed == Some(base))
|
||||||
}
|
|
||||||
|
|
||||||
test("should return lsb, msb, and if the UUID is zero") {
|
|
||||||
val uuid = UUID.parse("00000000-0000-0000-0000-000000000000")
|
|
||||||
assertEquals(uuid.map(_.lsb()), Some(0L))
|
|
||||||
assertEquals(uuid.map(_.msb()), Some(0L))
|
|
||||||
assertEquals(uuid.map(_.isZero()), Some(true))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def doGen(
|
private def doGen(
|
||||||
|
|
Loading…
Add table
Reference in a new issue