diff --git a/gradle.properties b/gradle.properties
index 06e6f52c40fde50f12b8f953b7c5eef140d5af1d..42e8ad257b73c648331866de0f55314cd0527827 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -6,7 +6,7 @@ kotlinBitflagsVersion=1.1.0
 sl4jVersion=1.7.30
 testcontainersCiVersion=1.1.0
 GROUP=de.justjanne.libquassel
-VERSION_NAME=0.1.0
+VERSION_NAME=0.2.0
 POM_URL=https://git.kuschku.de/justJanne/libquassel
 POM_SCM_URL=https://git.kuschku.de/justJanne/libquassel
 POM_SCM_CONNECTION=scm:git:https://git.kuschku.de/justJanne/libquassel.git
diff --git a/libquassel-client/build.gradle.kts b/libquassel-client/build.gradle.kts
index 63ff1a47bcc37ff7338ad208790d2a3e14619dca..4159a46011efbffa02a2d96fbfa8b1e8c7c88e7a 100644
--- a/libquassel-client/build.gradle.kts
+++ b/libquassel-client/build.gradle.kts
@@ -3,7 +3,7 @@ plugins {
 }
 
 dependencies {
-  api(project(":libquassel-messages"))
+  api(project(":libquassel-protocol"))
 
   val testcontainersCiVersion: String by project
   testImplementation("de.justjanne", "testcontainers-ci", testcontainersCiVersion)
diff --git a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/EndToEndTest.kt b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/EndToEndTest.kt
index 818a6b233a94f0ee85ef523bbad6cd822cf48f42..c7941c2d1bddf6993d4caa7ba4ac5dc20dacb326 100644
--- a/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/EndToEndTest.kt
+++ b/libquassel-client/src/test/kotlin/de/justjanne/libquassel/client/EndToEndTest.kt
@@ -23,21 +23,21 @@ import de.justjanne.bitflags.of
 import de.justjanne.libquassel.client.io.CoroutineChannel
 import de.justjanne.libquassel.client.testutil.QuasselCoreContainer
 import de.justjanne.libquassel.client.testutil.TestX509TrustManager
-import de.justjanne.libquassel.messages.handshake.ClientInitSerializer
-import de.justjanne.libquassel.messages.handshake.ClientLoginSerializer
-import de.justjanne.libquassel.messages.handshake.CoreSetupDataSerializer
-import de.justjanne.libquassel.messages.handshake.HandshakeMessage
-import de.justjanne.libquassel.messages.handshake.HandshakeSerializers
-import de.justjanne.libquassel.protocol.connection.ConnectionHeader
-import de.justjanne.libquassel.protocol.connection.ConnectionHeaderSerializer
+import de.justjanne.libquassel.protocol.connection.ClientHeader
+import de.justjanne.libquassel.protocol.connection.ClientHeaderSerializer
+import de.justjanne.libquassel.protocol.connection.CoreHeaderSerializer
 import de.justjanne.libquassel.protocol.connection.ProtocolFeature
-import de.justjanne.libquassel.protocol.connection.ProtocolInfoSerializer
 import de.justjanne.libquassel.protocol.connection.ProtocolMeta
 import de.justjanne.libquassel.protocol.connection.ProtocolVersion
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializers
+import de.justjanne.libquassel.protocol.serializers.handshake.ClientInitSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.ClientLoginSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.CoreSetupDataSerializer
 import de.justjanne.libquassel.protocol.serializers.qt.HandshakeMapSerializer
 import de.justjanne.libquassel.protocol.serializers.qt.IntSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.testcontainersci.api.providedContainer
 import de.justjanne.testcontainersci.extension.CiContainers
@@ -80,17 +80,17 @@ class EndToEndTest {
 
     println("Writing protocol")
     write(sizePrefix = false) {
-      ConnectionHeaderSerializer.serialize(
+      ClientHeaderSerializer.serialize(
         it,
-        ConnectionHeader(
+        ClientHeader(
           features = ProtocolFeature.of(
             ProtocolFeature.Compression,
             ProtocolFeature.TLS
           ),
           versions = listOf(
             ProtocolMeta(
-              0x0000u,
               ProtocolVersion.Datastream,
+              0x0000u,
             ),
           )
         ),
@@ -100,19 +100,19 @@ class EndToEndTest {
 
     println("Reading protocol")
     read(4) {
-      val protocol = ProtocolInfoSerializer.deserialize(it, connectionFeatureSet)
+      val protocol = CoreHeaderSerializer.deserialize(it, connectionFeatureSet)
       assertEquals(
         ProtocolFeature.of(
           ProtocolFeature.TLS,
           ProtocolFeature.Compression
         ),
-        protocol.flags
+        protocol.features
       )
       println("Negotiated protocol $protocol")
-      if (protocol.flags.contains(ProtocolFeature.TLS)) {
+      if (protocol.features.contains(ProtocolFeature.TLS)) {
         channel.enableTLS(sslContext)
       }
-      if (protocol.flags.contains(ProtocolFeature.Compression)) {
+      if (protocol.features.contains(ProtocolFeature.Compression)) {
         channel.enableCompression()
       }
     }
diff --git a/libquassel-messages/build.gradle.kts b/libquassel-messages/build.gradle.kts
deleted file mode 100644
index 84b7c31d4acfa8c65ea89c403b23bb63082446a4..0000000000000000000000000000000000000000
--- a/libquassel-messages/build.gradle.kts
+++ /dev/null
@@ -1,12 +0,0 @@
-plugins {
-  id("com.vanniktech.maven.publish")
-}
-
-dependencies {
-  api(project(":libquassel-protocol"))
-
-  val testcontainersCiVersion: String by project
-  testImplementation("de.justjanne", "testcontainers-ci", testcontainersCiVersion)
-  val sl4jVersion: String by project
-  testImplementation("org.slf4j", "slf4j-simple", sl4jVersion)
-}
diff --git a/libquassel-messages/gradle.properties b/libquassel-messages/gradle.properties
deleted file mode 100644
index 49edf04efa2da15732c293e78745c11e670bb18b..0000000000000000000000000000000000000000
--- a/libquassel-messages/gradle.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-POM_ARTIFACT_ID=libquassel-messages
-POM_NAME=libquassel Messages
-POM_DESCRIPTION=Library implementing Quassel's RPC messages for Kotlin
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/byteBufferOf.kt b/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/byteBufferOf.kt
deleted file mode 100644
index 267a6f37510aaa42fd7453c66ccc7374c2c29a48..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/byteBufferOf.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2021 Janne Mareike Koschinski
- * Copyright (c) 2021 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package de.justjanne.libquassel.messages.testutil
-
-import java.nio.ByteBuffer
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun byteBufferOf(
-  vararg elements: Byte
-): ByteBuffer = ByteBuffer.wrap(byteArrayOf(*elements))
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun byteBufferOf(
-  vararg elements: UByte
-): ByteBuffer = ByteBuffer.wrap(ubyteArrayOf(*elements).toByteArray())
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun byteBufferOf(): ByteBuffer =
-  ByteBuffer.allocateDirect(0)
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/deserialize.kt b/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/deserialize.kt
deleted file mode 100644
index 7de507ecff17f2c1ab6cc8d58fdf39d9db5e937e..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/deserialize.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2021 Janne Mareike Koschinski
- * Copyright (c) 2021 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package de.justjanne.libquassel.messages.testutil
-
-import de.justjanne.libquassel.messages.handshake.HandshakeSerializer
-import de.justjanne.libquassel.protocol.features.FeatureSet
-import de.justjanne.libquassel.protocol.serializers.Serializer
-import de.justjanne.libquassel.protocol.serializers.qt.HandshakeMapSerializer
-import org.hamcrest.Matcher
-import org.hamcrest.MatcherAssert.assertThat
-import org.junit.jupiter.api.Assertions.assertEquals
-import java.nio.ByteBuffer
-
-fun <T> deserialize(
-  serializer: Serializer<T>,
-  buffer: ByteBuffer,
-  featureSet: FeatureSet = FeatureSet.all()
-): T {
-  val result = serializer.deserialize(buffer, featureSet)
-  assertEquals(0, buffer.remaining())
-  return result
-}
-
-fun <T> testDeserialize(
-  serializer: HandshakeSerializer<T>,
-  matcher: Matcher<in T>,
-  buffer: ByteBuffer,
-  featureSet: FeatureSet = FeatureSet.all()
-) {
-  val map = deserialize(HandshakeMapSerializer, buffer, featureSet)
-  val after = serializer.deserialize(map)
-  assertThat(after, matcher)
-}
-
-fun <T> testDeserialize(
-  serializer: HandshakeSerializer<T>,
-  data: T,
-  buffer: ByteBuffer,
-  featureSet: FeatureSet = FeatureSet.all()
-) {
-  val map = deserialize(HandshakeMapSerializer, buffer, featureSet)
-  val after = serializer.deserialize(map)
-  assertEquals(data, after)
-}
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/BomMatcherChar.kt b/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/BomMatcherChar.kt
deleted file mode 100644
index 4c83d1ed37716611e025d5b106536bc835734f5c..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/BomMatcherChar.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2021 Janne Mareike Koschinski
- * Copyright (c) 2021 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package de.justjanne.libquassel.protocol.testutil.matchers
-
-import org.hamcrest.BaseMatcher
-import org.hamcrest.Description
-
-class BomMatcherChar(private val expected: Char) : BaseMatcher<Char>() {
-  private val malformed = charArrayOf(
-    '\uFFFE', '\uFEFF', '\uFFFD', ''
-  )
-
-  override fun describeTo(description: Description?) {
-    description?.appendText(expected.toString())
-  }
-
-  override fun matches(item: Any?): Boolean {
-    if (item is Char) {
-      return (item == expected) || (item in malformed && expected in malformed)
-    }
-    return false
-  }
-}
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/BomMatcherString.kt b/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/BomMatcherString.kt
deleted file mode 100644
index 4173866984c836da611bf13b198d32b608a7c3a9..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/BomMatcherString.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2021 Janne Mareike Koschinski
- * Copyright (c) 2021 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package de.justjanne.libquassel.protocol.testutil.matchers
-
-import org.hamcrest.BaseMatcher
-import org.hamcrest.Description
-
-class BomMatcherString(private val expected: String?) : BaseMatcher<String?>() {
-  private val malformed = charArrayOf(
-    '￾', ''
-  )
-
-  override fun describeTo(description: Description?) {
-    description?.appendText(expected)
-  }
-
-  override fun matches(item: Any?) =
-    (item as? String)?.endsWith(expected?.trimStart(*malformed) ?: "") == true
-}
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/ByteBufferMatcher.kt b/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/ByteBufferMatcher.kt
deleted file mode 100644
index e8a6e9cf42635a794f7ea94d7dff3a08fe436b93..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/ByteBufferMatcher.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2021 Janne Mareike Koschinski
- * Copyright (c) 2021 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package de.justjanne.libquassel.protocol.testutil.matchers
-
-import de.justjanne.libquassel.protocol.io.contentToString
-import de.justjanne.libquassel.protocol.io.isEmpty
-import org.hamcrest.BaseMatcher
-import org.hamcrest.Description
-import java.nio.ByteBuffer
-
-class ByteBufferMatcher(buffer: ByteBuffer?) : BaseMatcher<ByteBuffer>() {
-  private val expected = buffer?.let { original ->
-    val copy = ByteBuffer.allocateDirect(original.limit())
-    original.rewind()
-    copy.put(original)
-    copy.rewind()
-    original.rewind()
-    copy
-  }
-
-  override fun describeTo(description: Description?) {
-    description?.appendText(expected?.contentToString())
-  }
-
-  override fun describeMismatch(item: Any?, description: Description?) {
-    description?.appendText("was ")
-    description?.appendText((item as? ByteBuffer)?.rewind()?.contentToString())
-  }
-
-  override fun matches(item: Any?): Boolean {
-    val actual = item as? ByteBuffer
-
-    if (actual.isEmpty() && expected.isEmpty()) {
-      return true
-    }
-
-    return actual?.rewind()?.contentToString() == expected?.rewind()?.contentToString()
-  }
-}
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/MapMatcher.kt b/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/MapMatcher.kt
deleted file mode 100644
index cded0d1d530abb68c460d241a36ee7b071556e3b..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/MapMatcher.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2021 Janne Mareike Koschinski
- * Copyright (c) 2021 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package de.justjanne.libquassel.protocol.testutil.matchers
-
-import org.hamcrest.BaseMatcher
-import org.hamcrest.Description
-
-class MapMatcher<K, V>(
-  private val expected: Map<K, V>
-) : BaseMatcher<Map<K, V>>() {
-  override fun describeTo(description: Description?) {
-    description?.appendText(expected.toString())
-  }
-
-  override fun describeMismatch(item: Any?, description: Description?) {
-    if (item is Map<*, *>) {
-      for (key in expected.keys) {
-        if (!item.containsKey(key)) {
-          description?.appendText(" did not have key $key")
-        }
-        if (expected[key] != item[key]) {
-          description?.appendText(" key $key was: ${item[key]} instead of ${expected[key]}")
-        }
-      }
-    } else {
-      description?.appendText("was: $item")
-    }
-  }
-
-  override fun matches(item: Any?): Boolean {
-    if (item is Map<*, *>) {
-      for (key in expected.keys) {
-        if (!item.containsKey(key)) {
-          return false
-        }
-        if (expected[key] != item[key]) {
-          return false
-        }
-      }
-      return true
-    } else {
-      return false
-    }
-  }
-}
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/TemporalMatcher.kt b/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/TemporalMatcher.kt
deleted file mode 100644
index eb9a46cdc3d9a888d6978d8c75e6c45b0f85de7b..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/matchers/TemporalMatcher.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2021 Janne Mareike Koschinski
- * Copyright (c) 2021 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package de.justjanne.libquassel.protocol.testutil.matchers
-
-import org.hamcrest.BaseMatcher
-import org.hamcrest.Description
-import org.threeten.bp.Instant
-import org.threeten.bp.LocalDate
-import org.threeten.bp.LocalDateTime
-import org.threeten.bp.LocalTime
-import org.threeten.bp.OffsetDateTime
-import org.threeten.bp.ZonedDateTime
-import org.threeten.bp.temporal.Temporal
-
-class TemporalMatcher<T : Temporal>(
-  private val expected: T
-) : BaseMatcher<T>() {
-  override fun describeTo(description: Description?) {
-    description?.appendText(expected.toString())
-  }
-
-  override fun matches(item: Any?): Boolean {
-    return when {
-      expected is ZonedDateTime && item is ZonedDateTime ->
-        expected == item
-      expected is ZonedDateTime && item is OffsetDateTime ->
-        expected.toOffsetDateTime() == item
-      expected is OffsetDateTime && item is OffsetDateTime ->
-        expected == item
-      expected is LocalDateTime && item is LocalDateTime ->
-        expected == item
-      expected is LocalTime && item is LocalTime ->
-        expected == item
-      expected is LocalDate && item is LocalDate ->
-        expected == item
-      expected is Instant && item is Instant ->
-        expected == item
-      else ->
-        false
-    }
-  }
-}
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/serialize.kt b/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/serialize.kt
deleted file mode 100644
index b2be32a2cf24199c3b8e910258b882caebeba15e..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/serialize.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2021 Janne Mareike Koschinski
- * Copyright (c) 2021 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package de.justjanne.libquassel.messages.testutil
-
-import de.justjanne.libquassel.messages.handshake.HandshakeSerializer
-import de.justjanne.libquassel.protocol.features.FeatureSet
-import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
-import de.justjanne.libquassel.protocol.serializers.Serializer
-import de.justjanne.libquassel.protocol.serializers.qt.HandshakeMapSerializer
-import de.justjanne.libquassel.protocol.testutil.matchers.ByteBufferMatcher
-import org.hamcrest.MatcherAssert.assertThat
-import java.nio.ByteBuffer
-
-fun <T> serialize(
-  serializer: Serializer<T>,
-  data: T,
-  featureSet: FeatureSet = FeatureSet.all()
-): ByteBuffer {
-  val buffer = ChainedByteBuffer()
-  serializer.serialize(buffer, data, featureSet)
-  return buffer.toBuffer()
-}
-
-fun <T> testSerialize(
-  serializer: HandshakeSerializer<T>,
-  data: T,
-  buffer: ByteBuffer,
-  featureSet: FeatureSet = FeatureSet.all()
-) {
-  val map = serializer.serialize(data)
-  val after = serialize(HandshakeMapSerializer, map, featureSet)
-  assertThat(after, ByteBufferMatcher(buffer))
-}
diff --git a/libquassel-messages/src/test/resources/quasseltest.crt b/libquassel-messages/src/test/resources/quasseltest.crt
deleted file mode 100644
index 8d0bd31ab63dc21f63718901777d5bf2264bb2ef..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/resources/quasseltest.crt
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFHzCCAwegAwIBAgIUEV/Rf5DceQhjul2yqHDa/ODr5+YwDQYJKoZIhvcNAQEL
-BQAwHjEcMBoGA1UEAwwTcXVhc3NlbHRlc3QuaW52YWxpZDAgFw0yMTAyMDgyMzM5
-MjRaGA8yMTIxMDExNTIzMzkyNFowHjEcMBoGA1UEAwwTcXVhc3NlbHRlc3QuaW52
-YWxpZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAM2OZTae4BKzppB2
-nEF2e2oGLl1YGaCfqaVeQjKNS3DY8fjIG9lb6hDzE1MneoGtou7TafWvqh2u1Q8p
-aRNpcW+ftTqcUecGPuMTQHHSWjZJDocvH2vG5xM48u5DqLNUThs7eEoPis7AGpus
-7xm8wmjGokKYZb6WdXGLcOEPLb2ZSQH4MRHkAMtM1zF3/L0bYzRLil9+aQ6y0P3/
-4hRfUiy5ZkIiPS3+fJPOj/ZaABukLtffWicbeAvNDk7Jp2FvoVfXPXU14CXQaV16
-BhfCbWHamUM4d0ZWu85J8Jbon+JRfmIvg+0z4nlZaJ6a23nkO4ljL6IKdwlEUYbM
-uZ4bimCxmk2g3t27DxDBYAeudCQYQjvlA7fYf9b2tBjdvVx7BRyFk09Z+zSWKXVx
-67iL5nURY8iOY+sHF7t/D/vbDx1/nDkXZPxEl1jZlDnu2xCkM8sYgocXsfjIaW3f
-1dcGJ6lr50g69LgTBBuT2Db3Li91nAr3s+V5Urf1CcTMFipNAdeY3qN717LzKsJS
-FpjAtvUJQhPin9Is0AZkYCrDxIYZJYgQZaeDCrXRQwoS8qIhXWbgHXRPUTwgGzmS
-og62+rfwn3JDRDKOGuiYIc8uhBj0mOOV/GBegFg1cskaX+EMvdurx2jyNc6y1JOG
-WJHZ2ctMSHlkm4/vG9lEHoW43HcPAgMBAAGjUzBRMB0GA1UdDgQWBBQ4uKrImjUv
-C/TJhb03I3YJEjgjrjAfBgNVHSMEGDAWgBQ4uKrImjUvC/TJhb03I3YJEjgjrjAP
-BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCMahqY1LVdSny9oc7B
-AGET5Y/sTdALZN/GslYWjY9iTNx4kXz6u0654onDTBHZ6c+8+dmZdWFrdPTzJuJX
-dB4HqQyY2tLhR3N44F6LRkx97klbvSscMJr3QK4344AtksbEq1BGeDCm5VeaZZJU
-A+WSNXjJC22EFR5RLftdArRquJVcwCDPWI1lf/iv/iXJPpv8Mq5qFpY1Agusi/sv
-PLO6GVV2qPADoI0NjgYCjJ2VVJQeHasFCC+izihmrTQUMc4G/JF9gHMPOLRofm32
-zMQ8LK+iWa9p+VoRbdnsWDw4Fy9s34VXuT5ijAz6KbQ8v9alQv6VfYwnZCrylyKH
-K3vWg7g1tlyMZP7ExzHfu428lVmYZbf1k7GUA+2Qu9s/jPfszwQzdDnr5dN9jCUj
-CIqLXoHZeyIc2Cxu1KMaZvkPVn2/zJUa3RNLfcl+1pGOCwaUd5lcGtdzrk/9lZwR
-zHh9nvQWPAE2r36E7CtOgy0uMIfFdNnDc1iYKU2I9075k+bo7y4zvO9gQx3dmkxU
-SCm2sKQzkScSBPtCBtsfKfN4csL5FyLevl7C5izpQqtChqLZu9XXDNVTE7jd48Wy
-VrIlBGHwGkksmYUqALI81bvBaOZ1GytAIMbRNQ8YRLIPvjuL/CorfqrR5kEKXqsd
-eZw3w5qGASg6Xk0d9OxKyjHKeQ==
------END CERTIFICATE-----
diff --git a/libquassel-messages/src/test/resources/quasseltest.key b/libquassel-messages/src/test/resources/quasseltest.key
deleted file mode 100644
index 1a2218ebdb96f7af5e9018a7d883e85dccdd927b..0000000000000000000000000000000000000000
--- a/libquassel-messages/src/test/resources/quasseltest.key
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQDNjmU2nuASs6aQ
-dpxBdntqBi5dWBmgn6mlXkIyjUtw2PH4yBvZW+oQ8xNTJ3qBraLu02n1r6odrtUP
-KWkTaXFvn7U6nFHnBj7jE0Bx0lo2SQ6HLx9rxucTOPLuQ6izVE4bO3hKD4rOwBqb
-rO8ZvMJoxqJCmGW+lnVxi3DhDy29mUkB+DER5ADLTNcxd/y9G2M0S4pffmkOstD9
-/+IUX1IsuWZCIj0t/nyTzo/2WgAbpC7X31onG3gLzQ5Oyadhb6FX1z11NeAl0Gld
-egYXwm1h2plDOHdGVrvOSfCW6J/iUX5iL4PtM+J5WWiemtt55DuJYy+iCncJRFGG
-zLmeG4pgsZpNoN7duw8QwWAHrnQkGEI75QO32H/W9rQY3b1cewUchZNPWfs0lil1
-ceu4i+Z1EWPIjmPrBxe7fw/72w8df5w5F2T8RJdY2ZQ57tsQpDPLGIKHF7H4yGlt
-39XXBiepa+dIOvS4EwQbk9g29y4vdZwK97PleVK39QnEzBYqTQHXmN6je9ey8yrC
-UhaYwLb1CUIT4p/SLNAGZGAqw8SGGSWIEGWngwq10UMKEvKiIV1m4B10T1E8IBs5
-kqIOtvq38J9yQ0QyjhromCHPLoQY9JjjlfxgXoBYNXLJGl/hDL3bq8do8jXOstST
-hliR2dnLTEh5ZJuP7xvZRB6FuNx3DwIDAQABAoICAA1xaJEf5suSUCxWdXWaiAux
-B8s2/cYRawjTl0SzFOH2biy0+Y1Hg5FENFlV1Z8xedxgmydkK53xVyG8tZB9btu7
-+CAzJPAU6nvzQF2xQhEWygpxPH7R7T7GlKycZCYGN210gDNnvM40pgjUUHbAb35m
-rynnyY+jS173nZQ6Z+VkZu/oCV2AKcUh61ji3faIGf7Liesg20II074ow+JNMZSX
-M2bT0mh1ojQQaD3WOPeVzzJy+vRfyYQMDwl8CqRGpqiV/QDzWwteC+X/GvLm1jx2
-DVvmD3bcKUAeecuEvyAP8FH/hYM3x3HkNQFaY0wfbv1XLUBNqudCPoqwTNtYNb5q
-7/IDRJaAXv016XHd31AHPtbzwlLztFiTycnmL/exfxZDEXaAU28C5PuYyLQNqm7s
-k6A9BtNYwcffbs2TyAq6RgOQs2ERWdHhk8syPNwBdgeXTXSLqubTD87ySb/YfLhY
-/Y/o91a0N4AhJJDf5jJxJfkzDfRwIijo5mnUSpkEtd48uR14stsyOLtFWRl+oclN
-o8rCjwauHG7AeFpz1hdh2CQe0tMohf/TnuSpDxokJQwmTIKgXgubslfHtnoW0KFk
-jKhwQp2r3+1mnxOS1nqFUtnS+Gq6vYY/lT7q6nCjKKmll7c1n14Ptx+U6IoBrap1
-qt81ltxnTvYIorMGugphAoIBAQD/45TfSd5+G+Vc2i9rGk7XN3agWkmQtJWt19NF
-O7sFfPR3bA9JqI3YAl7z4hvu4nTQHEWMNUxDpDjg5/CEoyar4WcxMAQ85J0w2LcM
-IXSOICbpWHZx1TiAj/6iAjghfzYmQPcoQXs5GLlgN8IL6+jJGckacUdJJL8bG5UH
-objYg8Zc1D3qPEnLobL8Kt/ixS+lqsVw+FDF35alIUMD0ZJrSU94nDNqt+HCE1xP
-MFmWYsy68ey03gxC2vw3+tTDs0+521l/0yw+m/F4p/92BHnk/Jta8egF/4moJl+T
-j4AHnYiCpH+6O1KQkum82HkBGbMHkb6i0gMMtLbC5jHxGoZ5AoIBAQDNpTlXOld1
-9kzoII6ZDUQUEuHId9AdjCn7beki2PZOiq31j67QiSoCIAKtFhrb8PjJyaxNYKas
-NXk6P6MD5gVDQojeBv24cayGG95FCUYtIVD2Hrm7/sR2wkJRvBROlYakRC/zkPkG
-dyEtfivIUBznBM4MI3gx741lBVFppAdqw2qN6JQMoUVAoEPkiEg7wy+fQUWz2OMr
-vZ1yIPxJDh2c7PKIUf7x6H08THOXVZ+sWzoFHZ4CVsHbs23Z3IRLwT4YD+TdD+in
-zMa1m14e3xtt5qLpE+zeSB/WUWZKpSlgUKhRylgdqb/r85RIW7oaWk7ICfCa9YL1
-jeDyLyYubafHAoIBADhbhVRQTqJzvmZe34a1OpwH6SaT/BPU0gqBuFRNPXmN9cG/
-mPZeGy9yBjuslv5b/eI/98lTi8JyDtzp+H0d+cxtTm705loK99vkPxx62dLbnfZS
-t3OGxHT8QdaoqngmLmTqdgT1tw/yNBHO9fvuL0zrUvFx9YNUhoqP3pjZs35sN2oG
-jMRkFtS0flkvkDO/vii8ndOtvQx3nBQuaTYUGC1s7gXgUSq16RD3dqMyQOjwRar+
-0WVcalLnLBmgMvAPNAX5G5MdjWcUrXAngAocHkSipgy3rqRzjXvtR6uWNVp4BbLQ
-TBlWK28QDE69Vpk5cca/AL+XhXhs7LusO1+gufECggEAfGgLA2ERDhTdu8QOYDrt
-R3OQ0bTh2y4zK573XhSBFUzCJn8w04lXN4fj9pAb2Ziy+Wge64Sf8Cg9WWasGKyr
-3F/A6wixr0Zdh5gOZBdTM/QmxW4bEMb0VZ/5fPbaFhxRIsj5dVDrxeSF1r6wf/Mv
-OPboK+G9UgBIuqd38/++WPE1YfokrmtVuN37lKJ5iGXxRle3cjCwZYLFYAjidtOq
-SIfzxVJNeE0cjkD14MR031ElDXk4YNPZXS70Mss74ZRbGzVqT+3S4sh4Id+HFggE
-0Pyo63YZYvOhBwehaWD3YgQJf8l4eyF5MKXfu9J6CH0/kbapryT9f83AGuM5JvdB
-ewKCAQAoVN+HS/af2O09+3TEtFyv4m5ozFB6ntaC12dhrboVwAw8MPLGXaEqsfPV
-L9ORMA6lRL+4OIo2FcM6TklD/rMAHr/b9VtWou8EReiOR1zSgt7opCZ6wLhBnp9P
-msz1puP/O+SR3lrcQOmETMK7ofqoewem5rz0CmTraXqreHuzRX+c/nWQqmJDyN8o
-NeHhG5sItIhePpNQ+QcPezVyl++vMHFwOO92o+i/z7zH6ucR+g8OR41vXjIQEP5n
-5w9OGyOxVfgFhO6Q+CUfIs3JMlwo/XkwFp2NJohNWAPzPIyJ5V9XpJkuaWJ17c/U
-jwfYNzNlv1pDyVGAaI8oMDXRMaZ3
------END PRIVATE KEY-----
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/features/QuasselFeature.kt b/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/features/QuasselFeature.kt
deleted file mode 100644
index 23160e7b41521aa0f362078ba67b435408b654e6..0000000000000000000000000000000000000000
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/features/QuasselFeature.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Quasseldroid - Quassel client for Android
- *
- * Copyright (c) 2021 Janne Mareike Koschinski
- * Copyright (c) 2021 The Quassel Project
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package de.justjanne.libquassel.protocol.features
-
-import de.justjanne.libquassel.annotations.Generated
-
-@Generated
-inline class QuasselFeatureName(
-  val name: String,
-)
-
-enum class QuasselFeature {
-  SynchronizedMarkerLine,
-  SaslAuthentication,
-  SaslExternal,
-  HideInactiveNetworks,
-  PasswordChange,
-
-  /** IRCv3 capability negotiation, account tracking */
-  CapNegotiation,
-
-  /** IRC server SSL validation */
-  VerifyServerSSL,
-
-  /** IRC server custom message rate limits */
-  CustomRateLimits,
-
-  // Currently not supported
-  DccFileTransfer,
-
-  /** Timestamp formatting in away (e.g. %%hh:mm%%) */
-  AwayFormatTimestamp,
-
-  /** Whether or not the core supports auth backends. */
-  Authenticators,
-
-  /** Sync buffer activity status */
-  BufferActivitySync,
-
-  /** Core-Side highlight configuration and matching */
-  CoreSideHighlights,
-
-  /** Show prefixes for senders in backlog */
-  SenderPrefixes,
-
-  /** Supports RPC call disconnectFromCore to remotely disconnect a client */
-  RemoteDisconnect,
-
-  /** Transmit features as list of strings */
-  ExtendedFeatures,
-
-  /** Serialize message time as 64-bit */
-  LongTime,
-
-  /** Real Name and Avatar URL in backlog */
-  RichMessages,
-
-  /** Backlogmanager supports filtering backlog by messagetype */
-  BacklogFilterType,
-
-  /** ECDSA keys for CertFP in identities */
-  EcdsaCertfpKeys,
-
-  /** 64-bit IDs for messages */
-  LongMessageId,
-
-  /** CoreInfo dynamically updated using signals */
-  SyncedCoreInfo;
-
-  val feature = QuasselFeatureName(name)
-
-  companion object {
-    private val values = values().associateBy(QuasselFeature::feature)
-
-    @JvmStatic
-    fun valueOf(name: QuasselFeatureName): QuasselFeature? = values[name]
-  }
-}
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ConnectionHeader.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ClientHeader.kt
similarity index 81%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ConnectionHeader.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ClientHeader.kt
index bf056f5918b820118b328f2ba48b106394080725..9c7570e3bd5020847933eb4cb71f1bfa13e68a55 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ConnectionHeader.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ClientHeader.kt
@@ -19,7 +19,16 @@
 
 package de.justjanne.libquassel.protocol.connection
 
-data class ConnectionHeader(
+/**
+ * Model encapsulating the client side of protocol negotiation
+ */
+data class ClientHeader(
+  /**
+   * Supported protocol features
+   */
   val features: ProtocolFeatures,
+  /**
+   * Supported protocol version/meta pairs
+   */
   val versions: List<ProtocolMeta>
 )
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ConnectionHeaderSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ClientHeaderSerializer.kt
similarity index 92%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ConnectionHeaderSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ClientHeaderSerializer.kt
index 4cc3b7a0de318cffbbfc52b7b5d35eaeb3ccac08..802fe478bca01586c4fa6c7973223d19213b262a 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ConnectionHeaderSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ClientHeaderSerializer.kt
@@ -28,7 +28,10 @@ import de.justjanne.libquassel.protocol.serializers.qt.UByteSerializer
 import de.justjanne.libquassel.protocol.serializers.qt.UIntSerializer
 import java.nio.ByteBuffer
 
-object ConnectionHeaderSerializer : Serializer<ConnectionHeader> {
+/**
+ * Serializer for a [ClientHeader]
+ */
+object ClientHeaderSerializer : Serializer<ClientHeader> {
   private const val magic: UInt = 0x42b3_3f00u
   private const val featureMask: UInt = 0x0000_00ffu
   private const val lastMagic: UByte = 0x80u
@@ -69,14 +72,14 @@ object ConnectionHeaderSerializer : Serializer<ConnectionHeader> {
     return list
   }
 
-  override fun serialize(buffer: ChainedByteBuffer, data: ConnectionHeader, featureSet: FeatureSet) {
+  override fun serialize(buffer: ChainedByteBuffer, data: ClientHeader, featureSet: FeatureSet) {
     UIntSerializer.serialize(buffer, addMagic(data.features.toBits()), featureSet)
     writeList(buffer, data.versions, featureSet) {
       ProtocolMetaSerializer.serialize(buffer, it, featureSet)
     }
   }
 
-  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = ConnectionHeader(
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = ClientHeader(
     features = ProtocolFeature.of(
       removeMagic(UIntSerializer.deserialize(buffer, featureSet))
     ),
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolInfo.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/CoreHeader.kt
similarity index 75%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolInfo.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/CoreHeader.kt
index 920541d13f0700016cda0dd2b557de073a051023..7b097110cf24f2aafcf87f023959057072d541a8 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolInfo.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/CoreHeader.kt
@@ -19,7 +19,16 @@
 
 package de.justjanne.libquassel.protocol.connection
 
-data class ProtocolInfo(
-  val flags: ProtocolFeatures,
-  val meta: ProtocolMeta,
+/**
+ * Model encapsulating the core side of protocol negotiation
+ */
+data class CoreHeader(
+  /**
+   * Supported protocol features
+   */
+  val features: ProtocolFeatures,
+  /**
+   * Chosen protocol version/meta pair
+   */
+  val version: ProtocolMeta,
 )
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolInfoSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/CoreHeaderSerializer.kt
similarity index 79%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolInfoSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/CoreHeaderSerializer.kt
index a156b978dc046c2ead0d9dcfb829befd03afa478..d2b36a36348b57df859af59ef38f1955d18a1b91 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolInfoSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/CoreHeaderSerializer.kt
@@ -27,13 +27,16 @@ import de.justjanne.libquassel.protocol.serializers.Serializer
 import de.justjanne.libquassel.protocol.serializers.qt.UByteSerializer
 import java.nio.ByteBuffer
 
-object ProtocolInfoSerializer : Serializer<ProtocolInfo> {
-  override fun serialize(buffer: ChainedByteBuffer, data: ProtocolInfo, featureSet: FeatureSet) {
-    UByteSerializer.serialize(buffer, data.flags.toBits(), featureSet)
-    ProtocolMetaSerializer.serialize(buffer, data.meta, featureSet)
+/**
+ * Serializer for a [CoreHeader]
+ */
+object CoreHeaderSerializer : Serializer<CoreHeader> {
+  override fun serialize(buffer: ChainedByteBuffer, data: CoreHeader, featureSet: FeatureSet) {
+    UByteSerializer.serialize(buffer, data.features.toBits(), featureSet)
+    ProtocolMetaSerializer.serialize(buffer, data.version, featureSet)
   }
 
-  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = ProtocolInfo(
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = CoreHeader(
     ProtocolFeature.of(UByteSerializer.deserialize(buffer, featureSet)),
     ProtocolMetaSerializer.deserialize(buffer, featureSet)
   )
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolFeature.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolFeature.kt
similarity index 82%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolFeature.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolFeature.kt
index c0ada8fc7315afec1b9e66384ee226b7b8181d47..eb8a59ed16ce8f759e447b268a6c466ad13e80b9 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolFeature.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolFeature.kt
@@ -23,11 +23,19 @@ import de.justjanne.bitflags.Flag
 import de.justjanne.bitflags.Flags
 import de.justjanne.bitflags.toEnumSet
 
+/**
+ * Model representing protocol-level features
+ */
 enum class ProtocolFeature(
   override val value: UByte,
 ) : Flag<UByte> {
-  None(0x00u),
+  /**
+   * Model representing whether TLS is supported
+   */
   TLS(0x01u),
+  /**
+   * Model representing whether DEFLATE compression is supported
+   */
   Compression(0x02u);
 
   companion object : Flags<UByte, ProtocolFeature> {
@@ -36,4 +44,7 @@ enum class ProtocolFeature(
   }
 }
 
+/**
+ * Model representing a bitfield of [ProtocolFeature] flags
+ */
 typealias ProtocolFeatures = Set<ProtocolFeature>
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolMeta.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolMeta.kt
similarity index 81%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolMeta.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolMeta.kt
index c9165f3ea0bda833b9919a578d1694fd84580f21..b81652c1a6003a537c61d13a93b85d6dc2387c2a 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolMeta.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolMeta.kt
@@ -19,7 +19,16 @@
 
 package de.justjanne.libquassel.protocol.connection
 
+/**
+ * Model representing a supported protocol configuration
+ */
 data class ProtocolMeta(
-  val data: UShort,
-  val version: ProtocolVersion
+  /**
+   * Protocol version
+   */
+  val version: ProtocolVersion,
+  /**
+   * Protocol metadata
+   */
+  val data: UShort
 )
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolMetaSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolMetaSerializer.kt
similarity index 89%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolMetaSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolMetaSerializer.kt
index 7d6f2601a0d63c150dc07681f08cba5a09cb8c03..b3fd3bccc7c379c62aaa0632f792bcc68660a4a7 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolMetaSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolMetaSerializer.kt
@@ -26,6 +26,9 @@ import de.justjanne.libquassel.protocol.serializers.qt.UByteSerializer
 import de.justjanne.libquassel.protocol.serializers.qt.UShortSerializer
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for a [ProtocolMeta]
+ */
 object ProtocolMetaSerializer : Serializer<ProtocolMeta> {
   override fun serialize(buffer: ChainedByteBuffer, data: ProtocolMeta, featureSet: FeatureSet) {
     UShortSerializer.serialize(buffer, data.data, featureSet)
@@ -33,7 +36,7 @@ object ProtocolMetaSerializer : Serializer<ProtocolMeta> {
   }
 
   override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = ProtocolMeta(
-    UShortSerializer.deserialize(buffer, featureSet),
-    ProtocolVersion.of(UByteSerializer.deserialize(buffer, featureSet))
+    data = UShortSerializer.deserialize(buffer, featureSet),
+    version = ProtocolVersion.of(UByteSerializer.deserialize(buffer, featureSet))
   )
 }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolVersion.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolVersion.kt
similarity index 76%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolVersion.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolVersion.kt
index 8ffcabfc59584ec3a8379b9df82806b081107235..059edd04dedcc64e7f83060635aaf669d419987f 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/connection/ProtocolVersion.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/connection/ProtocolVersion.kt
@@ -19,14 +19,31 @@
 
 package de.justjanne.libquassel.protocol.connection
 
+/**
+ * Model representing the possible protocol versions
+ */
 enum class ProtocolVersion(
+  /**
+   * Protocol version id
+   */
   val value: UByte,
 ) {
+  /**
+   * Legacy protocol, used up til Quassel 0.10, not fully supported by this library
+   */
   Legacy(0x01u),
+
+  /**
+   * Datastream protocol, introduced in Quassel 0.10.
+   */
   Datastream(0x02u);
 
   companion object {
     private val values = values().associateBy(ProtocolVersion::value)
+
+    /**
+     * Obtain the protocol version for a protocol version id
+     */
     fun of(value: UByte): ProtocolVersion = values[value]
       ?: throw IllegalArgumentException("Protocol not supported: $value")
   }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/features/FeatureSet.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/FeatureSet.kt
similarity index 75%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/features/FeatureSet.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/FeatureSet.kt
index 9c34c5a207be1fb13ad9dadd0c55563662ff24a9..75adb73afd89b1328f5b0cf32cda2ecb8c4a020a 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/features/FeatureSet.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/FeatureSet.kt
@@ -21,20 +21,37 @@ package de.justjanne.libquassel.protocol.features
 
 import de.justjanne.bitflags.of
 
+/**
+ * Model representing the set of negotiated or supported features for a
+ * connection or library
+ */
 class FeatureSet internal constructor(
   private val features: Set<QuasselFeature>,
   private val additional: Set<QuasselFeatureName> = emptySet()
 ) {
+  /**
+   * Check whether a certain feature is supported
+   */
   fun hasFeature(feature: QuasselFeature) = features.contains(feature)
 
+  /**
+   * List of features with their name, for serialization
+   */
   fun featureList(): List<QuasselFeatureName> =
     features.map(QuasselFeature::feature) + additional
 
+  /**
+   * Set of supported [LegacyFeature]s
+   */
   fun legacyFeatures(): LegacyFeatures =
     LegacyFeature.of(features.mapNotNull(LegacyFeature.Companion::get))
 
   companion object {
-    fun parse(
+    /**
+     * Build a [FeatureSet] from a collection of feature names and a set of
+     * legacy features
+     */
+    fun build(
       legacy: LegacyFeatures,
       features: Collection<QuasselFeatureName>
     ) = FeatureSet(
@@ -42,9 +59,24 @@ class FeatureSet internal constructor(
       additional = unknownFeatures(features)
     )
 
+    /**
+     * Build a [FeatureSet] directly from features
+     */
     fun build(vararg features: QuasselFeature) = FeatureSet(features.toSet())
+
+    /**
+     * Build a [FeatureSet] directly from features
+     */
     fun build(features: Set<QuasselFeature>) = FeatureSet(features)
+
+    /**
+     * Model with all possible features enabled
+     */
     fun all() = build(*QuasselFeature.values())
+
+    /**
+     * Model with no features enabled
+     */
     fun none() = build()
 
     private fun parseFeatures(features: LegacyFeatures) =
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/features/LegacyFeature.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/LegacyFeature.kt
similarity index 61%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/features/LegacyFeature.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/LegacyFeature.kt
index 70ab07de1b650d75442500aae97f018a4eaf6181..114e3f5e6bdb6113e8b7f45e4d3aa94893e57a3b 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/features/LegacyFeature.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/LegacyFeature.kt
@@ -22,59 +22,106 @@ package de.justjanne.libquassel.protocol.features
 import de.justjanne.bitflags.Flag
 import de.justjanne.bitflags.Flags
 import de.justjanne.bitflags.toEnumSet
+import de.justjanne.libquassel.protocol.types.MessageType
 
 /**
- * A list of features that are optional in core and/or client, but need runtime checking
+ * List of optional features in a quassel connection.
  *
- * Some features require an uptodate counterpart, but don't justify a protocol break.
- * This is what we use this enum for. Add such features to it and check at runtime on the other
- * side for their existence.
- *
- * This list should be cleaned up after every protocol break, as we can assume them to be present then.
+ * Replaced by [QuasselFeature] negotiation if both sides of the connection are
+ * new enough
  */
 enum class LegacyFeature(
   override val value: UInt,
+  /**
+   * Modern feature corresponding to this legacy feature
+   */
   val feature: QuasselFeature,
 ) : Flag<UInt> {
+  /**
+   * Support for a synced marker line/last read position
+   */
   SynchronizedMarkerLine(0x0001u, QuasselFeature.SynchronizedMarkerLine),
+
+  /**
+   * Support for configurable SASL authentication to replace NickServ
+   */
   SaslAuthentication(0x0002u, QuasselFeature.SaslAuthentication),
+
+  /**
+   * Support for certificate based SASL EXTERNAL authentication
+   */
   SaslExternal(0x0004u, QuasselFeature.SaslExternal),
+
+  /**
+   * Support for hiding inactive/disconnected networks in a chat list
+   */
   HideInactiveNetworks(0x0008u, QuasselFeature.HideInactiveNetworks),
+
+  /**
+   * Support for changing the password through the client
+   */
   PasswordChange(0x0010u, QuasselFeature.PasswordChange),
 
-  /** IRCv3 capability negotiation, account tracking */
+  /**
+   * IRCv3 capability negotiation, account tracking
+   */
   CapNegotiation(0x0020u, QuasselFeature.CapNegotiation),
 
-  /** IRC server SSL validation */
+  /**
+   *  IRC server SSL validation
+   */
   VerifyServerSSL(0x0040u, QuasselFeature.VerifyServerSSL),
 
-  /** IRC server custom message rate limits */
+  /**
+   *  IRC server custom message rate limits
+   */
   CustomRateLimits(0x0080u, QuasselFeature.CustomRateLimits),
+  /**
+   *  (X)DCC direct file transfers (EXPERIMENTAL)
+   */
   DccFileTransfer(0x0100u, QuasselFeature.DccFileTransfer),
 
-  /** Timestamp formatting in away (e.g. %%hh:mm%%) */
+  /**
+   * Timestamp formatting in away (e.g. %%hh:mm%%)
+   */
   AwayFormatTimestamp(0x0200u, QuasselFeature.AwayFormatTimestamp),
 
-  /** Whether or not the core supports auth backends. */
+  /**
+   * Whether or not the core supports auth backends.
+   */
   Authenticators(0x0400u, QuasselFeature.Authenticators),
 
-  /** Sync buffer activity status */
+  /**
+   * Sync buffer activity status
+   */
   BufferActivitySync(0x0800u, QuasselFeature.BufferActivitySync),
 
-  /** Core-Side highlight configuration and matching */
+  /**
+   * Core-Side highlight configuration and matching
+   */
   CoreSideHighlights(0x1000u, QuasselFeature.CoreSideHighlights),
 
-  /** Show prefixes for senders in backlog */
+  /**
+   * Show prefixes for senders in backlog
+   */
   SenderPrefixes(0x2000u, QuasselFeature.SenderPrefixes),
 
-  /** Supports RPC call disconnectFromCore to remotely disconnect a client */
+  /**
+   * Supports RPC call disconnectFromCore to remotely disconnect a client
+   */
   RemoteDisconnect(0x4000u, QuasselFeature.RemoteDisconnect),
 
-  /** Transmit features as list of strings */
+  /**
+   * Transmit features as list of strings
+   */
   ExtendedFeatures(0x8000u, QuasselFeature.ExtendedFeatures);
 
   companion object : Flags<UInt, LegacyFeature> {
     private val features = values().associateBy(LegacyFeature::feature)
+
+    /**
+     * Obtain by modern feature corresponding to this feature
+     */
     fun get(feature: QuasselFeature) = features[feature]
 
     private val values = values().associateBy(LegacyFeature::value)
@@ -82,4 +129,7 @@ enum class LegacyFeature(
   }
 }
 
+/**
+ * Model representing a bitfield of [LegacyFeature] flags
+ */
 typealias LegacyFeatures = Set<LegacyFeature>
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/QuasselFeature.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/QuasselFeature.kt
new file mode 100644
index 0000000000000000000000000000000000000000..84d97d075c0c75b6932e28160e137c256431fa60
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/QuasselFeature.kt
@@ -0,0 +1,153 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2021 Janne Mareike Koschinski
+ * Copyright (c) 2021 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.justjanne.libquassel.protocol.features
+
+/**
+ * List of optional features in a quassel connection.
+ *
+ * Replaces [LegacyFeature] negotiation if both sides of the connection are new
+ * enough
+ */
+enum class QuasselFeature {
+  /**
+   * Support for a synced marker line/last read position
+   */
+  SynchronizedMarkerLine,
+
+  /**
+   * Support for configurable SASL authentication to replace NickServ
+   */
+  SaslAuthentication,
+
+  /**
+   * Support for certificate based SASL EXTERNAL authentication
+   */
+  SaslExternal,
+
+  /**
+   * Support for hiding inactive/disconnected networks in a chat list
+   */
+  HideInactiveNetworks,
+
+  /**
+   * Support for changing the password through the client
+   */
+  PasswordChange,
+
+  /**
+   * IRCv3 capability negotiation, account tracking
+   */
+  CapNegotiation,
+
+  /**
+   * IRC server SSL validation
+   */
+  VerifyServerSSL,
+
+  /**
+   * IRC server custom message rate limits
+   */
+  CustomRateLimits,
+
+  /**
+   *  (X)DCC direct file transfers (EXPERIMENTAL)
+   */
+  DccFileTransfer,
+
+  /**
+   * Timestamp formatting in away (e.g. %%hh:mm%%)
+   */
+  AwayFormatTimestamp,
+
+  /**
+   * Whether or not the core supports auth backends.
+   */
+  Authenticators,
+
+  /**
+   * Sync buffer activity status
+   */
+  BufferActivitySync,
+
+  /**
+   * Core-Side highlight configuration and matching
+   */
+  CoreSideHighlights,
+
+  /**
+   * Show prefixes for senders in backlog
+   */
+  SenderPrefixes,
+
+  /**
+   * Supports RPC call disconnectFromCore to remotely disconnect a client
+   */
+  RemoteDisconnect,
+
+  /**
+   * Transmit features as list of strings
+   */
+  ExtendedFeatures,
+
+  /**
+   * Serialize message time as 64-bit
+   */
+  LongTime,
+
+  /**
+   * Real Name and Avatar URL in backlog
+   */
+  RichMessages,
+
+  /**
+   * Backlogmanager supports filtering backlog by messagetype
+   */
+  BacklogFilterType,
+
+  /**
+   * ECDSA keys for CertFP in identities
+   */
+  EcdsaCertfpKeys,
+
+  /**
+   * 64-bit IDs for messages
+   */
+  LongMessageId,
+
+  /**
+   * CoreInfo dynamically updated using signals
+   */
+  SyncedCoreInfo;
+
+  /**
+   * Get the standardized feature name
+   */
+  val feature = QuasselFeatureName(name)
+
+  companion object {
+    private val values = values().associateBy(QuasselFeature::feature)
+
+    /**
+     * Get a [QuasselFeature], if existing, for a certain feature name
+     */
+    @JvmStatic
+    fun valueOf(name: QuasselFeatureName): QuasselFeature? = values[name]
+  }
+}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/QuasselFeatureName.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/QuasselFeatureName.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a2869a6c80a2b971daa3020d8900d85e1a5aa698
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/features/QuasselFeatureName.kt
@@ -0,0 +1,14 @@
+package de.justjanne.libquassel.protocol.features
+
+import de.justjanne.libquassel.annotations.Generated
+
+/**
+ * Inline class encapsulating a quassel feature name
+ */
+@Generated
+inline class QuasselFeatureName(
+  /**
+   * Standardized name of the feature
+   */
+  val name: String,
+)
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/io/ByteBufferUtil.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/io/ByteBufferUtil.kt
similarity index 71%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/io/ByteBufferUtil.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/io/ByteBufferUtil.kt
index 0beb4d258df10c946789000efc684aca657c36fc..e03ede5f366907e60f0019dce6d5788b118aa774 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/io/ByteBufferUtil.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/io/ByteBufferUtil.kt
@@ -21,6 +21,16 @@ package de.justjanne.libquassel.protocol.io
 
 import java.nio.ByteBuffer
 
+/**
+ * Copy data from one buffer to another
+ *
+ * Starts at the current position of each buffer, copies until either buffer
+ * is at its limit or the desired amount is reached.
+ *
+ * @param from source buffer to copy from
+ * @param to target buffer to copy to
+ * @param desiredAmount maximum amount to copy
+ */
 fun copyData(from: ByteBuffer, to: ByteBuffer, desiredAmount: Int) {
   val limit = from.limit()
   val availableAmount = minOf(from.remaining(), to.remaining())
@@ -30,12 +40,25 @@ fun copyData(from: ByteBuffer, to: ByteBuffer, desiredAmount: Int) {
   from.limit(limit)
 }
 
+/**
+ * Copy data from a buffer
+ *
+ * Starts at the current position of the buffer, copies until either the buffer
+ * is at its limit or the desired amount is reached.
+ *
+ * @param from source buffer to copy from
+ * @param desiredAmount maximum amount to copy
+ * @return buffer of the copied data
+ */
 fun copyData(from: ByteBuffer, desiredAmount: Int): ByteBuffer {
   val to = ByteBuffer.allocate(minOf(from.remaining(), desiredAmount))
   copyData(from, to, desiredAmount)
   return to.flip()
 }
 
+/**
+ * Utility function to determine whether a buffer can be read from/written to.
+ */
 fun ByteBuffer?.isEmpty() = this == null || !this.hasRemaining()
 
 private val alphabet = charArrayOf(
@@ -43,6 +66,9 @@ private val alphabet = charArrayOf(
   '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
 )
 
+/**
+ * Utility function to generate a hexdump of a buffer
+ */
 fun ByteBuffer.contentToString(): String {
   val position = position()
   val limit = limit()
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/io/ChainedByteBuffer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/io/ChainedByteBuffer.kt
similarity index 59%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/io/ChainedByteBuffer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/io/ChainedByteBuffer.kt
index 0ccd690b83fac0cd4c329b95f6e5067e4cd21ae6..d0b1726242284c794cc612157d104985ab2c1a62 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/io/ChainedByteBuffer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/io/ChainedByteBuffer.kt
@@ -20,16 +20,24 @@
 package de.justjanne.libquassel.protocol.io
 
 import java.nio.ByteBuffer
+import java.util.LinkedList
 
+/**
+ * Linked List of ByteBuffers, able to be written to as if it was a single one.
+ * Automatically expands if needed.
+ */
 class ChainedByteBuffer(
   private val chunkSize: Int = 1024,
   private val direct: Boolean = false,
   private val limit: Long = 0,
 ) : Iterable<ByteBuffer> {
-  private val bufferList: MutableList<ByteBuffer> = ArrayList()
+  private val bufferList: MutableList<ByteBuffer> = LinkedList()
 
   private var currentIndex = 0
 
+  /**
+   * Number of bytes in the buffer
+   */
   var size = 0
     private set
 
@@ -48,42 +56,99 @@ class ChainedByteBuffer(
     size += requested
   }
 
+  /**
+   * Write an 8-bit signed byte to the buffer and increment its position.
+   */
   fun put(value: Byte) {
     ensureSpace(1)
 
     bufferList.last().put(value)
   }
 
+  /**
+   * Write an 8-bit unsigned byte to the buffer and increment its position.
+   */
+  fun put(value: UByte) {
+    ensureSpace(1)
+
+    bufferList.last().put(value.toByte())
+  }
+
+  /**
+   * Write a 16-bit signed short to the buffer and increment its position.
+   */
   fun putShort(value: Short) {
     ensureSpace(2)
 
     bufferList.last().putShort(value)
   }
 
+  /**
+   * Write a 16-bit unsigned short to the buffer and increment its position.
+   */
+  fun putShort(value: UShort) {
+    ensureSpace(2)
+
+    bufferList.last().putShort(value.toShort())
+  }
+
+  /**
+   * Write a 32-bit signed int to the buffer and increment its position.
+   */
   fun putInt(value: Int) {
     ensureSpace(4)
 
     bufferList.last().putInt(value)
   }
 
+  /**
+   * Write a 32-bit unsigned int to the buffer and increment its position.
+   */
+  fun putInt(value: UInt) {
+    ensureSpace(4)
+
+    bufferList.last().putInt(value.toInt())
+  }
+
+  /**
+   * Write a 64-bit signed long to the buffer and increment its position.
+   */
   fun putLong(value: Long) {
     ensureSpace(8)
 
     bufferList.last().putLong(value)
   }
 
+  /**
+   * Write a 64-bit unsigned long to the buffer and increment its position.
+   */
+  fun putLong(value: ULong) {
+    ensureSpace(8)
+
+    bufferList.last().putLong(value.toLong())
+  }
+
+  /**
+   * Write a 32-bit float to the buffer and increment its position.
+   */
   fun putFloat(value: Float) {
     ensureSpace(4)
 
     bufferList.last().putFloat(value)
   }
 
+  /**
+   * Write a 64-bit double to the buffer and increment its position.
+   */
   fun putDouble(value: Double) {
     ensureSpace(8)
 
     bufferList.last().putDouble(value)
   }
 
+  /**
+   * Write the full remaining content of a bytebuffer to the buffer and increment its position
+   */
   fun put(value: ByteBuffer) {
     while (value.hasRemaining()) {
       val requested = minOf(value.remaining(), chunkSize)
@@ -97,17 +162,27 @@ class ChainedByteBuffer(
     }
   }
 
+  /**
+   * Write the full remaining content of a bytearray to the buffer and increment its position
+   */
   fun put(value: ByteArray) {
-    value.forEach(this::put)
+    this.put(ByteBuffer.wrap(value))
   }
 
+  /**
+   * Empty the buffer
+   */
   fun clear() {
     bufferList.clear()
     size = 0
   }
 
-  override fun iterator() = ChainedByteBufferIterator(this)
+  override fun iterator(): Iterator<ByteBuffer> =
+    ChainedByteBufferIterator(this)
 
+  /**
+   * Convert this buffer into a bytebuffer of the same capacity and content.
+   */
   fun toBuffer(): ByteBuffer {
     val byteBuffer = allocate(chunkSize * bufferList.size)
     for (buffer in iterator()) {
@@ -117,7 +192,7 @@ class ChainedByteBuffer(
     return byteBuffer
   }
 
-  class ChainedByteBufferIterator(
+  private class ChainedByteBufferIterator(
     private val buffer: ChainedByteBuffer
   ) : Iterator<ByteBuffer> {
     private var index = 0
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/io/StringEncoder.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/io/StringEncoder.kt
similarity index 88%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/io/StringEncoder.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/io/StringEncoder.kt
index 957e36a3e54614bf6f153556ed02524f4979ca46..49b9e889d6dcd9e8373f04f6c6b3d88f01260ad8 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/io/StringEncoder.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/io/StringEncoder.kt
@@ -23,6 +23,9 @@ import java.nio.ByteBuffer
 import java.nio.CharBuffer
 import java.nio.charset.Charset
 
+/**
+ * Class encapsulating encoding/decoding for a certain charset
+ */
 class StringEncoder(charset: Charset) {
   private val encoder = charset.newEncoder()
   private val decoder = charset.newDecoder()
@@ -41,6 +44,9 @@ class StringEncoder(charset: Charset) {
     return encoder.encode(data)
   }
 
+  /**
+   * Encode a string into a bytebuffer
+   */
   fun encode(data: String?): ByteBuffer {
     if (data == null || !encoder.canEncode(data)) {
       return ByteBuffer.allocateDirect(0)
@@ -64,6 +70,9 @@ class StringEncoder(charset: Charset) {
     }
   }
 
+  /**
+   * Encode a single char into a bytebuffer
+   */
   fun encodeChar(data: Char?): ByteBuffer {
     val charBuffer = charBuffer(1)
     charBuffer.put(replacementChar(data))
@@ -86,14 +95,23 @@ class StringEncoder(charset: Charset) {
     return charBuffer.flip()
   }
 
+  /**
+   * Decode a string with known length from a bytebuffer
+   */
   fun decode(source: ByteBuffer, length: Int): String {
     return decodeInternal(source, length).toString()
   }
 
+  /**
+   * Decode the full bytebuffer as string
+   */
   fun decode(source: ByteBuffer): String {
     return decodeInternal(source, source.remaining()).toString()
   }
 
+  /**
+   * Decode a single char from a bytebuffer
+   */
   fun decodeChar(source: ByteBuffer): Char {
     return decodeInternal(source, 2).get()
   }
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/HandshakeSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/HandshakeSerializer.kt
similarity index 63%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/HandshakeSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/HandshakeSerializer.kt
index 4c4116a0c5e7b17ddef1ec195ef94c7686f8b834..8e98f78484189c4ac04a67ff1a075ca93d02536c 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/HandshakeSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/HandshakeSerializer.kt
@@ -17,14 +17,31 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers
 
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 
+/** High-level serializer for handshake messages. */
 interface HandshakeSerializer<T> {
+  /**
+   * The underlying handshake message type this serializer can (de-)serialize.
+   * Used for type-safe serializer autodiscovery.
+   */
   val type: String
+
+  /**
+   * The underlying java type this serializer can (de-)serialize.
+   * Used for type-safe serializer autodiscovery.
+   */
   val javaType: Class<out T>
 
+  /**
+   * Serialize a handshake message into a [QVariantMap] (for further serialization)
+   */
   fun serialize(data: T): QVariantMap
+
+  /**
+   * Deserialize a handshake message from a [QVariantMap]
+   */
   fun deserialize(data: QVariantMap): T
 }
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/HandshakeSerializers.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/HandshakeSerializers.kt
similarity index 58%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/HandshakeSerializers.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/HandshakeSerializers.kt
index fdb5f6b0d8948a84deee2a03efffd835379328fc..14d64a41fb783d33aade8a638472416ca3dc9169 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/HandshakeSerializers.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/HandshakeSerializers.kt
@@ -17,10 +17,22 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers
 
-import de.justjanne.libquassel.protocol.serializers.NoSerializerForTypeException
+import de.justjanne.libquassel.protocol.serializers.handshake.ClientInitAckSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.ClientInitRejectSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.ClientInitSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.ClientLoginAckSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.ClientLoginRejectSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.ClientLoginSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.CoreSetupAckSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.CoreSetupDataSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.CoreSetupRejectSerializer
+import de.justjanne.libquassel.protocol.serializers.handshake.SessionInitSerializer
 
+/**
+ * Singleton object containing all serializers for handshake message types
+ */
 object HandshakeSerializers {
   private val serializers = listOf<HandshakeSerializer<*>>(
     ClientInitSerializer,
@@ -38,8 +50,14 @@ object HandshakeSerializers {
     SessionInitSerializer,
   ).associateBy(HandshakeSerializer<*>::type)
 
+  /**
+   * Obtain the serializer for a handshake message type
+   */
   operator fun get(type: String) = serializers[type]
 
+  /**
+   * Obtain the serializer for a handshake message type (type safe)
+   */
   @Suppress("UNCHECKED_CAST")
   inline fun <reified T> find(type: String): HandshakeSerializer<T> {
     val serializer = get(type)
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/NoSerializerForTypeException.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/NoSerializerForTypeException.kt
similarity index 75%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/NoSerializerForTypeException.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/NoSerializerForTypeException.kt
index 60d1568f0cfa1ddf00ac99233ae94f04dff64f3f..3a20043000d53fe08a4bfe14392f088f60a5eb7e 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/NoSerializerForTypeException.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/NoSerializerForTypeException.kt
@@ -22,7 +22,13 @@ package de.justjanne.libquassel.protocol.serializers
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.QuasselType
 
+/**
+ * Exception describing a missing serializer condition
+ */
 sealed class NoSerializerForTypeException : Exception() {
+  /**
+   * Exception describing a missing serializer condition for a qt type
+   */
   data class Qt(
     private val type: Int,
     private val javaType: Class<*>? = null
@@ -37,6 +43,9 @@ sealed class NoSerializerForTypeException : Exception() {
     }
   }
 
+  /**
+   * Exception describing a missing serializer condition for a quassel type
+   */
   data class Quassel(
     private val type: Int,
     private val typename: String?,
@@ -58,6 +67,9 @@ sealed class NoSerializerForTypeException : Exception() {
     }
   }
 
+  /**
+   * Exception describing a missing serializer condition for a handshake type
+   */
   data class Handshake(
     private val type: String,
     private val javaType: Class<*>? = null
@@ -66,4 +78,16 @@ sealed class NoSerializerForTypeException : Exception() {
       return "NoSerializerForTypeException.Handshake(type='$type', javaType=$javaType)"
     }
   }
+
+  /**
+   * Exception describing a missing serializer condition for a signal proxy type
+   */
+  data class SignalProxy(
+    private val type: String,
+    private val javaType: Class<*>? = null
+  ) : NoSerializerForTypeException() {
+    override fun toString(): String {
+      return "NoSerializerForTypeException.Handshake(type='$type', javaType=$javaType)"
+    }
+  }
 }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QtSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QtSerializer.kt
similarity index 65%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QtSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QtSerializer.kt
index e44f5adc2db23373445069500e9d97b84cc4c0c3..2298c5b2bd0fbe999ed44d5cc2a1eed881a69da8 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QtSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QtSerializer.kt
@@ -21,7 +21,22 @@ package de.justjanne.libquassel.protocol.serializers
 
 import de.justjanne.libquassel.protocol.variant.QtType
 
+/**
+ * Interface describing a serializer for a [QtType], that is a type introduced
+ * by qt, and serialized compatible with the QDataStream format.
+ *
+ * See [QDataStream Documentation](https://doc.qt.io/qt-5/qdatastream.html)
+ */
 interface QtSerializer<T> : Serializer<T> {
+  /**
+   * The underlying QtType this Serializer can (de-)serialize.
+   * Used for type-safe serializer autodiscovery.
+   */
   val qtType: QtType
+
+  /**
+   * The underlying Java type this Serializer can (de-)serialize.
+   * Used for type-safe serializer autodiscovery.
+   */
   val javaType: Class<out T>
 }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QtSerializers.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QtSerializers.kt
similarity index 94%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QtSerializers.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QtSerializers.kt
index baa34e1d07ab48a2a04b43b2349d8ee646453bb2..846ffc3c85229dbf5c3b6c5c0a193a9fdef7ca1d 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QtSerializers.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QtSerializers.kt
@@ -43,6 +43,9 @@ import de.justjanne.libquassel.protocol.serializers.qt.UShortSerializer
 import de.justjanne.libquassel.protocol.serializers.qt.VoidSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 
+/**
+ * Singleton object containing all serializers for qt types
+ */
 object QtSerializers {
   private val serializers = setOf<QtSerializer<*>>(
     VoidSerializer,
@@ -74,8 +77,14 @@ object QtSerializers {
     QVariantMapSerializer,
   ).associateBy(QtSerializer<*>::qtType)
 
+  /**
+   * Obtain the serializer for a qt type
+   */
   operator fun get(type: QtType) = serializers[type]
 
+  /**
+   * Obtain the serializer for a qt type (type safe)
+   */
   @Suppress("UNCHECKED_CAST")
   inline fun <reified T> find(type: QtType): QtSerializer<T> {
     val serializer = get(type)
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QuasselSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QuasselSerializer.kt
similarity index 81%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QuasselSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QuasselSerializer.kt
index bb897eaaad16c1d7fcb13526c1488487d613b99a..55fb54a56aeafc7619ad4be8819e9929c793339f 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QuasselSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QuasselSerializer.kt
@@ -22,7 +22,16 @@ package de.justjanne.libquassel.protocol.serializers
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.QuasselType
 
+/**
+ * Interface describing a serializer for a [QuasselType], that is a type
+ * custom to quassel.
+ */
 interface QuasselSerializer<T> : QtSerializer<T> {
   override val qtType: QtType get() = quasselType.qtType
+
+  /**
+   * The underlying quassel type this serializer can (de-)serialize.
+   * Used for type-safe serializer autodiscovery.
+   */
   val quasselType: QuasselType
 }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QuasselSerializers.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QuasselSerializers.kt
similarity index 92%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QuasselSerializers.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QuasselSerializers.kt
index 3ac6287d03a13314a2496dc34dfa52512220b108..7d2643cd9b92a6d6640fd72908a00746d1b044f5 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/QuasselSerializers.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/QuasselSerializers.kt
@@ -31,6 +31,9 @@ import de.justjanne.libquassel.protocol.serializers.quassel.PeerPtrSerializer
 import de.justjanne.libquassel.protocol.serializers.quassel.QHostAddressSerializer
 import de.justjanne.libquassel.protocol.variant.QuasselType
 
+/**
+ * Singleton object containing all serializers for quassel types
+ */
 object QuasselSerializers {
   private val serializers = listOf<QuasselSerializer<*>>(
     BufferIdSerializer,
@@ -50,8 +53,14 @@ object QuasselSerializers {
     PeerPtrSerializer,
   ).associateBy(QuasselSerializer<*>::quasselType)
 
+  /**
+   * Obtain the serializer for a quassel type
+   */
   operator fun get(type: QuasselType) = serializers[type]
 
+  /**
+   * Obtain the serializer for a quassel type (type safe)
+   */
   @Suppress("UNCHECKED_CAST")
   inline fun <reified T> find(type: QuasselType): QuasselSerializer<T> {
     val serializer = get(type)
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/Serializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/Serializer.kt
similarity index 62%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/Serializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/Serializer.kt
index 7162eae22de297a6288ed3ccabddc31bca864234..ebe9b15923cad83eae0ff86f426fc9f2ce68b542 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/Serializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/Serializer.kt
@@ -23,7 +23,26 @@ import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
 import java.nio.ByteBuffer
 
+/**
+ * Interface describing a generic quassel protocol serializer.
+ *
+ * Further specialized into [QtSerializer] and  [QuasselSerializer]
+ */
 interface Serializer<T> {
+  /**
+   * Serialize data with the Quassel protocol to a buffer
+   * @param buffer target buffer to serialize to
+   * @param data value to serialize
+   * @param featureSet features to use when serializing, usually the featureset
+   * of the currently negotiated connection
+   */
   fun serialize(buffer: ChainedByteBuffer, data: T, featureSet: FeatureSet)
+
+  /**
+   * Deserialize Quassel protocol data from a buffer
+   * @param buffer source buffer to deserialize from
+   * @param featureSet features to use when deserializing, usually the
+   * featureset of the currently negotiated connection
+   */
   fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): T
 }
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitAckSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
similarity index 90%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitAckSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
index b0be6306c46830c5fa244fbe8c2ce419a71359f3..c63b9910459904fc32c6ab8d5c265960d6329a1a 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitAckSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
@@ -17,18 +17,23 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
 import de.justjanne.bitflags.of
 import de.justjanne.bitflags.toBits
 import de.justjanne.libquassel.protocol.features.LegacyFeature
 import de.justjanne.libquassel.protocol.features.QuasselFeatureName
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QStringList
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.ClientInitAck]
+ */
 object ClientInitAckSerializer : HandshakeSerializer<HandshakeMessage.ClientInitAck> {
   override val type: String = "ClientInitAck"
   override val javaType: Class<out HandshakeMessage.ClientInitAck> =
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitRejectSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitRejectSerializer.kt
similarity index 85%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitRejectSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitRejectSerializer.kt
index 3a6ff2319c6cba4e5bc989781e605132f6f56238..f750b646a41fc54fa70818d22891d2f517f9b5f0 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitRejectSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitRejectSerializer.kt
@@ -17,13 +17,18 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.ClientInitReject]
+ */
 object ClientInitRejectSerializer : HandshakeSerializer<HandshakeMessage.ClientInitReject> {
   override val type: String = "ClientInitReject"
   override val javaType: Class<out HandshakeMessage.ClientInitReject> =
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
similarity index 89%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
index d1fc067e3e1f78de4561ac55a5513291c860477e..add62e8be88e5054b82b7cb5c9544e319567ab59 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
@@ -17,17 +17,22 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
 import de.justjanne.bitflags.of
 import de.justjanne.bitflags.toBits
 import de.justjanne.libquassel.protocol.features.LegacyFeature
 import de.justjanne.libquassel.protocol.features.QuasselFeatureName
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.ClientInit]
+ */
 object ClientInitSerializer : HandshakeSerializer<HandshakeMessage.ClientInit> {
   override val type: String = "ClientInit"
   override val javaType: Class<out HandshakeMessage.ClientInit> =
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientLoginAckSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientLoginAckSerializer.kt
similarity index 84%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientLoginAckSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientLoginAckSerializer.kt
index afd8ea3b1cc8a43b9d3aaed4b13da6e9f8ab307d..8ebf0383fcc8f8e359b1799d4992bd65ed290318 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientLoginAckSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientLoginAckSerializer.kt
@@ -17,12 +17,17 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.ClientLoginAck]
+ */
 object ClientLoginAckSerializer : HandshakeSerializer<HandshakeMessage.ClientLoginAck> {
   override val type: String = "ClientLoginAck"
   override val javaType: Class<out HandshakeMessage.ClientLoginAck> =
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientLoginRejectSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientLoginRejectSerializer.kt
similarity index 85%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientLoginRejectSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientLoginRejectSerializer.kt
index e12af1a37675acc238bfdd03dde853c7460eb605..1912cfad400af10a9e64b422a9b78af10ec934ca 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientLoginRejectSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientLoginRejectSerializer.kt
@@ -17,13 +17,18 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.ClientLoginReject]
+ */
 object ClientLoginRejectSerializer : HandshakeSerializer<HandshakeMessage.ClientLoginReject> {
   override val type: String = "ClientLoginReject"
   override val javaType: Class<out HandshakeMessage.ClientLoginReject> =
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientLoginSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientLoginSerializer.kt
similarity index 86%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientLoginSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientLoginSerializer.kt
index 621137137762b75460ce86e9e57c867cb2dea885..ba9016d9135caec54cce2cc8319b1ce0cd1ff08e 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/ClientLoginSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientLoginSerializer.kt
@@ -17,13 +17,18 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.ClientLogin]
+ */
 object ClientLoginSerializer : HandshakeSerializer<HandshakeMessage.ClientLogin> {
   override val type: String = "ClientLogin"
   override val javaType: Class<out HandshakeMessage.ClientLogin> =
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/CoreSetupAckSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/CoreSetupAckSerializer.kt
similarity index 84%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/CoreSetupAckSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/CoreSetupAckSerializer.kt
index da01a780da992c74512e4810616fd18afb09031d..3feecb10485a2efeffd2c5d7cf86b9ad23cf3eef 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/CoreSetupAckSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/CoreSetupAckSerializer.kt
@@ -17,12 +17,17 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.CoreSetupAck]
+ */
 object CoreSetupAckSerializer : HandshakeSerializer<HandshakeMessage.CoreSetupAck> {
   override val type: String = "CoreSetupAck"
   override val javaType: Class<out HandshakeMessage.CoreSetupAck> =
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/CoreSetupDataSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/CoreSetupDataSerializer.kt
similarity index 90%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/CoreSetupDataSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/CoreSetupDataSerializer.kt
index be39eb3144e2326a5d2d90fe54d56cca989bfb0b..613f414d1702287d4bcab788b545c81d5517638d 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/CoreSetupDataSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/CoreSetupDataSerializer.kt
@@ -17,13 +17,18 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.CoreSetupData]
+ */
 object CoreSetupDataSerializer : HandshakeSerializer<HandshakeMessage.CoreSetupData> {
   override val type: String = "CoreSetupData"
   override val javaType: Class<out HandshakeMessage.CoreSetupData> =
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/CoreSetupRejectSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/CoreSetupRejectSerializer.kt
similarity index 85%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/CoreSetupRejectSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/CoreSetupRejectSerializer.kt
index a36d0edc8401c9f4c4679e91b58b5daabc2182c7..03c99e319ffeb7161aef33751e72ce2dbce5d2bf 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/CoreSetupRejectSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/CoreSetupRejectSerializer.kt
@@ -17,13 +17,18 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.CoreSetupReject]
+ */
 object CoreSetupRejectSerializer : HandshakeSerializer<HandshakeMessage.CoreSetupReject> {
   override val type: String = "CoreSetupReject"
   override val javaType: Class<out HandshakeMessage.CoreSetupReject> =
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/SessionInitSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializer.kt
similarity index 88%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/SessionInitSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializer.kt
index 70309e86f8222d6dc1e26735026f211a67b6cec2..419ceabcae9018c0e7bdf30c0c28cb54d08f28a2 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/SessionInitSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/SessionInitSerializer.kt
@@ -17,13 +17,18 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.libquassel.protocol.variant.qVariant
 
+/**
+ * Serializer for [HandshakeMessage.SessionInit]
+ */
 object SessionInitSerializer : HandshakeSerializer<HandshakeMessage.SessionInit> {
   override val type: String = "SessionInit"
   override val javaType: Class<out HandshakeMessage.SessionInit> =
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/BoolSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/BoolSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/BoolSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/BoolSerializer.kt
index 13c82826e4edbe93a5e9ca67cc35a914ce675fea..113b69a5312ae633cc0e8253d486a6d32137f1a8 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/BoolSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/BoolSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [Boolean]
+ */
 object BoolSerializer : QtSerializer<Boolean> {
   override val qtType: QtType = QtType.Bool
   override val javaType: Class<Boolean> = Boolean::class.javaObjectType
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ByteBufferSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ByteBufferSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ByteBufferSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ByteBufferSerializer.kt
index 6dabf23f05087316f3d1bf1a832ebf7bb6218e2b..77e01be022b747a6a2e435abaa9882419e0e4d1d 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ByteBufferSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ByteBufferSerializer.kt
@@ -26,6 +26,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [ByteBuffer]
+ */
 object ByteBufferSerializer : QtSerializer<ByteBuffer?> {
   override val qtType: QtType = QtType.QByteArray
   override val javaType: Class<out ByteBuffer?> = ByteBuffer::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ByteSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ByteSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ByteSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ByteSerializer.kt
index 20afff7fe0140e3c5dd33520e0c446224a7f946b..3e80b34848ff222cf8b71412029a9428e78a0564 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ByteSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ByteSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [Byte]
+ */
 object ByteSerializer : QtSerializer<Byte> {
   override val qtType: QtType = QtType.Char
   override val javaType: Class<Byte> = Byte::class.javaObjectType
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/DateSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/DateSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/DateSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/DateSerializer.kt
index 8710ab9d1ca538202476c888e7003c61ae653d8a..663b21a3c08e331bd87e60983e14a2c1f9894204 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/DateSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/DateSerializer.kt
@@ -27,6 +27,9 @@ import org.threeten.bp.LocalDate
 import org.threeten.bp.temporal.JulianFields
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [LocalDate]
+ */
 object DateSerializer : QtSerializer<LocalDate> {
   override val qtType: QtType = QtType.QDate
   override val javaType: Class<out LocalDate> = LocalDate::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/DateTimeSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/DateTimeSerializer.kt
similarity index 96%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/DateTimeSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/DateTimeSerializer.kt
index 41fef1d70a4251cf24f3adcdfaae2f2563dc318a..c7ac7f93d522bdc6b405775615839ca6ff0053f9 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/DateTimeSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/DateTimeSerializer.kt
@@ -32,6 +32,9 @@ import org.threeten.bp.ZonedDateTime
 import org.threeten.bp.temporal.Temporal
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for temporal types such as [Instant], [ZonedDateTime], [OffsetDateTime] or [LocalDateTime]
+ */
 object DateTimeSerializer : QtSerializer<Temporal> {
   override val qtType: QtType = QtType.QDateTime
   override val javaType: Class<out Temporal> = Temporal::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/DoubleSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/DoubleSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/DoubleSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/DoubleSerializer.kt
index 4e35405c04a24d16b856229acd2a7a7b3d4ae215..12f0a1ac6ddc423fdb0b03735dd237716835345b 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/DoubleSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/DoubleSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [Double]
+ */
 object DoubleSerializer : QtSerializer<Double> {
   override val qtType: QtType = QtType.Double
   override val javaType: Class<Double> = Double::class.javaObjectType
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/FloatSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/FloatSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/FloatSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/FloatSerializer.kt
index bf8bad1b7b7dcd595ed4e5db727736ede77bbc1e..1fdccbfa14f01f9235190b5291dafd842a7bf6aa 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/FloatSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/FloatSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [Float]
+ */
 object FloatSerializer : QtSerializer<Float> {
   override val qtType: QtType = QtType.Float
   override val javaType: Class<Float> = Float::class.javaObjectType
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/HandshakeMapSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/HandshakeMapSerializer.kt
similarity index 94%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/HandshakeMapSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/HandshakeMapSerializer.kt
index 06278a7f27e5d600f871fcc2e0cd95d3830f7c4d..cad1368affd1c6977752330b56304cfa67903030 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/HandshakeMapSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/HandshakeMapSerializer.kt
@@ -29,6 +29,10 @@ import de.justjanne.libquassel.protocol.variant.into
 import de.justjanne.libquassel.protocol.variant.qVariant
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [QVariantMap] during handshake,
+ * which uses a special format instead of [QVariantMapSerializer]
+ */
 object HandshakeMapSerializer : QtSerializer<QVariantMap> {
   override val qtType = QtType.QVariantMap
 
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/IntSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/IntSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/IntSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/IntSerializer.kt
index 47aa3f029953509ea51510a844d80df0a07e26b6..eb10cd528bcef08749f6403b321b8c3427983ce8 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/IntSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/IntSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [Int]
+ */
 object IntSerializer : QtSerializer<Int> {
   override val qtType: QtType = QtType.Int
   override val javaType: Class<Int> = Int::class.javaObjectType
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/LongSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/LongSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/LongSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/LongSerializer.kt
index c04fee89b0b712dd0fc94595f7b2658a38793d22..6268691705939988c92736ac71ff80aef3b674e7 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/LongSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/LongSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [Long]
+ */
 object LongSerializer : QtSerializer<Long> {
   override val qtType: QtType = QtType.Long
   override val javaType: Class<Long> = Long::class.javaObjectType
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QCharSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QCharSerializer.kt
similarity index 98%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QCharSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QCharSerializer.kt
index 4eaa9eb645e2535f973fe50a5373a1f7093ce677..354e979a5875d5ea43df1de662b6d97f87df9da0 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QCharSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QCharSerializer.kt
@@ -27,6 +27,9 @@ import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 import kotlin.concurrent.getOrSet
 
+/**
+ * Serializer for [Char]
+ */
 object QCharSerializer : QtSerializer<Char> {
   override val qtType: QtType = QtType.QChar
   override val javaType: Class<out Char> = Char::class.javaObjectType
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QStringListSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QStringListSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QStringListSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QStringListSerializer.kt
index 3c1675bf728696189620e7eb3cc52fb327c4c369..bbdfa7a80f252122d75ef3a03a7da43e277e9159 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QStringListSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QStringListSerializer.kt
@@ -26,6 +26,9 @@ import de.justjanne.libquassel.protocol.variant.QStringList
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [QStringList]
+ */
 object QStringListSerializer : QtSerializer<QStringList> {
   override val qtType = QtType.QStringList
 
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QVariantListSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QVariantListSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QVariantListSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QVariantListSerializer.kt
index b216eee96bc6e895f27525a4b00a946774337387..520fe34873cf4bd29ddd8d811ed1a8d9038be526 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QVariantListSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QVariantListSerializer.kt
@@ -27,6 +27,9 @@ import de.justjanne.libquassel.protocol.variant.QVariant_
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [QVariantList]
+ */
 object QVariantListSerializer : QtSerializer<QVariantList> {
   override val qtType = QtType.QVariantList
 
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QVariantMapSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QVariantMapSerializer.kt
similarity index 98%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QVariantMapSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QVariantMapSerializer.kt
index b2043e436f78afb951593838e13ec4f1aa45e783..128a0988e5a42c224198cde604cd550b7985a3ca 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QVariantMapSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QVariantMapSerializer.kt
@@ -27,6 +27,9 @@ import de.justjanne.libquassel.protocol.variant.QVariant_
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [QVariantMap]
+ */
 object QVariantMapSerializer : QtSerializer<QVariantMap> {
   override val qtType = QtType.QVariantMap
 
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QVariantSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QVariantSerializer.kt
similarity index 96%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QVariantSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QVariantSerializer.kt
index 0486714dcdd45b9b10ddcbd538f93634dec84404..ac7beebcde8a5b77549a77f823c38530f652ef4a 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/QVariantSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/QVariantSerializer.kt
@@ -32,6 +32,9 @@ import de.justjanne.libquassel.protocol.variant.QtType
 import de.justjanne.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [QVariant]
+ */
 object QVariantSerializer : QtSerializer<QVariant_> {
   override val qtType = QtType.QVariant
   override val javaType: Class<QVariant_> = QVariant::class.java
@@ -39,7 +42,7 @@ object QVariantSerializer : QtSerializer<QVariant_> {
   override fun serialize(buffer: ChainedByteBuffer, data: QVariant_, featureSet: FeatureSet) {
     IntSerializer.serialize(buffer, data.serializer.qtType.id, featureSet)
     BoolSerializer.serialize(buffer, false, featureSet)
-    if (data is QVariant.Custom) {
+    if (data.serializer.qtType == QtType.UserType && data is QVariant.Custom) {
       StringSerializerAscii.serialize(buffer, data.serializer.quasselType.typeName, featureSet)
     }
     data.serialize(buffer, featureSet)
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ShortSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ShortSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ShortSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ShortSerializer.kt
index bbe4c9a867185a1897cf3f47cdf1c4536ad49c09..d0fdda41792f848a845ac7a51b1da3cf78216a94 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ShortSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ShortSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [Short]
+ */
 object ShortSerializer : QtSerializer<Short> {
   override val qtType: QtType = QtType.Short
   override val javaType: Class<Short> = Short::class.javaObjectType
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializer.kt
similarity index 94%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializer.kt
index 3b93ee44ed0486950252f17129abcaca35be4ea6..4174161a3dbfb18e60b9de81daacada938dcb001 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializer.kt
@@ -28,6 +28,11 @@ import java.nio.ByteBuffer
 import java.nio.charset.Charset
 import kotlin.concurrent.getOrSet
 
+/**
+ * Abstract serializer for Strings.
+ *
+ * For concrete implementations see [StringSerializerAscii], [StringSerializerUtf8] and [StringSerializerUtf16]
+ */
 abstract class StringSerializer(
   private val charset: Charset,
   private val nullLimited: Boolean,
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerAscii.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerAscii.kt
similarity index 95%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerAscii.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerAscii.kt
index 95d0ffb25b06731cc45f68f61d3891e111babbcc..928b990f65493a8d32789a09d963098702a2ae07 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerAscii.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerAscii.kt
@@ -19,4 +19,7 @@
 
 package de.justjanne.libquassel.protocol.serializers.qt
 
+/**
+ * Serializer for ASCII strings
+ */
 object StringSerializerAscii : StringSerializer(Charsets.ISO_8859_1, true)
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf16.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf16.kt
similarity index 95%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf16.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf16.kt
index 70aee02b8d80cadf8bd7e0b0f3d8c5674a2a40df..8d1c2d38134da9b33240537101f6983c44892dcb 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf16.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf16.kt
@@ -19,4 +19,7 @@
 
 package de.justjanne.libquassel.protocol.serializers.qt
 
+/**
+ * Serializer for UTF-16 strings
+ */
 object StringSerializerUtf16 : StringSerializer(Charsets.UTF_16BE, false)
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf8.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf8.kt
similarity index 95%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf8.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf8.kt
index 6a02d471686c59624512927b4ec0b68c12cccd0b..1133a064685568d979e7b3163e267d25fa306dff 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf8.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/StringSerializerUtf8.kt
@@ -19,4 +19,7 @@
 
 package de.justjanne.libquassel.protocol.serializers.qt
 
+/**
+ * Serializer for UTF-8 strings
+ */
 object StringSerializerUtf8 : StringSerializer(Charsets.UTF_8, false)
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/TimeSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/TimeSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/TimeSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/TimeSerializer.kt
index b6e472a69720da752ca164e7dfb7e4d8afab4cc5..8de939832c65d094611f35881c9e616ebf967f23 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/TimeSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/TimeSerializer.kt
@@ -26,6 +26,9 @@ import de.justjanne.libquassel.protocol.variant.QtType
 import org.threeten.bp.LocalTime
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [LocalTime]
+ */
 object TimeSerializer : QtSerializer<LocalTime> {
   override val qtType: QtType = QtType.QTime
   override val javaType: Class<out LocalTime> = LocalTime::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/UByteSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/UByteSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/UByteSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/UByteSerializer.kt
index 2c92292826d3baf419c83f2c67b81a498e441262..dfe17186b9a85cb8e14a0b0462a812b31850c123 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/UByteSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/UByteSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [UByte]
+ */
 object UByteSerializer : QtSerializer<UByte> {
   override val qtType: QtType = QtType.UChar
   override val javaType: Class<UByte> = UByte::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/UIntSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/UIntSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/UIntSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/UIntSerializer.kt
index c8ac10e5743395084d544a7ee31ed4ef793f0d3b..67cce793ef957257061f4420c33ae44be2d7126d 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/UIntSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/UIntSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [UInt]
+ */
 object UIntSerializer : QtSerializer<UInt> {
   override val qtType: QtType = QtType.UInt
   override val javaType: Class<UInt> = UInt::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ULongSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ULongSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ULongSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ULongSerializer.kt
index ee3a7bc2d3006b478e6fb438dbd4dff2bad713c7..a5015cd0da5b37f515ff66f5e53f7e4f7d12c5ad 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/ULongSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/ULongSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [ULong]
+ */
 object ULongSerializer : QtSerializer<ULong> {
   override val qtType: QtType = QtType.ULong
   override val javaType: Class<ULong> = ULong::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/UShortSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/UShortSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/UShortSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/UShortSerializer.kt
index 0037c34e8a28cdadfd7148b5f535402601b10233..28e9c074aa125ddc6d3a444c3e82b96fb6f33651 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/UShortSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/UShortSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [UShort]
+ */
 object UShortSerializer : QtSerializer<UShort> {
   override val qtType: QtType = QtType.UShort
   override val javaType: Class<UShort> = UShort::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/VoidSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/VoidSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/VoidSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/VoidSerializer.kt
index 9ebf40b47a655136deba8581dee8149b67a4d64a..9444f091f7074887312532d162adac9f1d90d343 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/qt/VoidSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/qt/VoidSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QtSerializer
 import de.justjanne.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for empty data
+ */
 object VoidSerializer : QtSerializer<Unit> {
   override val qtType: QtType = QtType.Void
   override val javaType: Class<out Unit> = Unit::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/BufferIdSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/BufferIdSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/BufferIdSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/BufferIdSerializer.kt
index a17ffe094ef53997da5b4efe0a0c98b3d1e8923a..622a0d1f6ae30e93f534b85f2cb2a1873e0ed715 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/BufferIdSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/BufferIdSerializer.kt
@@ -27,6 +27,9 @@ import de.justjanne.libquassel.protocol.types.BufferId
 import de.justjanne.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [BufferId]
+ */
 object BufferIdSerializer : QuasselSerializer<BufferId> {
   override val quasselType: QuasselType = QuasselType.BufferId
   override val javaType: Class<out BufferId> = BufferId::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/BufferInfoSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/BufferInfoSerializer.kt
similarity index 98%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/BufferInfoSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/BufferInfoSerializer.kt
index 356caba0917a06e6572e48409a6e370b9751fd75..553a92cce8705c547868b6f3144d14c687f4a240 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/BufferInfoSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/BufferInfoSerializer.kt
@@ -32,6 +32,9 @@ import de.justjanne.libquassel.protocol.types.BufferType
 import de.justjanne.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [BufferInfo]
+ */
 object BufferInfoSerializer : QuasselSerializer<BufferInfo> {
   override val quasselType: QuasselType = QuasselType.BufferInfo
   override val javaType: Class<out BufferInfo> = BufferInfo::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/DccIpDetectionModeSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/DccIpDetectionModeSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/DccIpDetectionModeSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/DccIpDetectionModeSerializer.kt
index 5fdc6dc241d67a7b0d0699d568e1a11ba78d5d70..607a8ba8c4339f41c9443f7d4f5a76623afac14c 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/DccIpDetectionModeSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/DccIpDetectionModeSerializer.kt
@@ -27,6 +27,9 @@ import de.justjanne.libquassel.protocol.types.DccIpDetectionMode
 import de.justjanne.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [DccIpDetectionMode]
+ */
 object DccIpDetectionModeSerializer : QuasselSerializer<DccIpDetectionMode?> {
   override val quasselType: QuasselType = QuasselType.DccConfigIpDetectionMode
 
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/DccPortSelectionModeSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/DccPortSelectionModeSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/DccPortSelectionModeSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/DccPortSelectionModeSerializer.kt
index f7a4e333b46fc2120151f7e8c765bcd0052d3e7a..da9ff12bb6a6f0b22b75fafcdbf19fe8699f2125 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/DccPortSelectionModeSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/DccPortSelectionModeSerializer.kt
@@ -27,6 +27,9 @@ import de.justjanne.libquassel.protocol.types.DccPortSelectionMode
 import de.justjanne.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [DccPortSelectionMode]
+ */
 object DccPortSelectionModeSerializer : QuasselSerializer<DccPortSelectionMode?> {
   override val quasselType: QuasselType = QuasselType.DccConfigPortSelectionMode
 
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/IdentityIdSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentityIdSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/IdentityIdSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentityIdSerializer.kt
index a259c7b214cafa535c4b5fcbdd17cc13bf9d301b..afa871d6767127474f5a7d3e0e09f6d60ad1635b 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/IdentityIdSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentityIdSerializer.kt
@@ -27,6 +27,9 @@ import de.justjanne.libquassel.protocol.types.IdentityId
 import de.justjanne.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [IdentityId]
+ */
 object IdentityIdSerializer : QuasselSerializer<IdentityId> {
   override val quasselType: QuasselType = QuasselType.IdentityId
   override val javaType: Class<out IdentityId> = IdentityId::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/MessageSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/MessageSerializer.kt
similarity index 99%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/MessageSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/MessageSerializer.kt
index 25b2770b7c167a2bcde10c374ae5afb6b5e9f898..372875947bda939c3aa67ac48ea70d47f15fc0ac 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/MessageSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/MessageSerializer.kt
@@ -37,6 +37,9 @@ import de.justjanne.libquassel.protocol.variant.QuasselType
 import org.threeten.bp.Instant
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [Message]
+ */
 object MessageSerializer : QuasselSerializer<Message> {
   override val quasselType: QuasselType = QuasselType.Message
   override val javaType: Class<out Message> = Message::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/MsgIdSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/MsgIdSerializer.kt
similarity index 98%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/MsgIdSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/MsgIdSerializer.kt
index 47da0194ad8a96f7b9c5f24b9f1deaa97651d8ba..6a381fba05888da5db1cec2933e516fe9eb7f09d 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/MsgIdSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/MsgIdSerializer.kt
@@ -29,6 +29,9 @@ import de.justjanne.libquassel.protocol.types.MsgId
 import de.justjanne.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [MsgId]
+ */
 object MsgIdSerializer : QuasselSerializer<MsgId> {
   override val quasselType: QuasselType = QuasselType.MsgId
   override val javaType: Class<out MsgId> = MsgId::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/NetworkIdSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkIdSerializer.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/NetworkIdSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkIdSerializer.kt
index e82dac94e9ce2e7fef0ed2f87d9ac0e5d9aa3d86..c09a58465632324a67110f59c6e284f80cddec1a 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/NetworkIdSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/NetworkIdSerializer.kt
@@ -27,6 +27,9 @@ import de.justjanne.libquassel.protocol.types.NetworkId
 import de.justjanne.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [NetworkId]
+ */
 object NetworkIdSerializer : QuasselSerializer<NetworkId> {
   override val quasselType: QuasselType = QuasselType.NetworkId
   override val javaType: Class<out NetworkId> = NetworkId::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/PeerPtrSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/PeerPtrSerializer.kt
similarity index 95%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/PeerPtrSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/PeerPtrSerializer.kt
index 74cc9cb386064bcffbc5ac2f4753e4eccc802986..40473caa77fdb3e3ef6000ae987a6f302af246d9 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/PeerPtrSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/PeerPtrSerializer.kt
@@ -25,6 +25,9 @@ import de.justjanne.libquassel.protocol.serializers.QuasselSerializer
 import de.justjanne.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for PeerPtr, which is implemented as [ULong]
+ */
 object PeerPtrSerializer : QuasselSerializer<ULong> {
   override val quasselType: QuasselType = QuasselType.PeerPtr
   override val javaType: Class<ULong> = ULong::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/QHostAddressSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/QHostAddressSerializer.kt
similarity index 98%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/QHostAddressSerializer.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/QHostAddressSerializer.kt
index d6d4d6e2b6b77508583dba04db7866fe094d8362..ac5bc810ec7fba29e77f6a357cc729331a945fe8 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/serializers/quassel/QHostAddressSerializer.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/QHostAddressSerializer.kt
@@ -30,6 +30,9 @@ import java.net.Inet6Address
 import java.net.InetAddress
 import java.nio.ByteBuffer
 
+/**
+ * Serializer for [InetAddress]
+ */
 object QHostAddressSerializer : QuasselSerializer<InetAddress> {
   override val quasselType: QuasselType = QuasselType.QHostAddress
   override val javaType: Class<out InetAddress> = InetAddress::class.java
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferActivity.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferActivity.kt
similarity index 77%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferActivity.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferActivity.kt
index 76228ed8f5e2736a69207fc13a64655b2a8d2109..458c7da74db0ef6ce982be24f912716b337194c4 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferActivity.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferActivity.kt
@@ -23,12 +23,25 @@ import de.justjanne.bitflags.Flag
 import de.justjanne.bitflags.Flags
 import de.justjanne.bitflags.toEnumSet
 
+/**
+ * Model representing all seen activity on a buffer
+ */
 enum class BufferActivity(
   override val value: UInt,
 ) : Flag<UInt> {
-  NoActivity(0x00u),
+  /**
+   * Other, unspecified activity has occurred on this buffer (join, part, quit, etc)
+   */
   OtherActivity(0x01u),
+
+  /**
+   * A new unread mesage is available on this buffer
+   */
   NewMessage(0x02u),
+
+  /**
+   * A highlight for the current user is available on this buffer
+   */
   Highlight(0x04u);
 
   companion object : Flags<UInt, BufferActivity> {
@@ -37,4 +50,7 @@ enum class BufferActivity(
   }
 }
 
+/**
+ * Model representing a bitfield of [BufferActivity] flags
+ */
 typealias BufferActivities = Set<BufferActivity>
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferId.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferId.kt
similarity index 79%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferId.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferId.kt
index 2bebd404e9f9b3d534f431f9c285af918ef254f7..8720e7afb0de008051157259130a67f674e97e1c 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferId.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferId.kt
@@ -21,11 +21,26 @@ package de.justjanne.libquassel.protocol.types
 
 private typealias BufferIdType = SignedIdType
 
-inline class BufferId(override val id: BufferIdType) : SignedId<BufferIdType> {
+/**
+ * A [SignedId] for a chat/buuffer
+ */
+inline class BufferId(
+  /**
+   * Native value
+   */
+  override val id: BufferIdType
+) : SignedId<BufferIdType> {
   override fun toString() = "BufferId($id)"
 
   companion object {
+    /**
+     * Lower limit for this type
+     */
     val MIN_VALUE = BufferId(BufferIdType.MIN_VALUE)
+
+    /**
+     * Upper limit for this type
+     */
     val MAX_VALUE = BufferId(BufferIdType.MAX_VALUE)
   }
 }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferInfo.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferInfo.kt
similarity index 77%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferInfo.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferInfo.kt
index cb49ccf3c2240cfb2fb5e1c25cf64bcb4a540ffb..b3531b1a556414cc15ded050274be0534bc378b5 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferInfo.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferInfo.kt
@@ -21,10 +21,28 @@ package de.justjanne.libquassel.protocol.types
 
 import de.justjanne.bitflags.none
 
+/**
+ * Model object representing metadata for a single chat
+ */
 data class BufferInfo(
+  /**
+   * Id of the chat
+   */
   val bufferId: BufferId = BufferId(-1),
+  /**
+   * Id of the network to which this chat belongs
+   */
   val networkId: NetworkId = NetworkId(-1),
+  /**
+   * type of this chat
+   */
   val type: BufferTypes = BufferType.none(),
+  /**
+   * Id of the group to which this chat belongs
+   */
   val groupId: Int = -1,
+  /**
+   * User-visible name of this chat
+   */
   val bufferName: String? = null,
 )
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferType.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferType.kt
similarity index 77%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferType.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferType.kt
index 8ee3b1add5a35e46311b1b1dde0c75ef3c573c7a..32257da7a9b810d41ef8d36316580e5749d80b1a 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/BufferType.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/BufferType.kt
@@ -23,13 +23,30 @@ import de.justjanne.bitflags.Flag
 import de.justjanne.bitflags.Flags
 import de.justjanne.bitflags.toEnumSet
 
+/**
+ * Model representing different types of chats
+ */
 enum class BufferType(
   override val value: UShort,
 ) : Flag<UShort> {
-  Invalid(0x00u),
+  /**
+   * Status chat with technical data and internal information
+   */
   Status(0x01u),
+
+  /**
+   * Named channel with potentially multiple users
+   */
   Channel(0x02u),
+
+  /**
+   * Direct chat with a single other user
+   */
   Query(0x04u),
+
+  /**
+   * Unnamed group between multiple users
+   */
   Group(0x08u);
 
   companion object : Flags<UShort, BufferType> {
@@ -38,4 +55,7 @@ enum class BufferType(
   }
 }
 
+/**
+ * Model representing a bitfield of [BufferType] flags
+ */
 typealias BufferTypes = Set<BufferType>
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/DccIpDetectionMode.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/DccIpDetectionMode.kt
similarity index 91%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/DccIpDetectionMode.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/DccIpDetectionMode.kt
index 153e5a5b99a2267bba0f94012069e5f9c67abf29..5b4ebdec567b614be3dc49830358408caa585257 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/DccIpDetectionMode.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/DccIpDetectionMode.kt
@@ -23,6 +23,9 @@ package de.justjanne.libquassel.protocol.types
  * Mode for detecting the outgoing IP
  */
 enum class DccIpDetectionMode(
+  /**
+   * Underlying representation
+   */
   val value: UByte,
 ) {
   /** Automatic detection (network socket or USERHOST) */
@@ -33,6 +36,10 @@ enum class DccIpDetectionMode(
 
   companion object {
     private val values = values().associateBy(DccIpDetectionMode::value)
+
+    /**
+     * Obtain from underlying representation
+     */
     fun of(value: UByte): DccIpDetectionMode? = values[value]
   }
 }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/DccPortSelectionMode.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/DccPortSelectionMode.kt
similarity index 91%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/DccPortSelectionMode.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/DccPortSelectionMode.kt
index b26a5fb71542ba65c86d844e5e93b8460174180f..462d11d520251b6311cb9d4b943e57389120f604 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/DccPortSelectionMode.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/DccPortSelectionMode.kt
@@ -23,6 +23,9 @@ package de.justjanne.libquassel.protocol.types
  * Mode for selecting the port range for DCC
  */
 enum class DccPortSelectionMode(
+  /**
+   * Underlying representation
+   */
   val value: UByte,
 ) {
   /** Automatic port selection */
@@ -33,6 +36,10 @@ enum class DccPortSelectionMode(
 
   companion object {
     private val values = values().associateBy(DccPortSelectionMode::value)
+
+    /**
+     * Obtain from underlying representation
+     */
     fun of(value: UByte): DccPortSelectionMode? = values[value]
   }
 }
diff --git a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/HandshakeMessage.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/HandshakeMessage.kt
similarity index 97%
rename from libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/HandshakeMessage.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/HandshakeMessage.kt
index 18786e0fa00c6d80c4b3709434f616c71cbb67be..7126e635c5a84b6cd0d3c3393bd30688936893e5 100644
--- a/libquassel-messages/src/main/kotlin/de/justjanne/libquassel/messages/handshake/HandshakeMessage.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/HandshakeMessage.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.types
 
 import de.justjanne.libquassel.protocol.features.LegacyFeatures
 import de.justjanne.libquassel.protocol.features.QuasselFeatureName
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/IdentityId.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/IdentityId.kt
similarity index 79%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/IdentityId.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/IdentityId.kt
index a6061e8d772086aa43864e4d7b34c5ffceceda94..1c3cd40d273729c062f29ca4ebcf19b49127ef3c 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/IdentityId.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/IdentityId.kt
@@ -20,12 +20,25 @@
 package de.justjanne.libquassel.protocol.types
 
 private typealias IdentityIdType = SignedIdType
-
-inline class IdentityId(override val id: IdentityIdType) : SignedId<IdentityIdType> {
+/**
+ * A [SignedId] for an identity object
+ */
+inline class IdentityId(
+  /**
+   * Native value
+   */
+  override val id: IdentityIdType
+) : SignedId<IdentityIdType> {
   override fun toString() = "IdentityId($id)"
 
   companion object {
+    /**
+     * Lower limit for this type
+     */
     val MIN_VALUE = IdentityId(IdentityIdType.MIN_VALUE)
+    /**
+     * Upper limit for this type
+     */
     val MAX_VALUE = IdentityId(IdentityIdType.MAX_VALUE)
   }
 }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/Message.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/Message.kt
similarity index 74%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/Message.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/Message.kt
index 809888037374a74f0c9d37b91e9ec671df5ccd65..682ee48b8395581229cea9743a3893aad37111d5 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/Message.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/Message.kt
@@ -21,16 +21,49 @@ package de.justjanne.libquassel.protocol.types
 
 import org.threeten.bp.Instant
 
+/**
+ * Model representing a chat message
+ */
 data class Message(
+  /**
+   * Id of the message
+   */
   val messageId: MsgId,
+  /**
+   * Timestamp at which the message was sent
+   */
   val time: Instant,
+  /**
+   * Message type
+   */
   val type: MessageTypes,
+  /**
+   * Set flags on the message
+   */
   val flag: MessageFlags,
+  /**
+   * Metadata of the buffer the message was received in
+   */
   val bufferInfo: BufferInfo,
+  /**
+   * nick!ident@host of the sender
+   */
   val sender: String,
+  /**
+   * Channel role prefixes of the sender
+   */
   val senderPrefixes: String,
+  /**
+   * Realname of the sender
+   */
   val realName: String,
+  /**
+   * Avatar of the sender
+   */
   val avatarUrl: String,
+  /**
+   * Message content
+   */
   val content: String
 ) {
   override fun toString(): String {
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/MessageFlag.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/MessageFlag.kt
similarity index 74%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/MessageFlag.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/MessageFlag.kt
index f95313927a61502f9614ea8f240f327099175432..59afe90f70af6f697a463617c3c4de790c18c59d 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/MessageFlag.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/MessageFlag.kt
@@ -23,13 +23,45 @@ import de.justjanne.bitflags.Flag
 import de.justjanne.bitflags.Flags
 import de.justjanne.bitflags.toEnumSet
 
+/**
+ * Model representing different types of message flags
+ */
 enum class MessageFlag(
   override val value: UInt,
 ) : Flag<UInt> {
+  /**
+   * Self-Message
+   *
+   * Sent by same user
+   */
   Self(0x01u),
+
+  /**
+   * Highlight
+   *
+   * User was mentioned
+   */
   Highlight(0x02u),
+
+  /**
+   * Redirected
+   *
+   * Message was redirected
+   */
   Redirected(0x04u),
+
+  /**
+   * ServerMsg
+   *
+   * Server info message
+   */
   ServerMsg(0x08u),
+
+  /**
+   * Backlog
+   *
+   * Message was loaded from history
+   */
   Backlog(0x80u);
 
   companion object : Flags<UInt, MessageFlag> {
@@ -38,4 +70,7 @@ enum class MessageFlag(
   }
 }
 
+/**
+ * Model representing a bitfield of [MessageFlag] flags
+ */
 typealias MessageFlags = Set<MessageFlag>
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/MessageType.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/MessageType.kt
similarity index 63%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/MessageType.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/MessageType.kt
index 8f8d3458d7a462218150ef1f9d6eed6c874ce3d6..d4606a7f95356755e60ee88b50c67c0952b2652b 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/MessageType.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/MessageType.kt
@@ -23,27 +23,105 @@ import de.justjanne.bitflags.Flag
 import de.justjanne.bitflags.Flags
 import de.justjanne.bitflags.toEnumSet
 
+/**
+ * Model representing different types of messages
+ */
 enum class MessageType(
   override val value: UInt,
 ) : Flag<UInt> {
+  /**
+   * Plain text message
+   */
   Plain(0x00001u),
+
+  /**
+   * Bot response/redirected notice
+   */
   Notice(0x00002u),
+
+  /**
+   * Third-person message
+   */
   Action(0x00004u),
+
+  /**
+   * Nick change
+   */
   Nick(0x00008u),
+
+  /**
+   * Mode change
+   */
   Mode(0x00010u),
+
+  /**
+   * Channel join
+   */
   Join(0x00020u),
+
+  /**
+   * Channel leave
+   */
   Part(0x00040u),
+
+  /**
+   * Network leave
+   */
   Quit(0x00080u),
+
+  /**
+   * Involuntary channel leave
+   */
   Kick(0x00100u),
+
+  /**
+   * Involuntary network leave
+   */
   Kill(0x00200u),
+
+  /**
+   * Server message
+   */
   Server(0x00400u),
+
+  /**
+   * Global info message
+   */
   Info(0x00800u),
+
+  /**
+   * Server error
+   */
   Error(0x01000u),
+
+  /**
+   * Midnight marker
+   */
   DayChange(0x02000u),
+
+  /**
+   * Channel topic has changed
+   */
   Topic(0x04000u),
+
+  /**
+   * Multiple users joined (usually due to a flaky server)
+   */
   NetsplitJoin(0x08000u),
+
+  /**
+   * Multiple users left (usually due to a flaky server)
+   */
   NetsplitQuit(0x10000u),
+
+  /**
+   * User invited to channel
+   */
   Invite(0x20000u),
+
+  /**
+   * Last read marker
+   */
   Markerline(0x40000u);
 
   companion object : Flags<UInt, MessageType> {
@@ -52,4 +130,7 @@ enum class MessageType(
   }
 }
 
+/**
+ * Model representing a bitfield of [MessageType] flags
+ */
 typealias MessageTypes = Set<MessageType>
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/MsgId.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/MsgId.kt
similarity index 75%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/MsgId.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/MsgId.kt
index 06c9df9ff0f0a2e045ea73160d49c321c4ec1cf1..6b54497944f9cdaf83616455a49e7231ee6e716e 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/MsgId.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/MsgId.kt
@@ -21,11 +21,27 @@ package de.justjanne.libquassel.protocol.types
 
 private typealias MsgIdType = SignedId64Type
 
-inline class MsgId(override val id: MsgIdType) : SignedId<MsgIdType> {
+/**
+ * A [SignedId] for an individual message
+ * Warning: this is the only id which can be backed by a 64-bit value
+ */
+inline class MsgId(
+  /**
+   * Native value
+   */
+  override val id: MsgIdType
+) : SignedId<MsgIdType> {
   override fun toString() = "MsgId($id)"
 
   companion object {
+    /**
+     * Lower limit for this type
+     */
     val MIN_VALUE = MsgId(MsgIdType.MIN_VALUE)
+
+    /**
+     * Upper limit for this type
+     */
     val MAX_VALUE = MsgId(MsgIdType.MAX_VALUE)
   }
 }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/NetworkId.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/NetworkId.kt
similarity index 79%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/NetworkId.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/NetworkId.kt
index 7ee94256fd2561d30ff356fe2ba83f021b1a6cee..46abe65252455af6a9eb535ef27c2172810da60f 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/NetworkId.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/NetworkId.kt
@@ -21,11 +21,26 @@ package de.justjanne.libquassel.protocol.types
 
 private typealias NetworkIdType = SignedIdType
 
-inline class NetworkId(override val id: NetworkIdType) : SignedId<NetworkIdType> {
+/**
+ * A [SignedId] for an irc network
+ */
+inline class NetworkId(
+  /**
+   * Native value
+   */
+  override val id: NetworkIdType
+) : SignedId<NetworkIdType> {
   override fun toString() = "NetworkId($id)"
 
   companion object {
+    /**
+     * Lower limit for this type
+     */
     val MIN_VALUE = NetworkId(NetworkIdType.MIN_VALUE)
+
+    /**
+     * Upper limit for this type
+     */
     val MAX_VALUE = NetworkId(NetworkIdType.MAX_VALUE)
   }
 }
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/NetworkLayerProtocol.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/NetworkLayerProtocol.kt
similarity index 68%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/NetworkLayerProtocol.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/NetworkLayerProtocol.kt
index db85d25eaef36862719ebcbae523cd24f3ed0c58..67bc28a163d417dd224d3e8e226f421f217b8426 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/NetworkLayerProtocol.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/NetworkLayerProtocol.kt
@@ -19,16 +19,45 @@
 
 package de.justjanne.libquassel.protocol.types
 
+/**
+ * Network protocol version
+ */
 enum class NetworkLayerProtocol(
+  /**
+   * Underlying representation
+   */
   val value: UByte,
 ) {
+  /**
+   * Internet Protocol Version 4
+   *
+   * See [RFC-791](https://tools.ietf.org/html/rfc791)
+   */
   IPv4Protocol(0x00u),
+  /**
+   * Internet Protocol Version 6
+   *
+   * See [RFC-2460](https://tools.ietf.org/html/rfc2460)
+   * See [RFC-8200](https://tools.ietf.org/html/rfc8200)
+   */
   IPv6Protocol(0x01u),
+
+  /**
+   * Any other IP based protocol
+   */
   AnyIPProtocol(0x02u),
+
+  /**
+   * Any other network protocol
+   */
   UnknownNetworkLayerProtocol(0xFFu);
 
   companion object {
     private val values = values().associateBy(NetworkLayerProtocol::value)
+
+    /**
+     * Obtain from underlying representation
+     */
     fun of(value: UByte): NetworkLayerProtocol? = values[value]
   }
 }
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/QStringList.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/QStringList.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e94eb6204d9da7681d8680edc46971d7d892e509
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/QStringList.kt
@@ -0,0 +1,6 @@
+package de.justjanne.libquassel.protocol.types
+
+/**
+ * Simple alias for a generic QStringList type
+ */
+typealias QStringList = List<String?>
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/SignedId.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/SignedId.kt
similarity index 84%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/SignedId.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/SignedId.kt
index 77dc79cca9cb1787c52d769f23a0d993677f5ba0..15d886205e2879e7feff7bfaf49e78ffba387a61 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/SignedId.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/SignedId.kt
@@ -22,11 +22,23 @@ package de.justjanne.libquassel.protocol.types
 import de.justjanne.libquassel.annotations.Generated
 import java.io.Serializable
 
+/**
+ * Native representation of a SignedId
+ */
 typealias SignedIdType = Int
+/**
+ * Native representation of a SignedId64
+ */
 typealias SignedId64Type = Long
 
+/**
+ * Base type for a signed id
+ */
 interface SignedId<T> : Serializable, Comparable<SignedId<T>>
   where T : Number, T : Comparable<T> {
+  /**
+   * Underlying representation
+   */
   val id: T
 
   override fun compareTo(other: SignedId<T>): Int {
@@ -34,11 +46,17 @@ interface SignedId<T> : Serializable, Comparable<SignedId<T>>
   }
 }
 
+/**
+ * Validity check for a signed id
+ */
 @Suppress("NOTHING_TO_INLINE")
 @JvmName("isValidId")
 @Generated
 inline fun SignedId<SignedIdType>.isValid() = id > 0
 
+/**
+ * Validity check for a signed id
+ */
 @Suppress("NOTHING_TO_INLINE")
 @JvmName("isValidId64")
 @Generated
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/TimeSpec.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/TimeSpec.kt
similarity index 100%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/types/TimeSpec.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/types/TimeSpec.kt
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/variant/QVariant.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariant.kt
similarity index 62%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/variant/QVariant.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariant.kt
index 30a1b1767daefa4f24e5b658115ccf7fa792cf97..e646a91eb0bd1ccac6025a02aaaf185d35915466 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/variant/QVariant.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariant.kt
@@ -28,32 +28,44 @@ import de.justjanne.libquassel.protocol.serializers.QuasselSerializer
 import de.justjanne.libquassel.protocol.serializers.QuasselSerializers
 import java.nio.ByteBuffer
 
+/**
+ * Simple alias for a generic QVariant type
+ */
 typealias QVariant_ = QVariant<*>
-typealias QVariantList = List<QVariant_>
-typealias QVariantMap = Map<String, QVariant_>
-typealias QStringList = List<String?>
 
+/**
+ * Variant box for generic types
+ */
 sealed class QVariant<T> {
-  abstract val data: T
-  abstract val serializer: QtSerializer<T>
+  @PublishedApi
+  internal abstract val data: T
+
+  @PublishedApi
+  internal abstract val serializer: QtSerializer<T>
 
-  data class Typed<T> internal constructor(
+  /**
+   * QVariant of a predefined qt type
+   */
+  data class Typed<T> @PublishedApi internal constructor(
     override val data: T,
     override val serializer: QtSerializer<T>
   ) : QVariant<T>() {
     override fun toString() = super.toString()
   }
 
-  data class Custom<T> internal constructor(
+  /**
+   * QVariant of an arbitrary custom type
+   *
+   * Serialized as [QtType.UserType] with the custom type name serialized as ASCII string
+   */
+  data class Custom<T> @PublishedApi internal constructor(
     override val data: T,
     override val serializer: QuasselSerializer<T>
   ) : QVariant<T>() {
     override fun toString() = super.toString()
   }
 
-  fun value(): T = data
-
-  fun serialize(buffer: ChainedByteBuffer, featureSet: FeatureSet) {
+  internal fun serialize(buffer: ChainedByteBuffer, featureSet: FeatureSet) {
     serializer.serialize(buffer, data, featureSet)
   }
 
@@ -66,25 +78,36 @@ sealed class QVariant<T> {
     }
   }
 
+  @PublishedApi
   @Suppress("UNCHECKED_CAST")
-  inline fun <reified T> withType(): QVariant<T>? =
-    if (serializer.javaType == T::class.java && this.value() is T) this as QVariant<T>
+  internal inline fun <reified T> withType(): QVariant<T>? =
+    if (serializer.javaType == T::class.java && this.data is T) this as QVariant<T>
     else null
-
-  companion object {
-    fun <T> of(data: T, serializer: QtSerializer<T>) = Typed(data, serializer)
-    fun <T> of(data: T, serializer: QuasselSerializer<T>) = Custom(data, serializer)
-  }
 }
 
+/**
+ * Construct a QVariant from data and type
+ */
 inline fun <reified T> qVariant(data: T, type: QtType): QVariant<T> =
-  QVariant.of(data, QtSerializers.find(type))
+  QVariant.Typed(data, QtSerializers.find(type))
 
+/**
+ * Construct a QVariant from data and type
+ */
 inline fun <reified T> qVariant(data: T, type: QuasselType): QVariant<T> =
-  QVariant.of(data, QuasselSerializers.find(type))
+  QVariant.Custom(data, QuasselSerializers.find(type))
 
+/**
+ * Extract the content of a QVariant in a type-safe manner
+ * @return value of the QVariant or null
+ */
 inline fun <reified T> QVariant_?.into(): T? =
-  this?.withType<T>()?.value()
+  this?.withType<T>()?.data
 
+/**
+ * Extract the content of a QVariant in a type-safe manner
+ * @param defValue default value if the type does not match or no value is found
+ * @return value of the QVariant or defValue
+ */
 inline fun <reified T> QVariant_?.into(defValue: T): T =
-  this?.withType<T>()?.value() ?: defValue
+  this?.withType<T>()?.data ?: defValue
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariantList.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariantList.kt
new file mode 100644
index 0000000000000000000000000000000000000000..91997768609729600e11b807219d3ddf57c59031
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariantList.kt
@@ -0,0 +1,6 @@
+package de.justjanne.libquassel.protocol.variant
+
+/**
+ * Simple alias for a generic QVariantList type
+ */
+typealias QVariantList = List<QVariant_>
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariantMap.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariantMap.kt
new file mode 100644
index 0000000000000000000000000000000000000000..76057f15745fcbb009ed3b8875cf35eb4b194780
--- /dev/null
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariantMap.kt
@@ -0,0 +1,6 @@
+package de.justjanne.libquassel.protocol.variant
+
+/**
+ * Simple alias for a generic QVariantMap type
+ */
+typealias QVariantMap = Map<String, QVariant_>
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/variant/QtType.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QtType.kt
similarity index 63%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/variant/QtType.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QtType.kt
index 607a0d2dbbcb3fc2c600949dd645e3afbd06f022..c99fc1a1fd5137cc1867f5d7f192c7845b827f49 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/variant/QtType.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QtType.kt
@@ -22,87 +22,26 @@ package de.justjanne.libquassel.protocol.variant
 enum class QtType(val id: kotlin.Int) {
   Void(0),
   Bool(1),
+  Char(131),
+  UChar(134),
+  Short(130),
+  UShort(133),
   Int(2),
   UInt(3),
-  LongLong(4),
-  ULongLong(5),
-
+  Long(129),
+  ULong(132),
+  Float(135),
   Double(6),
+  QDate(14),
+  QTime(15),
+  QDateTime(16),
   QChar(7),
-  QVariantMap(8),
-  QVariantList(9),
-
   QString(10),
   QStringList(11),
   QByteArray(12),
-
-  QBitArray(13),
-  QDate(14),
-  QTime(15),
-  QDateTime(16),
-  QUrl(17),
-
-  QLocale(18),
-  QRect(19),
-  QRectF(20),
-  QSize(21),
-  QSizeF(22),
-
-  QLine(23),
-  QLineF(24),
-  QPoint(25),
-  QPointF(26),
-  QRegExp(27),
-
-  QVariantHash(28),
-  QEasingCurve(29),
-
-  FirstGuiType(63),
-
-  QFont(64),
-  QPixmap(65),
-  QBrush(66),
-  QColor(67),
-  QPalette(68),
-
-  QIcon(69),
-  QImage(70),
-  QPolygon(71),
-  QRegion(72),
-  QBitmap(73),
-
-  QCursor(74),
-  QSizePolicy(75),
-  QKeySequence(76),
-  QPen(77),
-
-  QTextLength(78),
-  QTextFormat(79),
-  QMatrix(80),
-  QTransform(81),
-
-  QMatrix4x4(82),
-  QVector2D(83),
-  QVector3D(84),
-  QVector4D(85),
-
-  QQuaternion(86),
-
-  VoidStar(128),
-  Long(129),
-  Short(130),
-  Char(131),
-  ULong(132),
-
-  UShort(133),
-  UChar(134),
-  Float(135),
-  QObjectStar(136),
-  QWidgetStar(137),
-
   QVariant(138),
-
-  User(256),
+  QVariantMap(8),
+  QVariantList(9),
   UserType(127);
 
   companion object {
diff --git a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/variant/QuasselType.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QuasselType.kt
similarity index 97%
rename from libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/variant/QuasselType.kt
rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QuasselType.kt
index 3cd82d015e8f5b0ecc630345b62aed8daee63362..b1636181e610160c7631d8ba1da3114d1776dc60 100644
--- a/libquassel-protocol/src/main/java/de/justjanne/libquassel/protocol/variant/QuasselType.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QuasselType.kt
@@ -37,8 +37,7 @@ enum class QuasselType(
   NetworkInfo("NetworkInfo"),
   NetworkServer("Network::Server"),
   QHostAddress("QHostAddress"),
-  PeerPtr("PeerPtr"),
-  Unknown("");
+  PeerPtr("PeerPtr");
 
   companion object {
     private val values = values().associateBy(QuasselType::typeName)
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/connection/ConnectionHeaderSerializerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/connection/ClientHeaderSerializerTest.kt
similarity index 92%
rename from libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/connection/ConnectionHeaderSerializerTest.kt
rename to libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/connection/ClientHeaderSerializerTest.kt
index 7a2db6d1e0e0c5c3d985a84f731d6edb4ddfdc44..b1393774207ccf531c1207cfd5de58447df18876 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/connection/ConnectionHeaderSerializerTest.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/connection/ClientHeaderSerializerTest.kt
@@ -24,19 +24,19 @@ import de.justjanne.libquassel.protocol.testutil.byteBufferOf
 import de.justjanne.libquassel.protocol.testutil.serializerTest
 import org.junit.jupiter.api.Test
 
-class ConnectionHeaderSerializerTest {
+class ClientHeaderSerializerTest {
   @Test
   fun testQuasseldroid() = serializerTest(
-    ConnectionHeaderSerializer,
-    ConnectionHeader(
+    ClientHeaderSerializer,
+    ClientHeader(
       features = ProtocolFeature.of(
         ProtocolFeature.TLS,
         ProtocolFeature.Compression,
       ),
       versions = listOf(
         ProtocolMeta(
-          data = 0x0000u,
           version = ProtocolVersion.Datastream,
+          data = 0x0000u,
         )
       )
     ),
@@ -48,20 +48,20 @@ class ConnectionHeaderSerializerTest {
 
   @Test
   fun testQuasselClient() = serializerTest(
-    ConnectionHeaderSerializer,
-    ConnectionHeader(
+    ClientHeaderSerializer,
+    ClientHeader(
       features = ProtocolFeature.of(
         ProtocolFeature.TLS,
         ProtocolFeature.Compression,
       ),
       versions = listOf(
         ProtocolMeta(
-          data = 0x0000u,
           version = ProtocolVersion.Legacy,
+          data = 0x0000u,
         ),
         ProtocolMeta(
-          data = 0x0000u,
           version = ProtocolVersion.Datastream,
+          data = 0x0000u,
         )
       )
     ),
@@ -74,17 +74,17 @@ class ConnectionHeaderSerializerTest {
 
   @Test
   fun testDebugClient() = serializerTest(
-    ConnectionHeaderSerializer,
-    ConnectionHeader(
+    ClientHeaderSerializer,
+    ClientHeader(
       features = ProtocolFeature.of(),
       versions = listOf(
         ProtocolMeta(
-          data = 0x0000u,
           version = ProtocolVersion.Legacy,
+          data = 0x0000u,
         ),
         ProtocolMeta(
-          data = 0x0000u,
           version = ProtocolVersion.Datastream,
+          data = 0x0000u,
         )
       )
     ),
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/features/FeatureSetTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/features/FeatureSetTest.kt
index 4f0b689189bb40c04a87d303dd004e4cb82266f2..f0a44ca8ab1b213b666c636ab562aad4205aa36c 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/features/FeatureSetTest.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/features/FeatureSetTest.kt
@@ -29,7 +29,7 @@ class FeatureSetTest {
   fun testParse() {
     assertEquals(
       emptyList<QuasselFeatureName>(),
-      FeatureSet.parse(
+      FeatureSet.build(
         LegacyFeature.none(),
         emptyList()
       ).featureList()
@@ -41,7 +41,7 @@ class FeatureSetTest {
         QuasselFeature.ExtendedFeatures.feature,
         QuasselFeatureName("_unknownFeature")
       ),
-      FeatureSet.parse(
+      FeatureSet.build(
         LegacyFeature.of(
           LegacyFeature.SynchronizedMarkerLine
         ),
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitSerializerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitSerializerTest.kt
similarity index 91%
rename from libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitSerializerTest.kt
rename to libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitSerializerTest.kt
index d15075d1cc8a79f6cfebbf64314ceeab8adfa22d..2a356f336f9c3d3aa6a136ec4a8ffa16c61c5b5a 100644
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/handshake/ClientInitSerializerTest.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/serializers/handshake/ClientInitSerializerTest.kt
@@ -16,13 +16,15 @@
  * You should have received a copy of the GNU General Public License along
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
-package de.justjanne.libquassel.messages.handshake
+package de.justjanne.libquassel.protocol.serializers.handshake
 
 import de.justjanne.bitflags.none
-import de.justjanne.libquassel.messages.testutil.byteBufferOf
-import de.justjanne.libquassel.messages.testutil.handshakeSerializerTest
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.features.LegacyFeature
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializers
+import de.justjanne.libquassel.protocol.testutil.byteBufferOf
+import de.justjanne.libquassel.protocol.testutil.handshakeSerializerTest
+import de.justjanne.libquassel.protocol.types.HandshakeMessage
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Test
 
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/deserialize.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/deserialize.kt
index bbb0a8a7fb5bc8d03092e8f11e4fec51d6f46b90..833dc11e194a18619117c356addff47714e14b74 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/deserialize.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/deserialize.kt
@@ -19,7 +19,9 @@
 package de.justjanne.libquassel.protocol.testutil
 
 import de.justjanne.libquassel.protocol.features.FeatureSet
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
 import de.justjanne.libquassel.protocol.serializers.Serializer
+import de.justjanne.libquassel.protocol.serializers.qt.HandshakeMapSerializer
 import org.hamcrest.Matcher
 import org.hamcrest.MatcherAssert.assertThat
 import org.junit.jupiter.api.Assertions.assertEquals
@@ -54,3 +56,25 @@ fun <T> testDeserialize(
   val after = deserialize(serializer, buffer, featureSet)
   assertEquals(data, after)
 }
+
+fun <T> testDeserialize(
+  serializer: HandshakeSerializer<T>,
+  matcher: Matcher<in T>,
+  buffer: ByteBuffer,
+  featureSet: FeatureSet = FeatureSet.all()
+) {
+  val map = deserialize(HandshakeMapSerializer, buffer, featureSet)
+  val after = serializer.deserialize(map)
+  assertThat(after, matcher)
+}
+
+fun <T> testDeserialize(
+  serializer: HandshakeSerializer<T>,
+  data: T,
+  buffer: ByteBuffer,
+  featureSet: FeatureSet = FeatureSet.all()
+) {
+  val map = deserialize(HandshakeMapSerializer, buffer, featureSet)
+  val after = serializer.deserialize(map)
+  assertEquals(data, after)
+}
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/handshakeSerializerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/handshakeSerializerTest.kt
similarity index 93%
rename from libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/handshakeSerializerTest.kt
rename to libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/handshakeSerializerTest.kt
index 0640b992591b66018e5284f34083f78b561b27c9..d0e227107ad7d92b6c1582826e6cfe323cd26d0f 100644
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/handshakeSerializerTest.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/handshakeSerializerTest.kt
@@ -16,10 +16,10 @@
  * You should have received a copy of the GNU General Public License along
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
-package de.justjanne.libquassel.messages.testutil
+package de.justjanne.libquassel.protocol.testutil
 
-import de.justjanne.libquassel.messages.handshake.HandshakeSerializer
 import de.justjanne.libquassel.protocol.features.FeatureSet
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
 import org.hamcrest.Matcher
 import java.nio.ByteBuffer
 
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/serialize.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/serialize.kt
index e835d3d21f6f115a2404fa2a4c1bcf6c02464abf..c606ef856171e52e7eb903591dddf9314525bee9 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/serialize.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/serialize.kt
@@ -20,7 +20,9 @@ package de.justjanne.libquassel.protocol.testutil
 
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
 import de.justjanne.libquassel.protocol.serializers.Serializer
+import de.justjanne.libquassel.protocol.serializers.qt.HandshakeMapSerializer
 import de.justjanne.libquassel.protocol.testutil.matchers.ByteBufferMatcher
 import org.hamcrest.MatcherAssert.assertThat
 import java.nio.ByteBuffer
@@ -44,3 +46,14 @@ fun <T> testSerialize(
   val after = serialize(serializer, data, featureSet)
   assertThat(after, ByteBufferMatcher(buffer))
 }
+
+fun <T> testSerialize(
+  serializer: HandshakeSerializer<T>,
+  data: T,
+  buffer: ByteBuffer,
+  featureSet: FeatureSet = FeatureSet.all()
+) {
+  val map = serializer.serialize(data)
+  val after = serialize(HandshakeMapSerializer, map, featureSet)
+  assertThat(after, ByteBufferMatcher(buffer))
+}
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/testHandshakeSerializerDirect.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/testHandshakeSerializerDirect.kt
similarity index 90%
rename from libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/testHandshakeSerializerDirect.kt
rename to libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/testHandshakeSerializerDirect.kt
index b5b0091a01ad7d7e7767a34a8314db118a37df03..c1ad766257539968183c8bc5b8b9d60abdbd3ffc 100644
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/testHandshakeSerializerDirect.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/testHandshakeSerializerDirect.kt
@@ -16,9 +16,9 @@
  * You should have received a copy of the GNU General Public License along
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
-package de.justjanne.libquassel.messages.testutil
+package de.justjanne.libquassel.protocol.testutil
 
-import de.justjanne.libquassel.messages.handshake.HandshakeSerializer
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
 import org.hamcrest.Matcher
 import org.hamcrest.MatcherAssert.assertThat
 import org.junit.jupiter.api.Assertions.assertEquals
diff --git a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/testHandshakeSerializerEncoded.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/testHandshakeSerializerEncoded.kt
similarity index 92%
rename from libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/testHandshakeSerializerEncoded.kt
rename to libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/testHandshakeSerializerEncoded.kt
index 6248b4717a4e2b6f596c96de3565ab1602c93354..56692a983a9bb6ade35a0dac394e996d5771c22b 100644
--- a/libquassel-messages/src/test/kotlin/de/justjanne/libquassel/messages/testutil/testHandshakeSerializerEncoded.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/testHandshakeSerializerEncoded.kt
@@ -16,11 +16,11 @@
  * You should have received a copy of the GNU General Public License along
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
-package de.justjanne.libquassel.messages.testutil
+package de.justjanne.libquassel.protocol.testutil
 
-import de.justjanne.libquassel.messages.handshake.HandshakeSerializer
 import de.justjanne.libquassel.protocol.features.FeatureSet
 import de.justjanne.libquassel.protocol.io.ChainedByteBuffer
+import de.justjanne.libquassel.protocol.serializers.HandshakeSerializer
 import de.justjanne.libquassel.protocol.serializers.qt.HandshakeMapSerializer
 import org.hamcrest.Matcher
 import org.hamcrest.MatcherAssert.assertThat
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 09febef94c00e7428cc98907c814e68bcdba90ed..dd56c80dd0141e043ab48f91995b639532da65f0 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -4,6 +4,5 @@ include(
   ":libquassel-tests",
   ":libquassel-annotations",
   ":libquassel-protocol",
-  ":libquassel-messages",
   ":libquassel-client"
 )