Extract ProtoBuf format to the separate module

    * Including SerialId annotation that is clearly ProtoBuf-specific
    * Copy-paste some of the test (but not main!) sources to make it work. These classes will be extracted to mediator module to workaround KT-35073 when CBOR is extracted as well
    * Replace @SerialId in core tests with @Id from test sources
    * Postpone readme and publication for a while
    * Make some types public for the sake of simplicity, will be revisited them during cleanup phase
diff --git a/build.gradle b/build.gradle
index 10b4186..5c47b29 100644
--- a/build.gradle
+++ b/build.gradle
@@ -71,8 +71,6 @@
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
         classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
         classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$bintray_version"
-
-        // Protobuf is udes in JVM tests
         classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8'
 
         // Various benchmarking stuff
diff --git a/examples/example-visitors/src/test/kotlin/kotlinx/serialization/schema/ProtoSchemaTest.kt b/examples/example-visitors/src/test/kotlin/kotlinx/serialization/schema/ProtoSchemaTest.kt
index 2322e3f..a317ddf 100644
--- a/examples/example-visitors/src/test/kotlin/kotlinx/serialization/schema/ProtoSchemaTest.kt
+++ b/examples/example-visitors/src/test/kotlin/kotlinx/serialization/schema/ProtoSchemaTest.kt
@@ -16,7 +16,6 @@
 
 package kotlinx.serialization.schema
 
-import kotlinx.serialization.SerialId
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.protobuf.ProtoNumberType
 import kotlinx.serialization.protobuf.ProtoType
diff --git a/formats/protobuf/build.gradle b/formats/protobuf/build.gradle
new file mode 100644
index 0000000..9d4c7b0
--- /dev/null
+++ b/formats/protobuf/build.gradle
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+apply plugin: 'java' // Needed for protobuf plugin only
+apply plugin: 'kotlin-multiplatform'
+apply plugin: 'kotlinx-serialization'
+apply plugin: 'com.google.protobuf'
+apply from: rootProject.file("gradle/targets.gradle")
+apply from: rootProject.file("gradle/native_mpp.gradle")
+
+protobuf {
+    protoc {
+        // Download from repositories
+        artifact = 'com.google.protobuf:protoc:3.0.0'
+    }
+}
+
+clean {
+    delete protobuf.generatedFilesBaseDir
+}
+
+kotlin {
+    targets {
+        fromPreset(presets.jvm, 'jvm') {
+            withJava()
+            configure([compilations.main, compilations.test]) {
+                kotlinOptions {
+                    jvmTarget = '1.6'
+                }
+            }
+        }
+        fromPreset(presets.js, 'js') {
+            nodejs {}
+            configure([compilations.main, compilations.test]) {
+                kotlinOptions {
+                    sourceMap = true
+                    moduleKind = "umd"
+                    metaInfo = true
+                }
+            }
+        }
+    }
+
+    sourceSets.all {
+        kotlin.srcDirs = ["$it.name/src"]
+        resources.srcDirs = ["$it.name/resources"]
+        languageSettings {
+            progressiveMode = true
+            useExperimentalAnnotation("kotlin.Experimental")
+            useExperimentalAnnotation("kotlin.ExperimentalMultiplatform")
+            useExperimentalAnnotation("kotlin.ExperimentalStdlibApi")
+            useExperimentalAnnotation("kotlinx.serialization.InternalSerializationApi")
+        }
+    }
+
+    sourceSets {
+        commonMain {
+            dependencies {
+                api 'org.jetbrains.kotlin:kotlin-stdlib-common'
+                api project(":kotlinx-serialization-runtime")
+            }
+        }
+
+        commonTest {
+            dependencies {
+                api 'org.jetbrains.kotlin:kotlin-test-common'
+                api 'org.jetbrains.kotlin:kotlin-test-annotations-common'
+            }
+        }
+
+        jvmMain {
+            dependencies {
+                api 'org.jetbrains.kotlin:kotlin-stdlib'
+            }
+        }
+
+        jvmTest {
+            kotlin.srcDirs += file("${protobuf.generatedFilesBaseDir}/test/java")
+            dependencies {
+                api 'org.jetbrains.kotlin:kotlin-test-junit'
+                implementation 'com.google.protobuf:protobuf-java:3.0.0'
+                implementation 'io.kotlintest:kotlintest:2.0.7'
+            }
+        }
+
+        jsMain {
+            dependencies {
+                api 'org.jetbrains.kotlin:kotlin-stdlib-js'
+            }
+        }
+
+        jsTest {
+            dependencies {
+                api 'org.jetbrains.kotlin:kotlin-test-js'
+            }
+        }
+
+        nativeMain.dependencies {
+        }
+    }
+
+    sourceSets.findAll({ it.name.contains("Test") }).forEach { srcSet ->
+        srcSet.languageSettings {
+            it.useExperimentalAnnotation("kotlinx.serialization.UnstableDefault")
+            it.useExperimentalAnnotation("kotlinx.serialization.InternalSerializationApi")
+
+            if (srcSet.name.contains("jvm") || srcSet.name.contains("js")) {
+                it.useExperimentalAnnotation("kotlinx.serialization.ImplicitReflectionSerializer")
+            }
+        }
+    }
+}
+
+sourceSets.test.proto {
+    srcDirs = ['testProto']
+}
+
+compileTestKotlinJvm {
+    dependsOn 'generateTestProto'
+}
diff --git a/runtime/commonMain/src/kotlinx/serialization/protobuf/ProtoBuf.kt b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoBuf.kt
similarity index 100%
rename from runtime/commonMain/src/kotlinx/serialization/protobuf/ProtoBuf.kt
rename to formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoBuf.kt
diff --git a/runtime/commonMain/src/kotlinx/serialization/protobuf/ProtoTypes.kt b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoTypes.kt
similarity index 87%
rename from runtime/commonMain/src/kotlinx/serialization/protobuf/ProtoTypes.kt
rename to formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoTypes.kt
index 753c6d3..10a8d13 100644
--- a/runtime/commonMain/src/kotlinx/serialization/protobuf/ProtoTypes.kt
+++ b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/ProtoTypes.kt
@@ -25,3 +25,6 @@
 
 
 public class ProtobufDecodingException(message: String) : SerializationException(message)
+
+public fun getSerialId(desc: SerialDescriptor, index: Int): Int?
+        = desc.findAnnotation<SerialId>(index)?.id
diff --git a/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/SerialId.kt b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/SerialId.kt
new file mode 100644
index 0000000..f118aaa
--- /dev/null
+++ b/formats/protobuf/commonMain/src/kotlinx/serialization/protobuf/SerialId.kt
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.protobuf
+
+import kotlinx.serialization.*
+
+@SerialInfo
+@Target(AnnotationTarget.PROPERTY)
+annotation class SerialId(val id: Int)
diff --git a/formats/protobuf/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt
new file mode 100644
index 0000000..7fa95c2
--- /dev/null
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization
+
+import kotlinx.serialization.modules.SerializersModule
+import kotlinx.serialization.protobuf.*
+
+@Serializable
+open class PolyBase(@SerialId(1) val id: Int) {
+    override fun hashCode(): Int {
+        return id
+    }
+
+    override fun toString(): String {
+        return "PolyBase(id=$id)"
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || this::class != other::class) return false
+
+        other as PolyBase
+
+        if (id != other.id) return false
+
+        return true
+    }
+
+}
+
+@Serializable
+data class PolyDerived(@SerialId(2) val s: String) : PolyBase(1)
+
+val BaseAndDerivedModule = SerializersModule {
+    polymorphic(PolyBase::class, PolyBase.serializer()) {
+        PolyDerived::class with PolyDerived.serializer()
+    }
+}
+
+@Serializable
+abstract class SimpleAbstract
+
+@Serializable
+data class SimpleIntInheritor(val i: Int, val s: String) : SimpleAbstract()
+
+@Serializable
+data class SimpleStringInheritor(val s: String, val i: Int) : SimpleAbstract()
+
+@Serializable
+data class PolyBox(@Polymorphic val boxed: SimpleAbstract)
+
+val SimplePolymorphicModule = SerializersModule {
+    polymorphic<SimpleAbstract> {
+        SimpleIntInheritor::class with SimpleIntInheritor.serializer()
+        SimpleStringInheritor::class with SimpleStringInheritor.serializer()
+    }
+}
+
+@Serializable
+data class SealedBox(val boxed: List<SimpleSealed>)
+
+@Serializable
+sealed class SimpleSealed {
+    @Serializable
+    public data class SubSealedA(val s: String) : SimpleSealed()
+
+    @Serializable
+    public data class SubSealedB(val i: Int) : SimpleSealed()
+}
+
diff --git a/formats/protobuf/commonTest/src/kotlinx/serialization/TestUtils.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/TestUtils.kt
new file mode 100644
index 0000000..9084575
--- /dev/null
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/TestUtils.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization
+
+import kotlinx.serialization.internal.*
+import kotlin.test.*
+
+inline fun <reified T : Any> assertSerializedToBinaryAndRestored(
+    original: T,
+    serializer: KSerializer<T>,
+    format: BinaryFormat,
+    printResult: Boolean = false,
+    hexResultToCheck: String? = null
+) {
+    val bytes = format.dump(serializer, original)
+    val hexString = HexConverter.printHexBinary(bytes, lowerCase = true)
+    if (printResult) {
+        println("[Serialized form] $hexString")
+    }
+    if (hexResultToCheck != null) {
+        assertEquals(
+            hexResultToCheck.toLowerCase(),
+            hexString,
+            "Expected serialized binary to be equal in hex representation"
+        )
+    }
+    val restored = format.load(serializer, bytes)
+    if (printResult) println("[Restored form] $restored")
+    assertEquals(original, restored)
+}
diff --git a/runtime/commonTest/src/kotlinx/serialization/protobuf/AutoAssignIdsTest.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/AutoAssignIdsTest.kt
similarity index 97%
rename from runtime/commonTest/src/kotlinx/serialization/protobuf/AutoAssignIdsTest.kt
rename to formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/AutoAssignIdsTest.kt
index f96cb5a..d5cbea6 100644
--- a/runtime/commonTest/src/kotlinx/serialization/protobuf/AutoAssignIdsTest.kt
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/AutoAssignIdsTest.kt
@@ -16,7 +16,6 @@
 
 package kotlinx.serialization.protobuf
 
-import kotlinx.serialization.SerialId
 import kotlinx.serialization.Serializable
 import kotlin.test.Test
 import kotlin.test.assertEquals
diff --git a/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ByteArraySerializerTest.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ByteArraySerializerTest.kt
new file mode 100644
index 0000000..8c5cb6d
--- /dev/null
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ByteArraySerializerTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.protobuf
+
+import kotlinx.serialization.*
+import kotlinx.serialization.internal.ByteArraySerializer
+import kotlinx.serialization.json.Json
+import kotlin.random.Random
+import kotlin.test.*
+
+class ByteArraySerializerTest {
+
+    @Serializable
+    class ByteArrayCarrier(@SerialId(2) @Serializable(with = ByteArraySerializer::class) val data: ByteArray) {
+        override fun equals(other: Any?): Boolean {
+            if (this === other) return true
+            if (other == null || this::class != other::class) return false
+
+            other as ByteArrayCarrier
+
+            if (!data.contentEquals(other.data)) return false
+
+            return true
+        }
+
+        override fun hashCode(): Int {
+            return data.contentHashCode()
+        }
+
+        override fun toString(): String {
+            return "ByteArrayCarrier(data=${data.contentToString()})"
+        }
+    }
+
+    @Test
+    fun testByteArrayProtobuf() {
+        val obj = ByteArrayCarrier(byteArrayOf(42, 100))
+        val s = ProtoBuf.dumps(ByteArrayCarrier.serializer(), obj)
+        assertEquals("""12022a64""", s)
+        val obj2 = ProtoBuf.loads(ByteArrayCarrier.serializer(), s)
+        assertEquals(obj, obj2)
+    }
+
+    @Test
+    fun testWrappedByteArrayProtobuf() {
+        val arraySize = 301
+        val arr = Random.nextBytes(ByteArray(arraySize))
+        val obj = ByteArrayCarrier(arr)
+        val bytes = ProtoBuf.dump(ByteArrayCarrier.serializer(), obj)
+        assertEquals(obj, ProtoBuf.load(ByteArrayCarrier.serializer(), bytes))
+    }
+}
diff --git a/runtime/commonTest/src/kotlinx/serialization/protobuf/CustomSerializersProtobufTest.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/CustomSerializersProtobufTest.kt
similarity index 98%
rename from runtime/commonTest/src/kotlinx/serialization/protobuf/CustomSerializersProtobufTest.kt
rename to formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/CustomSerializersProtobufTest.kt
index cb95fd7..705d3d3 100644
--- a/runtime/commonTest/src/kotlinx/serialization/protobuf/CustomSerializersProtobufTest.kt
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/CustomSerializersProtobufTest.kt
@@ -6,7 +6,6 @@
 
 import kotlinx.serialization.*
 import kotlinx.serialization.modules.serializersModuleOf
-import kotlinx.serialization.json.JsonCustomSerializersTest.*
 import kotlin.test.Test
 import kotlin.test.assertEquals
 
diff --git a/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/CustomizedSerializableTestClasses.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/CustomizedSerializableTestClasses.kt
new file mode 100644
index 0000000..ee5ac8c
--- /dev/null
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/CustomizedSerializableTestClasses.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+@file:ContextualSerialization(B::class)
+package kotlinx.serialization.protobuf
+
+import kotlinx.serialization.*
+
+@Serializable
+data class A(@SerialId(1) val b: B)
+
+data class B(@SerialId(1) val value: Int)
+
+object BSerializer : KSerializer<B> {
+    override fun serialize(encoder: Encoder, obj: B) {
+        encoder.encodeInt(obj.value)
+    }
+
+    override fun deserialize(decoder: Decoder): B {
+        return B(decoder.decodeInt())
+    }
+
+    override val descriptor: SerialDescriptor = PrimitiveDescriptor("B", PrimitiveKind.INT)
+}
+
+@Serializable
+data class BList(@SerialId(1) val bs: List<B>)
+
+@Serializable
+data class C(@SerialId(1) val a: Int = 31, @SerialId(2) val b: Int = 42) {
+    @Serializer(forClass = C::class)
+    companion object: KSerializer<C> {
+        override fun serialize(encoder: Encoder, obj: C) {
+            val elemOutput = encoder.beginStructure(descriptor)
+            elemOutput.encodeIntElement(descriptor, 1, obj.b)
+            if (obj.a != 31) elemOutput.encodeIntElement(descriptor, 0, obj.a)
+            elemOutput.endStructure(descriptor)
+        }
+    }
+}
+
+@Serializable
+data class CList1(@SerialId(1) val c: List<C>)
+
+@Serializable
+data class CList2(@SerialId(1) val d: Int = 5, @SerialId(2) val c: List<C>) {
+    @Serializer(forClass = CList2::class)
+    companion object: KSerializer<CList2> {
+        override fun serialize(encoder: Encoder, obj: CList2) {
+            val elemOutput = encoder.beginStructure(descriptor)
+            elemOutput.encodeSerializableElement(descriptor, 1, C.list, obj.c)
+            if (obj.d != 5) elemOutput.encodeIntElement(descriptor, 0, obj.d)
+            elemOutput.endStructure(descriptor)
+        }
+    }
+}
+
+@Serializable
+data class CList3(@SerialId(1) val e: List<C> = emptyList(), @SerialId(2) val f: Int) {
+    @Serializer(forClass = CList3::class)
+    companion object: KSerializer<CList3> {
+        override fun serialize(encoder: Encoder, obj: CList3) {
+            val elemOutput = encoder.beginStructure(descriptor)
+            if (obj.e.isNotEmpty()) elemOutput.encodeSerializableElement(descriptor, 0, C.list, obj.e)
+            elemOutput.encodeIntElement(descriptor, 1, obj.f)
+            elemOutput.endStructure(descriptor)
+        }
+    }
+}
+
+@Serializable
+data class CList4(@SerialId(1) val g: List<C> = emptyList(), @SerialId(2) val h: Int) {
+    @Serializer(forClass = CList4::class)
+    companion object: KSerializer<CList4> {
+        override fun serialize(encoder: Encoder, obj: CList4) {
+            val elemOutput = encoder.beginStructure(descriptor)
+            elemOutput.encodeIntElement(descriptor, 1, obj.h)
+            if (obj.g.isNotEmpty()) elemOutput.encodeSerializableElement(descriptor, 0, C.list, obj.g)
+            elemOutput.endStructure(descriptor)
+        }
+    }
+}
+
+@Serializable
+data class CList5(@SerialId(1) val g: List<Int> = emptyList(), @SerialId(2) val h: Int) {
+    @Serializer(forClass = CList5::class)
+    companion object: KSerializer<CList5> {
+        override fun serialize(encoder: Encoder, obj: CList5) {
+            val elemOutput = encoder.beginStructure(descriptor)
+            elemOutput.encodeIntElement(descriptor, 1, obj.h)
+            if (obj.g.isNotEmpty()) elemOutput.encodeSerializableElement(descriptor, 0, IntSerializer.list,
+                obj.g)
+            elemOutput.endStructure(descriptor)
+        }
+    }
+}
diff --git a/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufMissingFieldsTest.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufMissingFieldsTest.kt
similarity index 100%
rename from runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufMissingFieldsTest.kt
rename to formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufMissingFieldsTest.kt
diff --git a/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufPolymorphismTest.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufPolymorphismTest.kt
similarity index 91%
rename from runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufPolymorphismTest.kt
rename to formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufPolymorphismTest.kt
index 0f7582f..8cf7129 100644
--- a/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufPolymorphismTest.kt
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufPolymorphismTest.kt
@@ -5,7 +5,6 @@
 package kotlinx.serialization.protobuf
 
 import kotlinx.serialization.*
-import kotlinx.serialization.test.assertSerializedToBinaryAndRestored
 import kotlin.test.Test
 
 class ProtobufPolymorphismTest {
diff --git a/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufPrimitivesTest.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufPrimitivesTest.kt
new file mode 100644
index 0000000..fee0814
--- /dev/null
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufPrimitivesTest.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package kotlinx.serialization.protobuf
+
+import kotlinx.serialization.*
+import kotlin.test.*
+
+// TODO these tests are far from being comoplete
+class ProtobufPrimitivesTest {
+
+    private fun <T> testConversion(data: T, serializer: KSerializer<T>, expectedHexString: String) {
+        val string = ProtoBuf.dumps(serializer, data).toUpperCase()
+        assertEquals(expectedHexString, string)
+        assertEquals(data, ProtoBuf.loads(serializer, string))
+    }
+
+    @Test
+    fun testSignedInteger() {
+        testConversion(TestInt(-150), TestInt.serializer(), "08AB02")
+    }
+
+    @Test
+    fun testIntList() {
+        testConversion(TestList(listOf(150, 228, 1337)), TestList.serializer(), "08960108E40108B90A")
+
+    }
+
+    @Test
+    fun testString() {
+        testConversion(TestString("testing"), TestString.serializer(), "120774657374696E67")
+    }
+
+    @Test
+    fun testTwiceNested() {
+        testConversion(TestInner(TestInt(-150)), TestInner.serializer(), "1A0308AB02")
+    }
+
+    @Test
+    fun testMixedTags() {
+        testConversion(TestComplex(42, "testing"), TestComplex.serializer(), "D0022A120774657374696E67")
+    }
+
+    @Test
+    fun testDefaultPrimitiveValues() {
+        testConversion(TestInt(0), TestInt.serializer(), "0800")
+        testConversion(TestList(listOf()), TestList.serializer(), "")
+        testConversion(TestString(""), TestString.serializer(), "1200")
+    }
+
+    @Test
+    fun testFixedIntWithLong() {
+        testConversion(TestNumbers(100500, Long.MAX_VALUE), TestNumbers.serializer(), "0D9488010010FFFFFFFFFFFFFFFF7F")
+    }
+}
diff --git a/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufUnionEnumTest.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufUnionEnumTest.kt
similarity index 90%
rename from runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufUnionEnumTest.kt
rename to formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufUnionEnumTest.kt
index f31f4ea..47245f0 100644
--- a/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufUnionEnumTest.kt
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufUnionEnumTest.kt
@@ -22,7 +22,7 @@
     fun testEnum() {
         val data = WithUnions("foo", SomeEnum.BETA)
         val hex = ProtoBuf.dumps(WithUnions.serializer(), data)
-        val restored = ProtoBuf.loads<WithUnions>(WithUnions.serializer(), hex)
+        val restored = ProtoBuf.loads(WithUnions.serializer(), hex)
         assertEquals(data, restored)
     }
 }
diff --git a/runtime/commonTest/src/kotlinx/serialization/protobuf/SampleClasses.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/SerializableTestClasses.kt
similarity index 78%
rename from runtime/commonTest/src/kotlinx/serialization/protobuf/SampleClasses.kt
rename to formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/SerializableTestClasses.kt
index 1a8d83a..01fa9f6 100644
--- a/runtime/commonTest/src/kotlinx/serialization/protobuf/SampleClasses.kt
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/SerializableTestClasses.kt
@@ -16,9 +16,7 @@
 
 package kotlinx.serialization.protobuf
 
-import kotlinx.serialization.SerialId
 import kotlinx.serialization.Serializable
-import kotlin.test.assertEquals
 
 @Serializable
 data class TestInt(@SerialId(1) @ProtoType(ProtoNumberType.SIGNED) val a: Int)
@@ -43,13 +41,3 @@
         @SerialId(1) val s: Int,
         @SerialId(10) val l: List<Int>
 )
-
-val t1 = TestInt(-150)
-val t1e = TestInt(0)
-val t2 = TestList(listOf(150, 228, 1337))
-val t2e = TestList(listOf())
-val t3 = TestString("testing")
-val t3e = TestString("")
-val t4 = TestInner(t1)
-val t5 = TestComplex(42, "testing")
-val t6 = TestNumbers(100500, Long.MAX_VALUE)
diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/FormatConverterHelpers.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/FormatConverterHelpers.kt
new file mode 100644
index 0000000..91b191b
--- /dev/null
+++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/FormatConverterHelpers.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.protobuf
+
+import com.google.protobuf.GeneratedMessageV3
+import kotlinx.io.*
+import java.io.ByteArrayOutputStream
+import kotlinx.serialization.dump
+import kotlinx.serialization.loads
+
+interface IMessage {
+    fun toProtobufMessage(): GeneratedMessageV3
+}
+
+fun GeneratedMessageV3.toHex(): String {
+    val b = ByteArrayOutputStream()
+    this.writeTo(b)
+    return (HexConverter.printHexBinary(b.toByteArray(), lowerCase = true))
+}
+
+inline fun <reified T : IMessage> dumpCompare(it: T): Boolean {
+    val msg = it.toProtobufMessage()
+    var parsed: GeneratedMessageV3?
+    val c = try {
+        val bytes = ProtoBuf.dump(it)
+        parsed = msg.parserForType.parseFrom(bytes)
+        msg == parsed
+    } catch (e: Exception) {
+        e.printStackTrace()
+        parsed = null
+        false
+    }
+    return c
+}
+
+inline fun <reified T : IMessage> readCompare(it: T, alwaysPrint: Boolean = false): Boolean {
+    var obj: T?
+    val c = try {
+        val msg = it.toProtobufMessage()
+        val hex = msg.toHex()
+        obj = ProtoBuf.loads(hex)
+        obj == it
+    } catch (e: Exception) {
+        obj = null
+        e.printStackTrace()
+        false
+    }
+    if (!c || alwaysPrint) println("Expected: $it\nfound: $obj")
+    return c
+}
+
+object HexConverter {
+    fun parseHexBinary(s: String): ByteArray {
+        val len = s.length
+        require(len % 2 == 0) { "HexBinary string must be even length" }
+        val bytes = ByteArray(len / 2)
+        var i = 0
+
+        while (i < len) {
+            val h = hexToInt(s[i])
+            val l = hexToInt(s[i + 1])
+            require(!(h == -1 || l == -1)) { "Invalid hex chars: ${s[i]}${s[i+1]}" }
+
+            bytes[i / 2] = ((h shl 4) + l).toByte()
+            i += 2
+        }
+
+        return bytes
+    }
+
+    private fun hexToInt(ch: Char): Int = when (ch) {
+        in '0'..'9' -> ch - '0'
+        in 'A'..'F' -> ch - 'A' + 10
+        in 'a'..'f' -> ch - 'a' + 10
+        else -> -1
+    }
+
+    private const val hexCode = "0123456789ABCDEF"
+
+    fun printHexBinary(data: ByteArray, lowerCase: Boolean = false): String {
+        val r = StringBuilder(data.size * 2)
+        for (b in data) {
+            r.append(hexCode[b.toInt() shr 4 and 0xF])
+            r.append(hexCode[b.toInt() and 0xF])
+        }
+        return if (lowerCase) r.toString().toLowerCase() else r.toString()
+    }
+
+    fun toHexString(n: Int) = printHexBinary(ByteBuffer.allocate(4).putInt(n).flip().array(), true)
+        .trimStart('0').takeIf { it.isNotEmpty() } ?: "0"
+}
diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/PolymorphicWithJvmClassTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/PolymorphicWithJvmClassTest.kt
new file mode 100644
index 0000000..e592a76
--- /dev/null
+++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/PolymorphicWithJvmClassTest.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.protobuf
+
+import kotlinx.serialization.*
+import kotlinx.serialization.modules.SerializersModule
+
+import org.junit.Test
+import java.text.*
+import java.util.*
+import kotlin.test.assertEquals
+
+class PolymorphicWithJvmClassTest {
+    @Serializable
+    data class DateWrapper(@SerialId(1) @Serializable(with = PolymorphicSerializer::class) val date: Date)
+
+    @Serializer(forClass = Date::class)
+    object DateSerializer : KSerializer<Date> {
+        override val descriptor: SerialDescriptor = PrimitiveDescriptor("java.util.Date", PrimitiveKind.STRING)
+
+        // Consider wrapping in ThreadLocal if serialization may happen in multiple threads
+        private val df: DateFormat = SimpleDateFormat("dd/MM/yyyy HH:mm:ss.SSS").apply {
+            timeZone = TimeZone.getTimeZone("GMT+2")
+        }
+
+        override fun serialize(encoder: Encoder, obj: Date) {
+            encoder.encodeString(df.format(obj))
+        }
+
+        override fun deserialize(decoder: Decoder): Date {
+            return df.parse(decoder.decodeString())
+        }
+    }
+
+    @Test
+    fun testPolymorphicWrappedOverride() {
+        val protobuf = ProtoBuf(context = SerializersModule { polymorphic(Date::class, DateSerializer) })
+        val obj = DateWrapper(Date())
+        val bytes = protobuf.dumps(obj)
+        val restored = protobuf.loads<DateWrapper>(bytes)
+        assertEquals(obj, restored)
+    }
+}
diff --git a/runtime/jvmTest/src/kotlinx/serialization/formats/protobuf/ProtoCompatibilityTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/ProtoCompatibilityTest.kt
similarity index 78%
rename from runtime/jvmTest/src/kotlinx/serialization/formats/protobuf/ProtoCompatibilityTest.kt
rename to formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/ProtoCompatibilityTest.kt
index 37101d1..21de867 100644
--- a/runtime/jvmTest/src/kotlinx/serialization/formats/protobuf/ProtoCompatibilityTest.kt
+++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/ProtoCompatibilityTest.kt
@@ -1,16 +1,18 @@
-package kotlinx.serialization.formats.protobuf
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.protobuf
 
 import kotlinx.serialization.*
-import kotlinx.serialization.formats.KTestData
-import kotlinx.serialization.formats.toHex
-import kotlinx.serialization.protobuf.ProtoBuf
 import org.junit.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertTrue
 
 class ProtoCompatibilityTest {
+
     @Test
-    fun mapTest() {
+    fun testMap() {
         val mapData = KTestData.KTestMap(mapOf("a" to "b", "c" to "d"), emptyMap())
         val kxData = ProtoBuf.dump(mapData)
         val kxHex = ProtoBuf.dumps(mapData)
diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/ProtobufEnumWithSerialIdTest.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/ProtobufEnumWithSerialIdTest.kt
new file mode 100644
index 0000000..152ba69
--- /dev/null
+++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/ProtobufEnumWithSerialIdTest.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.protobuf
+
+import kotlinx.serialization.Serializable
+import org.junit.*
+import kotlin.test.assertTrue
+
+class ProtobufEnumWithSerialIdTest {
+
+    @Serializable
+    enum class EnumWithIds(val id: Int) {
+        @SerialId(10)
+        FIRST(10),
+        @SerialId(20)
+        SECOND(20);
+    }
+
+    @Serializable
+    data class EnumHolder(@SerialId(5) val a: EnumWithIds) : IMessage {
+        override fun toProtobufMessage(): TestData.EnumHolder =
+            TestData.EnumHolder.newBuilder().setA(TestData.TestEnumWithIds.forNumber(a.id)).build()
+    }
+
+    @Test
+    fun testEnumsSupportSerialIds() {
+        assertTrue(readCompare(EnumHolder(EnumWithIds.SECOND)))
+        assertTrue(dumpCompare(EnumHolder(EnumWithIds.SECOND)))
+    }
+}
diff --git a/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/RandomTests.kt b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/RandomTests.kt
new file mode 100644
index 0000000..2d85c22
--- /dev/null
+++ b/formats/protobuf/jvmTest/src/kotlinx/serialization/protobuf/RandomTests.kt
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.protobuf
+
+import com.google.protobuf.GeneratedMessageV3
+import io.kotlintest.properties.Gen
+import io.kotlintest.properties.forAll
+import io.kotlintest.specs.ShouldSpec
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.protobuf.TestData.*
+
+fun Gen<String>.generateNotEmpty() = nextPrintableString(Gen.choose(1, 100).generate())
+
+object KTestData {
+    @Serializable
+    data class KTestInt32(@SerialId(1) val a: Int) : IMessage {
+        override fun toProtobufMessage(): GeneratedMessageV3 = TestInt32.newBuilder().setA(a).build()
+
+        companion object : Gen<KTestInt32> {
+            override fun generate(): KTestInt32 = KTestInt32(Gen.int().generate())
+        }
+    }
+
+    @Serializable
+    data class KTestSignedInt(@SerialId(1) @ProtoType(ProtoNumberType.SIGNED) val a: Int) : IMessage {
+        override fun toProtobufMessage(): GeneratedMessageV3 = TestSignedInt.newBuilder().setA(a).build()
+
+        companion object : Gen<KTestSignedInt> {
+            override fun generate(): KTestSignedInt = KTestSignedInt(Gen.int().generate())
+        }
+    }
+
+    @Serializable
+    data class KTestSignedLong(@SerialId(1) @ProtoType(ProtoNumberType.SIGNED) val a: Long) : IMessage {
+        override fun toProtobufMessage(): GeneratedMessageV3 = TestSignedLong.newBuilder().setA(a).build()
+
+        companion object : Gen<KTestSignedLong> {
+            override fun generate(): KTestSignedLong = KTestSignedLong(Gen.long().generate())
+        }
+    }
+
+    @Serializable
+    data class KTestFixedInt(@SerialId(1) @ProtoType(ProtoNumberType.FIXED) val a: Int) : IMessage {
+        override fun toProtobufMessage(): GeneratedMessageV3 = TestFixedInt.newBuilder().setA(a).build()
+
+        companion object : Gen<KTestFixedInt> {
+            override fun generate(): KTestFixedInt = KTestFixedInt(Gen.int().generate())
+        }
+    }
+
+    @Serializable
+    data class KTestDouble(@SerialId(1) val a: Double) : IMessage {
+        override fun toProtobufMessage(): GeneratedMessageV3 = TestDouble.newBuilder().setA(a).build()
+
+        companion object : Gen<KTestDouble> {
+            override fun generate(): KTestDouble = KTestDouble(Gen.double().generate())
+        }
+    }
+
+    @Serializable
+    data class KTestBoolean(@SerialId(1) val a: Boolean) : IMessage {
+        override fun toProtobufMessage(): GeneratedMessageV3 = TestBoolean.newBuilder().setA(a).build()
+
+        companion object : Gen<KTestBoolean> {
+            override fun generate(): KTestBoolean = KTestBoolean(Gen.bool().generate())
+        }
+    }
+
+    @Serializable
+    data class KTestAllTypes(
+            @SerialId(1) val i32: Int,
+            @SerialId(2) @ProtoType(ProtoNumberType.SIGNED) val si32: Int,
+            @SerialId(3) @ProtoType(ProtoNumberType.FIXED) val f32: Int,
+            @SerialId(10) val i64: Long,
+            @SerialId(11) @ProtoType(ProtoNumberType.SIGNED) val si64: Long,
+            @SerialId(12) @ProtoType(ProtoNumberType.FIXED) val f64: Long,
+            @SerialId(21) val f: Float,
+            @SerialId(22) val d: Double,
+            @SerialId(41) val b: Boolean = false,
+            @SerialId(51) val s: String
+    ) : IMessage {
+        override fun toProtobufMessage(): TestAllTypes = TestAllTypes.newBuilder()
+                .setI32(i32)
+                .setSi32(si32)
+                .setF32(f32)
+                .setI64(i64)
+                .setSi64(si64)
+                .setF64(f64)
+                .setF(f)
+                .setD(d)
+                .setB(b)
+                .setS(s)
+                .build()
+
+        companion object : Gen<KTestAllTypes> {
+            override fun generate(): KTestAllTypes = KTestAllTypes(
+                    Gen.int().generate(),
+                    Gen.int().generate(),
+                    Gen.int().generate(),
+                    Gen.long().generate(),
+                    Gen.long().generate(),
+                    Gen.long().generate(),
+                    Gen.float().generate(),
+                    Gen.double().generate(),
+                    Gen.bool().generate(),
+                    Gen.string().generateNotEmpty()
+            )
+        }
+    }
+
+    @Serializable
+    data class KTestOuterMessage(
+            @SerialId(1) val a: Int,
+            @SerialId(2) val b: Double,
+            @SerialId(10) val inner: KTestAllTypes,
+            @SerialId(20) val s: String
+    ) : IMessage {
+        override fun toProtobufMessage(): GeneratedMessageV3 = TestOuterMessage.newBuilder()
+                .setA(a)
+                .setB(b)
+                .setInner(inner.toProtobufMessage())
+                .setS(s)
+                .build()
+
+        companion object : Gen<KTestOuterMessage> {
+            override fun generate(): KTestOuterMessage = KTestOuterMessage(
+                    Gen.int().generate(),
+                    Gen.double().generate(),
+                    KTestAllTypes.generate(),
+                    Gen.string().generateNotEmpty()
+            )
+        }
+    }
+
+    @Serializable
+    data class KTestIntListMessage(
+            @SerialId(1) val s: Int,
+            @SerialId(10) val l: List<Int>
+    ) : IMessage {
+        override fun toProtobufMessage(): GeneratedMessageV3 = TestRepeatedIntMessage.newBuilder().setS(s).addAllB(l).build()
+
+        companion object : Gen<KTestIntListMessage> {
+            override fun generate() = KTestIntListMessage(Gen.int().generate(), Gen.list(Gen.int()).generate())
+        }
+    }
+
+    @Serializable
+    data class KTestObjectListMessage(
+            @SerialId(1) val inner: List<KTestAllTypes>
+    ) : IMessage {
+        override fun toProtobufMessage(): GeneratedMessageV3 = TestRepeatedObjectMessage.newBuilder().addAllInner(inner.map { it.toProtobufMessage() }).build()
+
+        companion object : Gen<KTestObjectListMessage> {
+            override fun generate() = KTestObjectListMessage(Gen.list(KTestAllTypes.Companion).generate())
+        }
+    }
+
+    enum class KCoffee { AMERICANO, LATTE, CAPPUCCINO }
+
+    @Serializable
+    data class KTestEnum(@SerialId(1) val a: KCoffee): IMessage {
+        override fun toProtobufMessage() = TestEnum.newBuilder().setA(TestEnum.Coffee.forNumber(a.ordinal)).build()
+
+        companion object : Gen<KTestEnum> {
+            override fun generate(): KTestEnum = KTestEnum(Gen.oneOf<KCoffee>().generate())
+        }
+    }
+
+    @Serializable
+    data class KTestMap(@SerialId(1) val s: Map<String, String>, @SerialId(2) val o: Map<Int, KTestAllTypes> = emptyMap()) :
+        IMessage {
+        override fun toProtobufMessage() = TestMap.newBuilder()
+            .putAllStringMap(s)
+            .putAllIntObjectMap(o.mapValues { it.value.toProtobufMessage() })
+            .build()
+
+        companion object : Gen<KTestMap> {
+            override fun generate(): KTestMap =
+                KTestMap(Gen.map(Gen.string(), Gen.string()).generate(), Gen.map(Gen.int(), KTestAllTypes).generate())
+        }
+    }
+}
+
+
+class RandomTest : ShouldSpec() {
+
+    init {
+        "Protobuf serialization" {
+            should("serialize random int32") { forAll(KTestData.KTestInt32.Companion) { dumpCompare(it) } }
+            should("serialize random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { dumpCompare(it) } }
+            should("serialize random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { dumpCompare(it) } }
+            should("serialize random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { dumpCompare(it) } }
+            should("serialize random doubles") { forAll(KTestData.KTestDouble.Companion) { dumpCompare(it) } }
+            should("serialize random booleans") { forAll(KTestData.KTestBoolean.Companion) { dumpCompare(it) } }
+            should("serialize random enums") { forAll(KTestData.KTestEnum.Companion) { dumpCompare(it) } }
+            should("serialize all base random types") { forAll(KTestData.KTestAllTypes.Companion) { dumpCompare(it) } }
+            should("serialize random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { dumpCompare(it) } }
+            should("serialize random messages with primitive list fields as repeated") { forAll(KTestData.KTestIntListMessage.Companion) { dumpCompare(it) } }
+            should("serialize messages with object list fields as repeated") { forAll(KTestData.KTestObjectListMessage.Companion) { dumpCompare(it) } }
+            should("serialize messages with scalar-key maps") { forAll(KTestData.KTestMap.Companion) { dumpCompare(it) } }
+        }
+
+        "Protobuf deserialization" {
+            should("read random int32") { forAll(KTestData.KTestInt32.Companion) { readCompare(it) } }
+            should("read random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { readCompare(it) } }
+            should("read random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { readCompare(it) } }
+            should("read random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { readCompare(it) } }
+            should("read random doubles") { forAll(KTestData.KTestDouble.Companion) { readCompare(it) } }
+            should("read random enums") { forAll(KTestData.KTestEnum.Companion) { readCompare(it) } }
+            should("read all base random types") { forAll(KTestData.KTestAllTypes.Companion) { readCompare(it) } }
+            should("read random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { readCompare(it) } }
+            should("read random messages with primitive list fields as repeated") { forAll(KTestData.KTestIntListMessage.Companion) { readCompare(it) } }
+            should("read random messages with object list fields as repeated") { forAll(KTestData.KTestObjectListMessage.Companion) { readCompare(it) } }
+            should("read messages with scalar-key maps") { forAll(KTestData.KTestMap.Companion) { readCompare(it) } }
+        }
+    }
+}
diff --git a/runtime/testProto/test_data.proto b/formats/protobuf/testProto/test_data.proto
similarity index 95%
rename from runtime/testProto/test_data.proto
rename to formats/protobuf/testProto/test_data.proto
index a0ba6ae..b9e3602 100644
--- a/runtime/testProto/test_data.proto
+++ b/formats/protobuf/testProto/test_data.proto
@@ -1,5 +1,5 @@
 syntax = "proto2";
-option java_package = "kotlinx.serialization.formats.proto";
+option java_package = "kotlinx.serialization.protobuf";
 
 message TestInt32 {
     required int32 a = 1;
diff --git a/gradle/publishing.gradle b/gradle/publishing.gradle
index 5b12a23..030dc68 100644
--- a/gradle/publishing.gradle
+++ b/gradle/publishing.gradle
@@ -10,7 +10,7 @@
 
 apply from: project.rootProject.file('gradle/mavenMetadata.gradle')
 
-def isMultiplatform = project.name == "kotlinx-serialization-runtime"
+def isMultiplatform = project.name == "kotlinx-serialization-runtime" || project.name == "kotlinx-serialization-protobuf"
 
 task stubSources(type: Jar) {
     classifier = 'sources'
diff --git a/runtime/build.gradle b/runtime/build.gradle
index 372f957..ec650bf 100644
--- a/runtime/build.gradle
+++ b/runtime/build.gradle
@@ -1,33 +1,16 @@
 /*
  * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
-apply plugin: 'java' // Needed for protobuf plugin only
 
 apply plugin: 'kotlin-multiplatform'
 apply plugin: 'kotlinx-serialization'
+apply from: rootProject.file("gradle/targets.gradle")
+apply from: rootProject.file("gradle/native_mpp.gradle")
 
 ext {
     jacksonVersion = '2.10.0.pr1'
 }
 
-// Protobuf plugin used in tests
-
-apply plugin: 'com.google.protobuf'
-
-protobuf {
-    protoc {
-        // Download from repositories
-        artifact = 'com.google.protobuf:protoc:3.0.0'
-    }
-}
-
-clean {
-    delete protobuf.generatedFilesBaseDir
-}
-
-apply from: rootProject.file("gradle/targets.gradle")
-apply from: rootProject.file("gradle/native_mpp.gradle")
-
 kotlin {
     targets {
         fromPreset(presets.jvm, 'jvm') {
@@ -83,23 +66,15 @@
         }
 
         jvmTest {
-            kotlin.srcDirs += file("${protobuf.generatedFilesBaseDir}/test/java")
-
             dependencies {
                 api 'org.jetbrains.kotlin:kotlin-test-junit'
-
                 implementation 'io.kotlintest:kotlintest:2.0.7'
                 implementation 'com.google.guava:guava:24.1.1-jre'
-
-                implementation 'com.google.protobuf:protobuf-java:3.0.0'
-
                 implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: jacksonVersion
                 implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: jacksonVersion
                 implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: jacksonVersion
                 implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-cbor', version: jacksonVersion
-
                 implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
-
                 implementation group: 'com.upokecenter', name: 'cbor', version: '4.0.0-beta1'
             }
         }
@@ -131,11 +106,3 @@
         }
     }
 }
-
-sourceSets.test.proto {
-    srcDirs = ['testProto']
-}
-
-compileTestKotlinJvm {
-    dependsOn 'generateTestProto'
-}
diff --git a/runtime/commonMain/src/kotlinx/serialization/SerialFormat.kt b/runtime/commonMain/src/kotlinx/serialization/SerialFormat.kt
index 53fbb29..f53eb79 100644
--- a/runtime/commonMain/src/kotlinx/serialization/SerialFormat.kt
+++ b/runtime/commonMain/src/kotlinx/serialization/SerialFormat.kt
@@ -29,6 +29,7 @@
     fun <T> load(deserializer: DeserializationStrategy<T>, bytes: ByteArray): T
 }
 
+// TODO migrate
 fun <T> BinaryFormat.dumps(serializer: SerializationStrategy<T>, obj: T): String =
     HexConverter.printHexBinary(dump(serializer, obj), lowerCase = true)
 
diff --git a/runtime/commonMain/src/kotlinx/serialization/Shorthands.kt b/runtime/commonMain/src/kotlinx/serialization/Shorthands.kt
index 80592d9..ecb0c63 100644
--- a/runtime/commonMain/src/kotlinx/serialization/Shorthands.kt
+++ b/runtime/commonMain/src/kotlinx/serialization/Shorthands.kt
@@ -52,7 +52,7 @@
  * Returns null if there are no annotations with such type.
  * Throws [IllegalStateException] if there are duplicated annotations for a given type.
  */
-internal inline fun <reified A: Annotation> SerialDescriptor.findAnnotation(elementIndex: Int): A? {
+public inline fun <reified A: Annotation> SerialDescriptor.findAnnotation(elementIndex: Int): A? {
     val candidates = getElementAnnotations(elementIndex).filterIsInstance<A>()
     return when (candidates.size) {
         0 -> null
diff --git a/runtime/commonMain/src/kotlinx/serialization/Tagged.kt b/runtime/commonMain/src/kotlinx/serialization/Tagged.kt
index 02444fc..32b7606 100644
--- a/runtime/commonMain/src/kotlinx/serialization/Tagged.kt
+++ b/runtime/commonMain/src/kotlinx/serialization/Tagged.kt
@@ -4,14 +4,9 @@
 
 package kotlinx.serialization
 
-import kotlinx.serialization.CompositeDecoder.Companion.READ_ALL
 import kotlinx.serialization.modules.EmptyModule
 import kotlinx.serialization.modules.SerialModule
 
-@SerialInfo
-@Target(AnnotationTarget.PROPERTY)
-annotation class SerialId(val id: Int)
-
 abstract class TaggedEncoder<Tag : Any?> : Encoder, CompositeEncoder {
 
     /**
@@ -132,10 +127,6 @@
             throw SerializationException("No tag in stack for requested element")
 }
 
-abstract class IntTaggedEncoder : TaggedEncoder<Int?>() {
-    final override fun SerialDescriptor.getTag(index: Int): Int? = getSerialId(this, index)
-}
-
 abstract class NamedValueEncoder(val rootName: String = "") : TaggedEncoder<String>() {
     final override fun SerialDescriptor.getTag(index: Int): String = nested(elementName(this, index))
 
@@ -144,9 +135,6 @@
     open fun composeName(parentName: String, childName: String) = if (parentName.isEmpty()) childName else "$parentName.$childName"
 }
 
-internal fun getSerialId(desc: SerialDescriptor, index: Int): Int?
-        = desc.findAnnotation<SerialId>(index)?.id
-
 abstract class TaggedDecoder<Tag : Any?> : Decoder, CompositeDecoder {
     override val context: SerialModule
         get() = EmptyModule
@@ -198,7 +186,6 @@
         return this
     }
 
-
     final override fun decodeUnitElement(desc: SerialDescriptor, index: Int) = decodeTaggedUnit(desc.getTag(index))
     final override fun decodeBooleanElement(desc: SerialDescriptor, index: Int): Boolean = decodeTaggedBoolean(desc.getTag(index))
     final override fun decodeByteElement(desc: SerialDescriptor, index: Int): Byte = decodeTaggedByte(desc.getTag(index))
@@ -255,10 +242,6 @@
     }
 }
 
-abstract class IntTaggedDecoder: TaggedDecoder<Int?>() {
-    final override fun SerialDescriptor.getTag(index: Int): Int? = getSerialId(this, index)
-}
-
 abstract class NamedValueDecoder(val rootName: String = "") : TaggedDecoder<String>() {
     final override fun SerialDescriptor.getTag(index: Int): String = nested(elementName(this, index))
 
diff --git a/runtime/commonMain/src/kotlinx/serialization/internal/Tuples.kt b/runtime/commonMain/src/kotlinx/serialization/internal/Tuples.kt
index 61960be..8012765 100644
--- a/runtime/commonMain/src/kotlinx/serialization/internal/Tuples.kt
+++ b/runtime/commonMain/src/kotlinx/serialization/internal/Tuples.kt
@@ -8,7 +8,7 @@
 
 private val NULL = Any()
 
-internal sealed class KeyValueSerializer<K, V, R>(
+public sealed class KeyValueSerializer<K, V, R>(
     private val keySerializer: KSerializer<K>,
     private val valueSerializer: KSerializer<V>
 ) : KSerializer<R> {
@@ -57,7 +57,7 @@
 }
 
 @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
-internal class MapEntrySerializer<K, V>(
+public class MapEntrySerializer<K, V>(
     keySerializer: KSerializer<K>,
     valueSerializer: KSerializer<V>
 ) : KeyValueSerializer<K, V, Map.Entry<K, V>>(keySerializer, valueSerializer) {
diff --git a/runtime/commonMain/src/kotlinx/serialization/internal/Util.kt b/runtime/commonMain/src/kotlinx/serialization/internal/Util.kt
index f3a9193..6a10940 100644
--- a/runtime/commonMain/src/kotlinx/serialization/internal/Util.kt
+++ b/runtime/commonMain/src/kotlinx/serialization/internal/Util.kt
@@ -8,7 +8,7 @@
 import kotlinx.io.IOException
 import kotlinx.io.InputStream
 
-internal fun InputStream.readExactNBytes(bytes: Int): ByteArray {
+public fun InputStream.readExactNBytes(bytes: Int): ByteArray {
     val array = ByteArray(bytes)
     var read = 0
     while (read < bytes) {
@@ -19,7 +19,7 @@
     return array
 }
 
-internal fun InputStream.readToByteBuffer(bytes: Int): ByteBuffer {
+public fun InputStream.readToByteBuffer(bytes: Int): ByteBuffer {
     val arr = readExactNBytes(bytes)
     val buf = ByteBuffer.allocate(bytes)
     buf.put(arr).flip()
diff --git a/runtime/commonTest/src/kotlinx/serialization/EnumSerializationTest.kt b/runtime/commonTest/src/kotlinx/serialization/EnumSerializationTest.kt
index 522ce8c..7002232 100644
--- a/runtime/commonTest/src/kotlinx/serialization/EnumSerializationTest.kt
+++ b/runtime/commonTest/src/kotlinx/serialization/EnumSerializationTest.kt
@@ -16,7 +16,7 @@
         @SerialName("foo_a")
         FooA,
         @SerialName("foo_b")
-        @SerialId(10)
+        @Id(10)
         FooB
     }
 
diff --git a/runtime/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt b/runtime/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt
index 4250143..5180ac6 100644
--- a/runtime/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt
+++ b/runtime/commonTest/src/kotlinx/serialization/PolymorphismTestData.kt
@@ -7,7 +7,7 @@
 import kotlinx.serialization.modules.SerializersModule
 
 @Serializable
-open class PolyBase(@SerialId(1) val id: Int) {
+open class PolyBase(@Id(1) val id: Int) {
     override fun hashCode(): Int {
         return id
     }
@@ -30,7 +30,7 @@
 }
 
 @Serializable
-data class PolyDerived(@SerialId(2) val s: String) : PolyBase(1)
+data class PolyDerived(@Id(2) val s: String) : PolyBase(1)
 
 val BaseAndDerivedModule = SerializersModule {
     polymorphic(PolyBase::class, PolyBase.serializer()) {
diff --git a/runtime/commonTest/src/kotlinx/serialization/SerialDescriptorSpecificationTest.kt b/runtime/commonTest/src/kotlinx/serialization/SerialDescriptorSpecificationTest.kt
index 4e2ee2e..03e7f19 100644
--- a/runtime/commonTest/src/kotlinx/serialization/SerialDescriptorSpecificationTest.kt
+++ b/runtime/commonTest/src/kotlinx/serialization/SerialDescriptorSpecificationTest.kt
@@ -6,13 +6,13 @@
 
 import kotlinx.serialization.CompositeDecoder.Companion.UNKNOWN_NAME
 import kotlinx.serialization.internal.*
-import kotlinx.serialization.test.*
+
 import kotlin.test.*
 
 class SerialDescriptorSpecificationTest {
 
     @Serializable
-    class Holder(val a: Int?, @SerialId(42) val b: String = "", @SerialName("c") val d: Long)
+    class Holder(val a: Int?, @Id(42) val b: String = "", @SerialName("c") val d: Long)
 
     @Test
     fun testAutoGeneratedDescriptorContract() {
@@ -34,7 +34,7 @@
             addElement("b", true)
             pushDescriptor(StringSerializer.descriptor)
             // Can't create an annotation manually
-            pushAnnotation(Holder.serializer().descriptor.findAnnotation<SerialId>(1)!!)
+            pushAnnotation(Holder.serializer().descriptor.findAnnotation<Id>(1)!!)
 
             addElement("c")
             pushDescriptor(LongSerializer.descriptor)
@@ -60,7 +60,7 @@
         // Children annotations
         run {
             assertEquals(0, d.getElementAnnotations(0).size)
-            d.assertSingleAnnotation(1) { it is SerialId && it.id == 42 }
+            d.assertSingleAnnotation(1) { it is Id && it.id == 42 }
             assertEquals(0, d.getElementAnnotations(2).size)
         }
         // Optionality
@@ -95,7 +95,7 @@
     @Serializable
     @Suppress("UNUSED")
     enum class NamedEnum {
-        @SerialId(42)
+        @Id(42)
         FIRST,
         @SerialName("SECOND")
         THIRD
@@ -117,7 +117,7 @@
         assertEquals("SECOND", d.getElementName(1))
         assertFailsWith<IndexOutOfBoundsException> { d.getElementName(2) }
         // Annotations
-        d.assertSingleAnnotation(0) { it is SerialId && it.id == 42 }
+        d.assertSingleAnnotation(0) { it is Id && it.id == 42 }
         assertEquals(0, d.getElementAnnotations(1).size)
         // Element descriptors
         assertSame(d, d.getElementDescriptor(0))
diff --git a/runtime/commonTest/src/kotlinx/serialization/TaggedTest.kt b/runtime/commonTest/src/kotlinx/serialization/TaggedTest.kt
index 3a9df6a..25597f9 100644
--- a/runtime/commonTest/src/kotlinx/serialization/TaggedTest.kt
+++ b/runtime/commonTest/src/kotlinx/serialization/TaggedTest.kt
@@ -14,22 +14,25 @@
 
     @Serializable
     data class DataWithId(
-        @SerialId(1) val first: Int,
-        @SerialId(2) val second: String,
+        @Id(1) val first: Int,
+        @Id(2) val second: String,
         val noId: Unit = Unit,
-        @SerialId(42) val last: Boolean = true
+        @Id(42) val last: Boolean = true
     )
 
-    class Collector : IntTaggedEncoder() {
+    class Collector : TaggedEncoder<Int?>() {
+        override fun SerialDescriptor.getTag(index: Int): Int? = getSerialId(this, index)
         val tagList = mutableMapOf<Int?, Any>()
         override fun encodeTaggedValue(tag: Int?, value: Any) {
             tagList[tag] = value
         }
     }
 
-    class Emitter(val collected: Collector) : IntTaggedDecoder() {
+    class Emitter(val collected: Collector) : TaggedDecoder<Int?>() {
         private var i = 0
+
         override fun decodeSequentially(): Boolean = true
+        override fun SerialDescriptor.getTag(index: Int): Int? = getSerialId(this, index)
 
         override fun decodeElementIndex(desc: SerialDescriptor): Int {
             // js doesn't generate code for .decodeSequentially for the sake of keeping output small
diff --git a/runtime/commonTest/src/kotlinx/serialization/TestId.kt b/runtime/commonTest/src/kotlinx/serialization/TestId.kt
new file mode 100644
index 0000000..2d3d1c5
--- /dev/null
+++ b/runtime/commonTest/src/kotlinx/serialization/TestId.kt
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization
+
+@SerialInfo
+@Target(AnnotationTarget.PROPERTY)
+annotation class Id(val id: Int)
+
+public fun getSerialId(desc: SerialDescriptor, index: Int): Int?
+        = desc.findAnnotation<Id>(index)?.id
diff --git a/runtime/commonTest/src/kotlinx/serialization/features/ByteArraySerializerTest.kt b/runtime/commonTest/src/kotlinx/serialization/features/ByteArraySerializerTest.kt
index e7488aa..4119356 100644
--- a/runtime/commonTest/src/kotlinx/serialization/features/ByteArraySerializerTest.kt
+++ b/runtime/commonTest/src/kotlinx/serialization/features/ByteArraySerializerTest.kt
@@ -7,35 +7,35 @@
 import kotlinx.serialization.*
 import kotlinx.serialization.internal.ByteArraySerializer
 import kotlinx.serialization.json.Json
-import kotlinx.serialization.protobuf.ProtoBuf
 import kotlin.random.Random
 import kotlin.test.*
 
-@Serializable
-class ByteArrayCarrier(@SerialId(2) @Serializable(with = ByteArraySerializer::class) val data: ByteArray) {
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null || this::class != other::class) return false
-
-        other as ByteArrayCarrier
-
-        if (!data.contentEquals(other.data)) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        return data.contentHashCode()
-    }
-
-    override fun toString(): String {
-        return "ByteArrayCarrier(data=${data.contentToString()})"
-    }
-}
-
 class ByteArraySerializerTest {
+
+    @Serializable
+    class ByteArrayCarrier(@Id(2) @Serializable(with = ByteArraySerializer::class) val data: ByteArray) {
+        override fun equals(other: Any?): Boolean {
+            if (this === other) return true
+            if (other == null || this::class != other::class) return false
+
+            other as ByteArrayCarrier
+
+            if (!data.contentEquals(other.data)) return false
+
+            return true
+        }
+
+        override fun hashCode(): Int {
+            return data.contentHashCode()
+        }
+
+        override fun toString(): String {
+            return "ByteArrayCarrier(data=${data.contentToString()})"
+        }
+    }
+
     @Test
-    fun plain() {
+    fun testByteArrayJson() {
         val bytes = byteArrayOf(42, 43, 44, 45)
         val s = Json.stringify(ByteArraySerializer, bytes)
         assertEquals(s, """[42,43,44,45]""")
@@ -44,30 +44,11 @@
     }
 
     @Test
-    fun inObject() {
+    fun testWrappedByteArrayJson() {
         val obj = ByteArrayCarrier(byteArrayOf(42, 100))
         val s = Json.stringify(ByteArrayCarrier.serializer(), obj)
         assertEquals("""{"data":[42,100]}""", s)
         val obj2 = Json.parse(ByteArrayCarrier.serializer(), s)
         assertEquals(obj, obj2)
     }
-
-    @Test
-    fun inProto() {
-        val obj = ByteArrayCarrier(byteArrayOf(42, 100))
-        val s = ProtoBuf.dumps(ByteArrayCarrier.serializer(), obj)
-        assertEquals("""12022a64""", s)
-        val obj2 = ProtoBuf.loads(ByteArrayCarrier.serializer(), s)
-        assertEquals(obj, obj2)
-    }
-
-    @Test
-    fun serializeAndDeserializeLongArrays() {
-        val arraySize = 301
-        val arr = Random.nextBytes(ByteArray(arraySize))
-        val obj = ByteArrayCarrier(arr)
-        val bytes = ProtoBuf.dump(ByteArrayCarrier.serializer(), obj)
-        assertEquals(obj, ProtoBuf.load(ByteArrayCarrier.serializer(), bytes))
-    }
-
 }
diff --git a/runtime/commonTest/src/kotlinx/serialization/features/PolymorphismTest.kt b/runtime/commonTest/src/kotlinx/serialization/features/PolymorphismTest.kt
index cec5c4c..05fc183 100644
--- a/runtime/commonTest/src/kotlinx/serialization/features/PolymorphismTest.kt
+++ b/runtime/commonTest/src/kotlinx/serialization/features/PolymorphismTest.kt
@@ -7,15 +7,14 @@
 import kotlinx.serialization.*
 import kotlinx.serialization.json.Json
 import kotlinx.serialization.modules.*
-import kotlinx.serialization.protobuf.ProtoBuf
 import kotlin.test.*
 
 class PolymorphismTest {
 
     @Serializable
     data class Wrapper(
-        @SerialId(1) @Polymorphic val polyBase1: PolyBase,
-        @SerialId(2) @Polymorphic val polyBase2: PolyBase
+        @Id(1) @Polymorphic val polyBase1: PolyBase,
+        @Id(2) @Polymorphic val polyBase2: PolyBase
     )
 
     private val module: SerialModule = BaseAndDerivedModule + SerializersModule {
@@ -26,7 +25,7 @@
     }
 
     private val json = Json { unquoted = true; useArrayPolymorphism = true; serialModule = module }
-    private val protobuf = ProtoBuf(context = module)
+//    private val protobuf = ProtoBuf(context = module)
 
     @Test
     fun testInheritanceJson() {
@@ -41,16 +40,16 @@
         )
     }
 
-    @Test
-    fun testInheritanceProtobuf() {
-        val obj = Wrapper(
-            PolyBase(2),
-            PolyDerived("b")
-        )
-        val bytes = protobuf.dumps(Wrapper.serializer(), obj)
-        val restored = protobuf.loads(Wrapper.serializer(), bytes)
-        assertEquals(obj, restored)
-    }
+//    @Test
+//    fun testInheritanceProtobuf() {
+//        val obj = Wrapper(
+//            PolyBase(2),
+//            PolyDerived("b")
+//        )
+//        val bytes = protobuf.dumps(Wrapper.serializer(), obj)
+//        val restored = protobuf.loads(Wrapper.serializer(), bytes)
+//        assertEquals(obj, restored)
+//    }
 
     @Test
     fun testSerializeWithExplicitPolymorhpicSerializer() {
diff --git a/runtime/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt b/runtime/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt
index 683a5c0..cc5b62b 100644
--- a/runtime/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt
+++ b/runtime/commonTest/src/kotlinx/serialization/json/JsonCustomSerializersTest.kt
@@ -15,9 +15,9 @@
 class JsonCustomSerializersTest : JsonTestBase() {
     
     @Serializable
-    data class A(@SerialId(1) val b: B)
+    data class A(@Id(1) val b: B)
 
-    data class B(@SerialId(1) val value: Int)
+    data class B(@Id(1) val value: Int)
 
     object BSerializer : KSerializer<B> {
         override fun serialize(encoder: Encoder, obj: B) {
@@ -35,10 +35,10 @@
     }
 
     @Serializable
-    data class BList(@SerialId(1) val bs: List<B>)
+    data class BList(@Id(1) val bs: List<B>)
 
     @Serializable
-    data class C(@SerialId(1) val a: Int = 31, @SerialId(2) val b: Int = 42) {
+    data class C(@Id(1) val a: Int = 31, @Id(2) val b: Int = 42) {
         @Serializer(forClass = C::class)
         companion object: KSerializer<C> {
             override fun serialize(encoder: Encoder, obj: C) {
@@ -51,10 +51,10 @@
     }
 
     @Serializable
-    data class CList1(@SerialId(1) val c: List<C>)
+    data class CList1(@Id(1) val c: List<C>)
 
     @Serializable
-    data class CList2(@SerialId(1) val d: Int = 5, @SerialId(2) val c: List<C>) {
+    data class CList2(@Id(1) val d: Int = 5, @Id(2) val c: List<C>) {
         @Serializer(forClass = CList2::class)
         companion object: KSerializer<CList2> {
             override fun serialize(encoder: Encoder, obj: CList2) {
@@ -67,7 +67,7 @@
     }
 
     @Serializable
-    data class CList3(@SerialId(1) val e: List<C> = emptyList(), @SerialId(2) val f: Int) {
+    data class CList3(@Id(1) val e: List<C> = emptyList(), @Id(2) val f: Int) {
         @Serializer(forClass = CList3::class)
         companion object: KSerializer<CList3> {
             override fun serialize(encoder: Encoder, obj: CList3) {
@@ -80,7 +80,7 @@
     }
 
     @Serializable
-    data class CList4(@SerialId(1) val g: List<C> = emptyList(), @SerialId(2) val h: Int) {
+    data class CList4(@Id(1) val g: List<C> = emptyList(), @Id(2) val h: Int) {
         @Serializer(forClass = CList4::class)
         companion object: KSerializer<CList4> {
             override fun serialize(encoder: Encoder, obj: CList4) {
@@ -93,7 +93,7 @@
     }
 
     @Serializable
-    data class CList5(@SerialId(1) val g: List<Int> = emptyList(), @SerialId(2) val h: Int) {
+    data class CList5(@Id(1) val g: List<Int> = emptyList(), @Id(2) val h: Int) {
         @Serializer(forClass = CList5::class)
         companion object: KSerializer<CList5> {
             override fun serialize(encoder: Encoder, obj: CList5) {
diff --git a/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufReaderTest.kt b/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufReaderTest.kt
deleted file mode 100644
index 0527110..0000000
--- a/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufReaderTest.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.serialization.protobuf
-
-import kotlinx.serialization.loads
-import kotlinx.serialization.test.isNative
-import kotlinx.serialization.test.shouldBe
-import kotlin.test.Ignore
-import kotlin.test.Test
-
-class ProtobufReaderTest {
-
-    @Test
-    fun readSimpleObject() {
-        ProtoBuf.loads(TestInt.serializer(), "08ab02") shouldBe t1
-    }
-
-    @Test
-    fun readObjectWithString() {
-        ProtoBuf.loads(TestString.serializer(), "120774657374696E67") shouldBe t3
-    }
-
-    @Test
-    fun readObjectWithList() {
-        ProtoBuf.loads(TestList.serializer(), "08960108E40108B90A") shouldBe t2
-    }
-
-    @Test
-    fun readInnerObject() {
-        ProtoBuf.loads(TestInner.serializer(), "1a0308ab02") shouldBe t4
-    }
-
-    @Test
-    fun readObjectWithUnorderedTags() {
-        ProtoBuf.loads(TestComplex.serializer(), "120774657374696E67D0022A") shouldBe t5
-    }
-
-    @Test
-    fun readObjectsWithEmptyValues() {
-        ProtoBuf.loads(TestInt.serializer(), "0800") shouldBe t1e
-        ProtoBuf.loads(TestList.serializer(), "") shouldBe t2e
-        ProtoBuf.loads(TestString.serializer(), "1200") shouldBe t3e
-    }
-
-    @Test
-    fun readObjectWithUnknownFields() {
-        ProtoBuf.loads(TestInt.serializer(), "08960108E40108B90A08ab02120774657374696E67") shouldBe t1
-    }
-
-    @Test
-    fun readNumbers() {
-        ProtoBuf.loads(TestNumbers.serializer(), "0d9488010010ffffffffffffffff7f") shouldBe t6
-    }
-
-    @Test
-    fun mergeListIfSplitByAnotherField() {
-        if (isNative()) return // todo: support update on Native
-        ProtoBuf.loads(TestIntWithList.serializer(), "500308960150045005") shouldBe TestIntWithList(150, listOf(3, 4, 5))
-    }
-}
diff --git a/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufWriterTest.kt b/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufWriterTest.kt
deleted file mode 100644
index 45a1674..0000000
--- a/runtime/commonTest/src/kotlinx/serialization/protobuf/ProtobufWriterTest.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2017 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package kotlinx.serialization.protobuf
-
-import kotlinx.serialization.dumps
-import kotlinx.serialization.test.shouldBe
-import kotlin.test.Test
-
-class ProtobufWriterTest {
-
-    @Test
-    fun writeSignedInteger() {
-        ProtoBuf.dumps(TestInt.serializer(), t1).toLowerCase() shouldBe "08ab02"
-    }
-
-    @Test
-    fun writeListOfVarintIntegers() {
-        ProtoBuf.dumps(TestList.serializer(), t2).toUpperCase() shouldBe "08960108E40108B90A"
-    }
-
-    @Test
-    fun writeString() {
-        ProtoBuf.dumps(TestString.serializer(), t3).toUpperCase() shouldBe "120774657374696E67"
-    }
-
-    @Test
-    fun writeInnerObject() {
-        ProtoBuf.dumps(TestInner.serializer(), t4).toLowerCase() shouldBe "1a0308ab02"
-    }
-
-    @Test
-    fun writeObjectWithUnorderedTags() {
-        ProtoBuf.dumps(TestComplex.serializer(), t5).toUpperCase() shouldBe "D0022A120774657374696E67"
-    }
-
-    @Test
-    fun writeObjectsWithEmptyDefaultValues() {
-        ProtoBuf.dumps(TestInt.serializer(), t1e) shouldBe "0800"
-        ProtoBuf.dumps(TestList.serializer(), t2e) shouldBe ""
-        ProtoBuf.dumps(TestString.serializer(), t3e) shouldBe "1200"
-    }
-
-    @Test
-    fun writeNumbers() {
-        ProtoBuf.dumps(TestNumbers.serializer(), t6).toLowerCase() shouldBe "0d9488010010ffffffffffffffff7f"
-    }
-}
diff --git a/runtime/jvmTest/src/kotlinx/serialization/features/PolymorphicWithJvmClassTest.kt b/runtime/jvmTest/src/kotlinx/serialization/features/PolymorphicWithJvmClassTest.kt
deleted file mode 100644
index f21ea24..0000000
--- a/runtime/jvmTest/src/kotlinx/serialization/features/PolymorphicWithJvmClassTest.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2018 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package kotlinx.serialization.features
-
-import kotlinx.serialization.*
-import kotlinx.serialization.modules.SerializersModule
-import kotlinx.serialization.protobuf.ProtoBuf
-import org.junit.Test
-import java.util.*
-import kotlin.test.assertEquals
-
-class PolymorphicWithJvmClassTest {
-    @Serializable
-    data class DateWrapper(@SerialId(1) @Serializable(with = PolymorphicSerializer::class) val date: Date)
-
-    @Test
-    fun testPolymorphicWrappedOverride() {
-        val protobuf = ProtoBuf(context = SerializersModule { polymorphic(Date::class, DateSerializer) })
-        val obj = DateWrapper(Date())
-        val bytes = protobuf.dumps(obj)
-        val restored = protobuf.loads<DateWrapper>(bytes)
-        assertEquals(obj, restored)
-    }
-}
diff --git a/runtime/jvmTest/src/kotlinx/serialization/formats/FormatConverterHelpers.kt b/runtime/jvmTest/src/kotlinx/serialization/formats/FormatConverterHelpers.kt
deleted file mode 100644
index edab409..0000000
--- a/runtime/jvmTest/src/kotlinx/serialization/formats/FormatConverterHelpers.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.serialization.formats
-
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.dataformat.cbor.CBORFactory
-import com.fasterxml.jackson.module.kotlin.readValue
-import com.fasterxml.jackson.module.kotlin.registerKotlinModule
-import com.google.protobuf.GeneratedMessageV3
-import kotlinx.serialization.*
-import kotlinx.serialization.cbor.Cbor
-import kotlinx.serialization.internal.HexConverter
-import kotlinx.serialization.protobuf.ProtoBuf
-import java.io.ByteArrayOutputStream
-
-interface IMessage {
-    fun toProtobufMessage(): GeneratedMessageV3
-}
-
-fun GeneratedMessageV3.toHex(): String {
-    val b = ByteArrayOutputStream()
-    this.writeTo(b)
-    return (HexConverter.printHexBinary(b.toByteArray(), lowerCase = true))
-}
-
-inline fun <reified T : IMessage> dumpCompare(it: T, alwaysPrint: Boolean = false): Boolean {
-    val msg = it.toProtobufMessage()
-    var parsed: GeneratedMessageV3?
-    val c = try {
-        val bytes = ProtoBuf.dump(it)
-        if (alwaysPrint) println("Serialized bytes: ${HexConverter.printHexBinary(bytes)}")
-        parsed = msg.parserForType.parseFrom(bytes)
-        msg == parsed
-    } catch (e: Exception) {
-        e.printStackTrace()
-        parsed = null
-        false
-    }
-    if (!c || alwaysPrint) println("Expected: $msg\nfound: $parsed")
-    return c
-}
-
-inline fun <reified T : IMessage> readCompare(it: T, alwaysPrint: Boolean = false): Boolean {
-    var obj: T?
-    val c = try {
-        val msg = it.toProtobufMessage()
-        val hex = msg.toHex()
-        obj = ProtoBuf.loads<T>(hex)
-        obj == it
-    } catch (e: Exception) {
-        obj = null
-        e.printStackTrace()
-        false
-    }
-    if (!c || alwaysPrint) println("Expected: $it\nfound: $obj")
-    return c
-}
-
-internal val cborJackson = ObjectMapper(CBORFactory()).apply { registerKotlinModule() }
-
-internal inline fun <reified T : IMessage> dumpCborCompare(it: T, alwaysPrint: Boolean = false): Boolean {
-    var parsed: T?
-    val c = try {
-        val bytes = Cbor.dump(it)
-        parsed = cborJackson.readValue<T>(bytes)
-        it == parsed
-    } catch (e: Exception) {
-        e.printStackTrace()
-        parsed = null
-        false
-    }
-    if (!c || alwaysPrint) println("Expected: $it\nfound: $parsed")
-    return c
-}
-
-internal inline fun <reified T : IMessage> readCborCompare(it: T, alwaysPrint: Boolean = false): Boolean {
-    var obj: T?
-    val c = try {
-        val hex = cborJackson.writeValueAsBytes(it)
-        obj = Cbor.load<T>(hex)
-        obj == it
-    } catch (e: Exception) {
-        obj = null
-        e.printStackTrace()
-        false
-    }
-    if (!c || alwaysPrint) println("Expected: $it\nfound: $obj")
-    return c
-}
diff --git a/runtime/jvmTest/src/kotlinx/serialization/formats/RandomTests.kt b/runtime/jvmTest/src/kotlinx/serialization/formats/RandomTests.kt
index 7135186..7e35c7d 100644
--- a/runtime/jvmTest/src/kotlinx/serialization/formats/RandomTests.kt
+++ b/runtime/jvmTest/src/kotlinx/serialization/formats/RandomTests.kt
@@ -2,249 +2,247 @@
  * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
 
-package kotlinx.serialization.formats
-
-import com.google.protobuf.GeneratedMessageV3
-import io.kotlintest.properties.Gen
-import io.kotlintest.properties.forAll
-import io.kotlintest.specs.ShouldSpec
-import kotlinx.serialization.SerialId
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.formats.proto.TestData.*
-import kotlinx.serialization.protobuf.ProtoNumberType
-import kotlinx.serialization.protobuf.ProtoType
-
-fun Gen<String>.generateNotEmpty() = nextPrintableString(Gen.choose(1, 100).generate())
-
-object KTestData {
-    @Serializable
-    data class KTestInt32(@SerialId(1) val a: Int) : IMessage {
-        override fun toProtobufMessage(): GeneratedMessageV3 = TestInt32.newBuilder().setA(a).build()
-
-        companion object : Gen<KTestInt32> {
-            override fun generate(): KTestInt32 = KTestInt32(Gen.int().generate())
-        }
-    }
-
-    @Serializable
-    data class KTestSignedInt(@SerialId(1) @ProtoType(ProtoNumberType.SIGNED) val a: Int) : IMessage {
-        override fun toProtobufMessage(): GeneratedMessageV3 = TestSignedInt.newBuilder().setA(a).build()
-
-        companion object : Gen<KTestSignedInt> {
-            override fun generate(): KTestSignedInt = KTestSignedInt(Gen.int().generate())
-        }
-    }
-
-    @Serializable
-    data class KTestSignedLong(@SerialId(1) @ProtoType(ProtoNumberType.SIGNED) val a: Long) : IMessage {
-        override fun toProtobufMessage(): GeneratedMessageV3 = TestSignedLong.newBuilder().setA(a).build()
-
-        companion object : Gen<KTestSignedLong> {
-            override fun generate(): KTestSignedLong = KTestSignedLong(Gen.long().generate())
-        }
-    }
-
-    @Serializable
-    data class KTestFixedInt(@SerialId(1) @ProtoType(ProtoNumberType.FIXED) val a: Int) : IMessage {
-        override fun toProtobufMessage(): GeneratedMessageV3 = TestFixedInt.newBuilder().setA(a).build()
-
-        companion object : Gen<KTestFixedInt> {
-            override fun generate(): KTestFixedInt = KTestFixedInt(Gen.int().generate())
-        }
-    }
-
-    @Serializable
-    data class KTestDouble(@SerialId(1) val a: Double) : IMessage {
-        override fun toProtobufMessage(): GeneratedMessageV3 = TestDouble.newBuilder().setA(a).build()
-
-        companion object : Gen<KTestDouble> {
-            override fun generate(): KTestDouble = KTestDouble(Gen.double().generate())
-        }
-    }
-
-    @Serializable
-    data class KTestBoolean(@SerialId(1) val a: Boolean) : IMessage {
-        override fun toProtobufMessage(): GeneratedMessageV3 = TestBoolean.newBuilder().setA(a).build()
-
-        companion object : Gen<KTestBoolean> {
-            override fun generate(): KTestBoolean = KTestBoolean(Gen.bool().generate())
-        }
-    }
-
-    @Serializable
-    data class KTestAllTypes(
-            @SerialId(1) val i32: Int,
-            @SerialId(2) @ProtoType(ProtoNumberType.SIGNED) val si32: Int,
-            @SerialId(3) @ProtoType(ProtoNumberType.FIXED) val f32: Int,
-            @SerialId(10) val i64: Long,
-            @SerialId(11) @ProtoType(ProtoNumberType.SIGNED) val si64: Long,
-            @SerialId(12) @ProtoType(ProtoNumberType.FIXED) val f64: Long,
-            @SerialId(21) val f: Float,
-            @SerialId(22) val d: Double,
-            @SerialId(41) val b: Boolean = false,
-            @SerialId(51) val s: String
-    ) : IMessage {
-        override fun toProtobufMessage(): TestAllTypes = TestAllTypes.newBuilder()
-                .setI32(i32)
-                .setSi32(si32)
-                .setF32(f32)
-                .setI64(i64)
-                .setSi64(si64)
-                .setF64(f64)
-                .setF(f)
-                .setD(d)
-                .setB(b)
-                .setS(s)
-                .build()
-
-        companion object : Gen<KTestAllTypes> {
-            override fun generate(): KTestAllTypes = KTestAllTypes(
-                    Gen.int().generate(),
-                    Gen.int().generate(),
-                    Gen.int().generate(),
-                    Gen.long().generate(),
-                    Gen.long().generate(),
-                    Gen.long().generate(),
-                    Gen.float().generate(),
-                    Gen.double().generate(),
-                    Gen.bool().generate(),
-                    Gen.string().generateNotEmpty()
-            )
-        }
-    }
-
-    @Serializable
-    data class KTestOuterMessage(
-            @SerialId(1) val a: Int,
-            @SerialId(2) val b: Double,
-            @SerialId(10) val inner: KTestAllTypes,
-            @SerialId(20) val s: String
-    ) : IMessage {
-        override fun toProtobufMessage(): GeneratedMessageV3 = TestOuterMessage.newBuilder()
-                .setA(a)
-                .setB(b)
-                .setInner(inner.toProtobufMessage())
-                .setS(s)
-                .build()
-
-        companion object : Gen<KTestOuterMessage> {
-            override fun generate(): KTestOuterMessage = KTestOuterMessage(
-                    Gen.int().generate(),
-                    Gen.double().generate(),
-                    KTestAllTypes.generate(),
-                    Gen.string().generateNotEmpty()
-            )
-        }
-    }
-
-    @Serializable
-    data class KTestIntListMessage(
-            @SerialId(1) val s: Int,
-            @SerialId(10) val l: List<Int>
-    ) : IMessage {
-        override fun toProtobufMessage(): GeneratedMessageV3 = TestRepeatedIntMessage.newBuilder().setS(s).addAllB(l).build()
-
-        companion object : Gen<KTestIntListMessage> {
-            override fun generate() = KTestIntListMessage(Gen.int().generate(), Gen.list(Gen.int()).generate())
-        }
-    }
-
-    @Serializable
-    data class KTestObjectListMessage(
-            @SerialId(1) val inner: List<KTestAllTypes>
-    ) : IMessage {
-        override fun toProtobufMessage(): GeneratedMessageV3 = TestRepeatedObjectMessage.newBuilder().addAllInner(inner.map { it.toProtobufMessage() }).build()
-
-        companion object : Gen<KTestObjectListMessage> {
-            override fun generate() = KTestObjectListMessage(Gen.list(KTestAllTypes.Companion).generate())
-        }
-    }
-
-    enum class KCoffee { AMERICANO, LATTE, CAPPUCCINO }
-
-    @Serializable
-    data class KTestEnum(@SerialId(1) val a: KCoffee): IMessage {
-        override fun toProtobufMessage() = TestEnum.newBuilder().setA(TestEnum.Coffee.forNumber(a.ordinal)).build()
-
-        companion object : Gen<KTestEnum> {
-            override fun generate(): KTestEnum = KTestEnum(Gen.oneOf<KCoffee>().generate())
-        }
-    }
-
-    @Serializable
-    data class KTestMap(@SerialId(1) val s: Map<String, String>, @SerialId(2) val o: Map<Int, KTestAllTypes> = emptyMap()) :
-        IMessage {
-        override fun toProtobufMessage() = TestMap.newBuilder()
-            .putAllStringMap(s)
-            .putAllIntObjectMap(o.mapValues { it.value.toProtobufMessage() })
-            .build()
-
-        companion object : Gen<KTestMap> {
-            override fun generate(): KTestMap =
-                KTestMap(Gen.map(Gen.string(), Gen.string()).generate(), Gen.map(Gen.int(), KTestAllTypes).generate())
-        }
-    }
-}
-
-
-class RandomTest : ShouldSpec() {
-
-    init {
-        "Protobuf serialization" {
-            should("serialize random int32") { forAll(KTestData.KTestInt32.Companion) { dumpCompare(it) } }
-            should("serialize random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { dumpCompare(it) } }
-            should("serialize random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { dumpCompare(it) } }
-            should("serialize random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { dumpCompare(it) } }
-            should("serialize random doubles") { forAll(KTestData.KTestDouble.Companion) { dumpCompare(it) } }
-            should("serialize random booleans") { forAll(KTestData.KTestBoolean.Companion) { dumpCompare(it) } }
-            should("serialize random enums") { forAll(KTestData.KTestEnum.Companion) { dumpCompare(it) } }
-            should("serialize all base random types") { forAll(KTestData.KTestAllTypes.Companion) { dumpCompare(it) } }
-            should("serialize random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { dumpCompare(it) } }
-            should("serialize random messages with primitive list fields as repeated") { forAll(KTestData.KTestIntListMessage.Companion) { dumpCompare(it) } }
-            should("serialize messages with object list fields as repeated") { forAll(KTestData.KTestObjectListMessage.Companion) { dumpCompare(it) } }
-            should("serialize messages with scalar-key maps") { forAll(KTestData.KTestMap.Companion) { dumpCompare(it) } }
-        }
-
-        "Protobuf deserialization" {
-            should("read random int32") { forAll(KTestData.KTestInt32.Companion) { readCompare(it) } }
-            should("read random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { readCompare(it) } }
-            should("read random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { readCompare(it) } }
-            should("read random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { readCompare(it) } }
-            should("read random doubles") { forAll(KTestData.KTestDouble.Companion) { readCompare(it) } }
-            should("read random enums") { forAll(KTestData.KTestEnum.Companion) { readCompare(it) } }
-            should("read all base random types") { forAll(KTestData.KTestAllTypes.Companion) { readCompare(it) } }
-            should("read random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { readCompare(it) } }
-            should("read random messages with primitive list fields as repeated") { forAll(KTestData.KTestIntListMessage.Companion) { readCompare(it) } }
-            should("read random messages with object list fields as repeated") { forAll(KTestData.KTestObjectListMessage.Companion) { readCompare(it) } }
-            should("read messages with scalar-key maps") { forAll(KTestData.KTestMap.Companion) { readCompare(it) } }
-        }
-
-        "CBOR Writer" {
-            should("serialize random int32") { forAll(KTestData.KTestInt32.Companion) { dumpCborCompare(it) } }
-            should("serialize random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { dumpCborCompare(it) } }
-            should("serialize random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { dumpCborCompare(it) } }
-            should("serialize random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { dumpCborCompare(it) } }
-            should("serialize random doubles") { forAll(KTestData.KTestDouble.Companion) { dumpCborCompare(it) } }
-            should("serialize random booleans") { forAll(KTestData.KTestBoolean.Companion) { dumpCborCompare(it) } }
-            should("serialize random enums") { forAll(KTestData.KTestEnum.Companion) { dumpCborCompare(it) } }
-            should("serialize all base random types") { forAll(KTestData.KTestAllTypes.Companion) { dumpCborCompare(it) } }
-            should("serialize random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { dumpCborCompare(it) } }
-            should("serialize random messages with primitive list fields") { forAll(KTestData.KTestIntListMessage.Companion) { dumpCborCompare(it) } }
-            should("serialize messages with object list fields") { forAll(KTestData.KTestObjectListMessage.Companion) { dumpCborCompare(it) } }
-            should("serialize messages with scalar-key maps") { forAll(KTestData.KTestMap.Companion) { dumpCborCompare(it) } }
-        }
-
-        "CBOR Reader" {
-            should("read random int32") { forAll(KTestData.KTestInt32.Companion) { readCborCompare(it) } }
-            should("read random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { readCborCompare(it) } }
-            should("read random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { readCborCompare(it) } }
-            should("read random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { readCborCompare(it) } }
-            should("read random doubles") { forAll(KTestData.KTestDouble.Companion) { readCborCompare(it) } }
-            should("read random enums") { forAll(KTestData.KTestEnum.Companion) { readCborCompare(it) } }
-            should("read all base random types") { forAll(KTestData.KTestAllTypes.Companion) { readCborCompare(it) } }
-            should("read random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { readCborCompare(it) } }
-            should("read random messages with primitive list fields") { forAll(KTestData.KTestIntListMessage.Companion) { readCborCompare(it) } }
-            should("read random messages with object list fields") { forAll(KTestData.KTestObjectListMessage.Companion) { readCborCompare(it) } }
-        }
-    }
-}
+//package kotlinx.serialization.formats
+//
+//import com.google.protobuf.GeneratedMessageV3
+//import io.kotlintest.properties.Gen
+//import io.kotlintest.properties.forAll
+//import io.kotlintest.specs.ShouldSpec
+//import kotlinx.serialization.SerialId
+//import kotlinx.serialization.Serializable
+//import kotlinx.serialization.formats.proto.TestData.*
+//
+//fun Gen<String>.generateNotEmpty() = nextPrintableString(Gen.choose(1, 100).generate())
+//
+//object KTestData {
+//    @Serializable
+//    data class KTestInt32(@SerialId(1) val a: Int) : IMessage {
+//        override fun toProtobufMessage(): GeneratedMessageV3 = TestInt32.newBuilder().setA(a).build()
+//
+//        companion object : Gen<KTestInt32> {
+//            override fun generate(): KTestInt32 = KTestInt32(Gen.int().generate())
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestSignedInt(@SerialId(1) @ProtoType(ProtoNumberType.SIGNED) val a: Int) : IMessage {
+//        override fun toProtobufMessage(): GeneratedMessageV3 = TestSignedInt.newBuilder().setA(a).build()
+//
+//        companion object : Gen<KTestSignedInt> {
+//            override fun generate(): KTestSignedInt = KTestSignedInt(Gen.int().generate())
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestSignedLong(@SerialId(1) @ProtoType(ProtoNumberType.SIGNED) val a: Long) : IMessage {
+//        override fun toProtobufMessage(): GeneratedMessageV3 = TestSignedLong.newBuilder().setA(a).build()
+//
+//        companion object : Gen<KTestSignedLong> {
+//            override fun generate(): KTestSignedLong = KTestSignedLong(Gen.long().generate())
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestFixedInt(@SerialId(1) @ProtoType(ProtoNumberType.FIXED) val a: Int) : IMessage {
+//        override fun toProtobufMessage(): GeneratedMessageV3 = TestFixedInt.newBuilder().setA(a).build()
+//
+//        companion object : Gen<KTestFixedInt> {
+//            override fun generate(): KTestFixedInt = KTestFixedInt(Gen.int().generate())
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestDouble(@SerialId(1) val a: Double) : IMessage {
+//        override fun toProtobufMessage(): GeneratedMessageV3 = TestDouble.newBuilder().setA(a).build()
+//
+//        companion object : Gen<KTestDouble> {
+//            override fun generate(): KTestDouble = KTestDouble(Gen.double().generate())
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestBoolean(@SerialId(1) val a: Boolean) : IMessage {
+//        override fun toProtobufMessage(): GeneratedMessageV3 = TestBoolean.newBuilder().setA(a).build()
+//
+//        companion object : Gen<KTestBoolean> {
+//            override fun generate(): KTestBoolean = KTestBoolean(Gen.bool().generate())
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestAllTypes(
+//            @SerialId(1) val i32: Int,
+//            @SerialId(2) @ProtoType(ProtoNumberType.SIGNED) val si32: Int,
+//            @SerialId(3) @ProtoType(ProtoNumberType.FIXED) val f32: Int,
+//            @SerialId(10) val i64: Long,
+//            @SerialId(11) @ProtoType(ProtoNumberType.SIGNED) val si64: Long,
+//            @SerialId(12) @ProtoType(ProtoNumberType.FIXED) val f64: Long,
+//            @SerialId(21) val f: Float,
+//            @SerialId(22) val d: Double,
+//            @SerialId(41) val b: Boolean = false,
+//            @SerialId(51) val s: String
+//    ) : IMessage {
+//        override fun toProtobufMessage(): TestAllTypes = TestAllTypes.newBuilder()
+//                .setI32(i32)
+//                .setSi32(si32)
+//                .setF32(f32)
+//                .setI64(i64)
+//                .setSi64(si64)
+//                .setF64(f64)
+//                .setF(f)
+//                .setD(d)
+//                .setB(b)
+//                .setS(s)
+//                .build()
+//
+//        companion object : Gen<KTestAllTypes> {
+//            override fun generate(): KTestAllTypes = KTestAllTypes(
+//                    Gen.int().generate(),
+//                    Gen.int().generate(),
+//                    Gen.int().generate(),
+//                    Gen.long().generate(),
+//                    Gen.long().generate(),
+//                    Gen.long().generate(),
+//                    Gen.float().generate(),
+//                    Gen.double().generate(),
+//                    Gen.bool().generate(),
+//                    Gen.string().generateNotEmpty()
+//            )
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestOuterMessage(
+//            @SerialId(1) val a: Int,
+//            @SerialId(2) val b: Double,
+//            @SerialId(10) val inner: KTestAllTypes,
+//            @SerialId(20) val s: String
+//    ) : IMessage {
+//        override fun toProtobufMessage(): GeneratedMessageV3 = TestOuterMessage.newBuilder()
+//                .setA(a)
+//                .setB(b)
+//                .setInner(inner.toProtobufMessage())
+//                .setS(s)
+//                .build()
+//
+//        companion object : Gen<KTestOuterMessage> {
+//            override fun generate(): KTestOuterMessage = KTestOuterMessage(
+//                    Gen.int().generate(),
+//                    Gen.double().generate(),
+//                    KTestAllTypes.generate(),
+//                    Gen.string().generateNotEmpty()
+//            )
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestIntListMessage(
+//            @SerialId(1) val s: Int,
+//            @SerialId(10) val l: List<Int>
+//    ) : IMessage {
+//        override fun toProtobufMessage(): GeneratedMessageV3 = TestRepeatedIntMessage.newBuilder().setS(s).addAllB(l).build()
+//
+//        companion object : Gen<KTestIntListMessage> {
+//            override fun generate() = KTestIntListMessage(Gen.int().generate(), Gen.list(Gen.int()).generate())
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestObjectListMessage(
+//            @SerialId(1) val inner: List<KTestAllTypes>
+//    ) : IMessage {
+//        override fun toProtobufMessage(): GeneratedMessageV3 = TestRepeatedObjectMessage.newBuilder().addAllInner(inner.map { it.toProtobufMessage() }).build()
+//
+//        companion object : Gen<KTestObjectListMessage> {
+//            override fun generate() = KTestObjectListMessage(Gen.list(KTestAllTypes.Companion).generate())
+//        }
+//    }
+//
+//    enum class KCoffee { AMERICANO, LATTE, CAPPUCCINO }
+//
+//    @Serializable
+//    data class KTestEnum(@SerialId(1) val a: KCoffee): IMessage {
+//        override fun toProtobufMessage() = TestEnum.newBuilder().setA(TestEnum.Coffee.forNumber(a.ordinal)).build()
+//
+//        companion object : Gen<KTestEnum> {
+//            override fun generate(): KTestEnum = KTestEnum(Gen.oneOf<KCoffee>().generate())
+//        }
+//    }
+//
+//    @Serializable
+//    data class KTestMap(@SerialId(1) val s: Map<String, String>, @SerialId(2) val o: Map<Int, KTestAllTypes> = emptyMap()) :
+//        IMessage {
+//        override fun toProtobufMessage() = TestMap.newBuilder()
+//            .putAllStringMap(s)
+//            .putAllIntObjectMap(o.mapValues { it.value.toProtobufMessage() })
+//            .build()
+//
+//        companion object : Gen<KTestMap> {
+//            override fun generate(): KTestMap =
+//                KTestMap(Gen.map(Gen.string(), Gen.string()).generate(), Gen.map(Gen.int(), KTestAllTypes).generate())
+//        }
+//    }
+//}
+//
+//
+//class RandomTest : ShouldSpec() {
+//
+//    init {
+//        "Protobuf serialization" {
+//            should("serialize random int32") { forAll(KTestData.KTestInt32.Companion) { dumpCompare(it) } }
+//            should("serialize random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { dumpCompare(it) } }
+//            should("serialize random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { dumpCompare(it) } }
+//            should("serialize random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { dumpCompare(it) } }
+//            should("serialize random doubles") { forAll(KTestData.KTestDouble.Companion) { dumpCompare(it) } }
+//            should("serialize random booleans") { forAll(KTestData.KTestBoolean.Companion) { dumpCompare(it) } }
+//            should("serialize random enums") { forAll(KTestData.KTestEnum.Companion) { dumpCompare(it) } }
+//            should("serialize all base random types") { forAll(KTestData.KTestAllTypes.Companion) { dumpCompare(it) } }
+//            should("serialize random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { dumpCompare(it) } }
+//            should("serialize random messages with primitive list fields as repeated") { forAll(KTestData.KTestIntListMessage.Companion) { dumpCompare(it) } }
+//            should("serialize messages with object list fields as repeated") { forAll(KTestData.KTestObjectListMessage.Companion) { dumpCompare(it) } }
+//            should("serialize messages with scalar-key maps") { forAll(KTestData.KTestMap.Companion) { dumpCompare(it) } }
+//        }
+//
+//        "Protobuf deserialization" {
+//            should("read random int32") { forAll(KTestData.KTestInt32.Companion) { readCompare(it) } }
+//            should("read random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { readCompare(it) } }
+//            should("read random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { readCompare(it) } }
+//            should("read random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { readCompare(it) } }
+//            should("read random doubles") { forAll(KTestData.KTestDouble.Companion) { readCompare(it) } }
+//            should("read random enums") { forAll(KTestData.KTestEnum.Companion) { readCompare(it) } }
+//            should("read all base random types") { forAll(KTestData.KTestAllTypes.Companion) { readCompare(it) } }
+//            should("read random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { readCompare(it) } }
+//            should("read random messages with primitive list fields as repeated") { forAll(KTestData.KTestIntListMessage.Companion) { readCompare(it) } }
+//            should("read random messages with object list fields as repeated") { forAll(KTestData.KTestObjectListMessage.Companion) { readCompare(it) } }
+//            should("read messages with scalar-key maps") { forAll(KTestData.KTestMap.Companion) { readCompare(it) } }
+//        }
+//
+//        "CBOR Writer" {
+//            should("serialize random int32") { forAll(KTestData.KTestInt32.Companion) { dumpCborCompare(it) } }
+//            should("serialize random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { dumpCborCompare(it) } }
+//            should("serialize random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { dumpCborCompare(it) } }
+//            should("serialize random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { dumpCborCompare(it) } }
+//            should("serialize random doubles") { forAll(KTestData.KTestDouble.Companion) { dumpCborCompare(it) } }
+//            should("serialize random booleans") { forAll(KTestData.KTestBoolean.Companion) { dumpCborCompare(it) } }
+//            should("serialize random enums") { forAll(KTestData.KTestEnum.Companion) { dumpCborCompare(it) } }
+//            should("serialize all base random types") { forAll(KTestData.KTestAllTypes.Companion) { dumpCborCompare(it) } }
+//            should("serialize random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { dumpCborCompare(it) } }
+//            should("serialize random messages with primitive list fields") { forAll(KTestData.KTestIntListMessage.Companion) { dumpCborCompare(it) } }
+//            should("serialize messages with object list fields") { forAll(KTestData.KTestObjectListMessage.Companion) { dumpCborCompare(it) } }
+//            should("serialize messages with scalar-key maps") { forAll(KTestData.KTestMap.Companion) { dumpCborCompare(it) } }
+//        }
+//
+//        "CBOR Reader" {
+//            should("read random int32") { forAll(KTestData.KTestInt32.Companion) { readCborCompare(it) } }
+//            should("read random signed int32") { forAll(KTestData.KTestSignedInt.Companion) { readCborCompare(it) } }
+//            should("read random signed int64") { forAll(KTestData.KTestSignedLong.Companion) { readCborCompare(it) } }
+//            should("read random fixed int32") { forAll(KTestData.KTestFixedInt.Companion) { readCborCompare(it) } }
+//            should("read random doubles") { forAll(KTestData.KTestDouble.Companion) { readCborCompare(it) } }
+//            should("read random enums") { forAll(KTestData.KTestEnum.Companion) { readCborCompare(it) } }
+//            should("read all base random types") { forAll(KTestData.KTestAllTypes.Companion) { readCborCompare(it) } }
+//            should("read random messages with embedded message") { forAll(KTestData.KTestOuterMessage.Companion) { readCborCompare(it) } }
+//            should("read random messages with primitive list fields") { forAll(KTestData.KTestIntListMessage.Companion) { readCborCompare(it) } }
+//            should("read random messages with object list fields") { forAll(KTestData.KTestObjectListMessage.Companion) { readCborCompare(it) } }
+//        }
+//    }
+//}
diff --git a/runtime/jvmTest/src/kotlinx/serialization/formats/protobuf/ProtobufEnumWithSerialIdTest.kt b/runtime/jvmTest/src/kotlinx/serialization/formats/protobuf/ProtobufEnumWithSerialIdTest.kt
deleted file mode 100644
index d2c8d79..0000000
--- a/runtime/jvmTest/src/kotlinx/serialization/formats/protobuf/ProtobufEnumWithSerialIdTest.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.serialization.formats.protobuf
-
-import kotlinx.serialization.SerialId
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.formats.*
-import kotlinx.serialization.formats.proto.TestData
-import org.junit.Test
-import kotlin.test.assertTrue
-
-@Serializable
-enum class EnumWithIds(val id: Int) {
-    @SerialId(10)
-    FIRST(10),
-    @SerialId(20)
-    SECOND(20);
-}
-
-@Serializable
-data class EnumHolder(@SerialId(5) val a: EnumWithIds) : IMessage {
-    override fun toProtobufMessage(): TestData.EnumHolder =
-        TestData.EnumHolder.newBuilder().setA(TestData.TestEnumWithIds.forNumber(a.id)).build()
-}
-
-class ProtobufEnumWithSerialIdTest {
-    @Test
-    fun enumsSupportSerialIds() {
-        assertTrue(readCompare(EnumHolder(EnumWithIds.SECOND), alwaysPrint = true))
-    }
-
-    @Test
-    fun enumsSupportSerialIds2() {
-        assertTrue(dumpCompare(EnumHolder(EnumWithIds.SECOND), alwaysPrint = true))
-    }
-}
diff --git a/settings.gradle b/settings.gradle
index b7cb4d8..703166a 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,17 +1,5 @@
 /*
- * Copyright 2018 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
 
 rootProject.name = 'kotlinx-serialization'
@@ -20,9 +8,11 @@
 include ':kotlinx-serialization-runtime'
 project(':kotlinx-serialization-runtime').projectDir = file('./runtime')
 
+include ':kotlinx-serialization-protobuf'
+project(':kotlinx-serialization-protobuf').projectDir = file('./formats/protobuf')
+
 include ':kotlinx-serialization-runtime-configparser'
 project(':kotlinx-serialization-runtime-configparser').projectDir = file('./formats/config')
 
-// todo: migrate benchmark to multiplatform benchmarks?
 include ':benchmark'
 project(':benchmark').projectDir = file('./benchmark')