diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4f86a05b35ceea43b037194d8f628b1be52a3639..c1904b2850b6b24e58cd2763b1fa98b1d5803637 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -46,7 +46,7 @@ test:
 deploy-local:
   stage: "deploy"
   image: "k8r.eu/justjanne/docker-s3cmd:latest"
-  cache: {}
+  cache: { }
   only:
     refs:
       - "master"
@@ -65,7 +65,7 @@ deploy-local:
 deploy-beta:
   stage: "deploy"
   image: "k8r.eu/justjanne/docker-fastlane:latest"
-  cache: {}
+  cache: { }
   only:
     refs:
       - "master"
diff --git a/app/src/androidTest/java/de/kuschku/quasseldroid/ExampleInstrumentedTest.kt b/app/src/androidTest/java/de/kuschku/quasseldroid/ExampleInstrumentedTest.kt
index 5df983b03b579463530a45ed0fe96809a812bd49..18d842d7674be4d8c51bff34ec9ab802db30786f 100644
--- a/app/src/androidTest/java/de/kuschku/quasseldroid/ExampleInstrumentedTest.kt
+++ b/app/src/androidTest/java/de/kuschku/quasseldroid/ExampleInstrumentedTest.kt
@@ -1,13 +1,11 @@
 package de.kuschku.quasseldroid
 
-import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.ext.junit.runners.AndroidJUnit4
-
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
 
-import org.junit.Assert.*
-
 /**
  * Instrumented test, which will execute on an Android device.
  *
@@ -15,10 +13,10 @@ import org.junit.Assert.*
  */
 @RunWith(AndroidJUnit4::class)
 class ExampleInstrumentedTest {
-    @Test
-    fun useAppContext() {
-        // Context of the app under test.
-        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
-        assertEquals("de.kuschku.quasseldroid", appContext.packageName)
-    }
-}
\ No newline at end of file
+  @Test
+  fun useAppContext() {
+    // Context of the app under test.
+    val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+    assertEquals("de.kuschku.quasseldroid", appContext.packageName)
+  }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/MainActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/MainActivity.kt
index 25f2221c3e565cff46679fbaa53dfa44c7f655da..e7ebf86632c08d7c9c6f7716ca13dc34b785dab2 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/MainActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/MainActivity.kt
@@ -19,17 +19,13 @@ import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
-import androidx.lifecycle.LifecycleObserver
 import androidx.lifecycle.lifecycleScope
-import dagger.hilt.android.AndroidEntryPoint
 import de.kuschku.quasseldroid.ui.theme.QuasseldroidTheme
 import de.kuschku.quasseldroid.ui.theme.shapes
 import de.kuschku.quasseldroid.ui.theme.typography
 import dev.chrisbanes.accompanist.coil.CoilImage
-import kotlinx.coroutines.Job
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.flow
 import org.threeten.bp.ZonedDateTime
 import org.threeten.bp.format.DateTimeFormatter
 import kotlin.random.Random
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/ReadableWrappedChannel.kt b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/ReadableWrappedChannel.kt
index 7f8de746680e751bf6c3d0e2781d704e330fda7d..cc886b257e83ad7bc64310ac04c6712e13253594 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/ReadableWrappedChannel.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/ReadableWrappedChannel.kt
@@ -61,7 +61,7 @@ class ReadableWrappedChannel(
         }
 
         if (readData <= 0) {
-            Log.e("ReadableWrappedChannel", "Read: $readData")
+          Log.e("ReadableWrappedChannel", "Read: $readData")
         }
 
         // read is negative if no data was read, in that case, terminate
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Shape.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Shape.kt
index cbd3ea71cf3490886223db02b00a908cd26b4fa1..1e4b1f7da9028d51568f7c01cc4d1d582a63460b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Shape.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Shape.kt
@@ -5,7 +5,7 @@ import androidx.compose.material.Shapes
 import androidx.compose.ui.unit.dp
 
 val shapes = Shapes(
-        small = RoundedCornerShape(4.dp),
-        medium = RoundedCornerShape(4.dp),
-        large = RoundedCornerShape(0.dp)
-)
\ No newline at end of file
+  small = RoundedCornerShape(4.dp),
+  medium = RoundedCornerShape(4.dp),
+  large = RoundedCornerShape(0.dp)
+)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Theme.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Theme.kt
index 5e9387128ddf2b08f7affa441faa50d65bc393db..e18dfe0d3f8621ea4253405b4d592171991934e7 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Theme.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Theme.kt
@@ -7,38 +7,38 @@ import androidx.compose.material.lightColors
 import androidx.compose.runtime.Composable
 
 private val DarkColorPalette = darkColors(
-        primary = purple200,
-        primaryVariant = purple700,
-        secondary = teal200
+  primary = purple200,
+  primaryVariant = purple700,
+  secondary = teal200
 )
 
 private val LightColorPalette = lightColors(
-        primary = purple500,
-        primaryVariant = purple700,
-        secondary = teal200
+  primary = purple500,
+  primaryVariant = purple700,
+  secondary = teal200
 
-        /* Other default colors to override
-    background = Color.White,
-    surface = Color.White,
-    onPrimary = Color.White,
-    onSecondary = Color.Black,
-    onBackground = Color.Black,
-    onSurface = Color.Black,
-    */
+  /* Other default colors to override
+background = Color.White,
+surface = Color.White,
+onPrimary = Color.White,
+onSecondary = Color.Black,
+onBackground = Color.Black,
+onSurface = Color.Black,
+*/
 )
 
 @Composable
 fun QuasseldroidTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
-    val colors = if (darkTheme) {
-        DarkColorPalette
-    } else {
-        LightColorPalette
-    }
+  val colors = if (darkTheme) {
+    DarkColorPalette
+  } else {
+    LightColorPalette
+  }
 
-    MaterialTheme(
-            colors = colors,
-            typography = typography,
-            shapes = shapes,
-            content = content
-    )
-}
\ No newline at end of file
+  MaterialTheme(
+    colors = colors,
+    typography = typography,
+    shapes = shapes,
+    content = content
+  )
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Type.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Type.kt
index 88852f35d0d7fde4d5ba1d68512a041767e34a07..a2f199dd2100ff83cb1b861b6b21dfec642b42d4 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Type.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/theme/Type.kt
@@ -8,21 +8,21 @@ import androidx.compose.ui.unit.sp
 
 // Set of Material typography styles to start with
 val typography = Typography(
-        body1 = TextStyle(
-                fontFamily = FontFamily.Default,
-                fontWeight = FontWeight.Normal,
-                fontSize = 16.sp
-        )
-        /* Other default text styles to override
-    button = TextStyle(
-        fontFamily = FontFamily.Default,
-        fontWeight = FontWeight.W500,
-        fontSize = 14.sp
-    ),
-    caption = TextStyle(
-        fontFamily = FontFamily.Default,
-        fontWeight = FontWeight.Normal,
-        fontSize = 12.sp
-    )
-    */
-)
\ No newline at end of file
+  body1 = TextStyle(
+    fontFamily = FontFamily.Default,
+    fontWeight = FontWeight.Normal,
+    fontSize = 16.sp
+  )
+  /* Other default text styles to override
+button = TextStyle(
+  fontFamily = FontFamily.Default,
+  fontWeight = FontWeight.W500,
+  fontSize = 14.sp
+),
+caption = TextStyle(
+  fontFamily = FontFamily.Default,
+  fontWeight = FontWeight.Normal,
+  fontSize = 12.sp
+)
+*/
+)
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
index eca70cfe52eac1ba66ba280a68ca7be8fcf88a16..ea737cd48736015a18ac9e24cea52d418ad016e1 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
-    <background android:drawable="@drawable/ic_launcher_background" />
-    <foreground android:drawable="@drawable/ic_launcher_foreground" />
-</adaptive-icon>
\ No newline at end of file
+  <background android:drawable="@drawable/ic_launcher_background" />
+  <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index eca70cfe52eac1ba66ba280a68ca7be8fcf88a16..ea737cd48736015a18ac9e24cea52d418ad016e1 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
-    <background android:drawable="@drawable/ic_launcher_background" />
-    <foreground android:drawable="@drawable/ic_launcher_foreground" />
-</adaptive-icon>
\ No newline at end of file
+  <background android:drawable="@drawable/ic_launcher_background" />
+  <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index b62f69e5806cfa7ad1cbe7a8b6c7cd11323cb3c5..6951b1026985458babc78c305f5d4737a36835dc 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -1,16 +1,16 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
-    <!-- Base application theme. -->
-    <style name="Theme.Quasseldroid" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
-        <!-- Primary brand color. -->
-        <item name="colorPrimary">@color/purple_200</item>
-        <item name="colorPrimaryVariant">@color/purple_700</item>
-        <item name="colorOnPrimary">@color/black</item>
-        <!-- Secondary brand color. -->
-        <item name="colorSecondary">@color/teal_200</item>
-        <item name="colorSecondaryVariant">@color/teal_200</item>
-        <item name="colorOnSecondary">@color/black</item>
-        <!-- Status bar color. -->
-        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
-        <!-- Customize your theme here. -->
-    </style>
-</resources>
\ No newline at end of file
+  <!-- Base application theme. -->
+  <style name="Theme.Quasseldroid" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+    <!-- Primary brand color. -->
+    <item name="colorPrimary">@color/purple_200</item>
+    <item name="colorPrimaryVariant">@color/purple_700</item>
+    <item name="colorOnPrimary">@color/black</item>
+    <!-- Secondary brand color. -->
+    <item name="colorSecondary">@color/teal_200</item>
+    <item name="colorSecondaryVariant">@color/teal_200</item>
+    <item name="colorOnSecondary">@color/black</item>
+    <!-- Status bar color. -->
+    <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
+    <!-- Customize your theme here. -->
+  </style>
+</resources>
diff --git a/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt b/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt
index 16bd7c90f40dfeb4e9adb62b713045d28052993e..1eabb869f96f2ac800b9a7bccea3eff0de76d84d 100644
--- a/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt
+++ b/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt
@@ -1,16 +1,13 @@
 package de.kuschku.quasseldroid
 
-import de.kuschku.bitflags.of
 import de.kuschku.libquassel.protocol.connection.ProtocolInfoSerializer
 import de.kuschku.libquassel.protocol.features.FeatureSet
-import de.kuschku.libquassel.protocol.features.LegacyFeature
-import de.kuschku.libquassel.protocol.features.QuasselFeature
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.messages.handshake.ClientInit
 import de.kuschku.libquassel.protocol.serializers.handshake.ClientInitAckSerializer
 import de.kuschku.libquassel.protocol.serializers.handshake.ClientInitRejectSerializer
 import de.kuschku.libquassel.protocol.serializers.handshake.ClientInitSerializer
-import de.kuschku.libquassel.protocol.serializers.handshake.HandshakeMapSerializer
+import de.kuschku.libquassel.protocol.serializers.primitive.HandshakeMapSerializer
 import de.kuschku.libquassel.protocol.serializers.primitive.IntSerializer
 import de.kuschku.libquassel.protocol.serializers.primitive.UIntSerializer
 import de.kuschku.libquassel.protocol.variant.into
diff --git a/build.gradle.kts b/build.gradle.kts
index c3ad86bf6dfcf979fab67553e477b6bf83433dae..82cc8d6930788b8c97c77e71cfed399242656215 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -17,8 +17,6 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
-import org.jetbrains.kotlin.gradle.plugin.KaptExtension
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 buildscript {
diff --git a/buildSrc/src/main/kotlin/de/kuschku/justcode/NullOutputStream.kt b/buildSrc/src/main/kotlin/de/kuschku/justcode/NullOutputStream.kt
index 97c8e50426d08c12800d5ff349235a1d5a2f4114..e67610f5f93ab4c3c33eef2c74b0149843e63fd7 100644
--- a/buildSrc/src/main/kotlin/de/kuschku/justcode/NullOutputStream.kt
+++ b/buildSrc/src/main/kotlin/de/kuschku/justcode/NullOutputStream.kt
@@ -21,7 +21,6 @@ package de.kuschku.justcode
 
 import java.io.IOException
 import java.io.OutputStream
-import java.util.*
 
 class NullOutputStream : OutputStream() {
   @Volatile
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/features/LegacyFeature.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/LegacyFeature.kt
index a1585029db9dd569ac153139e1680551af6f264d..f069ccc4717e994949c122d042627d4b3d09d897 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/features/LegacyFeature.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/LegacyFeature.kt
@@ -22,7 +22,6 @@ package de.kuschku.libquassel.protocol.features
 import de.kuschku.bitflags.Flag
 import de.kuschku.bitflags.Flags
 import de.kuschku.bitflags.toEnumSet
-import java.util.*
 
 /**
  * A list of features that are optional in core and/or client, but need runtime checking
@@ -36,31 +35,41 @@ import java.util.*
 enum class LegacyFeature(
   override val value: UInt,
   val feature: QuasselFeature,
-): Flag<UInt> {
+) : Flag<UInt> {
   SynchronizedMarkerLine(0x0001u, QuasselFeature.SynchronizedMarkerLine),
   SaslAuthentication(0x0002u, QuasselFeature.SaslAuthentication),
   SaslExternal(0x0004u, QuasselFeature.SaslExternal),
   HideInactiveNetworks(0x0008u, QuasselFeature.HideInactiveNetworks),
   PasswordChange(0x0010u, QuasselFeature.PasswordChange),
+
   /** IRCv3 capability negotiation, account tracking */
   CapNegotiation(0x0020u, QuasselFeature.CapNegotiation),
+
   /** IRC server SSL validation */
   VerifyServerSSL(0x0040u, QuasselFeature.VerifyServerSSL),
+
   /** IRC server custom message rate limits */
   CustomRateLimits(0x0080u, QuasselFeature.CustomRateLimits),
   DccFileTransfer(0x0100u, QuasselFeature.DccFileTransfer),
+
   /** Timestamp formatting in away (e.g. %%hh:mm%%) */
   AwayFormatTimestamp(0x0200u, QuasselFeature.AwayFormatTimestamp),
+
   /** Whether or not the core supports auth backends. */
   Authenticators(0x0400u, QuasselFeature.Authenticators),
+
   /** Sync buffer activity status */
   BufferActivitySync(0x0800u, QuasselFeature.BufferActivitySync),
+
   /** Core-Side highlight configuration and matching */
   CoreSideHighlights(0x1000u, QuasselFeature.CoreSideHighlights),
+
   /** Show prefixes for senders in backlog */
   SenderPrefixes(0x2000u, QuasselFeature.SenderPrefixes),
+
   /** Supports RPC call disconnectFromCore to remotely disconnect a client */
   RemoteDisconnect(0x4000u, QuasselFeature.RemoteDisconnect),
+
   /** Transmit features as list of strings */
   ExtendedFeatures(0x8000u, QuasselFeature.ExtendedFeatures);
 
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/features/QuasselFeature.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/QuasselFeature.kt
index e827769a9fb5a2172e9d732d833bcf208d3e3811..3466e053d834b1cffb41d48c7a26fdab2b456809 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/features/QuasselFeature.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/QuasselFeature.kt
@@ -29,38 +29,55 @@ enum class QuasselFeature {
   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;
 
@@ -68,6 +85,7 @@ enum class QuasselFeature {
 
   companion object {
     private val values = values().associateBy(QuasselFeature::feature)
+
     @JvmStatic
     fun valueOf(name: QuasselFeatureName): QuasselFeature? = values[name]
   }
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/io/ChainedByteBuffer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/io/ChainedByteBuffer.kt
index 88e6997edbb0240361ff03df4a9e5b7bcc23e118..bb493d2bad3d400a1c8b0fb87f5ff4fdf24cff1f 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/io/ChainedByteBuffer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/io/ChainedByteBuffer.kt
@@ -31,7 +31,7 @@ class ChainedByteBuffer(private val bufferSize: Int = 1024, private val direct:
   private var currentBuffer = 0
 
   private fun allocate(size: Int) = when (direct) {
-    true  -> ByteBuffer.allocateDirect(size)
+    true -> ByteBuffer.allocateDirect(size)
     false -> ByteBuffer.allocate(size)
   }
 
@@ -48,7 +48,7 @@ class ChainedByteBuffer(private val bufferSize: Int = 1024, private val direct:
     this.size += size
   }
 
-  fun <T> withBuffer(length: Int = 0, f: (ByteBuffer) -> T) : T{
+  fun <T> withBuffer(length: Int = 0, f: (ByteBuffer) -> T): T {
     ensureSpace(length)
     val buffer = bufferList.last()
     val positionBefore = buffer.position()
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitReject.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitReject.kt
index 66cad259d5cb74a45880aff899ee66326aa49e43..d7710d492cbc5cc30f8a03d7be5f8981859c0d0c 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitReject.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitReject.kt
@@ -22,3 +22,4 @@ package de.kuschku.libquassel.protocol.messages.handshake
 data class ClientInitReject(
   val errorString: String?
 )
+
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientLogin.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientLogin.kt
new file mode 100644
index 0000000000000000000000000000000000000000..19dd2c25442af4c0cb06efe64ca24e1591d3ffc2
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientLogin.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.kuschku.libquassel.protocol.messages.handshake
+
+data class ClientLogin(
+  val user: String?,
+  val password: String?
+)
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientLoginAck.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientLoginAck.kt
new file mode 100644
index 0000000000000000000000000000000000000000..077607e79b4dc65234daff60adb5c81301b6823e
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientLoginAck.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.kuschku.libquassel.protocol.messages.handshake
+
+object ClientLoginAck {
+  override fun toString(): String {
+    return "ClientLoginAck"
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientLoginReject.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientLoginReject.kt
new file mode 100644
index 0000000000000000000000000000000000000000..13eee3e7532e149f12e7b8fdc78bd966b6070f59
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientLoginReject.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.kuschku.libquassel.protocol.messages.handshake
+
+data class ClientLoginReject(
+  val errorString: String?
+)
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/CoreSetupAck.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/CoreSetupAck.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5bcf74827bc9d03a951eca8711f563a1782c0619
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/CoreSetupAck.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.kuschku.libquassel.protocol.messages.handshake
+
+object CoreSetupAck {
+  override fun toString(): String {
+    return "CoreSetupAck"
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/CoreSetupData.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/CoreSetupData.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b67d6cd718d05af4d23b4a05d438b2501dd4c3a3
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/CoreSetupData.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.kuschku.libquassel.protocol.messages.handshake
+
+import de.kuschku.libquassel.protocol.variant.QVariantMap
+
+data class CoreSetupData(
+  val adminUser: String?,
+  val adminPassword: String?,
+  val backend: String?,
+  val setupData: QVariantMap?,
+  val authenticator: String?,
+  val authSetupData: QVariantMap?
+)
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/CoreSetupReject.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/CoreSetupReject.kt
new file mode 100644
index 0000000000000000000000000000000000000000..4fc468d8f1a8afe2bec8ec15ecf8816e07269a37
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/CoreSetupReject.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.kuschku.libquassel.protocol.messages.handshake
+
+data class CoreSetupReject(
+  val errorString: String?
+)
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/SessionInit.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/SessionInit.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0716fa532641bf97cd234531fa442ded4f512fb2
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/SessionInit.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.kuschku.libquassel.protocol.messages.handshake
+
+import de.kuschku.libquassel.protocol.variant.QVariantList
+
+data class SessionInit(
+  val identities: QVariantList?,
+  val bufferInfos: QVariantList?,
+  val networkIds: QVariantList?
+)
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/HandshakeSerializers.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/HandshakeSerializers.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e11430ae86c2011b2ef4ee17bc76a13b22b11a5d
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/HandshakeSerializers.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.kuschku.libquassel.protocol.serializers
+
+import de.kuschku.libquassel.protocol.serializers.handshake.ClientInitAckSerializer
+import de.kuschku.libquassel.protocol.serializers.handshake.ClientInitRejectSerializer
+import de.kuschku.libquassel.protocol.serializers.handshake.ClientInitSerializer
+import de.kuschku.libquassel.protocol.serializers.handshake.HandshakeSerializer
+import de.kuschku.libquassel.protocol.serializers.primitive.*
+import java.util.*
+
+object HandshakeSerializers {
+  private val serializers = listOf<HandshakeSerializer<*>>(
+    ClientInitSerializer,
+    ClientInitAckSerializer,
+    ClientInitRejectSerializer,
+  ).associateBy(HandshakeSerializer<*>::type)
+
+  @PublishedApi
+  internal fun find(type: String) = serializers[type]
+
+  @Suppress("UNCHECKED_CAST")
+  inline operator fun <reified T> get(type: String): HandshakeSerializer<T> {
+    val serializer = find(type)
+      ?: throw NoSerializerForTypeException.Handshake(type, T::class.java)
+    if (serializer.javaType == T::class.java) {
+      return serializer as HandshakeSerializer<T>
+    } else {
+      throw NoSerializerForTypeException.Handshake(type, T::class.java)
+    }
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/NoSerializerForTypeException.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/NoSerializerForTypeException.kt
index 015a5391de4a8a3a33ab0a8acbab0892f61ccf1c..9ce61cef5e5da46faa7a00b01f41c8f6411293c2 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/NoSerializerForTypeException.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/NoSerializerForTypeException.kt
@@ -22,21 +22,36 @@ package de.kuschku.libquassel.protocol.serializers
 import de.kuschku.libquassel.protocol.variant.QtType
 import de.kuschku.libquassel.protocol.variant.QuasselType
 
-class NoSerializerForTypeException(
-  private val javaType: Class<*>?,
-  private val qtType: Int,
-  private val quasselType: String?,
-) : Exception() {
-  constructor(quasselType: QuasselType, javaType: Class<*>? = null) :
-    this(javaType, quasselType.qtType.id, quasselType.typeName)
-
-  constructor(qtType: QtType, javaType: Class<*>? = null) :
-    this(javaType, qtType.id, null)
+sealed class NoSerializerForTypeException : Exception() {
+  data class Qt(
+    private val type: Int,
+    private val javaType: Class<*>? = null
+  ) : NoSerializerForTypeException() {
+    constructor(
+      type: QtType,
+      javaType: Class<*>? = null
+    ) : this(type.id, javaType)
+  }
 
-  constructor(qtType: Int, quasselType: String?) :
-    this(null, qtType, quasselType)
+  data class Quassel(
+    private val type: Int,
+    private val typename: String?,
+    private val javaType: Class<*>? = null
+  ) : NoSerializerForTypeException() {
+    constructor(
+      type: QtType,
+      typename: String?,
+      javaType: Class<*>? = null
+    ) : this(type.id, typename, javaType)
 
-  override fun toString(): String {
-    return "NoSerializerForTypeException(javaType=$javaType, qtType=${QtType.of(qtType) ?: qtType}, quasselType=${QuasselType.of(quasselType) ?: quasselType})"
+    constructor(
+      type: QuasselType,
+      javaType: Class<*>? = null
+    ) : this(type.qtType, type.typeName, javaType)
   }
+
+  data class Handshake(
+    private val type: String,
+    private val javaType: Class<*>? = null
+  ) : NoSerializerForTypeException()
 }
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/QtSerializers.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/QtSerializers.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6cb668042b135917dd0bcf51c503f2dcc22d3ee1
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/QtSerializers.kt
@@ -0,0 +1,70 @@
+/*
+ * 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.kuschku.libquassel.protocol.serializers
+
+import de.kuschku.libquassel.protocol.serializers.primitive.*
+import de.kuschku.libquassel.protocol.variant.QtType
+import java.util.*
+
+object QtSerializers {
+  private val serializers = setOf<QtSerializer<*>>(
+    VoidSerializer,
+    BoolSerializer,
+
+    ByteSerializer,
+    UByteSerializer,
+    ShortSerializer,
+    UShortSerializer,
+    IntSerializer,
+    UIntSerializer,
+    LongSerializer,
+    ULongSerializer,
+
+    FloatSerializer,
+    DoubleSerializer,
+
+    QCharSerializer,
+    StringSerializerUtf16,
+    QStringListSerializer,
+    ByteBufferSerializer,
+
+    DateSerializer,
+    TimeSerializer,
+    DateTimeSerializer,
+
+    QVariantSerializer,
+    QVariantListSerializer,
+    QVariantMapSerializer,
+  ).associateBy(QtSerializer<*>::qtType)
+
+  @PublishedApi
+  internal fun find(type: QtType) = serializers[type]
+
+  @Suppress("UNCHECKED_CAST")
+  inline operator fun <reified T> get(type: QtType): QtSerializer<T> {
+    val serializer = find(type)
+      ?: throw NoSerializerForTypeException.Qt(type, T::class.java)
+    if (serializer.javaType == T::class.java) {
+      return serializer as QtSerializer<T>
+    } else {
+      throw NoSerializerForTypeException.Qt(type, T::class.java)
+    }
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/QuasselSerializers.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/QuasselSerializers.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0d201e7acba9bee560ec663c6332ffeb474a5778
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/QuasselSerializers.kt
@@ -0,0 +1,58 @@
+/*
+ * 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.kuschku.libquassel.protocol.serializers
+
+import de.kuschku.libquassel.protocol.serializers.primitive.*
+import de.kuschku.libquassel.protocol.variant.QuasselType
+import java.util.*
+
+object QuasselSerializers {
+  private val serializers = listOf<QuasselSerializer<*>>(
+    BufferIdSerializer,
+    BufferInfoSerializer,
+    //DccConfigIpDetectionModeSerializer,
+    //DccConfigPortSelectionModeSerializer,
+    //IrcUserSerializer,
+    //IrcChannelSerializer,
+    //IdentitySerializer,
+    IdentityIdSerializer,
+    MessageSerializer,
+    MsgIdSerializer,
+    NetworkIdSerializer,
+    //NetworkInfoSerializer,
+    //NetworkServerSerializer,
+    //QHostAddressSerializer,
+    PeerPtrSerializer,
+  ).associateBy(QuasselSerializer<*>::quasselType)
+
+  @PublishedApi
+  internal fun find(type: QuasselType) = serializers[type]
+
+  @Suppress("UNCHECKED_CAST")
+  inline operator fun <reified T> get(type: QuasselType): QuasselSerializer<T> {
+    val serializer = find(type)
+      ?: throw NoSerializerForTypeException.Quassel(type, T::class.java)
+    if (serializer.javaType == T::class.java) {
+      return serializer as QuasselSerializer<T>
+    } else {
+      throw NoSerializerForTypeException.Quassel(type, T::class.java)
+    }
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
index 80dc55499bd5988e8df8dcad9356a2147aeb3dbf..76236f54e24ec1c1e0b2dbd00bb34432e35b1969 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
@@ -19,16 +19,18 @@
 
 package de.kuschku.libquassel.protocol.serializers.handshake
 
-import de.kuschku.bitflags.toBits
 import de.kuschku.bitflags.of
-import de.kuschku.libquassel.protocol.features.QuasselFeatureName
+import de.kuschku.bitflags.toBits
 import de.kuschku.libquassel.protocol.features.LegacyFeature
+import de.kuschku.libquassel.protocol.features.QuasselFeatureName
 import de.kuschku.libquassel.protocol.messages.handshake.ClientInitAck
 import de.kuschku.libquassel.protocol.variant.*
 
 object ClientInitAckSerializer : HandshakeSerializer<ClientInitAck> {
+  override val type: String = "ClientInitAck"
+  override val javaType: Class<out ClientInitAck> = ClientInitAck::class.java
+
   override fun serialize(data: ClientInitAck) = mapOf(
-    "MsgType" to qVariant("ClientInitAck", QtType.QString),
     "CoreFeatures" to qVariant(data.coreFeatures.toBits(), QtType.UInt),
     "StorageBackends" to qVariant(data.backendInfo, QtType.QVariantList),
     "Authenticator" to qVariant(data.authenticatorInfo, QtType.QVariantList),
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitRejectSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitRejectSerializer.kt
index c42c2c7128376c86beea164950c06b3ba6739f8a..d064611743f1305945084890404c54da147816df 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitRejectSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitRejectSerializer.kt
@@ -26,8 +26,10 @@ import de.kuschku.libquassel.protocol.variant.into
 import de.kuschku.libquassel.protocol.variant.qVariant
 
 object ClientInitRejectSerializer : HandshakeSerializer<ClientInitReject> {
+  override val type: String = "ClientInitReject"
+  override val javaType: Class<out ClientInitReject> = ClientInitReject::class.java
+
   override fun serialize(data: ClientInitReject) = mapOf(
-    "MsgType" to qVariant("ClientInitReject", QtType.QString),
     "Error" to qVariant(data.errorString, QtType.QString)
   )
 
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
index 3b3de6a12c9e969738604d0f411dedfc3c20996e..0d1348698d1650398a914bb6887bb716d540c82a 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
@@ -19,10 +19,10 @@
 
 package de.kuschku.libquassel.protocol.serializers.handshake
 
-import de.kuschku.bitflags.toBits
 import de.kuschku.bitflags.of
-import de.kuschku.libquassel.protocol.features.QuasselFeatureName
+import de.kuschku.bitflags.toBits
 import de.kuschku.libquassel.protocol.features.LegacyFeature
+import de.kuschku.libquassel.protocol.features.QuasselFeatureName
 import de.kuschku.libquassel.protocol.messages.handshake.ClientInit
 import de.kuschku.libquassel.protocol.variant.QVariantMap
 import de.kuschku.libquassel.protocol.variant.QtType
@@ -30,8 +30,10 @@ import de.kuschku.libquassel.protocol.variant.into
 import de.kuschku.libquassel.protocol.variant.qVariant
 
 object ClientInitSerializer : HandshakeSerializer<ClientInit> {
+  override val type: String = "ClientInit"
+  override val javaType: Class<out ClientInit> = ClientInit::class.java
+
   override fun serialize(data: ClientInit) = mapOf(
-    "MsgType" to qVariant("ClientInit", QtType.QString),
     "ClientVersion" to qVariant(data.clientVersion, QtType.QString),
     "ClientDate" to qVariant(data.buildDate, QtType.QString),
     "Features" to qVariant(data.clientFeatures.toBits(), QtType.UInt),
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/HandshakeSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/HandshakeSerializer.kt
index 6abb586ee0ab4800a454eab69b3c5e040fb2662e..45e863f0ea420f76c5aa8967ce2572dbf68d7e37 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/HandshakeSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/HandshakeSerializer.kt
@@ -22,6 +22,9 @@ package de.kuschku.libquassel.protocol.serializers.handshake
 import de.kuschku.libquassel.protocol.variant.QVariantMap
 
 interface HandshakeSerializer<T> {
+  val type: String
+  val javaType: Class<out T>
+
   fun serialize(data: T): QVariantMap
   fun deserialize(data: QVariantMap): T
 }
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ByteBufferSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ByteBufferSerializer.kt
index 1aa629ec7d273262f66c4c6dcd7e5479696fdbbf..d510b502df5cad01d8c5f48ac68e5c3a5384a45e 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ByteBufferSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ByteBufferSerializer.kt
@@ -22,7 +22,6 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.io.copyData
-import de.kuschku.libquassel.protocol.io.print
 import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateSerializer.kt
index da03cc8e8b61890421b7169740b6a81d3394ab2b..6c11ed3e0564bde135de396c14f0755475d5ab51 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateSerializer.kt
@@ -23,7 +23,6 @@ import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.variant.QtType
 import org.threeten.bp.LocalDate
-import org.threeten.bp.LocalTime
 import org.threeten.bp.temporal.JulianFields
 import java.nio.ByteBuffer
 
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/HandshakeMapSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/HandshakeMapSerializer.kt
similarity index 82%
rename from protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/HandshakeMapSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/HandshakeMapSerializer.kt
index 5a8484134632c01777e8b7a1e6d7dfa98dd51a7e..5f7b4c2b1ad9b7ecf073f57465a08841656a2c08 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/HandshakeMapSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/HandshakeMapSerializer.kt
@@ -17,19 +17,16 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.libquassel.protocol.serializers.handshake
+package de.kuschku.libquassel.protocol.serializers.primitive
 
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
-import de.kuschku.libquassel.protocol.serializers.primitive.QVariantListSerializer
-import de.kuschku.libquassel.protocol.serializers.primitive.QtSerializer
-import de.kuschku.libquassel.protocol.serializers.primitive.StringSerializerAscii
-import de.kuschku.libquassel.protocol.serializers.primitive.StringSerializerUtf8
 import de.kuschku.libquassel.protocol.variant.*
 import java.nio.ByteBuffer
 
 object HandshakeMapSerializer : QtSerializer<QVariantMap> {
   override val qtType = QtType.QVariantMap
+
   @Suppress("UNCHECKED_CAST")
   override val javaType: Class<out QVariantMap> = Map::class.java as Class<QVariantMap>
 
@@ -46,7 +43,7 @@ object HandshakeMapSerializer : QtSerializer<QVariantMap> {
     val list = QVariantListSerializer.deserialize(buffer, featureSet)
     return (list.indices step 2).map {
       val encodedKey = list[it].into<ByteBuffer>(ByteBuffer.allocateDirect(0))
-      val value = list[it+1]
+      val value = list[it + 1]
 
       Pair(StringSerializerUtf8.deserializeRaw(encodedKey), value)
     }.toMap()
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IdentityIdSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IdentityIdSerializer.kt
index 3a27fb8c3a9bbdca571b9818516c09834e45dbf5..256f80a1ef7a52581dd85a660c8d568c25759ced 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IdentityIdSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IdentityIdSerializer.kt
@@ -21,7 +21,6 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
-import de.kuschku.libquassel.protocol.types.BufferId
 import de.kuschku.libquassel.protocol.types.IdentityId
 import de.kuschku.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/NetworkIdSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/NetworkIdSerializer.kt
index 62b6fe80980484751dcdb58ecf31f71561fe8b3d..6827e02a841231d5ce6ef40015f592710e004f9d 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/NetworkIdSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/NetworkIdSerializer.kt
@@ -21,8 +21,6 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
-import de.kuschku.libquassel.protocol.types.BufferId
-import de.kuschku.libquassel.protocol.types.IdentityId
 import de.kuschku.libquassel.protocol.types.NetworkId
 import de.kuschku.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/PeerPtrSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/PeerPtrSerializer.kt
index 9a927a077cfe1397318168867711e62cb589d207..461e0093590ebe29519662dff5026d54e743d681 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/PeerPtrSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/PeerPtrSerializer.kt
@@ -21,7 +21,6 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
-import de.kuschku.libquassel.protocol.variant.QtType
 import de.kuschku.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QStringListSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QStringListSerializer.kt
index 70779d2899844d28d98c541bb00d609b4cd69e21..4a3db40a1d0261ef95fa59e326dd9b410dd6f548 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QStringListSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QStringListSerializer.kt
@@ -22,13 +22,12 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.variant.QStringList
-import de.kuschku.libquassel.protocol.variant.QVariantList
-import de.kuschku.libquassel.protocol.variant.QVariant_
 import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object QStringListSerializer : QtSerializer<QStringList> {
   override val qtType = QtType.QStringList
+
   @Suppress("UNCHECKED_CAST")
   override val javaType: Class<QStringList> = List::class.java as Class<QStringList>
 
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantListSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantListSerializer.kt
index b77e47fbb8c8e06e8ba0df081f4e671d998f55e4..986fb566059ba270e53c224e94a170a67ecd1803 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantListSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantListSerializer.kt
@@ -28,6 +28,7 @@ import java.nio.ByteBuffer
 
 object QVariantListSerializer : QtSerializer<QVariantList> {
   override val qtType = QtType.QVariantList
+
   @Suppress("UNCHECKED_CAST")
   override val javaType: Class<QVariantList> = List::class.java as Class<QVariantList>
 
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantMapSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantMapSerializer.kt
index 956e58e26953465ebc0068672a4fe9c6cc555af9..7de2401591116480f0c7ffef3aea9779fea813a8 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantMapSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantMapSerializer.kt
@@ -28,6 +28,7 @@ import java.nio.ByteBuffer
 
 object QVariantMapSerializer : QtSerializer<QVariantMap> {
   override val qtType = QtType.QVariantMap
+
   @Suppress("UNCHECKED_CAST")
   override val javaType: Class<out QVariantMap> = Map::class.java as Class<QVariantMap>
 
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializer.kt
index b1caf13ea633a11f41222d15bd2c45c098c02197..8deb400fd4264eff1de2b28cb7919e256ca15d8a 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializer.kt
@@ -22,6 +22,8 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.serializers.NoSerializerForTypeException
+import de.kuschku.libquassel.protocol.serializers.QtSerializers
+import de.kuschku.libquassel.protocol.serializers.QuasselSerializers
 import de.kuschku.libquassel.protocol.variant.QVariant
 import de.kuschku.libquassel.protocol.variant.QVariant_
 import de.kuschku.libquassel.protocol.variant.QtType
@@ -44,14 +46,14 @@ object QVariantSerializer : QtSerializer<QVariant_> {
   override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): QVariant_ {
     val rawType = IntSerializer.deserialize(buffer, featureSet)
     val qtType = QtType.of(rawType)
-      ?: throw NoSerializerForTypeException(rawType, null)
+      ?: throw NoSerializerForTypeException.Qt(rawType, null)
     // isNull, but we ignore it as it has no meaning
     BoolSerializer.deserialize(buffer, featureSet)
 
     return if (qtType == QtType.UserType) {
       val name = StringSerializerAscii.deserialize(buffer, featureSet)
       val quasselType = QuasselType.of(name)
-        ?: throw NoSerializerForTypeException(qtType.id, name)
+        ?: throw NoSerializerForTypeException.Quassel(qtType.id, name)
       deserialize(quasselType, buffer, featureSet)
     } else {
       deserialize(qtType, buffer, featureSet)
@@ -60,16 +62,16 @@ object QVariantSerializer : QtSerializer<QVariant_> {
 
   @Suppress("UNCHECKED_CAST")
   private fun deserialize(type: QtType, buffer: ByteBuffer, featureSet: FeatureSet): QVariant_ {
-    val serializer = Serializers[type]
-      ?: throw NoSerializerForTypeException(type)
+    val serializer = QtSerializers.find(type)
+      ?: throw NoSerializerForTypeException.Qt(type)
     val value = serializer.deserialize(buffer, featureSet)
     return QVariant.of(value, serializer as QtSerializer<Any?>)
   }
 
   @Suppress("UNCHECKED_CAST")
   private fun deserialize(type: QuasselType, buffer: ByteBuffer, featureSet: FeatureSet): QVariant_ {
-    val serializer = Serializers[type]
-      ?: throw NoSerializerForTypeException(type)
+    val serializer = QuasselSerializers.find(type)
+      ?: throw NoSerializerForTypeException.Quassel(type)
     val value = serializer.deserialize(buffer, featureSet)
     return QVariant.of(value, serializer as QuasselSerializer<Any?>)
   }
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt
deleted file mode 100644
index a8001289c37e5d78772a2b6d302174ba7914a61f..0000000000000000000000000000000000000000
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt
+++ /dev/null
@@ -1,101 +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.kuschku.libquassel.protocol.serializers.primitive
-
-import de.kuschku.libquassel.protocol.serializers.NoSerializerForTypeException
-import de.kuschku.libquassel.protocol.serializers.primitive.*
-import de.kuschku.libquassel.protocol.variant.QtType
-import de.kuschku.libquassel.protocol.variant.QuasselType
-import java.util.*
-
-object Serializers {
-  private val qtSerializers = setOf<QtSerializer<*>>(
-    VoidSerializer,
-    BoolSerializer,
-
-    ByteSerializer,
-    UByteSerializer,
-    ShortSerializer,
-    UShortSerializer,
-    IntSerializer,
-    UIntSerializer,
-    LongSerializer,
-    ULongSerializer,
-
-    FloatSerializer,
-    DoubleSerializer,
-
-    QCharSerializer,
-    StringSerializerUtf16,
-    QStringListSerializer,
-    ByteBufferSerializer,
-
-    DateSerializer,
-    TimeSerializer,
-    DateTimeSerializer,
-
-    QVariantSerializer,
-    QVariantListSerializer,
-    QVariantMapSerializer,
-  ).associateBy(QtSerializer<*>::qtType)
-
-  private val quasselSerializers = listOf<QuasselSerializer<*>>(
-    BufferIdSerializer,
-    BufferInfoSerializer,
-    //DccConfigIpDetectionModeSerializer,
-    //DccConfigPortSelectionModeSerializer,
-    //IrcUserSerializer,
-    //IrcChannelSerializer,
-    //IdentitySerializer,
-    IdentityIdSerializer,
-    MessageSerializer,
-    MsgIdSerializer,
-    NetworkIdSerializer,
-    //NetworkInfoSerializer,
-    //NetworkServerSerializer,
-    //QHostAddressSerializer,
-    PeerPtrSerializer,
-  ).associateBy(QuasselSerializer<*>::quasselType)
-
-  operator fun get(type: QtType) = qtSerializers[type]
-  operator fun get(type: QuasselType) = quasselSerializers[type]
-}
-
-@Suppress("UNCHECKED_CAST")
-inline fun <reified T> serializerFor(type: QtType): QtSerializer<T> {
-  val serializer = Serializers[type]
-    ?: throw NoSerializerForTypeException(type, T::class.java)
-  if (serializer.javaType == T::class.java) {
-    return serializer as QtSerializer<T>
-  } else {
-    throw NoSerializerForTypeException(type, T::class.java)
-  }
-}
-
-@Suppress("UNCHECKED_CAST")
-inline fun <reified T> serializerFor(type: QuasselType): QuasselSerializer<T> {
-  val serializer = Serializers[type]
-    ?: throw NoSerializerForTypeException(type, T::class.java)
-  if (serializer.javaType == T::class.java) {
-    return serializer as QuasselSerializer<T>
-  } else {
-    throw NoSerializerForTypeException(type, T::class.java)
-  }
-}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializer.kt
index 7d2dae33fa0a4751c00ac5b1f81a32789345d9be..e2040f2e19fae9662e352f10ff5ed472693d2812 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializer.kt
@@ -22,7 +22,6 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.io.StringEncoder
-import de.kuschku.libquassel.protocol.io.print
 import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 import java.nio.charset.Charset
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerAscii.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerAscii.kt
index f13a9a51fe5b809180df02c148e15d1172d3a797..8811510ea70b0dd6d61ad5a953ab1f7894049858 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerAscii.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerAscii.kt
@@ -19,11 +19,5 @@
 
 package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.libquassel.protocol.features.FeatureSet
-import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
-import de.kuschku.libquassel.protocol.io.stringEncoderAscii
-import de.kuschku.libquassel.protocol.variant.QtType
-import java.nio.ByteBuffer
-
 object StringSerializerAscii : StringSerializer(Charsets.ISO_8859_1, true)
 
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/VoidSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/VoidSerializer.kt
index cc29434c6487ef6cecc71c54572f09cb9b8bab18..c3b9b60023cf535d02251dbb0b9f68578aac087e 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/VoidSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/VoidSerializer.kt
@@ -29,5 +29,5 @@ object VoidSerializer : QtSerializer<Unit> {
   override val javaType: Class<out Unit> = Unit::class.java
 
   override fun serialize(buffer: ChainedByteBuffer, data: Unit, featureSet: FeatureSet) = Unit
-  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet)  = Unit
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet) = Unit
 }
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferActivity.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferActivity.kt
index bbefa87b79f1f53dff6c0208f109f50a59cab76c..557155d5629c9584caba3545d620a117c99b86de 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferActivity.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferActivity.kt
@@ -22,11 +22,10 @@ package de.kuschku.libquassel.protocol.types
 import de.kuschku.bitflags.Flag
 import de.kuschku.bitflags.Flags
 import de.kuschku.bitflags.toEnumSet
-import de.kuschku.libquassel.protocol.features.LegacyFeature
 
 enum class BufferActivity(
   override val value: UInt,
-): Flag<UInt> {
+) : Flag<UInt> {
   NoActivity(0x00u),
   OtherActivity(0x01u),
   NewMessage(0x02u),
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferType.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferType.kt
index 44d0ca83018af758c69c17068df4c572f183be99..356d0bbf196e189e273adef04a9cd8ecabd62a36 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferType.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferType.kt
@@ -25,7 +25,7 @@ import de.kuschku.bitflags.toEnumSet
 
 enum class BufferType(
   override val value: UShort,
-): Flag<UShort> {
+) : Flag<UShort> {
   Invalid(0x00u),
   Status(0x01u),
   Channel(0x02u),
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QVariant.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QVariant.kt
index 93cb9358afe94d4e153c0ca294839c0fb700d59d..8747eeb4e2aef164a2ec50f5e5c24bf667aaef59 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QVariant.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QVariant.kt
@@ -22,9 +22,10 @@ package de.kuschku.libquassel.protocol.variant
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.io.contentToString
+import de.kuschku.libquassel.protocol.serializers.QtSerializers
+import de.kuschku.libquassel.protocol.serializers.QuasselSerializers
 import de.kuschku.libquassel.protocol.serializers.primitive.QtSerializer
 import de.kuschku.libquassel.protocol.serializers.primitive.QuasselSerializer
-import de.kuschku.libquassel.protocol.serializers.primitive.serializerFor
 import java.nio.ByteBuffer
 import java.util.*
 
@@ -59,6 +60,11 @@ sealed class QVariant<T> constructor(
       "QVariant(${serializer::class.java.simpleName}, $data)"
   }
 
+  @Suppress("UNCHECKED_CAST")
+  inline fun <reified T> withType(): QVariant<T>? =
+    if (serializer.javaType == T::class.java && this.value() 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)
@@ -66,15 +72,10 @@ sealed class QVariant<T> constructor(
 }
 
 inline fun <reified T> qVariant(data: T, type: QtType): QVariant<T> =
-  QVariant.of(data, serializerFor(type))
+  QVariant.of(data, QtSerializers[type])
 
 inline fun <reified T> qVariant(data: T, type: QuasselType): QVariant<T> =
-  QVariant.of(data, serializerFor(type))
-
-@Suppress("UNCHECKED_CAST")
-inline fun <reified T> QVariant_.withType(): QVariant<T>? =
-  if (this.serializer.javaType == T::class.java && this.value() is T) this as QVariant<T>
-  else null
+  QVariant.of(data, QuasselSerializers[type])
 
 inline fun <reified T> QVariant_?.into(): T? =
   this?.withType<T>()?.value()
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializerTest.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializerTest.kt
index 88f60db3fb84620165479476b32573d1c2524f2b..06e4907bbf994062414802bf8c321c25d6b04606 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializerTest.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializerTest.kt
@@ -21,11 +21,8 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 import de.kuschku.libquassel.protocol.serializers.NoSerializerForTypeException
 import de.kuschku.libquassel.protocol.testutil.byteBufferOf
 import de.kuschku.libquassel.protocol.testutil.deserialize
-import de.kuschku.libquassel.protocol.testutil.qtSerializerTest
-import de.kuschku.libquassel.protocol.variant.QtType
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.assertThrows
-import kotlin.experimental.inv
 
 class QVariantSerializerTest {
   @Test
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerTest.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerTest.kt
index b8510fa927337890f4e7d52f417afab4362c9e71..fe16a2e22653c9f390771668fa08539bc5086c9d 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerTest.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerTest.kt
@@ -18,9 +18,12 @@
  */
 package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.libquassel.protocol.testutil.*
+import de.kuschku.libquassel.protocol.testutil.byteBufferOf
+import de.kuschku.libquassel.protocol.testutil.deserialize
 import de.kuschku.libquassel.protocol.testutil.matchers.BomMatcherString
 import de.kuschku.libquassel.protocol.testutil.matchers.ByteBufferMatcher
+import de.kuschku.libquassel.protocol.testutil.testQtSerializerDirect
+import de.kuschku.libquassel.protocol.testutil.testQtSerializerVariant
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Test
 
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UByteSerializerTest.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UByteSerializerTest.kt
index 23e98606d459b18770566112ef22adcb254558f8..79766902bf9964ce148f887c0074cf45828aa19a 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UByteSerializerTest.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UByteSerializerTest.kt
@@ -21,7 +21,6 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 import de.kuschku.libquassel.protocol.testutil.byteBufferOf
 import de.kuschku.libquassel.protocol.testutil.qtSerializerTest
 import org.junit.jupiter.api.Test
-import kotlin.experimental.inv
 
 class UByteSerializerTest {
   @Test
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UIntSerializerTest.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UIntSerializerTest.kt
index 09edb18aaabf7e1ccdd1a0747c7bf9b83a4b8a0b..8b4d498581591e8aef78eaec5af0e9006e01accc 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UIntSerializerTest.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UIntSerializerTest.kt
@@ -21,7 +21,6 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 import de.kuschku.libquassel.protocol.testutil.byteBufferOf
 import de.kuschku.libquassel.protocol.testutil.qtSerializerTest
 import org.junit.jupiter.api.Test
-import kotlin.experimental.inv
 
 class UIntSerializerTest {
   @Test
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UShortSerializerTest.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UShortSerializerTest.kt
index 29863bbca06972625f3483100576a69979b81304..57192fb645b903663be3585aa7914ab5a9ee2425 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UShortSerializerTest.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/primitive/UShortSerializerTest.kt
@@ -21,7 +21,6 @@ package de.kuschku.libquassel.protocol.serializers.primitive
 import de.kuschku.libquassel.protocol.testutil.byteBufferOf
 import de.kuschku.libquassel.protocol.testutil.qtSerializerTest
 import org.junit.jupiter.api.Test
-import kotlin.experimental.inv
 
 class UShortSerializerTest {
   @Test
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/byteBufferOf.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/byteBufferOf.kt
index 74efbd6038bd4342144f33d15aae5c507e1a782c..65f2eb75cefd3b7d9faabdc0ea11587fd737343e 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/byteBufferOf.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/byteBufferOf.kt
@@ -17,6 +17,8 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.libquassel.protocol.testutil
+
 import java.nio.ByteBuffer
+
 inline fun byteBufferOf(vararg elements: Byte) = ByteBuffer.wrap(byteArrayOf(*elements))
 inline fun byteBufferOf(vararg elements: UByte) = ByteBuffer.wrap(ubyteArrayOf(*elements).toByteArray())
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/deserialize.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/deserialize.kt
index 1405e746aeab775419088747841b8b4b3bbd27cd..38acc37ea2907735e3b25fd831da02352efbd2c4 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/deserialize.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/deserialize.kt
@@ -17,14 +17,16 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.libquassel.protocol.testutil
+
 import de.kuschku.libquassel.protocol.features.FeatureSet
-import de.kuschku.libquassel.protocol.serializers.handshake.HandshakeMapSerializer
 import de.kuschku.libquassel.protocol.serializers.handshake.HandshakeSerializer
+import de.kuschku.libquassel.protocol.serializers.primitive.HandshakeMapSerializer
 import de.kuschku.libquassel.protocol.serializers.primitive.QtSerializer
 import org.hamcrest.Matcher
 import org.hamcrest.MatcherAssert.assertThat
 import org.junit.jupiter.api.Assertions.assertEquals
 import java.nio.ByteBuffer
+
 fun <T> deserialize(
   serializer: QtSerializer<T>,
   buffer: ByteBuffer,
@@ -34,6 +36,7 @@ fun <T> deserialize(
   assertEquals(0, buffer.remaining())
   return result
 }
+
 fun <T> testDeserialize(
   serializer: QtSerializer<T>,
   matcher: Matcher<in T>,
@@ -43,6 +46,7 @@ fun <T> testDeserialize(
   val after = deserialize(serializer, buffer, featureSet)
   assertThat(after, matcher)
 }
+
 fun <T> testDeserialize(
   serializer: QtSerializer<T>,
   data: T,
@@ -52,6 +56,7 @@ fun <T> testDeserialize(
   val after = deserialize(serializer, buffer, featureSet)
   assertEquals(data, after)
 }
+
 fun <T> testDeserialize(
   serializer: HandshakeSerializer<T>,
   matcher: Matcher<in T>,
@@ -62,6 +67,7 @@ fun <T> testDeserialize(
   val after = serializer.deserialize(map)
   assertThat(after, matcher)
 }
+
 fun <T> testDeserialize(
   serializer: HandshakeSerializer<T>,
   data: T,
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/matchers/BomMatcherString.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/matchers/BomMatcherString.kt
index 1ca92f1f0a3fd56473c3f674f75de4269659d53a..ac9e7121c75ee1eccedb9f3c04fe944235d30b27 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/matchers/BomMatcherString.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/matchers/BomMatcherString.kt
@@ -17,15 +17,19 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.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/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/matchers/ByteBufferMatcher.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/matchers/ByteBufferMatcher.kt
index e58c9aaaee4a5ccbf7df9b06a1b0dbc5b13deecd..c295170f8188710b9a69ec4253b8414868d785ce 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/matchers/ByteBufferMatcher.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/matchers/ByteBufferMatcher.kt
@@ -17,6 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.libquassel.protocol.testutil.matchers
+
 import de.kuschku.libquassel.protocol.io.contentToString
 import org.hamcrest.BaseMatcher
 import org.hamcrest.Description
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/qtSerializerTest.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/qtSerializerTest.kt
index 278da43f82613fb359e83d8404d9e3a6665b7d04..f830f90d9e451d18935d5ecdedea2bdbdf103aeb 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/qtSerializerTest.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/qtSerializerTest.kt
@@ -17,11 +17,12 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.libquassel.protocol.testutil
+
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.serializers.primitive.QtSerializer
-import de.kuschku.libquassel.protocol.serializers.primitive.QuasselSerializer
 import org.hamcrest.Matcher
 import java.nio.ByteBuffer
+
 fun <T> qtSerializerTest(
   serializer: QtSerializer<T>,
   value: T,
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testHandshakeSerializerEncoded.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testHandshakeSerializerEncoded.kt
index 9bdc85ac141fa34293167b97ee363c114deeebc3..5b4699eb50172c8871d169fbc37781017b74f29f 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testHandshakeSerializerEncoded.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testHandshakeSerializerEncoded.kt
@@ -17,11 +17,12 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.libquassel.protocol.testutil
+
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.io.print
-import de.kuschku.libquassel.protocol.serializers.handshake.HandshakeMapSerializer
 import de.kuschku.libquassel.protocol.serializers.handshake.HandshakeSerializer
+import de.kuschku.libquassel.protocol.serializers.primitive.HandshakeMapSerializer
 import org.hamcrest.Matcher
 import org.hamcrest.MatcherAssert.assertThat
 import org.junit.jupiter.api.Assertions.assertEquals
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQtSerializerDirect.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQtSerializerDirect.kt
index efa675b766421365cd710591c89b1d2d18ca6a2d..6f6967dcbde514288c4adf8b870f1f98db5e1c77 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQtSerializerDirect.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQtSerializerDirect.kt
@@ -17,6 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.libquassel.protocol.testutil
+
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.io.print
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQtSerializerVariant.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQtSerializerVariant.kt
index 6164467b13e80148de093a9f12335872a0327bdf..ea5bb24bc76bf6fe5467519dbe633d6f0501acf0 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQtSerializerVariant.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQtSerializerVariant.kt
@@ -17,6 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.libquassel.protocol.testutil
+
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.io.print
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQuasselSerializerDirect.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQuasselSerializerDirect.kt
index 2a23c84fdb897244986613705552cc98583da9fd..aa7e70834c2b9eaeb1147517feb703ab3442b0c7 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQuasselSerializerDirect.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQuasselSerializerDirect.kt
@@ -17,6 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.libquassel.protocol.testutil
+
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.io.print
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQuasselSerializerVariant.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQuasselSerializerVariant.kt
index 6c83a3fec886cf9f6e6c957b104ce5d4b8c24120..fff25c72499310cd6f7c3bc80d0399d2350eb3e2 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQuasselSerializerVariant.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/testutil/testQuasselSerializerVariant.kt
@@ -17,6 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 package de.kuschku.libquassel.protocol.testutil
+
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
 import de.kuschku.libquassel.protocol.io.print