diff --git a/library/error/api/error.api b/library/error/api/error.api index e69de29..3001060 100644 --- a/library/error/api/error.api +++ b/library/error/api/error.api @@ -0,0 +1,5 @@ +public final class org/kotlincrypto/error/PreconditionsKt { + public static final fun requireParam (Z)V + public static final fun requireParam (ZLkotlin/jvm/functions/Function0;)V +} + diff --git a/library/error/api/error.klib.api b/library/error/api/error.klib.api index 4d60cc2..6376a3b 100644 --- a/library/error/api/error.klib.api +++ b/library/error/api/error.klib.api @@ -67,3 +67,6 @@ open class org.kotlincrypto.error/ShortBufferException : org.kotlincrypto.error/ constructor () // org.kotlincrypto.error/ShortBufferException.|(){}[0] constructor (kotlin/String?) // org.kotlincrypto.error/ShortBufferException.|(kotlin.String?){}[0] } + +final inline fun org.kotlincrypto.error/requireParam(kotlin/Boolean) // org.kotlincrypto.error/requireParam|requireParam(kotlin.Boolean){}[0] +final inline fun org.kotlincrypto.error/requireParam(kotlin/Boolean, kotlin/Function0) // org.kotlincrypto.error/requireParam|requireParam(kotlin.Boolean;kotlin.Function0){}[0] diff --git a/library/error/src/commonMain/kotlin/org/kotlincrypto/error/Preconditions.kt b/library/error/src/commonMain/kotlin/org/kotlincrypto/error/Preconditions.kt new file mode 100644 index 0000000..1c29255 --- /dev/null +++ b/library/error/src/commonMain/kotlin/org/kotlincrypto/error/Preconditions.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +@file:Suppress("KotlinRedundantDiagnosticSuppress", "NOTHING_TO_INLINE") + +package org.kotlincrypto.error + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract + +/** + * Throws [InvalidParameterException] when [condition] is false. + * */ +@OptIn(ExperimentalContracts::class) +public inline fun requireParam(condition: Boolean) { + contract { + returns() implies condition + } + requireParam(condition) { "Parameter check failed." } +} + +/** + * Throws [InvalidParameterException] with the result of calling [lazyMessage] when [condition] is false. + * */ +@OptIn(ExperimentalContracts::class) +public inline fun requireParam(condition: Boolean, lazyMessage: () -> Any) { + contract { + returns() implies condition + } + if (condition) return + val message = lazyMessage() + throw InvalidParameterException(message.toString()) +} diff --git a/library/error/src/commonTest/kotlin/org/kotlincrypto/error/PreconditionsUnitTest.kt b/library/error/src/commonTest/kotlin/org/kotlincrypto/error/PreconditionsUnitTest.kt new file mode 100644 index 0000000..6dde126 --- /dev/null +++ b/library/error/src/commonTest/kotlin/org/kotlincrypto/error/PreconditionsUnitTest.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Matthew Nelson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +package org.kotlincrypto.error + +import kotlin.test.Test +import kotlin.test.assertFailsWith + +class PreconditionsUnitTest { + + @Test + fun givenRequireParam_whenConditionTrue_thenDoesNotThrow() { + requireParam(true) + requireParam(true) { "fail" } + } + + @Test + fun givenRequireParam_whenConditionFalse_thenThrows() { + assertFailsWith { requireParam(false) } + assertFailsWith { requireParam(false) { "fail" } } + } +}