Protobuf: rewrited ProtoKot runtime library, now CodedStreams use ByteArray as an argument of constructor. Removed exceptions
This commit is contained in:
Binary file not shown.
@@ -15,10 +15,11 @@ import WireFormat.VARINT_UTIL_BIT_MASK
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: refactor correctness checks into readTag
|
// TODO: refactor correctness checks into readTag
|
||||||
class CodedInputStream(input: java.io.InputStream) {
|
class CodedInputStream(buffer: ByteArray) {
|
||||||
val bufferedInput: java.io.BufferedInputStream
|
var errorMessage: String = ""
|
||||||
|
val inputStream: KotlinInputStream
|
||||||
init {
|
init {
|
||||||
bufferedInput = java.io.BufferedInputStream(input) // TODO: Java's realization uses hand-written buffers. Why?
|
inputStream = KotlinInputStream(buffer) // TODO: Java's realization uses hand-written buffers. Why?
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readInt32(expectedFieldNumber: Int): Int {
|
fun readInt32(expectedFieldNumber: Int): Int {
|
||||||
@@ -66,7 +67,10 @@ class CodedInputStream(input: java.io.InputStream) {
|
|||||||
val boolValue = when (readValue) {
|
val boolValue = when (readValue) {
|
||||||
0 -> false
|
0 -> false
|
||||||
1 -> true
|
1 -> true
|
||||||
else -> throw InvalidProtocolBufferException("Expected boolean-encoding (1 or 0), got $readValue")
|
else -> {
|
||||||
|
errorMessage = "Expected boolean-encoding (1 or 0), got $readValue"
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return boolValue
|
return boolValue
|
||||||
}
|
}
|
||||||
@@ -181,14 +185,18 @@ class CodedInputStream(input: java.io.InputStream) {
|
|||||||
expectedWireType: WireType,
|
expectedWireType: WireType,
|
||||||
actualWireType: WireType) {
|
actualWireType: WireType) {
|
||||||
if (expectedFieldNumber != actualFieldNumber) {
|
if (expectedFieldNumber != actualFieldNumber) {
|
||||||
throw InvalidProtocolBufferException(
|
errorMessage =
|
||||||
"Error in protocol format: \n " +
|
"Error in protocol format: \n " +
|
||||||
"Expected field number ${expectedFieldNumber}, got ${actualFieldNumber}")
|
"Expected field number ${expectedFieldNumber}, got ${actualFieldNumber}"
|
||||||
|
println(errorMessage)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expectedWireType != actualWireType) {
|
if (expectedWireType != actualWireType) {
|
||||||
throw InvalidProtocolBufferException("Error in protocol format: \n " +
|
errorMessage = "Error in protocol format: \n " +
|
||||||
"Expected ${expectedWireType.name} type, got ${actualWireType.name}")
|
"Expected ${expectedWireType.name} type, got ${actualWireType.name}"
|
||||||
|
println(errorMessage)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +227,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
|||||||
fun readRawBytes(count: Int): ByteArray {
|
fun readRawBytes(count: Int): ByteArray {
|
||||||
val ba = ByteArray(count)
|
val ba = ByteArray(count)
|
||||||
for (i in 0..(count - 1)) {
|
for (i in 0..(count - 1)) {
|
||||||
ba[i] = bufferedInput.read().toByte()
|
ba[i] = inputStream.read().toByte()
|
||||||
}
|
}
|
||||||
return ba
|
return ba
|
||||||
}
|
}
|
||||||
@@ -231,7 +239,8 @@ class CodedInputStream(input: java.io.InputStream) {
|
|||||||
}
|
}
|
||||||
val tag = readInt32NoTag()
|
val tag = readInt32NoTag()
|
||||||
if (tag == 0) { // if we somehow had read 0-tag, then message is corrupted
|
if (tag == 0) { // if we somehow had read 0-tag, then message is corrupted
|
||||||
throw InvalidProtocolBufferException("Invalid tag 0")
|
errorMessage = "Invalid tag 0"
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
val actualFieldNumber = WireFormat.getTagFieldNumber(tag)
|
||||||
@@ -246,7 +255,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
|||||||
var result: Int = 0
|
var result: Int = 0
|
||||||
var step: Int = 0
|
var step: Int = 0
|
||||||
while (!done) {
|
while (!done) {
|
||||||
val byte: Int = bufferedInput.read()
|
val byte: Int = inputStream.read().toInt()
|
||||||
result = result or
|
result = result or
|
||||||
(
|
(
|
||||||
(byte and VARINT_INFO_BITS_MASK)
|
(byte and VARINT_INFO_BITS_MASK)
|
||||||
@@ -267,7 +276,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
|||||||
var result: Long = 0
|
var result: Long = 0
|
||||||
var step: Int = 0
|
var step: Int = 0
|
||||||
while (!done) {
|
while (!done) {
|
||||||
val byte: Int = bufferedInput.read()
|
val byte: Int = inputStream.read().toInt()
|
||||||
result = result or
|
result = result or
|
||||||
(
|
(
|
||||||
(byte and VARINT_INFO_BITS_MASK).toLong()
|
(byte and VARINT_INFO_BITS_MASK).toLong()
|
||||||
@@ -275,7 +284,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
|||||||
(VARINT_INFO_BITS_COUNT * step)
|
(VARINT_INFO_BITS_COUNT * step)
|
||||||
)
|
)
|
||||||
step++
|
step++
|
||||||
if ((byte and VARINT_UTIL_BIT_MASK) == 0 || byte == -1) {
|
if ((byte and VARINT_UTIL_BIT_MASK) == 0 /* || byte == -1 ???? */) {
|
||||||
done = true
|
done = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,10 +305,7 @@ class CodedInputStream(input: java.io.InputStream) {
|
|||||||
|
|
||||||
// checks if at least one more byte can be read from underlying input stream
|
// checks if at least one more byte can be read from underlying input stream
|
||||||
fun isAtEnd(): Boolean {
|
fun isAtEnd(): Boolean {
|
||||||
bufferedInput.mark(1)
|
return inputStream.isAtEnd()
|
||||||
val byte = bufferedInput.read()
|
|
||||||
bufferedInput.reset()
|
|
||||||
return byte == -1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,13 @@ import WireFormat.VARINT_UTIL_BIT_MASK
|
|||||||
* Created by user on 7/6/16.
|
* Created by user on 7/6/16.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CodedOutputStream(val output: java.io.OutputStream) {
|
class CodedOutputStream(val buffer: ByteArray) {
|
||||||
|
val output = KotlinOutputStream(buffer)
|
||||||
|
|
||||||
|
fun toByteArray(): ByteArray {
|
||||||
|
return buffer
|
||||||
|
}
|
||||||
|
|
||||||
fun writeTag(fieldNumber: Int, type: WireType) {
|
fun writeTag(fieldNumber: Int, type: WireType) {
|
||||||
val tag = (fieldNumber shl 3) or type.ordinal
|
val tag = (fieldNumber shl 3) or type.ordinal
|
||||||
writeInt32NoTag(tag)
|
writeInt32NoTag(tag)
|
||||||
@@ -156,6 +162,9 @@ class CodedOutputStream(val output: java.io.OutputStream) {
|
|||||||
|
|
||||||
fun writeBytes(fieldNumber: Int, value: ByteArray?) {
|
fun writeBytes(fieldNumber: Int, value: ByteArray?) {
|
||||||
value ?: return
|
value ?: return
|
||||||
|
if (value.size == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
writeTag(fieldNumber, WireType.LENGTH_DELIMITED)
|
writeTag(fieldNumber, WireType.LENGTH_DELIMITED)
|
||||||
writeBytesNoTag(value)
|
writeBytesNoTag(value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Created by user on 8/8/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class KotlinInputStream(val buffer: ByteArray) {
|
||||||
|
var pos = 0
|
||||||
|
|
||||||
|
fun read(): Byte {
|
||||||
|
pos += 1
|
||||||
|
return buffer[pos - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isAtEnd(): Boolean {
|
||||||
|
return pos >= buffer.size
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Created by user on 8/8/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class KotlinOutputStream(val buffer: ByteArray) {
|
||||||
|
var pos = 0
|
||||||
|
|
||||||
|
fun write (data: ByteArray) {
|
||||||
|
write(data, 0, data.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun write (data: ByteArray, begin: Int, size: Int) {
|
||||||
|
for (i in begin..(begin + size - 1)) {
|
||||||
|
buffer[pos] = data[i]
|
||||||
|
pos += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ object WireFormat {
|
|||||||
val FIXED_64_BYTE_SIZE: Int = 8
|
val FIXED_64_BYTE_SIZE: Int = 8
|
||||||
|
|
||||||
fun getTagWireType(tag: Int): WireType {
|
fun getTagWireType(tag: Int): WireType {
|
||||||
return WireType from (tag and TAG_TYPE_MASK).toByte()
|
return WireType.from ( (tag and TAG_TYPE_MASK).toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTagFieldNumber(tag: Int): Int {
|
fun getTagFieldNumber(tag: Int): Int {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Created by Dmitry Savvinov on 7/6/16.
|
* Created by Dmitry Savvinov on 7/6/16.
|
||||||
* Enum for possible WireTypes.
|
* Enum for possible WireTypes.
|
||||||
* See details at [official Google reference]()https://developers.google.com/protocol-buffers/docs/encoding#structure)
|
* See details at [official Google reference](https://developers.google.com/protocol-buffers/docs/encoding#structure)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum class WireType(val id: Int) {
|
enum class WireType(val id: Int) {
|
||||||
@@ -10,10 +10,11 @@ enum class WireType(val id: Int) {
|
|||||||
LENGTH_DELIMITED(2), // string, bytes, embedded messages, packed repeated fields
|
LENGTH_DELIMITED(2), // string, bytes, embedded messages, packed repeated fields
|
||||||
START_GROUP(3), // groups (deprecated)
|
START_GROUP(3), // groups (deprecated)
|
||||||
END_GROUP(4), // groups (deprecated)
|
END_GROUP(4), // groups (deprecated)
|
||||||
FIX_32(5); // fixed32, sfixed32, float
|
FIX_32(5), // fixed32, sfixed32, float
|
||||||
|
UNDEFINED(6); // indicates error when parsing from Int
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
infix fun from (value: Byte): WireType {
|
fun from (value: Byte): WireType {
|
||||||
return when (value) {
|
return when (value) {
|
||||||
0.toByte() -> VARINT
|
0.toByte() -> VARINT
|
||||||
1.toByte() -> FIX_64
|
1.toByte() -> FIX_64
|
||||||
@@ -21,7 +22,7 @@ enum class WireType(val id: Int) {
|
|||||||
3.toByte() -> START_GROUP
|
3.toByte() -> START_GROUP
|
||||||
4.toByte() -> END_GROUP
|
4.toByte() -> END_GROUP
|
||||||
5.toByte() -> FIX_32
|
5.toByte() -> FIX_32
|
||||||
else -> throw IllegalArgumentException()
|
else -> UNDEFINED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user