diff --git a/proto/compiler/.gitignore b/proto/compiler/.gitignore
new file mode 100644
index 00000000000..5b4bbf65181
--- /dev/null
+++ b/proto/compiler/.gitignore
@@ -0,0 +1,21 @@
+.DS_Store
+.idea/shelf
+/dependencies
+/dist
+out
+tmp
+workspace.xml
+*.versionsBackup
+
+.gradle
+/build/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+# Cache of project
+.gradletasknamecache
+
diff --git a/proto/compiler/.idea/compiler.iml b/proto/compiler/.idea/compiler.iml
new file mode 100644
index 00000000000..d6ebd480598
--- /dev/null
+++ b/proto/compiler/.idea/compiler.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/proto/compiler/.idea/compiler.xml b/proto/compiler/.idea/compiler.xml
new file mode 100644
index 00000000000..96cc43efa6a
--- /dev/null
+++ b/proto/compiler/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/proto/compiler/.idea/copyright/profiles_settings.xml b/proto/compiler/.idea/copyright/profiles_settings.xml
new file mode 100644
index 00000000000..e7bedf3377d
--- /dev/null
+++ b/proto/compiler/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/proto/compiler/.idea/misc.xml b/proto/compiler/.idea/misc.xml
new file mode 100644
index 00000000000..880e17b132c
--- /dev/null
+++ b/proto/compiler/.idea/misc.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/proto/compiler/.idea/modules.xml b/proto/compiler/.idea/modules.xml
new file mode 100644
index 00000000000..b67420d2e33
--- /dev/null
+++ b/proto/compiler/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/proto/compiler/lib/kotlin-reflect.jar b/proto/compiler/lib/kotlin-reflect.jar
new file mode 100644
index 00000000000..62340e2dae4
Binary files /dev/null and b/proto/compiler/lib/kotlin-reflect.jar differ
diff --git a/proto/compiler/lib/kotlin-runtime-sources.jar b/proto/compiler/lib/kotlin-runtime-sources.jar
new file mode 100644
index 00000000000..e661b30034a
Binary files /dev/null and b/proto/compiler/lib/kotlin-runtime-sources.jar differ
diff --git a/proto/compiler/lib/kotlin-runtime.jar b/proto/compiler/lib/kotlin-runtime.jar
new file mode 100644
index 00000000000..4d7a92703f8
Binary files /dev/null and b/proto/compiler/lib/kotlin-runtime.jar differ
diff --git a/proto/compiler/protobuf_draft.iml b/proto/compiler/protobuf_draft.iml
new file mode 100644
index 00000000000..7fa3b1b2717
--- /dev/null
+++ b/proto/compiler/protobuf_draft.iml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/proto/compiler/src/CodedInputStream.kt b/proto/compiler/src/CodedInputStream.kt
new file mode 100644
index 00000000000..a63b8f5012f
--- /dev/null
+++ b/proto/compiler/src/CodedInputStream.kt
@@ -0,0 +1,234 @@
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+
+/**
+ * Created by Dmitry Savvinov on 7/6/16.
+ *
+ * Hides details of work with Protobuf encoding
+ *
+ * Note that CodedInputStream reads protobuf-defined types from stream (such as int32, sint32, etc),
+ * while CodedOutputStream has methods for writing Kotlin-types (such as Boolean, Int, Long, Short, etc)
+ *
+ */
+
+// TODO: decide, if we want to optimize for performance (then we have to deal with spaghetti-code)
+class CodedInputStream(input: java.io.InputStream) {
+
+ data class Field (val fieldNumber: Int, val wireType: WireType, val value: ValueType) // TODO: think about variance
+
+ val bufferedInput: java.io.BufferedInputStream
+ init {
+ bufferedInput = java.io.BufferedInputStream(input) // TODO: Java's realization uses hand-written buffers. Why?
+ }
+
+ fun readInt32(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.VARINT)
+ throw InvalidProtocolBufferException("Expected Varint tag, got ${wireType.name}")
+ val value = readRawVarint32()
+ return Field(fieldNumber, wireType, value)
+ }
+
+ // Note that unsigned integer types are stored as their signed counterparts with top bit
+ // simply stored in the sign bit - similar to Java's protobuf implementation. Hence, all
+ // methods, reading unsigned ints simply redirect call to corresponding signed-reading method
+ fun readUInt32(): Field {
+ return readInt32()
+ }
+
+ fun readInt64(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.VARINT)
+ throw InvalidProtocolBufferException("Expected Varint tag, got ${wireType.name}")
+ val value = readRawVarint64()
+ return Field(fieldNumber, wireType, value)
+ }
+
+ // See note on unsigned integers implementations above
+ fun readUInt64(): Field {
+ return readUInt64()
+ }
+
+ fun readBool(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.VARINT)
+ throw InvalidProtocolBufferException("Expected Varint tag, got ${wireType.name}")
+
+ val readValue = readRawVarint32()
+ val boolValue = when (readValue) {
+ 0 -> false
+ 1 -> true
+ else -> throw InvalidProtocolBufferException("Expected boolean-encoding (1 or 0), got $readValue")
+ }
+
+ return Field(fieldNumber, wireType, boolValue)
+ }
+
+ // Reading enums is like reading one int32 number. Caller is responsible for converting this ordinal to enum-object
+ fun readEnum(): Field {
+ return readInt32()
+ }
+
+ fun readSInt32(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.VARINT)
+ throw InvalidProtocolBufferException("Expected Varint tag, got ${wireType.name}")
+ val value = readZigZag32()
+ return Field(fieldNumber, wireType, value)
+ }
+
+ fun readSInt64(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.VARINT)
+ throw InvalidProtocolBufferException("Expected Varint tag, got ${wireType.name}")
+ val value = readZigZag64()
+ return Field(fieldNumber, wireType, value)
+ }
+
+ fun readFixed32(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.FIX_32)
+ throw InvalidProtocolBufferException("Expected FIX_32 tag, got ${wireType.name}")
+ val value = readLittleEndianInt()
+ return Field(fieldNumber, wireType, value)
+ }
+
+ fun readSFixed32(): Field {
+ return readFixed32()
+ }
+
+ fun readFixed64(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.FIX_64)
+ throw InvalidProtocolBufferException("Expected FIX_64 tag, got ${wireType.name}")
+ val value = readLittleEndianLong()
+ return Field(fieldNumber, wireType, value)
+ }
+
+ fun readSFixed64(): Field {
+ return readFixed64()
+ }
+
+ fun readDouble(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.FIX_64)
+ throw InvalidProtocolBufferException("Expected FIX_64 tag, got ${wireType.name}")
+ val value = readLittleEndianDouble()
+ return Field(fieldNumber, wireType, value)
+ }
+
+ fun readFloat(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.FIX_32)
+ throw InvalidProtocolBufferException("Expected FIX_64 tag, got ${wireType.name}")
+ val value = readLittleEndianFloat()
+ return Field(fieldNumber, wireType, value)
+ }
+
+ fun readString(): Field {
+ val (fieldNumber, wireType) = readAndParseTag()
+ if (wireType != WireType.LENGTH_DELIMITED)
+ throw InvalidProtocolBufferException("Expected LENGTH_DELMITED tag, got ${wireType.name}")
+ val length = readRawVarint32()
+ val value = String(readRawBytes(length))
+ return Field(fieldNumber, wireType, value)
+ }
+
+ // ============ private methods ==================
+
+ private fun readLittleEndianDouble(): Double {
+ val byteBuffer = ByteBuffer.wrap(readRawBytes(8))
+ byteBuffer.order(ByteOrder.LITTLE_ENDIAN)
+ return byteBuffer.getDouble(0)
+ }
+
+ private fun readLittleEndianFloat(): Float {
+ val byteBuffer = ByteBuffer.wrap(readRawBytes(4))
+ byteBuffer.order(ByteOrder.LITTLE_ENDIAN)
+ return byteBuffer.getFloat(0)
+ }
+
+ private fun readLittleEndianInt(): Int {
+ val byteBuffer = ByteBuffer.wrap(readRawBytes(8))
+ byteBuffer.order(ByteOrder.LITTLE_ENDIAN)
+ return byteBuffer.getInt(0)
+ }
+
+ private fun readLittleEndianLong(): Long {
+ val byteBuffer = ByteBuffer.wrap(readRawBytes(4))
+ byteBuffer.order(ByteOrder.LITTLE_ENDIAN)
+ return byteBuffer.getLong(0)
+ }
+
+ private fun readRawBytes(count: Int): ByteArray {
+ val ba = ByteArray(count)
+ for (i in 0..(count - 1)) {
+ ba[i] = bufferedInput.read().toByte()
+ }
+ return ba
+ }
+
+ private fun readTag(): Int {
+ if (isAtEnd()) {
+ return 0 // we can safely return 0 as sign of end of message, because 0-tags are illegal
+ }
+ val tag = readRawVarint32()
+ if (tag == 0) { // if we somehow read 0-tag, then message is corrupted
+ throw InvalidProtocolBufferException("Invalid tag 0")
+ }
+ return tag
+ }
+
+ private fun readAndParseTag(): Pair {
+ val tag = readTag()
+ return Pair(WireFormat.getTagFieldNumber(tag), WireFormat.getTagWireType(tag))
+ }
+
+ private fun readRawVarint32(): Int {
+ var done: Boolean = false
+ var result: Int = 0
+ var step: Int = 0
+ while (!done) {
+ val byte: Int = bufferedInput.read()
+ result = result or ((byte and 127) shl (7 * step))
+ step++
+ if ((byte and 128) == 0) {
+ done = true
+ }
+ }
+ return result
+ }
+
+ private fun readRawVarint64(): Long {
+ var done: Boolean = false
+ var result: Long = 0
+ var step: Int = 0
+ while (!done) {
+ val byte: Int = bufferedInput.read()
+ result = result or ((byte and 127).toLong() shl (7 * step))
+ step++
+ if ((byte and 128) == 0 || byte == -1) {
+ done = true
+ }
+ }
+ return result
+ }
+
+ private fun readZigZag32(): Int {
+ val value = readRawVarint32()
+ return (value shr 1) xor (-(value and 1))
+ }
+
+ private fun readZigZag64(): Long {
+ val value = readRawVarint64()
+ return (value shr 1) xor (-(value and 1L))
+ }
+
+ private fun isAtEnd(): Boolean {
+ bufferedInput.mark(1)
+ val byte = bufferedInput.read()
+ bufferedInput.reset()
+ return byte == -1
+ }
+}
+
diff --git a/proto/compiler/src/CodedOutputStream.kt b/proto/compiler/src/CodedOutputStream.kt
new file mode 100644
index 00000000000..04a1fdd3bcd
--- /dev/null
+++ b/proto/compiler/src/CodedOutputStream.kt
@@ -0,0 +1,149 @@
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+
+/**
+ * Created by user on 7/6/16.
+ */
+
+class CodedOutputStream(val output: java.io.OutputStream) {
+ fun writeTag(fieldNumber: Int, type: WireType) {
+ val tag = (fieldNumber shl 3) or type.ordinal
+ writeVarint32(tag)
+ }
+
+ fun writeInt32(fieldNumber: Int, value: Int) {
+ writeTag(fieldNumber, WireType.VARINT)
+ writeVarint32(value)
+ }
+
+ // Note that unsigned integer types are stored as their signed counterparts with top bit
+ // simply stored in the sign bit - similar to Java's protobuf implementation. Hence, all
+ // methods, writing unsigned ints simply redirect call to corresponding signed-writing method
+ fun writeUInt32(fieldNumber: Int, value: Int) {
+ writeInt32(fieldNumber, value)
+ }
+
+ fun writeInt64(fieldNumber: Int, value: Long) {
+ writeTag(fieldNumber, WireType.VARINT)
+ writeVarint64(value)
+ }
+
+ // See notes on unsigned integers implementation above
+ fun writeUIn64(fieldNumber: Int, value: Long) {
+ writeInt64(fieldNumber, value)
+ }
+
+ fun writeBool(fieldNumber: Int, value: Boolean) {
+ writeInt32(fieldNumber, if (value) 1 else 0)
+ }
+
+ // Writing enums is like writing one int32 number. Caller is responsible for converting enum-object to ordinal
+ fun writeEnum(fieldNumber: Int, value: Int) {
+ writeInt32(fieldNumber, value)
+ }
+
+ fun writeSInt32(fieldNumber: Int, value: Int) {
+ writeInt32(fieldNumber, (value shl 1) xor (value shr 31))
+ }
+
+ fun writeSInt64(fieldNumber: Int, value: Long) {
+ writeInt64(fieldNumber, (value shl 1) xor (value shr 31))
+ }
+
+ fun writeFixed32(fieldNumber: Int, value: Int) {
+ writeTag(fieldNumber, WireType.FIX_32)
+ writeLittleEndian(value)
+ }
+
+ // See notes on unsigned integers implementation above
+ fun writeSFixed32(fieldNumber: Int, value: Int) {
+ writeFixed32(fieldNumber, value)
+ }
+
+ fun writeFixed64(fieldNumber: Int, value: Long) {
+ writeTag(fieldNumber, WireType.FIX_64)
+ writeLittleEndian(value)
+ }
+
+ // See notes on unsigned integers implementation above
+ fun writeSFixed64(fieldNumber: Int, value: Long) {
+ writeFixed64(fieldNumber, value)
+ }
+
+ fun writeDouble(fieldNumber: Int, value: Double) {
+ writeTag(fieldNumber, WireType.FIX_64)
+ writeLittleEndian(value)
+ }
+
+ fun writeFloat(fieldNumber: Int, value: Float) {
+ writeTag(fieldNumber, WireType.FIX_32)
+ writeLittleEndian(value)
+ }
+
+ fun writeString(fieldNumber: Int, value: String) {
+ writeTag(fieldNumber, WireType.LENGTH_DELIMITED)
+ writeVarint32(value.length)
+ output.write(value.toByteArray())
+ }
+
+ fun writeLittleEndian(value: Int) {
+ val bb = ByteBuffer.allocate(4)
+ bb.order(ByteOrder.LITTLE_ENDIAN)
+ bb.putInt(value)
+ output.write(bb.array())
+ }
+
+ fun writeLittleEndian(value: Long) {
+ val bb = ByteBuffer.allocate(8)
+ bb.order(ByteOrder.LITTLE_ENDIAN)
+ bb.putLong(value)
+ output.write(bb.array())
+ }
+
+ fun writeLittleEndian(value: Double) {
+ val bb = ByteBuffer.allocate(8)
+ bb.order(ByteOrder.LITTLE_ENDIAN)
+ bb.putDouble(value)
+ output.write(bb.array())
+ }
+
+ fun writeLittleEndian(value: Float) {
+ val bb = ByteBuffer.allocate(4)
+ bb.order(ByteOrder.LITTLE_ENDIAN)
+ bb.putFloat(value)
+ output.write(bb.array())
+ }
+
+ fun writeVarint32(value: Int) {
+ var curValue = value
+ val res = ByteArray(5)
+ var resSize = 0
+ do {
+ var curByte = (curValue and 127)
+ curValue = curValue ushr 7
+ if (curValue != 0) {
+ curByte = curByte or 128
+ }
+ res[resSize] = curByte.toByte()
+ resSize++
+ } while(curValue != 0)
+ output.write(res, 0, resSize)
+ }
+
+ fun writeVarint64(value: Long) {
+ var curValue = value
+ val res = ByteArray(10) // we reserve 10 bytes for the cases when value was negative int32/int64
+ var resSize = 0
+ while(curValue != 0L) {
+ var curByte = (curValue and 127L)
+ curValue = curValue ushr 7
+ if (curValue != 0L) {
+ curByte = curByte or 128L
+ }
+
+ res[resSize] = curByte.toByte()
+ resSize++
+ }
+ output.write(res, 0, resSize)
+ }
+}
diff --git a/proto/compiler/src/InvalidProtocolBufferException.kt b/proto/compiler/src/InvalidProtocolBufferException.kt
new file mode 100644
index 00000000000..91f59d8a91e
--- /dev/null
+++ b/proto/compiler/src/InvalidProtocolBufferException.kt
@@ -0,0 +1,10 @@
+/**
+ * Created by user on 7/7/16.
+ */
+
+class InvalidProtocolBufferException(
+ override val message: String? = null,
+ override val cause : Throwable? = null
+ ) : Throwable(message, cause) {
+
+}
\ No newline at end of file
diff --git a/proto/compiler/src/Message.kt b/proto/compiler/src/Message.kt
new file mode 100644
index 00000000000..0cb812de2db
--- /dev/null
+++ b/proto/compiler/src/Message.kt
@@ -0,0 +1,15 @@
+/**
+ * Created by user on 7/8/16.
+ */
+
+interface Message {
+ fun writeTo(output: CodedOutputStream)
+ fun readFrom(input: CodedInputStream) : Message
+ fun getBuilder() : Builder
+
+ //TODO: think about something similar to static method getDefaultInstance()
+
+ interface Builder {
+ fun build(): Message
+ }
+}
diff --git a/proto/compiler/src/PersonMessage.kt b/proto/compiler/src/PersonMessage.kt
new file mode 100644
index 00000000000..01fd498807c
--- /dev/null
+++ b/proto/compiler/src/PersonMessage.kt
@@ -0,0 +1,48 @@
+/**
+ * Created by user on 7/8/16.
+ */
+
+// We don't use Message interface for a moment because of LLVM-translator restrictions
+class PersonMessage(val name: String, val id: Long, val hasCat: Boolean) // : Message
+{
+ fun writeTo(output: CodedOutputStream) {
+ output.writeString(1, name)
+ output.writeInt64(2, id)
+ output.writeBool(3, hasCat)
+ }
+
+ fun readFrom(input: CodedInputStream) : PersonMessage {
+ val newName = input.readString().value
+ val newId = input.readInt64().value
+ val newHasCatFlag = input.readBool().value
+ return PersonMessage(newName, newId, newHasCatFlag)
+ }
+
+ fun getBuilder(): PersonBuilder {
+ return PersonBuilder()
+ }
+
+ // No interface, see above
+ class PersonBuilder { // : Message.Builder
+ // TODO: think how can we
+ var name_: String = ""
+ var id_: Long = 0
+ var hasCat_: Boolean = false
+
+ fun setName(name: String) {
+ name_ = name
+ }
+
+ fun setId(id: Long) {
+ id_ = id
+ }
+
+ fun setHasCat(hasCat: Boolean) {
+ hasCat_ = hasCat
+ }
+
+ fun build(): PersonMessage {
+ return PersonMessage(name_, id_, hasCat_) // Java implementation caches such instances
+ }
+ }
+}
\ No newline at end of file
diff --git a/proto/compiler/src/TestMessages.kt b/proto/compiler/src/TestMessages.kt
new file mode 100644
index 00000000000..d148ece15a1
--- /dev/null
+++ b/proto/compiler/src/TestMessages.kt
@@ -0,0 +1,24 @@
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+
+/**
+ * Created by user on 7/8/16.
+ */
+
+fun testMessageSerialization() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ val msg = PersonMessage(name = "John Doe", id = 42, hasCat = true)
+ msg.writeTo(outs)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ val readMsg = PersonMessage("", 0, false)
+ readMsg.readFrom(ins)
+
+ assert(msg == readMsg)
+}
+
+fun main(args: Array) {
+ testMessageSerialization()
+ println("OK")
+}
diff --git a/proto/compiler/src/TestStreams.kt b/proto/compiler/src/TestStreams.kt
new file mode 100644
index 00000000000..d0b315fe85d
--- /dev/null
+++ b/proto/compiler/src/TestStreams.kt
@@ -0,0 +1,159 @@
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+
+/**
+ * Created by user on 7/7/16.
+ */
+
+fun testTrivialPositiveVarInts() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeInt32(1, 42)
+ outs.writeInt32(16, 1)
+ outs.writeInt32(2, -2)
+ outs.writeInt32(3, -21321)
+ outs.writeInt64(5, 42L)
+ outs.writeInt64(6, 1232132131212321L)
+ outs.writeInt64(7, -2)
+ outs.writeInt64(8, -21321L)
+ outs.writeInt64(9, -32132132132131L)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(1, 42, ins.readInt32())
+ assertSuccessfulRead(42, 1, ins.readInt32())
+ assertSuccessfulRead(2, -2, ins.readInt32())
+ assertSuccessfulRead(3, -21321, ins.readInt32())
+ assertSuccessfulRead(5, 42L, ins.readInt64())
+ assertSuccessfulRead(6, 1232132131212321L, ins.readInt64())
+ assertSuccessfulRead(7, -2, ins.readInt64())
+ assertSuccessfulRead(8, -21321L, ins.readInt64())
+ assertSuccessfulRead(9, -32132132132131L, ins.readInt64())
+}
+
+
+fun testMinPossibleVarInts() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeInt32(1, Int.MIN_VALUE)
+ outs.writeInt64(2, Long.MIN_VALUE)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(1, Int.MIN_VALUE, ins.readInt32())
+ assertSuccessfulRead(2, Long.MIN_VALUE, ins.readInt64())
+}
+
+fun testMaxPossibleVarInts() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeInt32(1, Int.MAX_VALUE)
+ outs.writeInt64(2, Long.MAX_VALUE)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(1, Int.MAX_VALUE, ins.readInt32())
+ assertSuccessfulRead(2, Long.MAX_VALUE, ins.readInt64())
+}
+
+fun testMaxPossibleFieldNumber() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeInt64(536870911, Long.MAX_VALUE)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(536870911, Long.MAX_VALUE, ins.readInt64())
+}
+
+fun testZigZag32() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeSInt32(5, -213123)
+ outs.writeSInt32(1, 3123123)
+ outs.writeSInt32(4, -12345675)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(5, -213123, ins.readSInt32())
+ assertSuccessfulRead(1, 3123123, ins.readSInt32())
+ assertSuccessfulRead(4, -12345675, ins.readSInt32())
+}
+
+fun testZigZag64() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeSInt64(5, -213123L)
+ outs.writeSInt64(1, 3123123L)
+ outs.writeSInt64(4, -12345675L)
+ outs.writeSInt64(12, -123456789012L)
+ outs.writeSInt64(42, 483567314231L)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(5, -213123L, ins.readSInt64())
+ assertSuccessfulRead(1, 3123123L, ins.readSInt64())
+ assertSuccessfulRead(4, -12345675L, ins.readSInt64())
+ assertSuccessfulRead(12, -123456789012L, ins.readSInt64())
+ assertSuccessfulRead(42, 483567314231L, ins.readSInt64())
+}
+
+fun testBoolean() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeBool(1, true)
+ outs.writeBool(2, false)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(1, true, ins.readBool())
+ assertSuccessfulRead(2, false, ins.readBool())
+}
+
+fun testEnum() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeEnum(1, WireType.END_GROUP.ordinal)
+ outs.writeEnum(2, WireType.FIX_64.ordinal)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(1, WireType.END_GROUP.ordinal, ins.readEnum())
+ assertSuccessfulRead(2, WireType.FIX_64.ordinal, ins.readEnum())
+}
+
+fun testFloatAndDouble() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeDouble(42, 123212.34282)
+ outs.writeDouble(15, Math.PI)
+ outs.writeFloat(14, -1.32131321f)
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(42, 123212.34282, ins.readDouble())
+ assertSuccessfulRead(15, Math.PI, ins.readDouble())
+ assertSuccessfulRead(14, -1.32131321f, ins.readFloat())
+}
+
+fun testStrings() {
+ val s = ByteArrayOutputStream()
+ val outs = CodedOutputStream(s)
+ outs.writeString(42, "dasddasd asd ")
+ outs.writeString(15, """!@#$%^&*()QWERTYUI выфвфывфы""")
+
+ val ins = CodedInputStream(ByteArrayInputStream(s.toByteArray()))
+ assertSuccessfulRead(42, "dasddasd asd ", ins.readString())
+ assertSuccessfulRead(15, """!@#$%^&*()QWERTYUI выфвфывфы""", ins.readString())
+}
+
+fun assertSuccessfulRead(fieldNumber: Int, value: T, field: CodedInputStream.Field) {
+ assert(field.fieldNumber == fieldNumber)
+ assert(field.wireType == WireType.VARINT)
+ assert(field.value == value)
+}
+
+fun main(args: Array) {
+ testTrivialPositiveVarInts()
+ testMinPossibleVarInts()
+ testMaxPossibleVarInts()
+ testMaxPossibleFieldNumber()
+ testZigZag32()
+ testZigZag64()
+ testBoolean()
+ testEnum()
+ testFloatAndDouble()
+ testStrings()
+ print("OK")
+}
\ No newline at end of file
diff --git a/proto/compiler/src/WireFormat.kt b/proto/compiler/src/WireFormat.kt
new file mode 100644
index 00000000000..ebe56175fee
--- /dev/null
+++ b/proto/compiler/src/WireFormat.kt
@@ -0,0 +1,17 @@
+/**
+ * Created by user on 7/6/16.
+ */
+
+
+object WireFormat {
+ val TAG_TYPE_BITS: Int = 3
+ val TAG_TYPE_MASK: Int = (1 shl TAG_TYPE_BITS) - 1
+
+ fun getTagWireType(tag: Int): WireType {
+ return WireType from (tag and TAG_TYPE_MASK).toByte()
+ }
+
+ fun getTagFieldNumber(tag: Int): Int {
+ return tag ushr TAG_TYPE_BITS
+ }
+}
\ No newline at end of file
diff --git a/proto/compiler/src/WireType.kt b/proto/compiler/src/WireType.kt
new file mode 100644
index 00000000000..6cc55da3f42
--- /dev/null
+++ b/proto/compiler/src/WireType.kt
@@ -0,0 +1,28 @@
+/**
+ * Created by Dmitry Savvinov on 7/6/16.
+ * Enum for possible WireTypes.
+ * See details at [official Google reference]()https://developers.google.com/protocol-buffers/docs/encoding#structure)
+ */
+
+enum class WireType(val id: Int) {
+ VARINT(0), // int32, int64, uint32, uint64, sint32, sint64, bool, enum
+ FIX_64(1), // fixed64, sfixed64, double
+ LENGTH_DELIMITED(2), // string, bytes, embedded messages, packed repeated fields
+ START_GROUP(3), // groups (deprecated)
+ END_GROUP(4), // groups (deprecated)
+ FIX_32(5); // fixed32, sfixed32, float
+
+ companion object {
+ infix fun from (value: Byte): WireType {
+ return when (value) {
+ 0.toByte() -> VARINT
+ 1.toByte() -> FIX_64
+ 2.toByte() -> LENGTH_DELIMITED
+ 3.toByte() -> START_GROUP
+ 4.toByte() -> END_GROUP
+ 5.toByte() -> FIX_32
+ else -> throw IllegalArgumentException()
+ }
+ }
+ }
+}
\ No newline at end of file