From e6e10d125968481e06dbe64364447ced7a88673a Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Fri, 5 Feb 2021 21:02:43 +0100
Subject: [PATCH] Split code into modules, implement early parts for later
 module usage

---
 app/build.gradle.kts                          |  2 +
 .../protocol/io/CoroutineChannel.kt           |  4 +-
 .../protocol/io/FixedDeflaterOutputStream.kt  |  2 +-
 .../protocol/io/ReadableWrappedChannel.kt     |  2 +-
 .../quasseldroid/protocol/io/StreamChannel.kt |  2 +-
 .../protocol/io/WritableWrappedChannel.kt     |  2 +-
 .../kuschku/quasseldroid/ExampleUnitTest.kt   | 12 ++--
 bitflags/build.gradle.kts                     |  9 +++
 .../src/main/java/de/kuschku/bitflags/Flag.kt | 24 +++++++
 .../main/java/de/kuschku/bitflags/Flags.kt    | 25 ++++++++
 .../main/java/de/kuschku/bitflags/toBits.kt   | 39 +++++-------
 .../java/de/kuschku/bitflags/toEnumSet.kt     | 26 ++++++++
 .../main/java/de/kuschku/bitflags/toFlag.kt   | 63 +++++++++++++++++++
 build.gradle                                  |  6 ++
 protocol/build.gradle.kts                     | 10 +++
 .../protocol/connection}/ProtocolInfo.kt      |  2 +-
 .../protocol/features}/ExtendedFeature.kt     |  4 +-
 .../protocol/features}/LegacyFeature.kt       | 13 +++-
 .../protocol/io/ChainedByteBuffer.kt          |  2 +-
 .../libquassel}/protocol/io/StringEncoder.kt  |  4 +-
 .../libquassel}/protocol/io/StringEncoders.kt |  2 +-
 .../messages}/handshake/ClientInit.kt         | 13 ++--
 .../messages/handshake/ClientInitAck.kt       | 32 ++++++++++
 .../messages/handshake/ClientInitReject.kt    | 24 +++++++
 .../NoSerializerForTypeException.kt           |  6 +-
 .../handshake/ClientInitAckSerializer.kt      | 47 ++++++++++++++
 .../handshake/ClientInitRejectSerializer.kt   | 37 +++++++++++
 .../handshake/ClientInitSerializer.kt         | 52 +++++++++++++++
 .../handshake/HandshakeSerializer.kt          | 27 ++++++++
 .../serializers/primitive/BoolSerializer.kt   |  7 +--
 .../serializers/primitive/ByteSerializer.kt   |  9 ++-
 .../serializers/primitive/IntSerializer.kt    |  9 ++-
 .../serializers/primitive/LongSerializer.kt   |  9 ++-
 .../primitive/ProtocolInfoSerializer.kt       |  9 ++-
 .../primitive/QVariantMapSerializer.kt        | 17 +++--
 .../primitive/QVariantSerializer.kt           | 16 ++---
 .../serializers/primitive}/QtSerializer.kt    |  6 +-
 .../primitive}/QuasselSerializer.kt           |  6 +-
 .../serializers/primitive}/Serializers.kt     | 21 ++++---
 .../serializers/primitive/ShortSerializer.kt  |  7 +--
 .../primitive/StringSerializerAscii.kt        |  9 ++-
 .../primitive/StringSerializerUtf16.kt        |  9 ++-
 .../primitive/StringSerializerUtf8.kt         |  9 ++-
 .../serializers/primitive/UByteSerializer.kt  |  7 +--
 .../serializers/primitive/UIntSerializer.kt   |  7 +--
 .../serializers/primitive/ULongSerializer.kt  |  7 +--
 .../serializers/primitive/UShortSerializer.kt |  7 +--
 .../libquassel}/protocol/variant/QVariant.kt  | 35 ++++++-----
 .../libquassel}/protocol/variant/QtType.kt    |  2 +-
 .../protocol/variant/QuasselType.kt           |  2 +-
 settings.gradle.kts                           |  4 +-
 51 files changed, 545 insertions(+), 162 deletions(-)
 create mode 100644 bitflags/build.gradle.kts
 create mode 100644 bitflags/src/main/java/de/kuschku/bitflags/Flag.kt
 create mode 100644 bitflags/src/main/java/de/kuschku/bitflags/Flags.kt
 rename app/src/main/java/de/kuschku/quasseldroid/protocol/Flag.kt => bitflags/src/main/java/de/kuschku/bitflags/toBits.kt (60%)
 create mode 100644 bitflags/src/main/java/de/kuschku/bitflags/toEnumSet.kt
 create mode 100644 bitflags/src/main/java/de/kuschku/bitflags/toFlag.kt
 create mode 100644 protocol/build.gradle.kts
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel/protocol/connection}/ProtocolInfo.kt (94%)
 rename {app/src/main/java/de/kuschku/quasseldroid/protocol => protocol/src/main/java/de/kuschku/libquassel/protocol/features}/ExtendedFeature.kt (94%)
 rename {app/src/main/java/de/kuschku/quasseldroid/protocol => protocol/src/main/java/de/kuschku/libquassel/protocol/features}/LegacyFeature.kt (85%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/io/ChainedByteBuffer.kt (98%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/io/StringEncoder.kt (97%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/io/StringEncoders.kt (96%)
 rename {app/src/main/java/de/kuschku/quasseldroid/protocol => protocol/src/main/java/de/kuschku/libquassel/protocol/messages}/handshake/ClientInit.kt (70%)
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitAck.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitReject.kt
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/NoSerializerForTypeException.kt (89%)
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitRejectSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/HandshakeSerializer.kt
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/BoolSerializer.kt (82%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/ByteSerializer.kt (79%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/IntSerializer.kt (79%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/LongSerializer.kt (79%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/ProtocolInfoSerializer.kt (83%)
 rename app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/VariantMapSerializer.kt => protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantMapSerializer.kt (73%)
 rename app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/VariantSerializer.kt => protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializer.kt (84%)
 rename {app/src/main/java/de/kuschku/quasseldroid/protocol/serializers => protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive}/QtSerializer.kt (84%)
 rename {app/src/main/java/de/kuschku/quasseldroid/protocol/serializers => protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive}/QuasselSerializer.kt (83%)
 rename {app/src/main/java/de/kuschku/quasseldroid/protocol/serializers => protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive}/Serializers.kt (84%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/ShortSerializer.kt (81%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/StringSerializerAscii.kt (82%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/StringSerializerUtf16.kt (82%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/StringSerializerUtf8.kt (82%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/UByteSerializer.kt (81%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/UIntSerializer.kt (81%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/ULongSerializer.kt (82%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/serializers/primitive/UShortSerializer.kt (82%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/variant/QVariant.kt (74%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/variant/QtType.kt (98%)
 rename {app/src/main/java/de/kuschku/quasseldroid => protocol/src/main/java/de/kuschku/libquassel}/protocol/variant/QuasselType.kt (96%)

diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 0277ac3b2..e719474e3 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -60,6 +60,8 @@ dependencies {
 
   implementation("org.threeten", "threetenbp", "1.4.0")
 
+  implementation(project(":protocol"))
+
   implementation("io.coil-kt", "coil", "1.1.1")
   implementation("dev.chrisbanes.accompanist", "accompanist-coil", "0.5.0")
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/CoroutineChannel.kt b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/CoroutineChannel.kt
index 156c6ec4a..28d09482a 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/CoroutineChannel.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/CoroutineChannel.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.io
+package de.kuschku.libquassel.protocol.io
 
 import de.kuschku.quasseldroid.util.TlsInfo
 import kotlinx.coroutines.Dispatchers
@@ -68,7 +68,7 @@ class CoroutineChannel {
     this.channel.write(buffer)
   }
 
-  suspend fun write(chainedBuffer: ChainedByteBuffer) {
+  suspend fun write(chainedBuffer: de.kuschku.libquassel.protocol.io.ChainedByteBuffer) {
     for (buffer in chainedBuffer.buffers()) {
       write(buffer)
     }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/FixedDeflaterOutputStream.kt b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/FixedDeflaterOutputStream.kt
index abdad9f25..1e86f2284 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/FixedDeflaterOutputStream.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/FixedDeflaterOutputStream.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.io
+package de.kuschku.libquassel.protocol.io
 
 import java.io.OutputStream
 import java.util.zip.DeflaterOutputStream
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 ea399d6e8..36377b113 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
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.io
+package de.kuschku.libquassel.protocol.io
 
 import android.util.Log
 import java.io.InputStream
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/StreamChannel.kt b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/StreamChannel.kt
index 28d2697ea..eaec977eb 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/StreamChannel.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/StreamChannel.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.io
+package de.kuschku.libquassel.protocol.io
 
 import de.kuschku.quasseldroid.util.TlsInfo
 import java.io.Flushable
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/WritableWrappedChannel.kt b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/WritableWrappedChannel.kt
index 9e7fe390c..abd9ecc5b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/WritableWrappedChannel.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/protocol/io/WritableWrappedChannel.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.io
+package de.kuschku.libquassel.protocol.io
 
 import java.io.OutputStream
 import java.nio.ByteBuffer
diff --git a/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt b/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt
index f5e8fb03f..d3fe73cb4 100644
--- a/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt
+++ b/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt
@@ -1,10 +1,10 @@
 package de.kuschku.quasseldroid
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.primitive.IntSerializer
-import de.kuschku.quasseldroid.protocol.serializers.primitive.ProtocolInfoSerializer
-import de.kuschku.quasseldroid.protocol.serializers.primitive.UIntSerializer
-import de.kuschku.quasseldroid.protocol.io.CoroutineChannel
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.serializers.primitive.IntSerializer
+import de.kuschku.libquassel.protocol.serializers.primitive.ProtocolInfoSerializer
+import de.kuschku.libquassel.protocol.serializers.primitive.UIntSerializer
+import de.kuschku.libquassel.protocol.io.CoroutineChannel
 import kotlinx.coroutines.runBlocking
 import org.junit.Assert.assertEquals
 import org.junit.Test
@@ -45,7 +45,7 @@ class ExampleUnitTest {
 
     runBlocking {
       val sizeBuffer = ByteBuffer.allocateDirect(4)
-      val sendBuffer = ChainedByteBuffer(direct = true)
+      val sendBuffer = de.kuschku.libquassel.protocol.io.ChainedByteBuffer(direct = true)
       val channel = CoroutineChannel()
       channel.connect(InetSocketAddress("kuschku.de", 4242))
       val readBuffer = ByteBuffer.allocateDirect(4)
diff --git a/bitflags/build.gradle.kts b/bitflags/build.gradle.kts
new file mode 100644
index 000000000..8c7ddc04e
--- /dev/null
+++ b/bitflags/build.gradle.kts
@@ -0,0 +1,9 @@
+plugins {
+  kotlin("jvm")
+}
+
+dependencies {
+  implementation(kotlin("stdlib"))
+
+  testImplementation("junit", "junit", "4.13.1")
+}
diff --git a/bitflags/src/main/java/de/kuschku/bitflags/Flag.kt b/bitflags/src/main/java/de/kuschku/bitflags/Flag.kt
new file mode 100644
index 000000000..1a89c5853
--- /dev/null
+++ b/bitflags/src/main/java/de/kuschku/bitflags/Flag.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.bitflags
+
+interface Flag<T> {
+  val value: T
+}
diff --git a/bitflags/src/main/java/de/kuschku/bitflags/Flags.kt b/bitflags/src/main/java/de/kuschku/bitflags/Flags.kt
new file mode 100644
index 000000000..23fa4e46b
--- /dev/null
+++ b/bitflags/src/main/java/de/kuschku/bitflags/Flags.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.bitflags
+
+interface Flags<T, U : Flag<T>> {
+  operator fun get(value: T): U?
+  fun all(): Collection<U>
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/Flag.kt b/bitflags/src/main/java/de/kuschku/bitflags/toBits.kt
similarity index 60%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/Flag.kt
rename to bitflags/src/main/java/de/kuschku/bitflags/toBits.kt
index f524148d2..fd822c25c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/Flag.kt
+++ b/bitflags/src/main/java/de/kuschku/bitflags/toBits.kt
@@ -17,51 +17,46 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol
+package de.kuschku.bitflags
 
 import kotlin.experimental.or
 
-
-interface Flag<T> {
-  val value: T
-}
-
 @JvmName("toByteFlag")
-fun Set<Flag<Byte>>.toFlag(): Byte = fold(0.toByte()) { acc, el ->
+fun Set<Flag<Byte>>?.toBits(): Byte = this?.fold(0.toByte()) { acc, el ->
   acc or el.value
-}
+} ?: 0.toByte()
 
 @JvmName("toUByteFlag")
-fun Set<Flag<UByte>>.toFlag(): UByte = fold(0.toUByte()) { acc, el ->
+fun Set<Flag<UByte>>?.toBits(): UByte = this?.fold(0.toUByte()) { acc, el ->
   acc or el.value
-}
+} ?: 0.toUByte()
 
 @JvmName("toShortFlag")
-fun Set<Flag<Short>>.toFlag(): Short = fold(0.toShort()) { acc, el ->
+fun Set<Flag<Short>>?.toBits(): Short = this?.fold(0.toShort()) { acc, el ->
   acc or el.value
-}
+} ?: 0.toShort()
 
 @JvmName("toUShortFlag")
-fun Set<Flag<UShort>>.toFlag(): UShort = fold(0.toUShort()) { acc, el ->
+fun Set<Flag<UShort>>?.toBits(): UShort = this?.fold(0.toUShort()) { acc, el ->
   acc or el.value
-}
+} ?: 0.toUShort()
 
 @JvmName("toIntFlag")
-fun Set<Flag<Int>>.toFlag(): Int = fold(0) { acc, el ->
+fun Set<Flag<Int>>?.toBits(): Int = this?.fold(0) { acc, el ->
   acc or el.value
-}
+} ?: 0
 
 @JvmName("toUIntFlag")
-fun Set<Flag<UInt>>.toFlag(): UInt = fold(0.toUInt()) { acc, el ->
+fun Set<Flag<UInt>>?.toBits(): UInt = this?.fold(0.toUInt()) { acc, el ->
   acc or el.value
-}
+} ?: 0u
 
 @JvmName("toLongFlag")
-fun Set<Flag<Long>>.toFlag(): Long = fold(0.toLong()) { acc, el ->
+fun Set<Flag<Long>>?.toBits(): Long = this?.fold(0.toLong()) { acc, el ->
   acc or el.value
-}
+} ?: 0L
 
 @JvmName("toULongFlag")
-fun Set<Flag<ULong>>.toFlag(): ULong = fold(0.toULong()) { acc, el ->
+fun Set<Flag<ULong>>?.toBits(): ULong = this?.fold(0.toULong()) { acc, el ->
   acc or el.value
-}
+} ?: 0uL
diff --git a/bitflags/src/main/java/de/kuschku/bitflags/toEnumSet.kt b/bitflags/src/main/java/de/kuschku/bitflags/toEnumSet.kt
new file mode 100644
index 000000000..eb000188f
--- /dev/null
+++ b/bitflags/src/main/java/de/kuschku/bitflags/toEnumSet.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.bitflags
+
+import java.util.*
+
+inline fun <reified T : Enum<T>> List<T>.toEnumSet(): EnumSet<T> =
+  if (this.isEmpty()) EnumSet.noneOf(T::class.java)
+  else EnumSet.of(this.first(), *this.subList(1, this.size).toTypedArray())
diff --git a/bitflags/src/main/java/de/kuschku/bitflags/toFlag.kt b/bitflags/src/main/java/de/kuschku/bitflags/toFlag.kt
new file mode 100644
index 000000000..12083c14f
--- /dev/null
+++ b/bitflags/src/main/java/de/kuschku/bitflags/toFlag.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.bitflags
+
+import java.util.*
+import kotlin.experimental.and
+
+inline fun <reified T> Flags<Byte, T>.toFlag(value: Byte?): EnumSet<T> where T: Flag<Byte>, T: Enum<T> {
+  if (value == null) return emptyList<T>().toEnumSet()
+  return this.all().filter { (value and it.value) != 0.toByte() }.toEnumSet()
+}
+
+inline fun <reified T> Flags<UByte, T>.toFlag(value: UByte?): EnumSet<T> where T: Flag<UByte>, T: Enum<T> {
+  if (value == null) return emptyList<T>().toEnumSet()
+  return this.all().filter { (value and it.value) != 0.toUByte() }.toEnumSet()
+}
+
+inline fun <reified T> Flags<Short, T>.toFlag(value: Short?): EnumSet<T> where T: Flag<Short>, T: Enum<T> {
+  if (value == null) return emptyList<T>().toEnumSet()
+  return this.all().filter { (value and it.value) != 0.toShort() }.toEnumSet()
+}
+
+inline fun <reified T> Flags<UShort, T>.toFlag(value: UShort?): EnumSet<T> where T: Flag<UShort>, T: Enum<T> {
+  if (value == null) return emptyList<T>().toEnumSet()
+  return this.all().filter { (value and it.value) != 0.toUShort() }.toEnumSet()
+}
+
+inline fun <reified T> Flags<Int, T>.toFlag(value: Int?): EnumSet<T> where T: Flag<Int>, T: Enum<T> {
+  if (value == null) return emptyList<T>().toEnumSet()
+  return this.all().filter { (value and it.value) != 0 }.toEnumSet()
+}
+
+inline fun <reified T> Flags<UInt, T>.toFlag(value: UInt?): EnumSet<T> where T: Flag<UInt>, T: Enum<T> {
+  if (value == null) return emptyList<T>().toEnumSet()
+  return this.all().filter { (value and it.value) != 0u }.toEnumSet()
+}
+
+inline fun <reified T> Flags<Long, T>.toFlag(value: Long?): EnumSet<T> where T: Flag<Long>, T: Enum<T> {
+  if (value == null) return emptyList<T>().toEnumSet()
+  return this.all().filter { (value and it.value) != 0L }.toEnumSet()
+}
+
+inline fun <reified T> Flags<ULong, T>.toFlag(value: ULong?): EnumSet<T> where T: Flag<ULong>, T: Enum<T> {
+  if (value == null) return emptyList<T>().toEnumSet()
+  return this.all().filter { (value and it.value) != 0uL }.toEnumSet()
+}
diff --git a/build.gradle b/build.gradle
index bec9fa1f2..10a970267 100644
--- a/build.gradle
+++ b/build.gradle
@@ -16,3 +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/>.
  */
+
+buildscript {
+    dependencies {
+        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21'
+    }
+}
diff --git a/protocol/build.gradle.kts b/protocol/build.gradle.kts
new file mode 100644
index 000000000..f909252e7
--- /dev/null
+++ b/protocol/build.gradle.kts
@@ -0,0 +1,10 @@
+plugins {
+  kotlin("jvm")
+}
+
+dependencies {
+  implementation(kotlin("stdlib"))
+  api(project(":bitflags"))
+
+  testImplementation("junit", "junit", "4.13.1")
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ProtocolInfo.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/connection/ProtocolInfo.kt
similarity index 94%
rename from app/src/main/java/de/kuschku/quasseldroid/ProtocolInfo.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/connection/ProtocolInfo.kt
index 2cfe00e00..f71e8185e 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ProtocolInfo.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/connection/ProtocolInfo.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid
+package de.kuschku.libquassel.protocol.connection
 
 data class ProtocolInfo(
   val flags: UByte,
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/ExtendedFeature.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/ExtendedFeature.kt
similarity index 94%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/ExtendedFeature.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/features/ExtendedFeature.kt
index 7f5fd5073..f5cd94c1e 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/ExtendedFeature.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/ExtendedFeature.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol
+package de.kuschku.libquassel.protocol.features
 
 inline class ExtendedFeatureName(
   val name: String,
@@ -64,5 +64,5 @@ enum class ExtendedFeature {
   /** CoreInfo dynamically updated using signals */
   SyncedCoreInfo;
 
-  fun name(): ExtendedFeatureName = ExtendedFeatureName(name)
+  fun feature(): ExtendedFeatureName = ExtendedFeatureName(name)
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/LegacyFeature.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/LegacyFeature.kt
similarity index 85%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/LegacyFeature.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/features/LegacyFeature.kt
index 672974f71..362e6b6dd 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/LegacyFeature.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/LegacyFeature.kt
@@ -17,7 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol
+package de.kuschku.libquassel.protocol.features
+
+import de.kuschku.bitflags.Flag
+import de.kuschku.bitflags.Flags
 
 /**
  * A list of features that are optional in core and/or client, but need runtime checking
@@ -55,4 +58,12 @@ enum class LegacyFeature(override val value: UInt): Flag<UInt> {
   RemoteDisconnect(0x4000u),
   /** Transmit features as list of strings */
   ExtendedFeatures(0x8000u);
+
+  companion object : Flags<UInt, LegacyFeature> {
+    private val values = values().associateBy(LegacyFeature::value)
+    override fun get(value: UInt) = values[value]
+    override fun all() = values.values
+  }
 }
+
+typealias LegacyFeatures = Set<LegacyFeature>
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/ChainedByteBuffer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/io/ChainedByteBuffer.kt
similarity index 98%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/io/ChainedByteBuffer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/io/ChainedByteBuffer.kt
index 139b12972..ac9622e7d 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/ChainedByteBuffer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/io/ChainedByteBuffer.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.io
+package de.kuschku.libquassel.protocol.io
 
 import java.nio.ByteBuffer
 import java.util.*
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/StringEncoder.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/io/StringEncoder.kt
similarity index 97%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/io/StringEncoder.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/io/StringEncoder.kt
index 694d2291b..d86c16efa 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/StringEncoder.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/io/StringEncoder.kt
@@ -1,5 +1,5 @@
 /*
- * Quasseldroid 1 Quassel client for Android
+ * Quasseldroid - Quassel client for Android
  *
  * Copyright (c) 2021 Janne Mareike Koschinski
  * Copyright (c) 2021 The Quassel Project
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.io
+package de.kuschku.libquassel.protocol.io
 
 import java.nio.ByteBuffer
 import java.nio.CharBuffer
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/StringEncoders.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/io/StringEncoders.kt
similarity index 96%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/io/StringEncoders.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/io/StringEncoders.kt
index f32172bc8..b6f016609 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/io/StringEncoders.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/io/StringEncoders.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.io
+package de.kuschku.libquassel.protocol.io
 
 import kotlin.concurrent.getOrSet
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/handshake/ClientInit.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInit.kt
similarity index 70%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/handshake/ClientInit.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInit.kt
index 9a271d523..7bc0a07b5 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/handshake/ClientInit.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInit.kt
@@ -17,15 +17,14 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.handshake
+package de.kuschku.libquassel.protocol.messages.handshake
 
-import de.kuschku.quasseldroid.protocol.ExtendedFeature
-import de.kuschku.quasseldroid.protocol.LegacyFeature
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
+import de.kuschku.libquassel.protocol.features.LegacyFeatures
+import de.kuschku.libquassel.protocol.features.ExtendedFeatureName
 
-class ClientInit(
+data class ClientInit(
   val clientVersion: String?,
   val buildDate: String?,
-  val clientFeatures: Set<LegacyFeature>?,
-  val featureList: List<ExtendedFeature>?,
+  val clientFeatures: LegacyFeatures,
+  val featureList: List<ExtendedFeatureName>
 )
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitAck.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitAck.kt
new file mode 100644
index 000000000..cd2e16d44
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitAck.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.features.ExtendedFeatureName
+import de.kuschku.libquassel.protocol.features.LegacyFeatures
+import de.kuschku.libquassel.protocol.variant.QVariantList
+
+data class ClientInitAck(
+        val coreFeatures: LegacyFeatures,
+        val coreConfigured: Boolean?,
+        val backendInfo: QVariantList,
+        val authenticatorInfo: QVariantList,
+        val featureList: List<ExtendedFeatureName>
+)
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
new file mode 100644
index 000000000..66cad259d
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/messages/handshake/ClientInitReject.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 ClientInitReject(
+  val errorString: String?
+)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/NoSerializerForTypeException.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/NoSerializerForTypeException.kt
similarity index 89%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/NoSerializerForTypeException.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/NoSerializerForTypeException.kt
index 0cf1b79f7..015a5391d 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/NoSerializerForTypeException.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/NoSerializerForTypeException.kt
@@ -17,10 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers
+package de.kuschku.libquassel.protocol.serializers
 
-import de.kuschku.quasseldroid.protocol.variant.QtType
-import de.kuschku.quasseldroid.protocol.variant.QuasselType
+import de.kuschku.libquassel.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.variant.QuasselType
 
 class NoSerializerForTypeException(
   private val javaType: Class<*>?,
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
new file mode 100644
index 000000000..76b74d167
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.handshake
+
+import de.kuschku.bitflags.toBits
+import de.kuschku.bitflags.toFlag
+import de.kuschku.libquassel.protocol.features.ExtendedFeatureName
+import de.kuschku.libquassel.protocol.features.LegacyFeature
+import de.kuschku.libquassel.protocol.messages.handshake.ClientInitAck
+import de.kuschku.libquassel.protocol.variant.*
+
+object ClientInitAckSerializer : HandshakeSerializer<ClientInitAck> {
+  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),
+    "Configured" to qVariant(data.coreConfigured, QtType.Bool),
+    "FeatureList" to qVariant(data.featureList, QtType.QStringList)
+  )
+
+  override fun deserialize(data: QVariantMap) = ClientInitAck(
+    coreFeatures = LegacyFeature.toFlag(data["CoreFeatures"].into<UInt>()),
+    backendInfo = data["StorageBackends"].into(emptyList()),
+    authenticatorInfo = data["Authenticators"].into(emptyList()),
+    coreConfigured = data["Configured"].into(),
+    featureList = data["FeatureList"].into<QStringList>(emptyList())
+      .map(::ExtendedFeatureName),
+  )
+}
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
new file mode 100644
index 000000000..c42c2c712
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitRejectSerializer.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.handshake
+
+import de.kuschku.libquassel.protocol.messages.handshake.ClientInitReject
+import de.kuschku.libquassel.protocol.variant.QVariantMap
+import de.kuschku.libquassel.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.variant.into
+import de.kuschku.libquassel.protocol.variant.qVariant
+
+object ClientInitRejectSerializer : HandshakeSerializer<ClientInitReject> {
+  override fun serialize(data: ClientInitReject) = mapOf(
+    "MsgType" to qVariant("ClientInitReject", QtType.QString),
+    "Error" to qVariant(data.errorString, QtType.QString)
+  )
+
+  override fun deserialize(data: QVariantMap) = ClientInitReject(
+    errorString = data["Error"].into()
+  )
+}
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
new file mode 100644
index 000000000..cb44de100
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
@@ -0,0 +1,52 @@
+/*
+ * 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.handshake
+
+import de.kuschku.bitflags.toBits
+import de.kuschku.bitflags.toFlag
+import de.kuschku.libquassel.protocol.features.ExtendedFeatureName
+import de.kuschku.libquassel.protocol.features.LegacyFeature
+import de.kuschku.libquassel.protocol.messages.handshake.ClientInit
+import de.kuschku.libquassel.protocol.variant.QVariantMap
+import de.kuschku.libquassel.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.variant.into
+import de.kuschku.libquassel.protocol.variant.qVariant
+
+object ClientInitSerializer : HandshakeSerializer<ClientInit> {
+  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),
+    "FeatureList" to qVariant(
+      data.featureList.map(ExtendedFeatureName::name),
+      QtType.QStringList
+    ),
+  )
+
+  override fun deserialize(data: QVariantMap): ClientInit {
+    return ClientInit(
+      clientVersion = data["ClientVersion"].into(),
+      buildDate = data["ClientDate"].into(),
+      clientFeatures = LegacyFeature.toFlag(data["Features"].into<UInt>()),
+      featureList = data["FeatureList"].into(emptyList()),
+    )
+  }
+}
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
new file mode 100644
index 000000000..6abb586ee
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/HandshakeSerializer.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.handshake
+
+import de.kuschku.libquassel.protocol.variant.QVariantMap
+
+interface HandshakeSerializer<T> {
+  fun serialize(data: T): QVariantMap
+  fun deserialize(data: QVariantMap): T
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/BoolSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BoolSerializer.kt
similarity index 82%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/BoolSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BoolSerializer.kt
index 30af9a947..c31721a49 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/BoolSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BoolSerializer.kt
@@ -17,11 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object BoolSerializer : QtSerializer<Boolean> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ByteSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ByteSerializer.kt
similarity index 79%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ByteSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ByteSerializer.kt
index 7235b80c2..7866c1bb1 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ByteSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ByteSerializer.kt
@@ -17,11 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object ByteSerializer : QtSerializer<Byte> {
@@ -29,7 +28,7 @@ object ByteSerializer : QtSerializer<Byte> {
   override val javaType: Class<Byte> = Byte::class.java
 
   override fun serialize(buffer: ChainedByteBuffer, data: Byte) {
-    buffer.put(data ?: 0)
+    buffer.put(data)
   }
 
   override fun deserialize(buffer: ByteBuffer): Byte {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/IntSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IntSerializer.kt
similarity index 79%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/IntSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IntSerializer.kt
index 996200595..2327a2ffa 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/IntSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IntSerializer.kt
@@ -17,11 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object IntSerializer : QtSerializer<Int> {
@@ -29,7 +28,7 @@ object IntSerializer : QtSerializer<Int> {
   override val javaType: Class<Int> = Int::class.java
 
   override fun serialize(buffer: ChainedByteBuffer, data: Int) {
-    buffer.putInt(data ?: 0)
+    buffer.putInt(data)
   }
 
   override fun deserialize(buffer: ByteBuffer): Int {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/LongSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/LongSerializer.kt
similarity index 79%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/LongSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/LongSerializer.kt
index 31f095031..58b441cae 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/LongSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/LongSerializer.kt
@@ -17,11 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object LongSerializer : QtSerializer<Long> {
@@ -29,7 +28,7 @@ object LongSerializer : QtSerializer<Long> {
   override val javaType: Class<Long> = Long::class.java
 
   override fun serialize(buffer: ChainedByteBuffer, data: Long) {
-    buffer.putLong(data?: 0)
+    buffer.putLong(data)
   }
 
   override fun deserialize(buffer: ByteBuffer): Long {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ProtocolInfoSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ProtocolInfoSerializer.kt
similarity index 83%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ProtocolInfoSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ProtocolInfoSerializer.kt
index 60fe5d2c2..228d917d4 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ProtocolInfoSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ProtocolInfoSerializer.kt
@@ -17,12 +17,11 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.ProtocolInfo
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.connection.ProtocolInfo
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object ProtocolInfoSerializer : QtSerializer<ProtocolInfo> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/VariantMapSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantMapSerializer.kt
similarity index 73%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/VariantMapSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantMapSerializer.kt
index 74cc2382b..dc9480e29 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/VariantMapSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantMapSerializer.kt
@@ -17,16 +17,15 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QVariantMap
-import de.kuschku.quasseldroid.protocol.variant.QVariant_
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QVariantMap
+import de.kuschku.libquassel.protocol.variant.QVariant_
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
-object VariantMapSerializer : QtSerializer<QVariantMap> {
+object QVariantMapSerializer : QtSerializer<QVariantMap> {
   override val qtType = QtType.QVariantMap
   @Suppress("UNCHECKED_CAST")
   override val javaType: Class<out QVariantMap> = Map::class.java as Class<QVariantMap>
@@ -35,7 +34,7 @@ object VariantMapSerializer : QtSerializer<QVariantMap> {
     IntSerializer.serialize(buffer, data.size)
     data.entries.forEach { (key, value) ->
       StringSerializerUtf16.serialize(buffer, key)
-      VariantSerializer.serialize(buffer, value)
+      QVariantSerializer.serialize(buffer, value)
     }
   }
 
@@ -43,7 +42,7 @@ object VariantMapSerializer : QtSerializer<QVariantMap> {
     val result = mutableMapOf<String, QVariant_>()
     val length = IntSerializer.deserialize(buffer)
     for (i in 0 until length) {
-      result[StringSerializerUtf16.deserialize(buffer) ?: ""] = VariantSerializer.deserialize(buffer)
+      result[StringSerializerUtf16.deserialize(buffer) ?: ""] = QVariantSerializer.deserialize(buffer)
     }
     return result
   }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/VariantSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializer.kt
similarity index 84%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/VariantSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializer.kt
index 7c4f18414..4481125d9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/VariantSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QVariantSerializer.kt
@@ -17,17 +17,17 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.*
-import de.kuschku.quasseldroid.protocol.variant.QVariant
-import de.kuschku.quasseldroid.protocol.variant.QVariant_
-import de.kuschku.quasseldroid.protocol.variant.QtType
-import de.kuschku.quasseldroid.protocol.variant.QuasselType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.serializers.*
+import de.kuschku.libquassel.protocol.variant.QVariant
+import de.kuschku.libquassel.protocol.variant.QVariant_
+import de.kuschku.libquassel.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.variant.QuasselType
 import java.nio.ByteBuffer
 
-object VariantSerializer : QtSerializer<QVariant_> {
+object QVariantSerializer : QtSerializer<QVariant_> {
   override val qtType = QtType.QVariant
   override val javaType: Class<QVariant_> = QVariant::class.java
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/QtSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QtSerializer.kt
similarity index 84%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/QtSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QtSerializer.kt
index 1066584e2..89854b79d 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/QtSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QtSerializer.kt
@@ -17,10 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 interface QtSerializer<T> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/QuasselSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QuasselSerializer.kt
similarity index 83%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/QuasselSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QuasselSerializer.kt
index 651497420..a2530f4a9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/QuasselSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/QuasselSerializer.kt
@@ -17,10 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.variant.QtType
-import de.kuschku.quasseldroid.protocol.variant.QuasselType
+import de.kuschku.libquassel.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.variant.QuasselType
 
 interface QuasselSerializer<T> : QtSerializer<T> {
   override val qtType: QtType get() = quasselType.qtType
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/Serializers.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt
similarity index 84%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/Serializers.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt
index db203e6b3..b3e4a711f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/Serializers.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt
@@ -17,27 +17,28 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.serializers.primitive.*
-import de.kuschku.quasseldroid.protocol.variant.QtType
-import de.kuschku.quasseldroid.protocol.variant.QuasselType
+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 = listOf<QtSerializer<*>>(
     BoolSerializer,
+    UByteSerializer,
     ByteSerializer,
-    IntSerializer,
-    LongSerializer,
     ShortSerializer,
-    UByteSerializer,
+    UShortSerializer,
+    IntSerializer,
     UIntSerializer,
+    LongSerializer,
     ULongSerializer,
-    UShortSerializer,
     StringSerializerUtf16,
-    VariantSerializer,
-    VariantMapSerializer,
+    QVariantSerializer,
+    QVariantMapSerializer,
   ).associateBy(QtSerializer<*>::qtType)
 
   private val quasselSerializers = listOf<QuasselSerializer<*>>(
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ShortSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ShortSerializer.kt
similarity index 81%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ShortSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ShortSerializer.kt
index aeb0e5dd5..e429280eb 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ShortSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ShortSerializer.kt
@@ -17,11 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object ShortSerializer : QtSerializer<Short> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/StringSerializerAscii.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerAscii.kt
similarity index 82%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/StringSerializerAscii.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerAscii.kt
index 3f2d326d0..2c5933c53 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/StringSerializerAscii.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerAscii.kt
@@ -17,12 +17,11 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.io.stringEncoderAscii
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+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 : QtSerializer<String?> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/StringSerializerUtf16.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerUtf16.kt
similarity index 82%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/StringSerializerUtf16.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerUtf16.kt
index 5f11ccafc..add6cbf8c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/StringSerializerUtf16.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerUtf16.kt
@@ -17,12 +17,11 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.io.stringEncoderUtf16
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.io.stringEncoderUtf16
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object StringSerializerUtf16 : QtSerializer<String?> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/StringSerializerUtf8.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerUtf8.kt
similarity index 82%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/StringSerializerUtf8.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerUtf8.kt
index c400b6dc8..6324179fe 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/StringSerializerUtf8.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/StringSerializerUtf8.kt
@@ -17,12 +17,11 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.io.stringEncoderUtf8
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.io.stringEncoderUtf8
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object StringSerializerUtf8 : QtSerializer<String?> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/UByteSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/UByteSerializer.kt
similarity index 81%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/UByteSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/UByteSerializer.kt
index 221a4b528..fb5af5e06 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/UByteSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/UByteSerializer.kt
@@ -17,11 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object UByteSerializer : QtSerializer<UByte> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/UIntSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/UIntSerializer.kt
similarity index 81%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/UIntSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/UIntSerializer.kt
index c416039a9..35bdb1afe 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/UIntSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/UIntSerializer.kt
@@ -17,11 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object UIntSerializer : QtSerializer<UInt> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ULongSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ULongSerializer.kt
similarity index 82%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ULongSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ULongSerializer.kt
index 1bf483839..ffea3f6ea 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/ULongSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/ULongSerializer.kt
@@ -17,11 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object ULongSerializer : QtSerializer<ULong> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/UShortSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/UShortSerializer.kt
similarity index 82%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/UShortSerializer.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/UShortSerializer.kt
index 330da157b..50b956415 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/serializers/primitive/UShortSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/UShortSerializer.kt
@@ -17,11 +17,10 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.serializers.primitive
+package de.kuschku.libquassel.protocol.serializers.primitive
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
 import java.nio.ByteBuffer
 
 object UShortSerializer : QtSerializer<UShort> {
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/variant/QVariant.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QVariant.kt
similarity index 74%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/variant/QVariant.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QVariant.kt
index 77f58ce59..b83839b90 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/variant/QVariant.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QVariant.kt
@@ -17,20 +17,20 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.variant
+package de.kuschku.libquassel.protocol.variant
 
-import de.kuschku.quasseldroid.protocol.io.ChainedByteBuffer
-import de.kuschku.quasseldroid.protocol.serializers.QtSerializer
-import de.kuschku.quasseldroid.protocol.serializers.QuasselSerializer
-import de.kuschku.quasseldroid.protocol.serializers.primitive.IntSerializer
-import de.kuschku.quasseldroid.protocol.serializers.serializerFor
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.serializers.primitive.QtSerializer
+import de.kuschku.libquassel.protocol.serializers.primitive.QuasselSerializer
+import de.kuschku.libquassel.protocol.serializers.primitive.serializerFor
 
 typealias QVariant_ = QVariant<*>
 typealias QVariantList = List<QVariant_>
 typealias QVariantMap = Map<String, QVariant_>
+typealias QStringList = List<String>
 
 sealed class QVariant<T> constructor(
-  val data: T,
+  internal val data: T,
   open val serializer: QtSerializer<T>,
 ) {
   class Typed<T> internal constructor(data: T, serializer: QtSerializer<T>) :
@@ -73,27 +73,32 @@ sealed class QVariant<T> constructor(
     }
   }
 
+  fun value(): T = data
+
   fun serialize(buffer: ChainedByteBuffer) {
     serializer.serialize(buffer, data)
   }
 
-  fun or(defValue: T): T {
-    return data ?: defValue
-  }
-
   companion object {
     fun <T> of(data: T, serializer: QtSerializer<T>) = Typed(data, serializer)
     fun <T> of(data: T, serializer: QuasselSerializer<T>) = Custom(data, serializer)
   }
 }
 
-inline fun <reified T> of(data: T, type: QtType): QVariant<T> =
+inline fun <reified T> qVariant(data: T, type: QtType): QVariant<T> =
   QVariant.of(data, serializerFor(type))
 
-inline fun <reified T> of(data: T, type: QuasselType): QVariant<T> =
+inline fun <reified T> qVariant(data: T, type: QuasselType): QVariant<T> =
   QVariant.of(data, serializerFor(type))
 
 @Suppress("UNCHECKED_CAST")
-inline fun <reified T> QVariant_.into(): QVariant<T>? =
-  if (this.serializer.javaType == T::class.java) this as QVariant<T>
+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
+
+inline fun <reified T> QVariant_?.into(): T? =
+  this?.withType<T>()?.value()
+
+inline fun <reified T> QVariant_?.into(defValue: T): T =
+  this?.withType<T>()?.value() ?: defValue
+
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/variant/QtType.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QtType.kt
similarity index 98%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/variant/QtType.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QtType.kt
index f80dc2ca8..3f9ef4037 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/variant/QtType.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QtType.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.variant
+package de.kuschku.libquassel.protocol.variant
 
 import java.util.*
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/protocol/variant/QuasselType.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QuasselType.kt
similarity index 96%
rename from app/src/main/java/de/kuschku/quasseldroid/protocol/variant/QuasselType.kt
rename to protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QuasselType.kt
index e38ab4ece..77e581685 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/protocol/variant/QuasselType.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/variant/QuasselType.kt
@@ -17,7 +17,7 @@
  * with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.quasseldroid.protocol.variant
+package de.kuschku.libquassel.protocol.variant
 
 enum class QuasselType(
   val typeName: String,
diff --git a/settings.gradle.kts b/settings.gradle.kts
index ef0ce5d14..e4af358e3 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -21,5 +21,7 @@ rootProject.name = "Quasseldroid"
 rootProject.buildFileName = "build.gradle.kts"
 
 include(
-  ":app"
+  ":app",
+  ":bitflags",
+  ":protocol"
 )
-- 
GitLab