Skip to content

Commit

Permalink
Introduce multiplatform Uuid type #KT-31880
Browse files Browse the repository at this point in the history
  • Loading branch information
qurbonzoda authored and qodana-bot committed Jun 25, 2024
1 parent 3f10b2d commit 25ea5e8
Show file tree
Hide file tree
Showing 21 changed files with 1,500 additions and 5 deletions.
4 changes: 2 additions & 2 deletions kotlin-native/konan/konan.properties
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ clangOptFlags.mingw_x64 = -O3 -ffunction-sections
clangNooptFlags.mingw_x64 = -O1
linkerNoDebugFlags.mingw_x64 = -Wl,-S
linkerDynamicFlags.mingw_x64 = -shared
linkerKonanFlags.mingw_x64 =-static-libgcc -static-libstdc++ \
linkerKonanFlags.mingw_x64 = -static-libgcc -static-libstdc++ -lbcrypt \
-Wl,--dynamicbase \
-Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic
linkerOptimizationFlags.mingw_x64 = -Wl,--gc-sections
Expand Down Expand Up @@ -984,7 +984,7 @@ clangOptFlags.mingw_x86 = -O3 -ffunction-sections
clangNooptFlags.mingw_x86 = -O1
linkerNoDebugFlags.mingw_x86 = -Wl,-S
linkerDynamicFlags.mingw_x86 = -shared
linkerKonanFlags.mingw_x86 = -static-libgcc -static-libstdc++ \
linkerKonanFlags.mingw_x86 = -static-libgcc -static-libstdc++ -lbcrypt \
-Wl,--dynamicbase \
-Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive,-Bdynamic
mimallocLinkerDependencies.mingw_x86 = -lbcrypt
Expand Down
1 change: 1 addition & 0 deletions kotlin-native/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ add_executable(runtime
src/main/cpp/Porting.cpp
src/main/cpp/Regex.cpp
src/main/cpp/ReturnSlot.cpp
src/main/cpp/Random.cpp
src/main/cpp/Runtime.cpp
src/main/cpp/StdCppStubs.cpp
src/main/cpp/Time.cpp
Expand Down
1 change: 1 addition & 0 deletions kotlin-native/runtime/src/main/cpp/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void RUNTIME_NORETURN ThrowNotImplementedError();
void RUNTIME_NORETURN ThrowCharacterCodingException();
void RUNTIME_NORETURN ThrowIllegalArgumentException();
void RUNTIME_NORETURN ThrowIllegalStateException();
void RUNTIME_NORETURN ThrowIllegalStateExceptionWithMessage(KConstRef message);
void RUNTIME_NORETURN ThrowInvalidMutabilityException(KConstRef where);
void RUNTIME_NORETURN ThrowIncorrectDereferenceException();
void RUNTIME_NORETURN ThrowFileFailedToInitializeException(KRef reason);
Expand Down
77 changes: 77 additions & 0 deletions kotlin-native/runtime/src/main/cpp/Random.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

#include <stdio.h>
#include <stdarg.h>

#if KONAN_MACOSX || KONAN_IOS || KONAN_TVOS || KONAN_WATCHOS || KONAN_ANDROID
#include <stdlib.h>
#elif KONAN_LINUX
#include <unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#elif KONAN_WINDOWS
#include <windows.h>
#include <bcrypt.h>
#include <ntdef.h>
#endif

#include "KString.h"
#include "Exceptions.h"
#include "Format.h"
#include "Memory.h"
#include "Natives.h"

namespace {

#if KONAN_LINUX || KONAN_WINDOWS
void throwReadingRandomBytesFailed(const char* format, ...) {
va_list args;
va_start(args, format);
std::array<char, 128> buffer;
kotlin::std_support::span<char> span(buffer);
span = kotlin::VFormatToSpan(span, format, args);
va_end(args);

ObjHolder holder;
StringFromUtf8Buffer(buffer.data(), buffer.size() - span.size(), holder.slot());
ThrowIllegalStateExceptionWithMessage(holder.obj());
}
#endif

} // namespace


extern "C" {

// Mostly taken from kotlin-native/runtime/src/mimalloc/c/random.c
void Kotlin_Uuid_getRandomBytes(KRef byteArray, KInt size) {
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
ArrayHeader* array = byteArray->array();
uint8_t* address = reinterpret_cast<uint8_t*>(ByteArrayAddressOfElementAt(array, 0));

#if KONAN_MACOSX || KONAN_IOS || KONAN_TVOS || KONAN_WATCHOS || KONAN_ANDROID
arc4random_buf(address, size);
#elif KONAN_LINUX
long count = 0;
while (count < size) {
long ret = syscall(SYS_getrandom, address + count, size - count, 0); // blocking
if (ret >= 0) {
count += ret;
} else if (errno != EINTR) { // repeat if interrupted
throwReadingRandomBytesFailed("getrandom returned a negative value: %ld, errno: %d", ret, errno);
}
}
#elif KONAN_WINDOWS
NTSTATUS status = BCryptGenRandom(NULL, (PUCHAR)address, (ULONG)size, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
if (!NT_SUCCESS(status)) {
throwReadingRandomBytesFailed("Unexpected failure in random bytes generation: %ld", status);
}
#else
#error "How to Kotlin_Uuid_getRandomBytes()?"
#endif
}

} // extern "C"
18 changes: 18 additions & 0 deletions kotlin-native/runtime/src/main/kotlin/kotlin/uuid/UuidNative.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

package kotlin.uuid

import kotlin.native.internal.GCUnsafeCall

@GCUnsafeCall("Kotlin_Uuid_getRandomBytes")
private external fun getRandomBytes(byteArray: ByteArray, size: Int): Unit

@ExperimentalStdlibApi
internal actual fun secureRandomUuid(): Uuid {
val randomBytes = ByteArray(Uuid.SIZE_BYTES)
getRandomBytes(randomBytes, randomBytes.size)
return uuidFromRandomBytes(randomBytes)
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ void RUNTIME_NORETURN ThrowIllegalStateException() {
throw std::runtime_error("Not implemented for tests");
}

void RUNTIME_NORETURN ThrowIllegalStateExceptionWithMessage(KConstRef message) {
throw std::runtime_error("Not implemented for tests");
}

void RUNTIME_NORETURN ThrowInvalidMutabilityException(KConstRef where) {
throw std::runtime_error("Not implemented for tests");
}
Expand Down
41 changes: 41 additions & 0 deletions libraries/stdlib/api/js/kotlin.uuid.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
@kotlin.SinceKotlin(version = "2.0")
@kotlin.ExperimentalStdlibApi
public final class Uuid : kotlin.io.Serializable {
public open override operator fun equals(other: kotlin.Any?): kotlin.Boolean

public open override fun hashCode(): kotlin.Int

public final fun toByteArray(): kotlin.ByteArray

public final fun toHexString(): kotlin.String

@kotlin.internal.InlineOnly
public final inline fun <T> toLongs(action: (mostSignificantBits: kotlin.Long, leastSignificantBits: kotlin.Long) -> T): T

public open override fun toString(): kotlin.String

@kotlin.internal.InlineOnly
public final inline fun <T> toULongs(action: (mostSignificantBits: kotlin.ULong, leastSignificantBits: kotlin.ULong) -> T): T

public companion object of Uuid {
public final val LEXICAL_ORDER: kotlin.Comparator<kotlin.uuid.Uuid> { get; }

public final val NIL: kotlin.uuid.Uuid { get; }

public const final val SIZE_BITS: kotlin.Int = 128 { get; }

public const final val SIZE_BYTES: kotlin.Int = 16 { get; }

public final fun fromByteArray(byteArray: kotlin.ByteArray): kotlin.uuid.Uuid

public final fun fromLongs(mostSignificantBits: kotlin.Long, leastSignificantBits: kotlin.Long): kotlin.uuid.Uuid

public final fun fromULongs(mostSignificantBits: kotlin.ULong, leastSignificantBits: kotlin.ULong): kotlin.uuid.Uuid

public final fun parse(uuidString: kotlin.String): kotlin.uuid.Uuid

public final fun parseHex(hexString: kotlin.String): kotlin.uuid.Uuid

public final fun random(): kotlin.uuid.Uuid
}
}
2 changes: 2 additions & 0 deletions libraries/stdlib/js-ir-minimal-for-test/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ val commonMainSources by task<Sync> {
"libraries/stdlib/src/kotlin/time/**",
"libraries/stdlib/src/kotlin/util/KotlinVersion.kt",
"libraries/stdlib/src/kotlin/util/Tuples.kt",
"libraries/stdlib/src/kotlin/uuid/Uuid.kt",
"libraries/stdlib/src/kotlin/enums/**"
)
)
Expand Down Expand Up @@ -118,6 +119,7 @@ val jsMainSources by task<Sync> {
"kotlinx/dom/**",
"kotlinx/browser/**",
"kotlin/enums/**",
"kotlin/uuid/UuidJs.kt",
)
}
from {
Expand Down
13 changes: 13 additions & 0 deletions libraries/stdlib/js/src/kotlin/uuid/UuidJs.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/

package kotlin.uuid

@ExperimentalStdlibApi
internal actual fun secureRandomUuid(): Uuid {
val randomBytes = ByteArray(16)
js("crypto").getRandomValues(randomBytes)
return uuidFromRandomBytes(randomBytes)
}
1 change: 1 addition & 0 deletions libraries/stdlib/jvm/java9/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
exports kotlin.system;
exports kotlin.text;
exports kotlin.time;
exports kotlin.uuid;

exports kotlin.experimental;

Expand Down
Loading

0 comments on commit 25ea5e8

Please sign in to comment.