Git Product home page Git Product logo

kotlinx-io's Introduction

kotlinx-io

Kotlin Alpha JetBrains incubator project GitHub license Download Kotlin TeamCity build KDoc link

A multiplatform Kotlin library providing basic IO primitives. kotlinx-io is based on Okio but does not preserve backward compatibility with it.

Overview

kotlinx-io is built around Buffer - a mutable sequence of bytes.

Buffer works like a queue, allowing to read data from its head or to write data to its tail. Buffer provides functions to read and write data of different built-in types, and to copy data to or from other Buffers. Depending on the target platform, extension functions allowing data exchange with platform-specific types are also available.

A Buffer consists of segments organized as a linked list: segments allow reducing memory allocations during the buffer's expansion and copy, with the latter achieved by delegating or sharing the ownership over the underlying buffer's segments with other buffers.

kotlinx-io provides interfaces representing data sources and destinations - Source and Sink, and in addition to the mutable Buffer the library also provides an immutable sequence of bytes - ByteString.

An experimental filesystem support is shipped under the kotlinx.io.files package, which includes the FileSystem interface and its default implementation - SystemFileSystem.

FileSystem provides basic operations for working with files and directories, which are represented by yet another class under the same package - Path.

There are two kotlinx-io modules:

Using in your projects

Note that the library is experimental, and the API is subject to change.

Gradle

Make sure that you have mavenCentral() in the list of repositories:

repositories {
    mavenCentral()
}

Add the library to dependencies:

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.3.4")
}

In multiplatform projects, add a dependency to the commonMain source set dependencies:

kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.3.4")
            }
        }
    }
}

Maven

Add the library to dependencies:

<dependency>
    <groupId>org.jetbrains.kotlinx</groupId>
    <artifactId>kotlinx-io-core-jvm</artifactId>
    <version>0.3.4</version>
</dependency>

Android

kotlinx-io is not tested on Android on a regular basis, but the library is compatible with Android 5.0+ (API level 21+).

Contributing

Read the Contributing Guidelines.

Code of Conduct

This project and the corresponding community are governed by the JetBrains Open Source and Community Code of Conduct. Please make sure you read it.

License

kotlinx-io is licensed under the Apache 2.0 License.

Credits

Thanks to everyone involved in the project.

An honorable mention goes to the developers of Okio that served as the foundation for kotlinx-io and to Jesse Wilson, for the help with Okio adaption, his suggestions, assistance and guidance with kotlinx-io development.

kotlinx-io's People

Contributors

0xflotus avatar cy6ergn0m avatar dominaezzz avatar e5l avatar elizarov avatar etolstoy avatar fzhinkin avatar goooler avatar hhariri avatar jeffdgr8 avatar lppedd avatar lukellmann avatar martinbonnin avatar orangy avatar qwwdfsad avatar recursive-rat4 avatar salomonbrys avatar sebastianaigner avatar shanshin avatar whyoleg avatar wldeh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kotlinx-io's Issues

There should be a Native IoBuffer constructor public

What if we want an IoBuffer to use as memory backend a specific CPointer ?
There are a lot of use cases for this:

  • Manual allocation of a specific known size
  • Read from a pointer received from a C/C++ library
  • etc.

I suggest the following addtion to the Native IoBuffer class:

constructor(content: CPointer<ByteVar>, contentCapacity: Int) : this(content, contentCapacity, null)

Of course, the memory management of the CPointer's memory is the programmer's repsonsability.
This could be emphasized by using a companion object method instead of a constructor:

companion object {
    fun makeView(content: CPointer<ByteVar>, contentCapacity: Int) = IoBuffer(content, contentCapacity, null)
}

The core may be duplicated with Okio2?

Okio 2 is also making an effort to multiplatform base on kotlin. And the functions provided by core are supported by Okio. So, why not to concern to use Okio to as kotlin-io library? Or, what's the main difference between this library and Okio?

Invalid decode utf-8 bytes

The following test is failing:

    @Test
    fun testInputEncoding() {
        val string = "file content with unicode 🌀 : здороваться : 여보세요 : 你好 : ñç"
        val inputBytes = buildPacket { writeStringUtf8(string) }.readBytes()
        val inputFromAppendBytes = buildPacket { append(string) }.readBytes()
        val data = string.toByteArray()

        assertArrayEquals(inputBytes, inputFromAppendBytes)
        assertArrayEquals(data, inputBytes) // ---> fail
    }

Note that there are 2 methods: append and writeStringUtf8 and the difference is not so obvious.

Easy way to implement limit?

I want to be able to limit an Input, but it doesn't seem like the functionality exists. I attempted to implement it with a new AbstractInput subclass, but I couldn't understand how head and remaining are supposed to function. I want to know if it would be possible to add this functionality to Input as an extension function, or -- if this is actual trivial to implement on my end -- some direction on how AbstractInput functions.

Support more native targets

I'm mostly thinking of androidNativeArm64, androidNativeArm32 and wasm but you might as well just publish for all them.

I want to get a Vulkan sample working on native android and I use this library for IoBuffer (until Memory is released).

Is there anything blocking the support of other targets?

Add some useful extensions

Let's consider to add some useful extensions:

  • fun String.toByteReadChannel(charset)
  • interface Closeable
  • ObjectPool<T>.use(block):R
  • readUntil for primitive types and ByteArray
  • readLine with CharsetDecoder
  • readLine until delimiter
  • Input.skip(count) (Input.discard)
  • ByteReadChannel.skip(count)
  • ByteReadPacket(ByteArray)
  • Input.lines(): Sequence | List
  • revert ByteReadChannel.totalBytesRead
  • Input.copyTo(Output) + joinTo
  • ByteWriteChannel.writeFully(Input)

Jvm integration

  • Input.asStream(): InputStream
  • InputStream.asInput(): Input

Charset shortcuts:

  • ISO_8859_1

Input/Output

  • BE and LE API for reading and writing(including primitive types)

Getting Instance is already consumed when reading two subsequent values from Input

on 0.1.1 I am getting java.lang.IllegalStateException: Instance is already consumed when trying read fixed length string after int from input. It works just fine in 0.1.0.

The full stack trace is following:

java.lang.IllegalStateException: Instance is already consumed

	at kotlinx.io.pool.SingleInstancePool.borrow(Pool.kt:73)
	at kotlinx.io.core.ByteReadPacketBase.fixGapAfterReadFallbackUnreserved(Packet.kt:662)
	at kotlinx.io.core.ByteReadPacketBase.fixGapAfterReadFallback(Packet.kt:644)
	at kotlinx.io.core.ByteReadPacketBase.fixGapAfterRead(Packet.kt:618)
	at kotlinx.io.core.internal.UnsafeKt.completeReadHead(Unsafe.kt:66)
	at kotlinx.io.charsets.CharsetJVMKt.decode(CharsetJVM.kt:555)
	at kotlinx.io.charsets.EncodingKt.decode(Encoding.kt:104)
	at kotlinx.io.core.StringsKt.readText(Strings.kt:339)
	at kotlinx.io.core.StringsKt.readText$default(Strings.kt:338)

I can give reference to the test if it would help.

[io-2] Reusable Input

Another feature I would like to see (and contribute) after io-2 release is the reusable Input (and maybe output) abstraction. It could look like this. The idea is that we have an Input provider that could be instantiated and reused in a safe way. Tho simple examples are file and a network stream. In case of file, we do not have to get file input, just a file reference, and the open, use and close the input automatically (my code have also an interface of RandomAccessBinary which could be used to access file not from the beginning). Another case is a network connection. Here, we won't close the input after read, but we will provide thread safe access for several readers to the same stream without them knowing about one another.

I am not sure about the size field. It is quite helpful in case one needs to copy the whole input to another binary, or in case of random access, but could be bothersome for infinite streams.

The same could be probably done for output, but I did not encounter use case so far.

Support mingwX64

I tried to use this in a multi-platform project and only the mingw target is not resolving the dependency.
Is there a reason why a KLIB for mingw hasn't been published?

How to consume ByteReadChannel

Sorry if this doesn't belong here, but I could use some documentation around how to consume ByteReadChannel correctly, I was expecting too see send() / receive() methods, like a regular coroutine channel but this isn't the case.

I'm using Ktor to download an image via HTTP and would like to log the progress while I do so.

// inside a coroutine

val response : HttpResponse = myService.getImage()

val byteArray = ByteArray(response.contentLength()!!.toInt())

while (response.content.readAvailable(byteArray) > 0) {
   log("downloading...")
}

log("downloaded $byteArray")

This doesn't seem to work (meaning can't decode this successfully into an android bitmap). On the other hand, this works just fine (no download progress tracking):

val byteArray = response.readBytes()

Getting buffer overflow randomly in tests

I am getting

java.nio.BufferOverflowException
	at java.base/java.nio.Buffer.nextPutIndex(Buffer.java:662)
	at java.base/java.nio.HeapByteBuffer.put(HeapByteBuffer.java:196)
	at kotlinx.io.core.IoBuffer.writeByte(IoBufferJVM.kt:164)
	at kotlinx.io.core.BytePacketBuilderBase.writeByte(Builder.kt:436)

in tests when I run a lot of tests simultaniously. When I run them individually, everything works fine. I tried to debug the problem, but it proved to be rather hard due to not always obvious borrowing logic. There is a check inside that should prevent this error, but is does not seem to work.

[io-2] Conceptual design for IO format

Here are some thoughts about IO format functionality I would like to add as soon as IO-2 is out. The idea is that we can add an easy way to write objects to streams and read them from streams. The resulting API could then simplify the work with serialization and file IO.

The idea is shown in the following example (using io-1 API):

interface IOFormat<T : Any> {
    fun Output.writeThis(obj: T)
    fun Input.readThis(): T
}

fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.run { readThis() }
fun <T : Any> Output.readWith(format: IOFormat<T>, obj: T) = format.run { writeThis(obj) }

class ListIOFormat<T : Any>(val format: IOFormat<T>) : IOFormat<List<T>> {
    override fun Output.writeThis(obj: List<T>) {
        writeInt(obj.size)
        format.run {
            obj.forEach {
                writeThis(it)
            }
        }
    }

    override fun Input.readThis(): List<T> {
        val size = readInt()
        return format.run {
            List(size) { readThis() }
        }
    }
}

val <T: Any> IOFormat<T>.list get() = ListIOFormat(this)

IOFormat represents a way to read and write data with Input and Output. One can construct a format for complex objects from the formats of individual parts. It could be probably used as a way to customize serialization backends. The similar idea is currently used in kmath in-memory operations on data: https://github.com/mipt-npm/kmath/blob/dev/kmath-memory/src/commonMain/kotlin/scientifik/memory/MemorySpec.kt.

update library version published to npm

the latest version of the library published to npm is currently 0.1.4-SNAPSHOT
any plans to update it to latest version? which version should I depend on, in the meanwhile, if use this library from node.js?

JVM Crash: No virtual method getParameterCount()I

Stacktrace:

2019-02-01 15:03:04.932 1952-2744/[REDACTED] E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
    Process: [REDACTED], PID: 1952
    java.lang.NoSuchMethodError: No virtual method getParameterCount()I in class Ljava/lang/reflect/Method; or its super classes (declaration of 'java.lang.reflect.Method' appears in /system/framework/core-oj.jar)
        at kotlinx.coroutines.io.internal.CoroutinesEventLoop$FutureReflectionImpl.<clinit>(EventLoopExperimental.kt:36)
        at kotlinx.coroutines.io.internal.EventLoopExperimentalKt.<clinit>(EventLoopExperimental.kt:48)
        at kotlinx.coroutines.io.internal.EventLoopExperimentalKt.detectEventLoop(EventLoopExperimental.kt:51)
        at kotlinx.coroutines.io.jvm.javaio.BlockingAdapter.parkingLoop(Blocking.kt:228)
        at kotlinx.coroutines.io.jvm.javaio.BlockingAdapter.submitAndAwait(Blocking.kt:215)
        at kotlinx.coroutines.io.jvm.javaio.BlockingAdapter.submitAndAwait(Blocking.kt:186)
        at kotlinx.coroutines.io.jvm.javaio.InputAdapter.read(Blocking.kt:55)
        at okio.Okio$2.read(Okio.java:140)
        at okio.RealBufferedSink.writeAll(RealBufferedSink.java:105)
        at io.ktor.client.engine.okhttp.StreamRequestBody.writeTo(StreamRequestBody.kt:13)
        at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:72)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:776)

Device used: Huawei Honor 6x, Android 7.0
Version used: 0.1.4 (dependency of ktor 1.1.2)

We're trying to find out more information.

Edit: as promised, more information:

  • also happens on Samsung Galaxy S6, Android 7.0
  • doesn't happen on an Android 9 device
  • the crash happens when doing the following ktor call, where the server does respond with no body at all (no JSON, no String, nothing):
client.post<String>("$endpoint/api/post") {
                
}

it also happens when using post<Unit>

Access underlying pointer of IOBuffer.

Would it be possible to allow access to the underlying pointer/Buffer of IOBuffer?
I'm writing a multi-platform vulkan wrapper (and possibly opengl) and I'm using IOBuffer as an abstraction over native data that will be passed to vulkan commands. On each platform I need to pass a CPointer or ByteBuffer to the platform specific command. At the moment I'm having to copy the data and pass the copy which I think is unnecessary.
Is this something IOBuffer can do for this use case?

java.lang.IllegalStateException: Reading is not available in state Reading

I'm seeing this bug in ktor client 1.1.3 on Android with OkHttp as the engine. It appears to have been a bug since at least ktor 1.0.1. You can see people posting this bug here:
ktorio/ktor#813

2019-03-14 12:53:57.109 2002-2002 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.rally.coach.internal.debug, PID: 2002
    java.lang.IllegalStateException: Reading is not available in state Reading
        at kotlinx.coroutines.io.internal.ReadWriteBufferState.startReading$kotlinx_coroutines_io(ReadWriteBufferState.kt:19)
        at kotlinx.coroutines.io.ByteBufferChannel.setupStateForRead(ByteBufferChannel.kt:238)
        at kotlinx.coroutines.io.ByteBufferChannel.access$setupStateForRead(ByteBufferChannel.kt:21)
        at kotlinx.coroutines.io.ByteBufferChannel.readAsMuchAsPossible(ByteBufferChannel.kt:2573)
        at kotlinx.coroutines.io.ByteBufferChannel.readAsMuchAsPossible$default(ByteBufferChannel.kt:436)
        at kotlinx.coroutines.io.ByteBufferChannel.readRemaining(ByteBufferChannel.kt:2161)
        at kotlinx.coroutines.io.ByteReadChannelKt.readRemaining(ByteReadChannel.kt:175)
        at io.ktor.client.response.HttpResponseKt.readText(HttpResponse.kt:75)
        at io.ktor.client.response.HttpResponseKt.readText$default(HttpResponse.kt:74)
        at com.rally.coach.api.service.utils.ApiExceptionUtilKt.toApiException(ApiExceptionUtil.kt:18)
        at com.rally.coach.api.BaseApi.withApiContext(BaseApi.kt:46)
        at com.rally.coach.api.BaseApi$withApiContext$1.invokeSuspend(Unknown Source:32)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
        at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:285)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Invalid usage of atomicfu

Take a note of this line: it declares compile-time dependency on atomicfu library, but it's wrong usage of atomicfu.

One more step required to properly integrate it to build process: adding a special task that transforms invocations of atomicfu calls to AtomicFieldUpdater/VarHandles native calls.
It allows to move atomicfu api to compileOnly scope and prevent leaking of atomicfu api to library users.

0.1.13 fails with new JS plugin

ERROR in .._imported/kotlinx-io/0.1.13/kotlinx-io.js
Module not found: Error: Can't resolve 'text-encoding' in 'D:\Work\Projects\dataforge-core\build\js\packages_imported\kotlinx-io\0.1.13'

Support a way to embed resources into code and use as a streams

Hi,
We are struggling to find a way how to include some html templates in our multiplatform project (JVM, iOS, JS) and it looks like there is no way how to do this.
I'd remembered from Flash Player that there was something called Assets Embedding, which uses annotation:

        [Embed(source="sound1.mp3")] 
        public var soundCls:Class; 

Maybe kotlinx.io could have some annotation:

@Embed(resource="...")
val bytes:BufferedInputStream;

which automatically embeds resource files into application during compilation.
Now it's hard to include some small binary files into project as now we need to bundle files into packages for each platform and deploy separately executables + assets and implement some ResourcesManager for each platform manually.

Do you have plan to implement Blocking IO Stream?

Hi guys:

I think kotlinx-io is started with NIO implementation for multiplatform.
But think about local file operation, Blocking IO is the most popular and simplest solution used for embedded platform(Android, iOS).
NIO is too complicated for them.
So do you have plan to implement Blocking IO, just like package java.io.*'s class / functions?

Thanks.

MPP JS client: Can't resolve 'text-encoding'

COPIED FROM: ktorio/ktor#961

Ktor Version
1.1.2

Ktor Engine Used(client or server and name)
Ktor client with default engine

JVM Version, Operating System and Relevant Context
JDK 1.8, Windows, Kotlin JS

Feedback
We are using the ktor client in a multiplatform project (android, iOS and web). Starting with version 1.1.0 the build of the JS client fails with the following message:

ERROR in ./kotlinx-io.js
Module not found: Error: Can't resolve 'text-encoding' in '<mypath>\kotlinmultiplatform\web\build\kotlin-js-min\main'
@ ./kotlinx-io.js 5309:21-45 5320:21-45
@ ./ktor-utils.js
@ ./web.js

If I manually add text-encoding as a npm-dependeny, it works.

If I list the npm dependency tree with the previous working ktor version 1.0.1 I get:

+-- [email protected] -> <mypath>\kotlinmultiplatform\web\build\node_modules_imported\kotlinx-io extraneous
+-- [email protected] -> <mypath>\kotlinmultiplatform\web\build\node_modules_imported\kotlinx-io-js
| +-- [email protected]
| +-- [email protected]
| | `-- [email protected] deduped
| +-- [email protected] -> <mypath>\kotlinmultiplatform\web\build\node_modules_imported\kotlinx-atomicfu deduped
| `-- [email protected]

If I list the npm dependency tree with a ktor version >= 1.1.0 the kotlinx-io-js (and of course text-encoding) is missing

The kotlinx.io.core.String(ByteArray, Int, Int, Charset) function ignores the length and offset arguments on JS

Description

Looks like the kotlinx.io.core.String(ByteArray, Int, Int, Charset) function just ignores the length and offset arguments on JS.
For example, the String(byteArrayOf(64, 64, 67, 67), length = 2, offset = 1) expression will return @@CC instead of @C.

Steps to Reproduce:

  1. Create a new Kotlin/JavaScript + Gradle project using IntelliJ IDEA.
  2. Make the build.gradle file look like that:
plugins {
    id 'java'
    id 'kotlin2js' version '1.3.20-dev-592'
}

group 'com.company.test'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    jcenter()
    maven { url 'http://dl.bintray.com/kotlin/kotlin-dev' }
    maven { url 'http://dl.bintray.com/kotlin/kotlinx' }
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-js"
    compile "org.jetbrains.kotlin:kotlin-test-js"
    compile "org.jetbrains.kotlinx:kotlinx-io-js:0.1.0-alpha-17-rc13"
}

compileKotlin2Js {
    kotlinOptions.moduleKind = 'umd'
}
  1. Make the settings.gradle file look like that:
pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == "kotlin2js") {
                useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
            }
        }
    }

    repositories {
        jcenter()
        maven { url 'http://dl.bintray.com/kotlin/kotlin-dev' }
    }
}
rootProject.name = 'test'
  1. Create a new package named "com.company.test" and a "Test.kt" file inside it with the following contents:
package com.company.test

import kotlinx.io.core.String

fun main(args: Array<String>) {
    println(String(byteArrayOf(64, 64, 67, 67), length = 2, offset = 1))
}
  1. Build the project and run it using Node.JS (I've been using v10.11.0).
  2. The @@CC will be printed instead of @C 😞.

Slow kotlinx.io.core.toByteArray

i use kotlinx-io not directly - just by ktor. My project is mobile app with shared library for ios & android, when i send very large textcontent by ktor (4mb photo from ios device encoded by base64) app stuck on call kotlinx.io.core.toByteArray and worked with 100% cpu usage by 30mins, and after it request is done and all complete. For fast fix i create my own TextContent, which use not kotlinx.io.core.toByteArray, but kotlinx.serialization.toUtf8Bytes on iOS platform. Here code:

class LargeTextContent(
    val text: String,
    override val contentType: ContentType,
    override val status: HttpStatusCode? = null
) : OutgoingContent.ByteArrayContent() {
    private val bytes by lazy(LazyThreadSafetyMode.NONE) {
        text.toByteArrayPlatform(contentType.charset() ?: Charsets.UTF_8)
    }

    override val contentLength: Long
        get() = bytes.size.toLong()

    override fun bytes(): ByteArray = bytes

    override fun toString(): String = "LargeTextContent[$contentType] \"${text.take(30)}\""
}

expect fun String.toByteArrayPlatform(charset: Charset): ByteArray

android (original version of toByteArray):

import kotlinx.io.charsets.Charset
import kotlinx.io.core.toByteArray

actual fun String.toByteArrayPlatform(charset: Charset): ByteArray {
    return toByteArray(charset)
}

ios (fixed for my case):

import kotlinx.io.charsets.Charset
import kotlinx.serialization.toUtf8Bytes

actual fun String.toByteArrayPlatform(charset: Charset): ByteArray {
    return toUtf8Bytes()
}

when i debugging i saw this stacktrace:
image (1)

here used versions:
kotlin_version=1.3.30
coroutines_version=1.2.0
ktor_version=1.1.4
klock_version=1.4.0
serialization_version=0.11.0

and i get this bug at this versions too:
kotlin_version=1.3.21
coroutines_version=1.1.1
ktor_version=1.1.3
klock_version=1.2.2
serialization_version=0.10.0

readFully/readAvailable length parameter default value

The array-reading functions readFully and readAvailable are defined with default values for the offset and length parameter.
If you only specify an explicit value for offset, length will default to array.size. If offset is not zero, this leads to an array bounds error, since it tries to write to the range of [offset, offset+length).

A more sensible default might be array.size - offset.

[io-2] Output->Input pipe

I've already encountered multiple cases, where I need to use direct pipe, that has Output on one side and an Input on the other side. Old io had copyTo operation, but it does not fully implement what I need, because one still needs some way to create those inputs and outputs, which in most cases requires additional copy operations. I am not sure about implementation yet, so putting it here for consideration for now. Probably there should be a specialized object, let's call it a Pipe, which implements both Input and Output (or provides input and output as properties). Inside that object there should be a synchronized queue of buffers, which could be written from one side and read from the other. The Pipe also should have an option to wait for the input which probably can't be done without coroutines.

MockEngine 'Invalid JSON at 4088: Unexpected end in string' on iOS

Ktor Version

1.1.2

###Kx.io Version
0.1.5-dev-4

Ktor Engine Used(client or server and name)

Ktor-client with MockEngine

JVM Version, Operating System and Relevant Context

The bug occurs in when running my project on iOS in a multi-platform (android/iOS) project.
In Android it works as expected

Feedback

I've recently came across this bug Kotlin/kotlinx.serialization#360 . After upgrading both kotlinx-io and kotlinx-coroutines-io to version 0.1.5-dev-4 the issue no long occured when making live requests to server.
But when i use the mock engine, with an content bigger than 4088 chars i got this error:
Invalid JSON at 4088: Unexpected end in string

If my content is smaller than 4088 it works fine.

Here's the code i use to create the MockEngin

val TOPOLOGY_ANSWER = """
  VERY BIG JSON STRING
"""

val httpMockEngine =  MockEngine {
        when (url.toString()) {
            "$baseUrl/${ApiEndpoints.TOPOLOGY}" -> {
                MockHttpResponse(
                    call,
                    HttpStatusCode.OK,                   
                    ByteReadChannel(TOPOLOGY_ANSWER.toByteArray(Charsets.UTF_8)),
                    headersOf("Content-Type" to listOf(ContentType.Application.Json.toString()))
                )
            }
            else -> {
                error("Unhandled $url")
            }
        }

val client: HttpClient = HttpClient(httpMockEngine) {
                install(JsonFeature) {
                    serializer = KotlinxSerializer(Json.nonstrict).apply {
                        setMapper(Topology::class, Topology.serializer())
                    }
                }

Thanks in advance

Is this library active/supported?

I'm very interested in using this library in an upcoming https://libp2p.io/ jvm implementation and I'm wondering what's it's current status. Is it under active development, ready for production or abandoned?

Furthermore, if this is still actively developed/maintained what are it's future plans, is there a roadmap of some sort?

[io-2] Make Buffer an interface and add BufferView

I encountered few places where I need to either partially read or partially write Buffer. For example I read some data read from file with limiting window. I would be easily done if I could open for input only part of the buffer. It would be quite easy to implement if Buffer would be an interface and not an expected class. I think it is a good idea to make it an interface in any case since we probably will want to have multiple buffer implementations for a single platform. It should not affect performance.

Can't Write/Read Int.MIN_VALUE as Bytes

I'm attempting to write an integer as a series, of 4 bytes, and then read it back from a socket. However unfortunately while writing tests for code I seemed to have stumbled across a bug. Mainly the fact I can't seem to write an Integer.MIN_VALUE. I've tried encoding in both BIG_ENDIAN/LITTLE_ENDIAN, and using different methods of encoding however all fail. Here, I've provided the simplest code I could think of to reproduce the error:

import kotlinx.coroutines.experimental.io.ByteReadChannel
import kotlinx.coroutines.experimental.runBlocking
import java.nio.ByteBuffer

fun main(args: Array<String>) {
        val min = Int.MIN_VALUE
        assert(min == -2147483648)
        val brc = ByteReadChannel(ByteBuffer.allocate(4).putInt(min))
        System.out.println(brc.availableForRead)
        val read = runBlocking { brc.readInt() }
        System.out.println(read)
}

Attempting to run this you should see: 0 printed to STDOUT, followed by an exception:

0

kotlinx.coroutines.experimental.channels.ClosedReceiveChannelException: EOF while an int expected
	at kotlinx.coroutines.experimental.io.ByteBufferChannel.readIntSuspend(ByteBufferChannel.kt:754)
	at kotlinx.coroutines.experimental.io.ByteBufferChannel.readInt(ByteBufferChannel.kt:748)
[...]

To be honest I'm not sure if this is an error with ByteReadChannel, or something else entirely. However, if this is the wrong place I'd be happy to file it elsewhere.

Windows HANDLE Input/Output

Not sure if this is the right format.

I recently needed a winapi HANDLE based Input/Output implementation, so I implemented one. I would like make a pull request for it, but I don't know how to integrate windows-specific code into the current project structure.

Unable to compile iOS module with kotlinx-io-native as dependency since the jar is empty

I got the following gradle file where kotlinx_io_version = 0.1.3 and kotlin_version = 1.3.11

plugins {
    id 'kotlin-multiplatform' version '1.3.11'
}

// Android part

kotlin {
    targets {
        fromPreset(presets.android, 'android')

        def buildForDevice = project.findProperty("device")?.toBoolean() ?: false
        def iosPreset = (buildForDevice) ? presets.iosArm64 : presets.iosX64
        fromPreset(iosPreset, 'ios') {
            compilations.main.outputKinds('FRAMEWORK')
        }
    }
    sourceSets {
        commonMain {
            dependencies {
                implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
                implementation "org.jetbrains.kotlinx:kotlinx-io:$kotlinx_io_version"
            }
        }
        commonTest {
            dependencies {
        		implementation 'org.jetbrains.kotlin:kotlin-test-common'
        		implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
            }
        }
        androidMain {
            dependencies {
                implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
                implementation "org.jetbrains.kotlinx:kotlinx-io-jvm:$kotlinx_io_version"
            }
        }
        androidTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test'
                implementation 'org.jetbrains.kotlin:kotlin-test-junit'
            }
        }
        iosMain {
            dependencies {
                implementation "org.jetbrains.kotlinx:kotlinx-io-native:$kotlinx_io_version"
            }
        }
        iosTest {
        }
    }
}

when compiling the iOS module, I got errors from the common module similar to this one:

error: unresolved reference: io
import kotlinx.io.core.ByteReadPacket

Since the kotlinx-io-native jar is empty I also tried without the dependency for the iosMain sourceSet but I got the same errors.
I noticed that the source jar for iOS does have the expected content. I suspect this is packaging issue.

If I remove kotlinx-io dependencies then the iOS module compiles without errors. Am I missing something?

`lookaheadSuspend.consumeEachRemaining` does not await properly on input bytes

The consumeEachRemaining method in the experimental lookaheadSuspend API does not await properly on the input bytes being received. It therefore does not consistently consume the input, and instead may read the input partially or not at all.

The workaround is to loop manually instead of using consumeEachRemaining e.g.:

lookAheadSuspend {
    // consumeEachRemaining does not work for now, use the loop logic from ktor
    // https://github.com/ktorio/ktor/blob/1.0.0/ktor-network/src/io/ktor/network/sockets/CIOWriter.kt#L62
    while (true) {
      val buffer = request(0, 1)
      if (buffer == null) {
        if (!awaitAtLeast(1)) break
      } else {
        val count = buffer.remaining()
        // do something with the buffer here, and then mark the bytes as consumed
        consumed(count)
      }
    }
  }

Build is failing on master (JS name clash)

This is fixed by #1 , I'm not sure if that's the best way, though :)

> Task :kotlinx-io-js:packages
e: /home/jansorg/source/kotlinx-io/src/main/kotlin/kotlinx/io/core/Builder.kt: (25, 1): JavaScript name (BytePacketBuilder) generated for this declaration clashes with another declaration: class BytePacketBuilder : BytePacketBuilderPlatformBase
e: /home/jansorg/source/kotlinx-io/src/main/kotlin/kotlinx/io/core/Builder.kt: (44, 7): JavaScript name (BytePacketBuilder) generated for this declaration clashes with another declaration: fun BytePacketBuilder(): BytePacketBuilder
> Task :kotlinx-io-js:compileKotlin2Js FAILED

Inconsistent Charset error handling in native and JVM

JVM currently replaces all malformed input during decoding while Native silently ignores it.
underflow, overflow, malformed and unmappable flags should be consistent with JVM by default especially in the face of packed-based Input, where some error should be ignored until reading from the next packet of input, and some should be propagated or re-checked on next read, which potentially makes Charset usage error-prone

Random access for IOBuffer or a separate random access structure

We have a rather unusual application for Buffers (not actually IO). We use buffers in mathematical application for high performance direct allocation of objects in memory. For that we need to be able to allocate one or several continuous memory buffers and be able to create a view (read-only or read-write) with given offset and given size. The whole buffer is allocated and released as a whole.

Currently, I am having following ideas:

  1. Introduce random access read-only and read-write structures. I do not think we should keep position from ByteBuffer as a part of buffer because it complicates things. The Buffer obviously won't inherit Input or Output.

  2. Introduce indexed read and write (for mutable version) operations on primitives.

  3. Introduce specifications for read and write of custom objects like it is done in kmath prototype. Those specifications could be used either as contexts for specific operations or passed as parameters for read/write operations on buffers. Those specifications could be used also to create nio-like view buffers.

  4. Introduce buffer windowed views. Meaning a sub-buffer that inherits parent read/write permissions. but could see only limited part of parent buffer. Those could be used for safe operations on buffer.

Further improvement could be achieved by using inline-classes on top of buffer views. If the idea proves to be good, it could later be implemented as a compiler plugin, which will generate specification automatically and allow to create non-boxing arrays.

Question: Implement custom multi-platform InputStream

Hello,

I have asked the question on StackOverflow, but didn't get any response there. So I'll try my luck here.

I’m looking for a multi-platform alternative to input streams. My concrete task is to fetch an encrypted file from a remote server via https and decrypt it on demand.

In Java land I would an implement InputStream which proxies the reads to the input stream from the https library. How can I do the same in kotlin targeting multiple platforms.

I see ktor returns an ByteReadChannel, but I don’t know which functions.

I’m lost and don’t know where to start. Thanks for your help in advance.

EXC_BAD_ACCESS (code=1, address=0x0) in AbstractOutput

Reproducer:

class Repro {

    class NoOpOutput() : AbstractOutput() {

        override fun close(): Unit {
        }

        @Suppress("CANNOT_OVERRIDE_INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
        override fun last(buffer: IoBuffer) {
            buffer.writeDirect { ptr ->
                0
            }
        }

        override fun flush() {
            last(IoBuffer.Empty)
        }
    }


    @Test
    fun foo() {
        writeBytes(ByteArray(128))
    }

    fun writeBytes(bytes: ByteArray): Unit =
        NoOpOutput().use {
            it.writeFully(bytes)
        }
}

Backtrace:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x0000000000000000
    frame #1: 0x00000001000dfc35 test.kexe`kfun:kotlinx.io.core.BytePacketBuilderBase.appendNewBuffer$kotlinx-io(<this>=0x0000000101a00498)kotlinx.io.core.IoBuffer at Builder.kt:695
    frame #2: 0x00000001000ec857 test.kexe`kfun:kotlinx.io.core.BytePacketBuilderBase.writeFully(<this>=0x0000000101a00498, src=0x0000000101a006f8, offset=0, length=128) at Builder.kt:702
    frame #3: 0x00000001000ed20e test.kexe`kfun:[email protected].(<this>=0x0000000101a00498, src=0x0000000101a006f8) at Output.kt:34
    frame #4: 0x0000000100008cf9 test.kexe`kfun:kotlinx.Repro.writeBytes(<this>=0x0000000101a004e8, bytes=0x0000000101a006f8) at Repro.kt:36
    frame #5: 0x0000000100008c27 test.kexe`kfun:kotlinx.Repro.foo(<this>=0x0000000101a004e8) at Repro.kt:28
    frame #6: 0x0000000100008b68 test.kexe`kfun:kotlinx.$Repro$test$0.$foo$FUNCTION_REFERENCE$1.invoke#internal(<this>=0x0000000101900178, p1=0x0000000101a004e8) at Repro.kt:0
    frame #7: 0x00000001000a754c test.kexe`kfun:kotlin.native.internal.test.BaseClassSuite.TestCase.run(<this>=0x0000000101900548) at no source file:1
    frame #8: 0x00000001000a12db test.kexe`kfun:kotlin.native.internal.test.TestRunner.run#internal(<this>=0x0000000101900628, <this>=0x0000000101900ac8) at TestRunner.kt:201
    frame #9: 0x00000001000a08f3 test.kexe`kfun:kotlin.native.internal.test.TestRunner.runIteration#internal(<this>=0x0000000101900628, iteration=1) at TestRunner.kt:226
    frame #10: 0x00000001000a00c3 test.kexe`kfun:kotlin.native.internal.test.TestRunner.run(<this>=0x0000000101900628)ValueType at TestRunner.kt:241
    frame #11: 0x000000010009f1fe test.kexe`kfun:kotlin.native.internal.test.testLauncherEntryPoint(args=0x0000000101900608)ValueType at Launcher.kt:19
    frame #12: 0x00000001000a6172 test.kexe`kfun:kotlin.native.internal.test.main(args=0x0000000101900608) at Launcher.kt:23
    frame #13: 0x00000001000088b6 test.kexe`EntryPointSelector + 6
    frame #14: 0x0000000100008827 test.kexe`Konan_start(args=0x0000000101900608) at start.kt:18
    frame #15: 0x00000001000087a1 test.kexe`Konan_run_start + 113
    frame #16: 0x000000010000871b test.kexe`main + 27
    frame #17: 0x00007fff74bf6015 libdyld.dylib`start + 1
    frame #18: 0x00007fff74bf6015 libdyld.dylib`start + 1

ByteReadPacket Does Not Respect ByteOrder

ShapeTest.tar.gz

Hello. I am loving the work done here to support io-processing in multiplaform. Thank you for your hard work. I have found a bug with ByteReadPacket not respecting byteOrder. I have attached a reproducible example. You can find the functions in shape.shapefile.kt commonMain. The two tests are in jvmTest.

Android task ':transformResourcesWithMergeJavaResForDebug' failure

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':transformResourcesWithMergeJavaResForDebug'.
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:110)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:77)
	at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
	at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
	at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.run(EventFiringTaskExecuter.java:51)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46)
	at org.gradle.execution.taskgraph.LocalTaskInfoExecutor.execute(LocalTaskInfoExecutor.java:42)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:277)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:262)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:135)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:130)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.execute(DefaultTaskPlanExecutor.java:200)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.executeWithWork(DefaultTaskPlanExecutor.java:191)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.run(DefaultTaskPlanExecutor.java:130)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: com.android.builder.merge.DuplicateRelativeFileException: More than one file was found with OS independent path 'META-INF/kotlinx-io.kotlin_module'
	at com.android.builder.merge.StreamMergeAlgorithms.lambda$acceptOnlyOne$2(StreamMergeAlgorithms.java:75)
	at com.android.builder.merge.StreamMergeAlgorithms.lambda$select$3(StreamMergeAlgorithms.java:100)
	at com.android.builder.merge.IncrementalFileMergerOutputs$1.create(IncrementalFileMergerOutputs.java:86)
	at com.android.builder.merge.DelegateIncrementalFileMergerOutput.create(DelegateIncrementalFileMergerOutput.java:61)
	at com.android.build.gradle.internal.transforms.MergeJavaResourcesTransform$1.create(MergeJavaResourcesTransform.java:379)
	at com.android.builder.merge.IncrementalFileMerger.updateChangedFile(IncrementalFileMerger.java:221)
	at com.android.builder.merge.IncrementalFileMerger.mergeChangedInputs(IncrementalFileMerger.java:190)
	at com.android.builder.merge.IncrementalFileMerger.merge(IncrementalFileMerger.java:77)
	at com.android.build.gradle.internal.transforms.MergeJavaResourcesTransform.transform(MergeJavaResourcesTransform.java:411)
	at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:221)
	at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:217)
	at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:102)
	at com.android.build.gradle.internal.pipeline.TransformTask.transform(TransformTask.java:212)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
	at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:50)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:131)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
	at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:120)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:99)
	... 34 more

build.gradle:

buildscript {
    ext.kotlin_version = '1.3.41'
    ext.ktor_version = '1.2.2'
    repositories {
        google()
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven { url "https://jitpack.io" }
    }
}


apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "motorbike.app"
        minSdkVersion 17
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }
    buildToolsVersion '27.0.3'
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:design:26.1.0'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation("io.ktor:ktor-client-android:$ktor_version")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.3.0-RC")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0-RC")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0-RC")
    implementation 'com.github.AndroidDeveloperLB:AutoFitTextView:4'
    testImplementation 'junit:junit:4.12'
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.