summaryrefslogtreecommitdiff
path: root/formats/protobuf
diff options
context:
space:
mode:
authorVsevolod Tolstopyatov <qwwdfsad@gmail.com>2020-06-29 05:36:02 -0700
committerGitHub <noreply@github.com>2020-06-29 15:36:02 +0300
commit36014b7293994870a146dbe9a9c7e193747a90cd (patch)
tree368085b14a7470487b6c7663b12c543e179ff0fd /formats/protobuf
parentd8c9fc704d4ca155eadd430f48bc8282168f47fb (diff)
downloadkotlinx.serialization-36014b7293994870a146dbe9a9c7e193747a90cd.tar.gz
[API stabilization] Hide public IO classes, copy them to ProtoBuf and CBOR, remove redundant symbols and make internal in order to reduce public API shape (#872)
Diffstat (limited to 'formats/protobuf')
-rw-r--r--formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoBuf.kt1
-rw-r--r--formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufReader.kt3
-rw-r--r--formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufWriter.kt5
-rw-r--r--formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/Streams.kt220
-rw-r--r--formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/Varint.kt5
5 files changed, 225 insertions, 9 deletions
diff --git a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoBuf.kt b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoBuf.kt
index 2d0ec746..e0c1ae31 100644
--- a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoBuf.kt
+++ b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoBuf.kt
@@ -4,7 +4,6 @@
package kotlinx.serialization.protobuf
-import kotlinx.io.*
import kotlinx.serialization.*
import kotlinx.serialization.CompositeDecoder.Companion.READ_DONE
import kotlinx.serialization.builtins.*
diff --git a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufReader.kt b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufReader.kt
index 7151fdff..2f6c08d9 100644
--- a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufReader.kt
+++ b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufReader.kt
@@ -4,7 +4,6 @@
package kotlinx.serialization.protobuf.internal
-import kotlinx.io.*
import kotlinx.serialization.protobuf.*
import kotlin.jvm.*
@@ -65,7 +64,7 @@ internal class ProtobufReader(private val input: ByteArrayInput) {
return input.readExactNBytes(length)
}
- private fun Input.readExactNBytes(bytesCount: Int): ByteArray {
+ private fun ByteArrayInput.readExactNBytes(bytesCount: Int): ByteArray {
if (bytesCount > availableBytes) {
error("Unexpected EOF, available $availableBytes bytes, requested: $bytesCount")
}
diff --git a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufWriter.kt b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufWriter.kt
index b843f1fe..24ab06f2 100644
--- a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufWriter.kt
+++ b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/ProtobufWriter.kt
@@ -4,7 +4,6 @@
package kotlinx.serialization.protobuf.internal
-import kotlinx.io.*
import kotlinx.serialization.protobuf.*
import kotlin.jvm.*
@@ -68,7 +67,7 @@ internal class ProtobufWriter(@JvmField val out: ByteArrayOutput) {
out.writeInt(value.reverseBytes())
}
- private fun Output.encode32(
+ private fun ByteArrayOutput.encode32(
number: Int,
format: ProtoNumberType = ProtoNumberType.DEFAULT
) {
@@ -79,7 +78,7 @@ internal class ProtobufWriter(@JvmField val out: ByteArrayOutput) {
}
}
- private fun Output.encode64(number: Long, format: ProtoNumberType = ProtoNumberType.DEFAULT) {
+ private fun ByteArrayOutput.encode64(number: Long, format: ProtoNumberType = ProtoNumberType.DEFAULT) {
when (format) {
ProtoNumberType.FIXED -> out.writeLong(number.reverseBytes())
ProtoNumberType.DEFAULT -> encodeVarint64(number)
diff --git a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/Streams.kt b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/Streams.kt
new file mode 100644
index 00000000..9e8d15b0
--- /dev/null
+++ b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/Streams.kt
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.protobuf.internal
+
+import kotlinx.serialization.*
+
+internal class ByteArrayInput(private var array: ByteArray) {
+ private var position: Int = 0
+ public 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 readString(length: Int): String {
+ val result = array.decodeToString(position, position + length)
+ position += length
+ return result
+ }
+
+ fun readVarint32(): Int {
+ if (position == array.size) {
+ error("Unexpected EOF")
+ }
+
+ // Fast-path: unrolled loop for single and two byte values
+ var currentPosition = position
+ var result = array[currentPosition++].toInt()
+ if (result >= 0) {
+ position = currentPosition
+ return result
+ } else if (array.size - position > 1) {
+ result = result xor (array[currentPosition++].toInt() shl 7)
+ if (result < 0) {
+ position = currentPosition
+ return result xor (0.inv() shl 7)
+ }
+ }
+
+ return readVarint32SlowPath()
+ }
+
+ fun readVarint64(eofAllowed: Boolean): Long {
+ if (position == array.size) {
+ if (eofAllowed) return -1
+ else error("Unexpected EOF")
+ }
+
+ // Fast-path: single and two byte values
+ var currentPosition = position
+ var result = array[currentPosition++].toLong()
+ if (result >= 0) {
+ position = currentPosition
+ return result
+ } else if (array.size - position > 1) {
+ result = result xor (array[currentPosition++].toLong() shl 7)
+ if (result < 0) {
+ position = currentPosition
+ return result xor (0L.inv() shl 7)
+ }
+ }
+
+ return readVarint64SlowPath()
+ }
+
+ private fun readVarint64SlowPath(): Long {
+ var result = 0L
+ var shift = 0
+ while (shift != 64) {
+ val byte = read()
+ result = result or ((byte and 0x7F).toLong() shl shift)
+ if (byte and 0x80 == 0) {
+ return result
+ }
+ shift += 7
+ }
+ throw SerializationException("Varint too long: exceeded 64 bits")
+ }
+
+ private fun readVarint32SlowPath(): Int {
+ var result = 0
+ var shift = 0
+ while (shift != 32) {
+ val byte = read()
+ result = result or ((byte and 0x7F) shl shift)
+ if (byte and 0x80 == 0) {
+ return result
+ }
+ shift += 7
+ }
+ throw SerializationException("Varint too long: exceeded 32 bits")
+ }
+}
+
+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
+ }
+
+ public fun size(): Int {
+ return position
+ }
+
+ public 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()
+ }
+
+ fun writeInt(intValue: Int) {
+ ensureCapacity(4)
+ for (i in 3 downTo 0) {
+ array[position++] = (intValue shr i * 8).toByte()
+ }
+ }
+
+ fun writeLong(longValue: Long) {
+ ensureCapacity(8)
+ for (i in 7 downTo 0) {
+ array[position++] = (longValue shr i * 8).toByte()
+ }
+ }
+
+ fun encodeVarint32(value: Int) {
+ ensureCapacity(5)
+ // Fast-path: unrolled loop for single byte
+ if (value and 0x7F.inv() == 0) {
+ array[position++] = value.toByte()
+ return
+ }
+ // Fast-path: unrolled loop for two bytes
+ var current = value
+ array[position++] = (current or 0x80).toByte()
+ current = current ushr 7
+ if (value and 0x7F.inv() == 0) {
+ array[position++] = value.toByte()
+ return
+ }
+ encodeVarint32SlowPath(current)
+ }
+
+ private fun encodeVarint32SlowPath(value: Int) {
+ var current = value
+ while (current and 0x7F.inv() != 0) {
+ array[position++] = ((current and 0x7F) or 0x80).toByte()
+ current = current ushr 7
+ }
+ array[position++] = (current and 0x7F).toByte()
+ }
+
+ fun encodeVarint64(value: Long) {
+ ensureCapacity(10)
+ var currentValue = value
+ while (true) {
+ if (currentValue and 0x7F.inv() == 0L) {
+ array[position++] = currentValue.toByte()
+ return
+ }
+ array[position++] = (currentValue.toInt() and 0x7F or 0x80).toByte()
+ currentValue = currentValue ushr 7
+ }
+ }
+}
diff --git a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/Varint.kt b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/Varint.kt
index 74edf39e..42300d32 100644
--- a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/Varint.kt
+++ b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/internal/Varint.kt
@@ -4,7 +4,6 @@
package kotlinx.serialization.protobuf.internal
-import kotlinx.io.*
import kotlin.jvm.*
/**
@@ -13,7 +12,7 @@ import kotlin.jvm.*
*/
internal object Varint {
@JvmStatic
- internal fun decodeSignedVarintInt(input: Input): Int {
+ internal fun decodeSignedVarintInt(input: ByteArrayInput): Int {
val raw = input.readVarint32()
val temp = raw shl 31 shr 31 xor raw shr 1
// This extra step lets us deal with the largest signed values by treating
@@ -23,7 +22,7 @@ internal object Varint {
}
@JvmStatic
- internal fun decodeSignedVarintLong(input: Input): Long {
+ internal fun decodeSignedVarintLong(input: ByteArrayInput): Long {
val raw = input.readVarint64(false)
val temp = raw shl 63 shr 63 xor raw shr 1
// This extra step lets us deal with the largest signed values by treating