diff --git a/.changes/1021e75a-45f3-4f3a-820c-700d9ec6e782.json b/.changes/1021e75a-45f3-4f3a-820c-700d9ec6e782.json deleted file mode 100644 index 0fad5e0349..0000000000 --- a/.changes/1021e75a-45f3-4f3a-820c-700d9ec6e782.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "1021e75a-45f3-4f3a-820c-700d9ec6e782", - "type": "bugfix", - "description": "Fix serialization of CBOR blobs" -} \ No newline at end of file diff --git a/.changes/4820850c-8916-47f5-a7e1-8880e6a00d22.json b/.changes/4820850c-8916-47f5-a7e1-8880e6a00d22.json deleted file mode 100644 index 297f7e603f..0000000000 --- a/.changes/4820850c-8916-47f5-a7e1-8880e6a00d22.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "4820850c-8916-47f5-a7e1-8880e6a00d22", - "type": "bugfix", - "description": "Fix errors in equality checks for `CaseInsensitiveMap` which affect `Headers` and `ValuesMap` implementations" -} \ No newline at end of file diff --git a/.changes/4855cecf-6a96-4622-b7ff-5d09e54f6564.json b/.changes/4855cecf-6a96-4622-b7ff-5d09e54f6564.json new file mode 100644 index 0000000000..6c781606fe --- /dev/null +++ b/.changes/4855cecf-6a96-4622-b7ff-5d09e54f6564.json @@ -0,0 +1,5 @@ +{ + "id": "4855cecf-6a96-4622-b7ff-5d09e54f6564", + "type": "bugfix", + "description": "Overwrite `Content-Length` header rather than appending in `CrtHttpEngine`" +} \ No newline at end of file diff --git a/.changes/7e4f8c08-941c-4ea5-91b3-4c284746c453.json b/.changes/7e4f8c08-941c-4ea5-91b3-4c284746c453.json deleted file mode 100644 index 2b126708dd..0000000000 --- a/.changes/7e4f8c08-941c-4ea5-91b3-4c284746c453.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "7e4f8c08-941c-4ea5-91b3-4c284746c453", - "type": "documentation", - "description": "Improve documentation for [`StandardRetryPolicy`](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries.policy/-standard-retry-policy/)" -} \ No newline at end of file diff --git a/.changes/c0040355-ffdc-4813-80e9-baf859ef02b9.json b/.changes/c0040355-ffdc-4813-80e9-baf859ef02b9.json deleted file mode 100644 index 42302b920d..0000000000 --- a/.changes/c0040355-ffdc-4813-80e9-baf859ef02b9.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "c0040355-ffdc-4813-80e9-baf859ef02b9", - "type": "bugfix", - "description": "fix: correct hash code calculation for case-insensitive map entries" -} \ No newline at end of file diff --git a/.changes/d3ce7511-6fb2-4435-8f46-db724551b384.json b/.changes/d3ce7511-6fb2-4435-8f46-db724551b384.json deleted file mode 100644 index aa89d9167e..0000000000 --- a/.changes/d3ce7511-6fb2-4435-8f46-db724551b384.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": "d3ce7511-6fb2-4435-8f46-db724551b384", - "type": "misc", - "description": "Add telemetry provider configuration to `DefaultAwsSigner`" -} \ No newline at end of file diff --git a/.github/workflows/api-compat-verification.yml b/.github/workflows/api-compat-verification.yml index 2d4a22452a..5d7de9de0c 100644 --- a/.github/workflows/api-compat-verification.yml +++ b/.github/workflows/api-compat-verification.yml @@ -7,6 +7,8 @@ on: - main - '*-main' +permissions: { } + jobs: api-compat-verification: runs-on: ubuntu-latest diff --git a/.github/workflows/changelog-verification.yml b/.github/workflows/changelog-verification.yml index bc9b81bded..ca9aaa3be7 100644 --- a/.github/workflows/changelog-verification.yml +++ b/.github/workflows/changelog-verification.yml @@ -4,7 +4,7 @@ permissions: id-token: write on: - pull_request_target: + pull_request: types: [ opened, synchronize, reopened, labeled, unlabeled ] branches: - main diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index da0bb593d6..40017ce513 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -8,6 +8,8 @@ on: pull_request: workflow_dispatch: +permissions: { } + # Allow one instance of this workflow per pull request, and cancel older runs when new changes are pushed concurrency: group: ci-pr-${{ github.ref }} diff --git a/.github/workflows/issue-regression-labeler.yml b/.github/workflows/issue-regression-labeler.yml index adecdbc628..97b857d60e 100644 --- a/.github/workflows/issue-regression-labeler.yml +++ b/.github/workflows/issue-regression-labeler.yml @@ -3,6 +3,7 @@ name: issue-regression-label on: issues: types: [opened, edited] +permissions: { } jobs: add-regression-label: runs-on: ubuntu-latest diff --git a/.github/workflows/jreleaser.yml b/.github/workflows/jreleaser.yml index 391e452d5d..93c5d7df6c 100644 --- a/.github/workflows/jreleaser.yml +++ b/.github/workflows/jreleaser.yml @@ -3,7 +3,7 @@ name: JReleaser check on: pull_request: - +permissions: { } jobs: jreleaser-check: permissions: {} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c8c67eb7f7..66035c5757 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,6 +12,8 @@ on: - '*-main' workflow_dispatch: +permissions: { } + env: PACKAGE_NAME: smithy-kotlin diff --git a/.github/workflows/merge-main.yml b/.github/workflows/merge-main.yml index b6316a2f38..7df49eda9a 100644 --- a/.github/workflows/merge-main.yml +++ b/.github/workflows/merge-main.yml @@ -3,7 +3,7 @@ on: push: branches: [ main ] workflow_dispatch: - +permissions: { } jobs: merge: runs-on: ubuntu-latest diff --git a/.github/workflows/minor-version-bump.yml b/.github/workflows/minor-version-bump.yml new file mode 100644 index 0000000000..f7a36f8153 --- /dev/null +++ b/.github/workflows/minor-version-bump.yml @@ -0,0 +1,11 @@ +name: Minor version bump check +on: + pull_request: +permissions: { } +jobs: + minor-version-bump-check: + permissions: {} + runs-on: ubuntu-latest + steps: + - name: Minor version bump check + uses: awslabs/aws-kotlin-repo-tools/.github/actions/minor-version-bump@main diff --git a/.github/workflows/release-readiness.yml b/.github/workflows/release-readiness.yml index 26a880217f..baa20268a2 100644 --- a/.github/workflows/release-readiness.yml +++ b/.github/workflows/release-readiness.yml @@ -7,6 +7,8 @@ on: pull_request: branches: [ main ] +permissions: { } + jobs: release-readiness: if: ${{ !contains(github.event.pull_request.labels.*.name, 'ready-for-release') }} diff --git a/.github/workflows/stale_issue.yaml b/.github/workflows/stale_issue.yaml index c6f1cb933f..ad5b31742f 100644 --- a/.github/workflows/stale_issue.yaml +++ b/.github/workflows/stale_issue.yaml @@ -5,6 +5,8 @@ on: schedule: - cron: "0 0/3 * * *" +permissions: { } + jobs: cleanup: name: Stale issue job diff --git a/.github/workflows/sync-mirror.yml b/.github/workflows/sync-mirror.yml index edc80ce30c..7643881e56 100644 --- a/.github/workflows/sync-mirror.yml +++ b/.github/workflows/sync-mirror.yml @@ -5,6 +5,8 @@ on: branches: [ main ] workflow_dispatch: +permissions: { } + jobs: git-sync: # Only sync when pushing to source repo diff --git a/CHANGELOG.md b/CHANGELOG.md index b10da529c5..fd7a74d5ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [1.5.10] - 09/22/2025 + +### Documentation +* Improve documentation for [`StandardRetryPolicy`](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.retries.policy/-standard-retry-policy/) + ## [1.5.8] - 09/04/2025 ## [1.5.7] - 09/04/2025 diff --git a/build.gradle.kts b/build.gradle.kts index 2a900f2cda..951d4fdeb8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,6 +4,7 @@ */ import aws.sdk.kotlin.gradle.dsl.configureJReleaser import aws.sdk.kotlin.gradle.dsl.configureLinting +import aws.sdk.kotlin.gradle.dsl.configureMinorVersionStrategyRules import aws.sdk.kotlin.gradle.util.typedProp import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -109,6 +110,7 @@ val lintPaths = listOf( ) configureLinting(lintPaths) +configureMinorVersionStrategyRules(lintPaths) // Binary compatibility apiValidation { diff --git a/gradle.properties b/gradle.properties index c90e8aaef3..f7dfebfe89 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,10 +14,10 @@ kotlinx.atomicfu.enableNativeIrTransformation=false org.gradle.jvmargs=-Xmx2G -XX:MaxMetaspaceSize=1G # SDK -sdkVersion=1.5.9-SNAPSHOT +sdkVersion=1.5.11-SNAPSHOT # codegen -codegenVersion=0.35.9-SNAPSHOT +codegenVersion=0.35.11-SNAPSHOT # FIXME Remove after Dokka 2.0 Gradle plugin is stable org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 78f8d1bc05..44c0f0b92b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin-version = "2.2.0" dokka-version = "2.0.0" -aws-kotlin-repo-tools-version = "0.4.56" +aws-kotlin-repo-tools-version = "0.4.57" # libs coroutines-version = "1.10.2" diff --git a/runtime/crt-util/jvm/src/aws/smithy/kotlin/runtime/crt/ReadChannelBodyStreamJvm.kt b/runtime/crt-util/jvm/src/aws/smithy/kotlin/runtime/crt/ReadChannelBodyStreamJvm.kt index cb2e691167..7703ef5895 100644 --- a/runtime/crt-util/jvm/src/aws/smithy/kotlin/runtime/crt/ReadChannelBodyStreamJvm.kt +++ b/runtime/crt-util/jvm/src/aws/smithy/kotlin/runtime/crt/ReadChannelBodyStreamJvm.kt @@ -7,6 +7,5 @@ package aws.smithy.kotlin.runtime.crt import aws.sdk.kotlin.crt.io.MutableBuffer import aws.smithy.kotlin.runtime.io.SdkBuffer -import aws.smithy.kotlin.runtime.io.read internal actual fun transferRequestBody(outgoing: SdkBuffer, dest: MutableBuffer) = outgoing.read(dest.buffer) diff --git a/runtime/protocol/http-client-engines/http-client-engine-crt/jvmAndNative/src/aws/smithy/kotlin/runtime/http/engine/crt/RequestUtil.kt b/runtime/protocol/http-client-engines/http-client-engine-crt/jvmAndNative/src/aws/smithy/kotlin/runtime/http/engine/crt/RequestUtil.kt index 5708f111b0..73f7d605a3 100644 --- a/runtime/protocol/http-client-engines/http-client-engine-crt/jvmAndNative/src/aws/smithy/kotlin/runtime/http/engine/crt/RequestUtil.kt +++ b/runtime/protocol/http-client-engines/http-client-engine-crt/jvmAndNative/src/aws/smithy/kotlin/runtime/http/engine/crt/RequestUtil.kt @@ -68,7 +68,7 @@ internal fun HttpRequest.toCrtRequest(callContext: CoroutineContext): aws.sdk.ko } val contentLength = body.contentLength?.takeIf { it >= 0 }?.toString() ?: headers[CONTENT_LENGTH_HEADER] - contentLength?.let { crtHeaders.append(CONTENT_LENGTH_HEADER, it) } + contentLength?.let { crtHeaders[CONTENT_LENGTH_HEADER] = it } return aws.sdk.kotlin.crt.http.HttpRequest(method.name, url.requestRelativePath, crtHeaders.build(), bodyStream) } diff --git a/runtime/protocol/http-client-engines/http-client-engine-crt/jvmAndNative/test/aws/smithy/kotlin/runtime/http/engine/crt/RequestUtilTest.kt b/runtime/protocol/http-client-engines/http-client-engine-crt/jvmAndNative/test/aws/smithy/kotlin/runtime/http/engine/crt/RequestUtilTest.kt index 25db47c70f..cb2d338588 100644 --- a/runtime/protocol/http-client-engines/http-client-engine-crt/jvmAndNative/test/aws/smithy/kotlin/runtime/http/engine/crt/RequestUtilTest.kt +++ b/runtime/protocol/http-client-engines/http-client-engine-crt/jvmAndNative/test/aws/smithy/kotlin/runtime/http/engine/crt/RequestUtilTest.kt @@ -4,7 +4,15 @@ */ package aws.smithy.kotlin.runtime.http.engine.crt +import aws.smithy.kotlin.runtime.content.ByteStream +import aws.smithy.kotlin.runtime.http.Headers +import aws.smithy.kotlin.runtime.http.HttpMethod +import aws.smithy.kotlin.runtime.http.request.HttpRequest +import aws.smithy.kotlin.runtime.http.toHttpBody +import aws.smithy.kotlin.runtime.net.url.Url +import kotlinx.coroutines.test.runTest import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -42,4 +50,19 @@ class RequestUtilTest { assertFalse(isRetryable(code, name), "Expected $name to not be retryable!") } } + + @Test + fun testContentLengthHeader() = runTest { + val data = "a".repeat(100) + + val request = HttpRequest( + HttpMethod.POST, + url = Url.parse("https://notarealurl.com"), + headers = Headers { set("Content-Length", data.length.toString()) }, + body = ByteStream.fromString(data).toHttpBody(), + ) + + val crtRequest = request.toCrtRequest(coroutineContext) + assertEquals(listOf(data.length.toString()), crtRequest.headers.getAll("Content-Length")) + } } diff --git a/runtime/protocol/http-client-engines/http-client-engine-okhttp/jvm/test/aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpRequestTest.kt b/runtime/protocol/http-client-engines/http-client-engine-okhttp/jvm/test/aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpRequestTest.kt index 16f6773008..760a947308 100644 --- a/runtime/protocol/http-client-engines/http-client-engine-okhttp/jvm/test/aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpRequestTest.kt +++ b/runtime/protocol/http-client-engines/http-client-engine-okhttp/jvm/test/aws/smithy/kotlin/runtime/http/engine/okhttp/OkHttpRequestTest.kt @@ -5,6 +5,7 @@ package aws.smithy.kotlin.runtime.http.engine.okhttp +import aws.smithy.kotlin.runtime.content.ByteStream import aws.smithy.kotlin.runtime.http.* import aws.smithy.kotlin.runtime.http.engine.internal.HttpClientMetrics import aws.smithy.kotlin.runtime.http.request.HttpRequest @@ -71,6 +72,22 @@ class OkHttpRequestTest { assertEquals(listOf("bar", "baz"), actual.headers("FoO")) } + @Test + fun itConvertsContentLengthHeader() { + val data = "a".repeat(100) + val url = Url.parse("https://aws.amazon.com") + val headers = Headers { + append("Content-Length", data.length.toString()) + } + val request = HttpRequest(HttpMethod.POST, url, headers, ByteStream.fromString(data).toHttpBody()) + + val execContext = ExecutionContext() + val actual = request.toOkHttpRequest(execContext, EmptyCoroutineContext, testMetrics) + + assertTrue(actual.headers.size >= 1) + assertEquals(listOf(data.length.toString()), actual.headers("Content-Length")) + } + @Test fun itSupportsNonAsciiHeaderValues() { val url = Url.parse("https://aws.amazon.com") diff --git a/runtime/runtime-core/api/runtime-core.api b/runtime/runtime-core/api/runtime-core.api index 597cdafe81..0e8f85de3a 100644 --- a/runtime/runtime-core/api/runtime-core.api +++ b/runtime/runtime-core/api/runtime-core.api @@ -39,6 +39,11 @@ public abstract interface annotation class aws/smithy/kotlin/runtime/IgnoreNativ public abstract interface annotation class aws/smithy/kotlin/runtime/InternalApi : java/lang/annotation/Annotation { } +public abstract interface annotation class aws/smithy/kotlin/runtime/PlannedRemoval : java/lang/annotation/Annotation { + public abstract fun major ()I + public abstract fun minor ()I +} + public abstract interface class aws/smithy/kotlin/runtime/ProtocolResponse { public abstract fun getSummary ()Ljava/lang/String; } @@ -391,6 +396,7 @@ public final class aws/smithy/kotlin/runtime/content/BigDecimal : java/lang/Numb public final fun floatValue ()F public final fun getExponent ()I public final fun getMantissa ()Laws/smithy/kotlin/runtime/content/BigInteger; + public final fun getValue ()Ljava/lang/String; public fun hashCode ()I public final fun intValue ()I public final fun longValue ()J @@ -416,6 +422,7 @@ public final class aws/smithy/kotlin/runtime/content/BigInteger : java/lang/Numb public final fun doubleValue ()D public fun equals (Ljava/lang/Object;)Z public final fun floatValue ()F + public final fun getValue ()Ljava/lang/String; public fun hashCode ()I public final fun intValue ()I public final fun longValue ()J @@ -864,10 +871,6 @@ public final class aws/smithy/kotlin/runtime/io/HashingSource : aws/smithy/kotli } public final class aws/smithy/kotlin/runtime/io/JavaIOKt { - public static final fun inputStream (Laws/smithy/kotlin/runtime/io/SdkBuffer;)Ljava/io/InputStream; - public static final fun isOpen (Laws/smithy/kotlin/runtime/io/SdkBuffer;)Z - public static final fun outputStream (Laws/smithy/kotlin/runtime/io/SdkBuffer;)Ljava/io/OutputStream; - public static final fun read (Laws/smithy/kotlin/runtime/io/SdkBuffer;Ljava/nio/ByteBuffer;)I public static final fun sink (Ljava/io/File;)Laws/smithy/kotlin/runtime/io/SdkSink; public static final fun sink (Ljava/io/OutputStream;)Laws/smithy/kotlin/runtime/io/SdkSink; public static final fun sink (Ljava/nio/file/Path;)Laws/smithy/kotlin/runtime/io/SdkSink; @@ -878,7 +881,6 @@ public final class aws/smithy/kotlin/runtime/io/JavaIOKt { public static final fun source (Ljava/nio/file/Path;Lkotlin/ranges/LongRange;)Laws/smithy/kotlin/runtime/io/SdkSource; public static synthetic fun source$default (Ljava/io/File;JJILjava/lang/Object;)Laws/smithy/kotlin/runtime/io/SdkSource; public static synthetic fun source$default (Ljava/nio/file/Path;JJILjava/lang/Object;)Laws/smithy/kotlin/runtime/io/SdkSource; - public static final fun write (Laws/smithy/kotlin/runtime/io/SdkBuffer;Ljava/nio/ByteBuffer;)I } public final class aws/smithy/kotlin/runtime/io/SdkBuffer : aws/smithy/kotlin/runtime/io/SdkBufferedSink, aws/smithy/kotlin/runtime/io/SdkBufferedSource { @@ -891,8 +893,12 @@ public final class aws/smithy/kotlin/runtime/io/SdkBuffer : aws/smithy/kotlin/ru public fun getBuffer ()Laws/smithy/kotlin/runtime/io/SdkBuffer; public final fun getSize ()J public fun hashCode ()I + public fun inputStream ()Ljava/io/InputStream; + public fun isOpen ()Z + public fun outputStream ()Ljava/io/OutputStream; public fun peek ()Laws/smithy/kotlin/runtime/io/SdkBufferedSource; public fun read (Laws/smithy/kotlin/runtime/io/SdkBuffer;J)J + public fun read (Ljava/nio/ByteBuffer;)I public fun read ([BII)I public fun readAll (Laws/smithy/kotlin/runtime/io/SdkSink;)J public fun readByte ()B @@ -912,6 +918,7 @@ public final class aws/smithy/kotlin/runtime/io/SdkBuffer : aws/smithy/kotlin/ru public fun toString ()Ljava/lang/String; public fun write (Laws/smithy/kotlin/runtime/io/SdkBuffer;J)V public fun write (Laws/smithy/kotlin/runtime/io/SdkSource;J)V + public fun write (Ljava/nio/ByteBuffer;)I public fun write ([BII)V public fun writeAll (Laws/smithy/kotlin/runtime/io/SdkSource;)J public fun writeByte (B)V @@ -924,9 +931,11 @@ public final class aws/smithy/kotlin/runtime/io/SdkBuffer : aws/smithy/kotlin/ru public fun writeUtf8 (Ljava/lang/String;II)V } -public abstract interface class aws/smithy/kotlin/runtime/io/SdkBufferedSink : aws/smithy/kotlin/runtime/io/SdkSink { +public abstract interface class aws/smithy/kotlin/runtime/io/SdkBufferedSink : aws/smithy/kotlin/runtime/io/SdkSink, java/nio/channels/WritableByteChannel { public abstract fun emit ()V + public abstract fun flush ()V public abstract fun getBuffer ()Laws/smithy/kotlin/runtime/io/SdkBuffer; + public abstract fun outputStream ()Ljava/io/OutputStream; public abstract fun write (Laws/smithy/kotlin/runtime/io/SdkSource;J)V public abstract fun write ([BII)V public static synthetic fun write$default (Laws/smithy/kotlin/runtime/io/SdkBufferedSink;[BIIILjava/lang/Object;)V @@ -947,9 +956,10 @@ public final class aws/smithy/kotlin/runtime/io/SdkBufferedSink$DefaultImpls { public static synthetic fun writeUtf8$default (Laws/smithy/kotlin/runtime/io/SdkBufferedSink;Ljava/lang/String;IIILjava/lang/Object;)V } -public abstract interface class aws/smithy/kotlin/runtime/io/SdkBufferedSource : aws/smithy/kotlin/runtime/io/SdkSource { +public abstract interface class aws/smithy/kotlin/runtime/io/SdkBufferedSource : aws/smithy/kotlin/runtime/io/SdkSource, java/nio/channels/ReadableByteChannel { public abstract fun exhausted ()Z public abstract fun getBuffer ()Laws/smithy/kotlin/runtime/io/SdkBuffer; + public abstract fun inputStream ()Ljava/io/InputStream; public abstract fun peek ()Laws/smithy/kotlin/runtime/io/SdkBufferedSource; public abstract fun read ([BII)I public static synthetic fun read$default (Laws/smithy/kotlin/runtime/io/SdkBufferedSource;[BIIILjava/lang/Object;)I diff --git a/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/Annotations.kt b/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/Annotations.kt index 30eed9afe4..fa8022f0fd 100644 --- a/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/Annotations.kt +++ b/runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/Annotations.kt @@ -59,6 +59,19 @@ public annotation class ExperimentalApi @DslMarker public annotation class SdkDsl +/** + * Indicates that the annotated API is deprecated and scheduled for removal in an upcoming version. + * Any code using this API should migrate to the suggested replacement as soon as possible. + */ +@RequiresOptIn( + message = "This API is deprecated and scheduled for removal in an upcoming version.", + level = RequiresOptIn.Level.WARNING, +) +public annotation class PlannedRemoval( + val major: Int, + val minor: Int, +) + /** * Marks a test that should be ignored on Native platforms */ diff --git a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/content/BigDecimalJVM.kt b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/content/BigDecimalJVM.kt index a7de1ab953..3890cfa9d9 100644 --- a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/content/BigDecimalJVM.kt +++ b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/content/BigDecimalJVM.kt @@ -45,6 +45,8 @@ public actual class BigDecimal private constructor(private val delegate: JvmBigD public actual val exponent: Int get() = delegate.scale() + public val value: String = delegate.toString() + public actual operator fun plus(other: BigDecimal): BigDecimal = coalesceOrCreate(delegate + other.delegate, this, other) diff --git a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/content/BigIntegerJVM.kt b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/content/BigIntegerJVM.kt index 2f864710b3..738d5ed102 100644 --- a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/content/BigIntegerJVM.kt +++ b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/content/BigIntegerJVM.kt @@ -35,6 +35,7 @@ public actual class BigInteger internal constructor(internal val delegate: JvmBi public actual override fun toDouble(): Double = delegate.toDouble() public actual override fun toString(): String = toString(10) public actual fun toString(radix: Int): String = delegate.toString(radix) + public val value: String = delegate.toString() public actual override fun hashCode(): Int = 17 + delegate.hashCode() public actual override fun equals(other: Any?): Boolean = other is BigInteger && delegate == other.delegate diff --git a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/BufferedSinkAdapterJVM.kt b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/BufferedSinkAdapterJVM.kt new file mode 100644 index 0000000000..404dd6d078 --- /dev/null +++ b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/BufferedSinkAdapterJVM.kt @@ -0,0 +1,20 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package aws.smithy.kotlin.runtime.io + +import java.io.OutputStream +import java.nio.ByteBuffer + +internal actual class BufferedSinkAdapter actual constructor( + sink: okio.BufferedSink, +) : AbstractBufferedSinkAdapter(sink), + SdkBufferedSink { + override fun write(src: ByteBuffer): Int = delegate.write(src) + + override fun isOpen(): Boolean = delegate.isOpen + + override fun outputStream(): OutputStream = delegate.outputStream() +} diff --git a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/BufferedSourceAdapterJVM.kt b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/BufferedSourceAdapterJVM.kt new file mode 100644 index 0000000000..e7b1c3d759 --- /dev/null +++ b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/BufferedSourceAdapterJVM.kt @@ -0,0 +1,21 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package aws.smithy.kotlin.runtime.io + +import java.io.InputStream +import java.nio.ByteBuffer + +internal actual class BufferedSourceAdapter actual constructor( + source: okio.BufferedSource, +) : AbstractBufferedSourceAdapter(source), + SdkBufferedSource { + + override fun read(dst: ByteBuffer): Int = delegate.read(dst) + + override fun isOpen(): Boolean = delegate.isOpen + + override fun inputStream(): InputStream = delegate.inputStream() +} diff --git a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/JavaIO.kt b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/JavaIO.kt index c035aa9a4c..e7578bfea4 100644 --- a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/JavaIO.kt +++ b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/JavaIO.kt @@ -9,7 +9,6 @@ import aws.smithy.kotlin.runtime.io.internal.toSdk import java.io.File import java.io.InputStream import java.io.OutputStream -import java.nio.ByteBuffer import java.nio.file.Path import okio.sink as okioSink import okio.source as okioSource @@ -60,20 +59,3 @@ public fun InputStream.source(): SdkSource = okioSource().toSdk() * Create a new [SdkSource] that reads from this [InputStream] */ public fun OutputStream.sink(): SdkSink = okioSink().toSdk() - -// BufferedSinkAdapter -internal fun BufferedSinkAdapter.outputStream(): OutputStream = delegate.outputStream() -internal fun BufferedSinkAdapter.write(src: ByteBuffer): Int = delegate.write(src) -internal fun BufferedSinkAdapter.isOpen(): Boolean = delegate.isOpen - -// BufferedSourceAdapter -internal fun BufferedSourceAdapter.read(dst: ByteBuffer): Int = delegate.read(dst) -internal fun BufferedSourceAdapter.isOpen(): Boolean = delegate.isOpen -internal fun BufferedSourceAdapter.inputStream(): InputStream = delegate.inputStream() - -// SdkBuffer -public fun SdkBuffer.read(dst: ByteBuffer): Int = wrapOkio { inner.read(dst) } -public fun SdkBuffer.write(src: ByteBuffer): Int = wrapOkio { inner.write(src) } -public fun SdkBuffer.isOpen(): Boolean = inner.isOpen -public fun SdkBuffer.inputStream(): InputStream = inner.inputStream() -public fun SdkBuffer.outputStream(): OutputStream = inner.outputStream() diff --git a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/SdkBufferJVM.kt b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/SdkBufferJVM.kt new file mode 100644 index 0000000000..c2f486c3c9 --- /dev/null +++ b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/SdkBufferJVM.kt @@ -0,0 +1,122 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package aws.smithy.kotlin.runtime.io + +import aws.smithy.kotlin.runtime.io.internal.* +import java.io.InputStream +import java.io.OutputStream +import java.nio.ByteBuffer + +// FIXME Commonize with Native after removing WritableByteStream / ReadableByteStream in 1.6.x +public actual class SdkBuffer : + SdkBufferedSource, + SdkBufferedSink { + public actual constructor() : this(okio.Buffer()) + + internal actual val inner: okio.Buffer + + internal actual constructor(buffer: okio.Buffer) { + this.inner = buffer + } + + public actual val size: Long + get() = inner.size + + actual override val buffer: SdkBuffer + get() = this + + override fun toString(): String = inner.toString() + + override fun hashCode(): Int = inner.hashCode() + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is SdkBuffer) return false + return inner == other.inner + } + + actual override fun skip(byteCount: Long): Unit = commonSkip(byteCount) + + actual override fun readByte(): Byte = commonReadByte() + + actual override fun readShort(): Short = commonReadShort() + + actual override fun readShortLe(): Short = commonReadShortLe() + + actual override fun readLong(): Long = commonReadLong() + + actual override fun readLongLe(): Long = commonReadLongLe() + + actual override fun readInt(): Int = commonReadInt() + + actual override fun readIntLe(): Int = commonReadIntLe() + + actual override fun readAll(sink: SdkSink): Long = commonReadAll(sink) + + actual override fun read(sink: ByteArray, offset: Int, limit: Int): Int = + commonRead(sink, offset, limit) + + actual override fun read(sink: SdkBuffer, limit: Long): Long = + commonRead(sink, limit) + + override fun read(dst: ByteBuffer): Int = inner.read(dst) + + actual override fun readByteArray(): ByteArray = commonReadByteArray() + + actual override fun readByteArray(byteCount: Long): ByteArray = commonReadByteArray(byteCount) + + actual override fun readUtf8(): String = commonReadUtf8() + + actual override fun readUtf8(byteCount: Long): String = commonReadUtf8(byteCount) + + actual override fun peek(): SdkBufferedSource = commonPeek() + + actual override fun exhausted(): Boolean = commonExhausted() + actual override fun request(byteCount: Long): Boolean = commonRequest(byteCount) + + actual override fun require(byteCount: Long): Unit = commonRequire(byteCount) + + actual override fun write(source: ByteArray, offset: Int, limit: Int): Unit = + commonWrite(source, offset, limit) + + actual override fun write(source: SdkSource, byteCount: Long): Unit = + commonWrite(source, byteCount) + + actual override fun write(source: SdkBuffer, byteCount: Long): Unit = + commonWrite(source, byteCount) + + override fun write(src: ByteBuffer): Int = inner.write(src) + + actual override fun writeAll(source: SdkSource): Long = commonWriteAll(source) + + actual override fun writeUtf8(string: String, start: Int, endExclusive: Int): Unit = + commonWriteUtf8(string, start, endExclusive) + + actual override fun writeByte(x: Byte): Unit = commonWriteByte(x) + + actual override fun writeShort(x: Short): Unit = commonWriteShort(x) + + actual override fun writeShortLe(x: Short): Unit = commonWriteShortLe(x) + + actual override fun writeInt(x: Int): Unit = commonWriteInt(x) + + actual override fun writeIntLe(x: Int): Unit = commonWriteIntLe(x) + + actual override fun writeLong(x: Long): Unit = commonWriteLong(x) + + actual override fun writeLongLe(x: Long): Unit = commonWriteLongLe(x) + + actual override fun flush(): Unit = commonFlush() + + actual override fun emit() { + inner.emit() + } + actual override fun close(): Unit = commonClose() + override fun isOpen(): Boolean = inner.isOpen + + override fun inputStream(): InputStream = inner.inputStream() + override fun outputStream(): OutputStream = inner.outputStream() +} diff --git a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/SdkBufferedSinkJVM.kt b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/SdkBufferedSinkJVM.kt new file mode 100644 index 0000000000..6a44c557a3 --- /dev/null +++ b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/SdkBufferedSinkJVM.kt @@ -0,0 +1,109 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package aws.smithy.kotlin.runtime.io + +import java.io.OutputStream +import java.nio.channels.WritableByteChannel +import kotlin.jvm.Throws + +/** + * A sink that keeps a buffer internally so that callers can do small writes without + * a performance penalty. + */ +public actual sealed interface SdkBufferedSink : + SdkSink, + WritableByteChannel { + /** + * The underlying buffer for this sink + */ + public actual val buffer: SdkBuffer + + /** + * Write [limit] bytes from [source] starting at [offset] + */ + @Throws(IOException::class) + public actual fun write(source: ByteArray, offset: Int, limit: Int): Unit + + /** + * Write all bytes from [source] to this sink. + * @return the number of bytes read which will be 0 if [source] is exhausted + */ + @Throws(IOException::class) + public actual fun writeAll(source: SdkSource): Long + + /** + * Removes [byteCount] bytes from [source] and writes them to this sink. + */ + @Throws(IOException::class) + public actual fun write(source: SdkSource, byteCount: Long): Unit + + /** + * Write UTF8-bytes of [string] to this sink starting at [start] index up to [endExclusive] index. + */ + @Throws(IOException::class) + public actual fun writeUtf8(string: String, start: Int, endExclusive: Int): Unit + + /** + * Writes byte [x] to this sink + */ + @Throws(IOException::class) + public actual fun writeByte(x: Byte): Unit + + /** + * Writes short [x] as a big-endian bytes to this sink + */ + @Throws(IOException::class) + public actual fun writeShort(x: Short): Unit + + /** + * Writes short [x] as a little-endian bytes to this sink + */ + @Throws(IOException::class) + public actual fun writeShortLe(x: Short): Unit + + /** + * Writes int [x] as a big-endian bytes to this sink + */ + @Throws(IOException::class) + public actual fun writeInt(x: Int): Unit + + /** + * Writes int [x] as a little-endian bytes to this sink + */ + @Throws(IOException::class) + public actual fun writeIntLe(x: Int): Unit + + /** + * Writes long [x] as a big-endian bytes to this sink + */ + @Throws(IOException::class) + public actual fun writeLong(x: Long): Unit + + /** + * Writes long [x] as a little-endian bytes to this sink + */ + @Throws(IOException::class) + public actual fun writeLongLe(x: Long): Unit + + /** + * Return an output stream that writes to this sink + */ + public fun outputStream(): OutputStream + + /** + * Writes all buffered data to the underlying sink. + */ + @Throws(IOException::class) + actual override fun flush(): Unit + + /** + * Writes all buffered data to the underlying sink. Like flush, but weaker (ensures data is pushed to the + * underlying sink but not necessarily all the way down the chain like [flush] does). Call before this sink + * goes out of scope to ensure any buffered data eventually gets to its final destination + */ + @Throws(IOException::class) + public actual fun emit(): Unit +} diff --git a/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/SdkBufferedSourceJVM.kt b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/SdkBufferedSourceJVM.kt new file mode 100644 index 0000000000..076502f7c5 --- /dev/null +++ b/runtime/runtime-core/jvm/src/aws/smithy/kotlin/runtime/io/SdkBufferedSourceJVM.kt @@ -0,0 +1,144 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package aws.smithy.kotlin.runtime.io + +import java.io.InputStream +import java.nio.channels.ReadableByteChannel + +public actual sealed interface SdkBufferedSource : + SdkSource, + ReadableByteChannel { + + /** + * The underlying buffer for this source + */ + public actual val buffer: SdkBuffer + + /** + * Discards [byteCount] bytes from this source. Throws [IOException] if source is exhausted before [byteCount] + * bytes can be discarded. + */ + @Throws(IOException::class) + public actual fun skip(byteCount: Long) + + /** + * Read a single byte from this source and return it + */ + @Throws(IOException::class) + public actual fun readByte(): Byte + + /** + * Read two bytes in big-endian order from this source and returns them as a short. + */ + @Throws(IOException::class) + public actual fun readShort(): Short + + /** + * Read two bytes in little-endian order from this source and returns them as a short. + */ + @Throws(IOException::class) + public actual fun readShortLe(): Short + + /** + * Read eight bytes in big-endian order from this source and returns them as a long. + */ + @Throws(IOException::class) + public actual fun readLong(): Long + + /** + * Read eight bytes in little-endian order from this source and returns them as a long. + */ + @Throws(IOException::class) + public actual fun readLongLe(): Long + + /** + * Read four bytes in big-endian order from this source and returns them as an int. + */ + @Throws(IOException::class) + public actual fun readInt(): Int + + /** + * Read four bytes in little-endian order from this source and returns them as an int. + */ + @Throws(IOException::class) + public actual fun readIntLe(): Int + + /** + * Reads all bytes from this and appends them to [sink]. Returns + * the total number of bytes written which will be 0 if this source + * is exhausted. + */ + @Throws(IOException::class) + public actual fun readAll(sink: SdkSink): Long + + /** + * Read up to [limit] bytes and write them to [sink] starting at [offset] + */ + @Throws(IOException::class) + public actual fun read(sink: ByteArray, offset: Int, limit: Int): Int + + /** + * Reads all bytes from this source and returns them as a byte array + * + * **Caution** This may pull a large amount of data into memory, only do this if you are sure + * the contents fit into memory. Throws [IllegalArgumentException] if the buffer size exceeds [Int.MAX_VALUE]. + */ + @Throws(IOException::class) + public actual fun readByteArray(): ByteArray + + /** + * Reads [byteCount] bytes from this source and returns them as a byte array + */ + @Throws(IOException::class) + public actual fun readByteArray(byteCount: Long): ByteArray + + /** + * Reads all bytes from this source, decodes them as UTF-8, and returns the string. + * + * **Caution** This may pull a large amount of data into memory, only do this if you are sure + * the contents fit into memory. Throws [IllegalArgumentException] if the buffer size exceeds [Int.MAX_VALUE]. + */ + @Throws(IOException::class) + public actual fun readUtf8(): String + + /** + * Reads [byteCount] bytes from this source, decodes them as UTF-8, and returns the string. + */ + @Throws(IOException::class) + public actual fun readUtf8(byteCount: Long): String + + /** + * Get an input stream that reads from this source + */ + public fun inputStream(): InputStream + + /** + * Returns a new [SdkBufferedSource] that can read data from this source + * without consuming it. The returned source becomes invalid once this source is next + * read or closed. + */ + public actual fun peek(): SdkBufferedSource + + /** + * Returns true if there are no more bytes in this source. This will block until there are bytes + * to read or the source is definitely exhausted. + */ + public actual fun exhausted(): Boolean + + /** + * Returns true when the buffer contains at least [byteCount] bytes. False if the source + * is exhausted before the requested number of bytes could be read + */ + @Throws(IOException::class) + public actual fun request(byteCount: Long): Boolean + + /** + * Returns when the buffer contains at least [byteCount] bytes or throws [EOFException] + * if the source is exhausted before the requested number of bytes could be read + */ + @Throws(IOException::class) + public actual fun require(byteCount: Long): Unit +} diff --git a/runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/BufferedSinkAdapterJvmAndNative.kt b/runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/BufferedSinkAdapterNative.kt similarity index 83% rename from runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/BufferedSinkAdapterJvmAndNative.kt rename to runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/BufferedSinkAdapterNative.kt index 7205c8d6a1..bf5767cf35 100644 --- a/runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/BufferedSinkAdapterJvmAndNative.kt +++ b/runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/BufferedSinkAdapterNative.kt @@ -4,9 +4,6 @@ */ package aws.smithy.kotlin.runtime.io -import aws.smithy.kotlin.runtime.InternalApi - -@InternalApi internal actual class BufferedSinkAdapter actual constructor(sink: okio.BufferedSink) : AbstractBufferedSinkAdapter(sink), SdkBufferedSink diff --git a/runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/BufferedSourceAdapterJvmAndNative.kt b/runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/BufferedSourceAdapterNative.kt similarity index 100% rename from runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/BufferedSourceAdapterJvmAndNative.kt rename to runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/BufferedSourceAdapterNative.kt diff --git a/runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/SdkBufferJvmAndNative.kt b/runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/SdkBufferNative.kt similarity index 97% rename from runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/SdkBufferJvmAndNative.kt rename to runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/SdkBufferNative.kt index c0472cd857..616ef39a76 100644 --- a/runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/SdkBufferJvmAndNative.kt +++ b/runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/SdkBufferNative.kt @@ -6,6 +6,7 @@ package aws.smithy.kotlin.runtime.io import aws.smithy.kotlin.runtime.io.internal.* +// FIXME Commonize with JVM after removing WritableByteStream / ReadableByteStream in 1.6.x public actual class SdkBuffer : SdkBufferedSource, SdkBufferedSink { diff --git a/runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/SdkBufferedSinkJvmAndNative.kt b/runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/SdkBufferedSinkNative.kt similarity index 100% rename from runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/SdkBufferedSinkJvmAndNative.kt rename to runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/SdkBufferedSinkNative.kt diff --git a/runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/SdkBufferedSourceJvmAndNative.kt b/runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/SdkBufferedSourceNative.kt similarity index 100% rename from runtime/runtime-core/jvmAndNative/src/aws/smithy/kotlin/runtime/io/SdkBufferedSourceJvmAndNative.kt rename to runtime/runtime-core/native/src/aws/smithy/kotlin/runtime/io/SdkBufferedSourceNative.kt