Skip to content

Commit

Permalink
Generate types and methods for subscriptions.
Browse files Browse the repository at this point in the history
Subscription calls differ from query and procedure calls in that they
are actually subscriptions to a websocket, not a standard HTTP call. For
this reason, they actually respond with a `Flow<*>`, not just one value.

Part of the actual CBOR implementation in kotlinx-serialization is
adapted here to support byte arrays as byte strings for parameterized
types, like List<ByteArray>.

Kotlin/kotlinx.serialization#2383
  • Loading branch information
christiandeange committed Aug 1, 2023
1 parent 3db1b5c commit 7246af5
Show file tree
Hide file tree
Showing 19 changed files with 1,084 additions and 50 deletions.
5 changes: 4 additions & 1 deletion api-gen-runtime-internal/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ kotlin {
val commonMain by getting {
dependencies {
api(libs.kotlinx.coroutines)
api(libs.kotlinx.serialization.json)
api(libs.kotlinx.serialization.core)
api(libs.ktor.core)

api(project(":api-gen-runtime"))

implementation(libs.kotlinx.serialization.cbor)
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.contentnegotiation)
implementation(libs.ktor.serialization.json)
implementation(libs.ktor.websockets)

implementation(kotlin("reflect"))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*
* Copied until https://github.com/Kotlin/kotlinx.serialization/pull/2383 is merged and productionized.
*/
package sh.christian.ozone.api.cbor

internal class ByteArrayInput(private var array: ByteArray) {
private var position: Int = 0
val availableBytes: Int get() = array.size - position

fun read(): Int {
return if (position < array.size) array[position++].toInt() and 0xFF else -1
}

fun read(b: ByteArray, offset: Int, length: Int): Int {
// avoid int overflow
if (offset < 0 || offset > b.size || length < 0
|| length > b.size - offset
) {
throw IndexOutOfBoundsException()
}
// Are there any bytes available?
if (this.position >= array.size) {
return -1
}
if (length == 0) {
return 0
}

val copied = if (this.array.size - position < length) this.array.size - position else length
array.copyInto(destination = b, destinationOffset = offset, startIndex = position, endIndex = position + copied)
position += copied
return copied
}

fun skip(length: Int) {
position += length
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*
* Copied until https://github.com/Kotlin/kotlinx.serialization/pull/2383 is merged and productionized.
*/
package sh.christian.ozone.api.cbor

internal class ByteArrayOutput {
private var array: ByteArray = ByteArray(32)
private var position: Int = 0

private fun ensureCapacity(elementsToAppend: Int) {
if (position + elementsToAppend <= array.size) {
return
}
val newArray = ByteArray((position + elementsToAppend).takeHighestOneBit() shl 1)
array.copyInto(newArray)
array = newArray
}

fun toByteArray(): ByteArray {
val newArray = ByteArray(position)
array.copyInto(newArray, startIndex = 0, endIndex = this.position)
return newArray
}

fun write(buffer: ByteArray, offset: Int = 0, count: Int = buffer.size) {
// avoid int overflow
if (offset < 0 || offset > buffer.size || count < 0
|| count > buffer.size - offset
) {
throw IndexOutOfBoundsException()
}
if (count == 0) {
return
}

ensureCapacity(count)
buffer.copyInto(
destination = array,
destinationOffset = this.position,
startIndex = offset,
endIndex = offset + count
)
this.position += count
}

fun write(byteValue: Int) {
ensureCapacity(1)
array[position++] = byteValue.toByte()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*
* Copied until https://github.com/Kotlin/kotlinx.serialization/pull/2383 is merged and productionized.
*/
package sh.christian.ozone.api.cbor

import kotlinx.serialization.SerializationException

internal class CborDecodingException(message: String) : SerializationException(message)

internal fun CborDecodingException(expected: String, foundByte: Int) =
CborDecodingException("Expected $expected, but found ${printByte(foundByte)}")

internal fun printByte(b: Int): String {
val hexCode = "0123456789ABCDEF"
return buildString {
append(hexCode[b shr 4 and 0xF])
append(hexCode[b and 0xF])
}
}

0 comments on commit 7246af5

Please sign in to comment.