Protobuf: rewrited ProtoKot runtime library, now CodedStreams use ByteArray as an argument of constructor. Removed exceptions

This commit is contained in:
dsavvinov
2016-08-08 12:36:07 +03:00
parent d004673f80
commit 2af51674ca
7 changed files with 73 additions and 23 deletions
+23 -17
View File
@@ -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
} }
} }
+10 -1
View File
@@ -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)
} }
+16
View File
@@ -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
}
}
+18
View File
@@ -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
}
}
}
+1 -1
View File
@@ -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 {
+5 -4
View File
@@ -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
} }
} }
} }