From 8432577f5d8a373981af436d242d832c7e6f5637 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Fri, 7 Jun 2024 15:43:25 +0200 Subject: [PATCH] [resources] Read exactly requested count of bytes from InputStream on jvm platforms. (#4943) In some cases the skip and read methods may handle less bytes then expected. The PR fixes it by proper API on the JVM and manual check on the Android. Fixes https://github.com/JetBrains/compose-multiplatform/issues/4938 ## Testing I manually checked it on the project from the issue. ## Release Notes ### Fixes - Resources - Read exactly requested count of bytes from InputStream on jvm platforms. --- .../resources/ResourceReader.android.kt | 24 +++++++++++++++++-- .../resources/ResourceReader.desktop.kt | 4 ++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt index 7c1ce6fdbf1..972cb39205f 100644 --- a/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt +++ b/components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt @@ -13,12 +13,32 @@ internal actual fun getPlatformResourceReader(): ResourceReader = object : Resou val resource = getResourceAsStream(path) val result = ByteArray(size.toInt()) resource.use { input -> - input.skip(offset) - input.read(result, 0, size.toInt()) + input.skipBytes(offset) + input.readBytes(result, 0, size.toInt()) } return result } + //skipNBytes requires API 34 + private fun InputStream.skipBytes(offset: Long) { + var skippedBytes = 0L + while (skippedBytes < offset) { + val count = skip(offset - skippedBytes) + if (count == 0L) break + skippedBytes += count + } + } + + //readNBytes requires API 34 + private fun InputStream.readBytes(byteArray: ByteArray, offset: Int, size: Int) { + var readBytes = 0 + while (readBytes < size) { + val count = read(byteArray, offset + readBytes, size - readBytes) + if (count <= 0) break + readBytes += count + } + } + override fun getUri(path: String): String { val classLoader = getClassLoader() val resource = classLoader.getResource(path) ?: run { diff --git a/components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt b/components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt index 3f9097e5206..da70a3899c7 100644 --- a/components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt +++ b/components/resources/library/src/desktopMain/kotlin/org/jetbrains/compose/resources/ResourceReader.desktop.kt @@ -12,8 +12,8 @@ internal actual fun getPlatformResourceReader(): ResourceReader = object : Resou val resource = getResourceAsStream(path) val result = ByteArray(size.toInt()) resource.use { input -> - input.skip(offset) - input.read(result, 0, size.toInt()) + input.skipNBytes(offset) + input.readNBytes(result, 0, size.toInt()) } return result }