diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 0277ac3b2d29c4592ce93d51fb61218218455d92..e719474e393ae5d21373c1e56e53ec40e2e35751 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 156c6ec4ae04ba051270c4f8bd07d2401c71dcfc..28d09482aff50e213beec4fbfe08901464d9e485 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 abdad9f25eddc40e639b1e0d094cf674f544cf4f..1e86f228408aca6b315bb1bb9fefccaa7ecb52e8 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 ea399d6e80fe15194cac9d9ba81413d704a029ac..36377b1134846e62abf20ec16a802410d7df9fb9 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 28d2697ea1cd7ceca71eebc54f9fda25e72afb5e..eaec977eb441427f8e16803a53140135860750f0 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 9e7fe390c9bb90ee60208b41443f3b77af0b30a4..abd9ecc5bd8d62327bc25190f3a41765a03ef29d 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 f5e8fb03f154c988a4c7648469d8209c3cfcca3c..d3fe73cb4a1ad26af687a6b92fe263562a7bcfd3 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 0000000000000000000000000000000000000000..8c7ddc04eea5321401c7cf583111db6c056f0bf9
--- /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 0000000000000000000000000000000000000000..1a89c5853ef0df1f59aa73cf01f41c63652f3264
--- /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 0000000000000000000000000000000000000000..23fa4e46bd79597996dee4a4ce46d073e7db0b1d
--- /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 f524148d2ad80245fe0ae033b125d37a96d0f86f..fd822c25c9a83861f5c29c96beb2f2b7fc40ed47 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 0000000000000000000000000000000000000000..eb000188f23372a6e1019a931c316060e4bfb0e3
--- /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 0000000000000000000000000000000000000000..12083c14f8f1c8801a46a6c3bdd8654ea64d365f
--- /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 bec9fa1f21c00e11a2d01b5cda2ee3cf60cd5c95..10a970267b6805d50442f0ec5621dc8f5019e98b 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 0000000000000000000000000000000000000000..f909252e7f26ac8ab91060b1293b38140366b9bb
--- /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 2cfe00e000f65d07a859194c736fd5c98f17d460..f71e8185e7249205bebe212f6b7e501277d16258 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 7f5fd50730abc37cb9bd3a707a30b0232674d965..f5cd94c1ea83a293b2fac96665655a539d037276 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 672974f719c9e13f3fd1e1a7d1d8207867c27187..362e6b6dd3e46c457f497ebd15d84941b7832d1a 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 139b1297243b15f6036af106557dfa72aad594c1..ac9622e7d11601c05cdab05ad84166009244e3a2 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 694d2291b2e9b38104292f60be6d489cfecb6da4..d86c16efa05d36b2b659f61792da6ffb084152a6 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 f32172bc8b410f8527719e6751244c29baa0e166..b6f016609629e2b9a2f99e7c7ddd0cb292ac2ff2 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 9a271d523900b1ab1072cc3b1c90debc76b37cbb..7bc0a07b558bbfbfbdc6b8b32e4c39e18c7f15db 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 0000000000000000000000000000000000000000..cd2e16d444d7996de05061dca866f77e67b91998
--- /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 0000000000000000000000000000000000000000..66cad259d5cb74a45880aff899ee66326aa49e43
--- /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 0cf1b79f732f306aab857b16a0106c6bae97aa04..015a5391de4a8a3a33ab0a8acbab0892f61ccf1c 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 0000000000000000000000000000000000000000..76b74d167ace1d8a1dc6eb9d99cdd5a25e8f9166
--- /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 0000000000000000000000000000000000000000..c42c2c7128376c86beea164950c06b3ba6739f8a
--- /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 0000000000000000000000000000000000000000..cb44de100afc62e6e88876cf7de2cb4ff2f46c16
--- /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 0000000000000000000000000000000000000000..6abb586ee0ab4800a454eab69b3c5e040fb2662e
--- /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 30af9a947325b4630803e2ae2dad86bc840d39d2..c31721a499c2cf501010822d2e014ab7df6b4f19 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 7235b80c2d927b25e80c6a955fa99fcff97375b0..7866c1bb1fc9d90b983c40bb200d182343a2c844 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 9962005954a98e7beb77a122fe500d61f1822bef..2327a2ffae103ed7d683217f72d5d13f478e22e6 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 31f09503163b0c0cd682ceb41220092a79febbaf..58b441caeb9975ef2a39d58388ccb6400bc7d57e 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 60fe5d2c28a9edf441d24aaddddaecced2fb0835..228d917d4160f231b4e085a6cf1832d4fe3147b3 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 74cc2382bac3877ddb6c27f99fc99807249f35d3..dc9480e294f8dfb18138bc4603ea1dc01fa6dee4 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 7c4f1841457930497e53991cb38f8938323b1908..4481125d9f28e70b835f8b5afddc75b569e42c3e 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 1066584e25a8482991193996d2f05fde8bdde787..89854b79d26a41349572fd79e38eda9dcccb28f3 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 651497420a862f00835262267b6800a046ae0cb3..a2530f4a99fb646f400e1ce672d1c6a11176f493 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 db203e6b367c1741f8de2f061aa8d189bc60be45..b3e4a711fef08b8ccfd3b8f42727872a6d7bda2f 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 aeb0e5dd52663cf5a70d8729486f9aad43584405..e429280eb9d5dd7d12a231b1c265f10d1a71cb6a 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 3f2d326d051869afbd4a6829038f3723544a19d0..2c5933c5321074c92225d0b26aeabda55f295ee9 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 5f11ccafc1e82d3af6af9878121ba0a81f0753ad..add6cbf8c5fab4098287a3fe45f08c704bd06138 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 c400b6dc8a61c22239dd0bf66fce197a0f875ae8..6324179fe79aca4d196ac7a507ea697ad9b798cb 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 221a4b528ad56743a893d2671bcc3cea7c1c966f..fb5af5e06467ebf7fd929a0d34926b75b1ba8e01 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 c416039a94270615d1a33928bf17c0e447fd0add..35bdb1afec3b783df0e9a730651ff241bd45e3f0 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 1bf483839d03997bade315ee4272dc10e0e75db7..ffea3f6ea8dbb449b3b26e8845f816929a8677d5 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 330da157bf16ef6798694fa40a5fb0553d64204b..50b9564153a53db00d4535ccd714be90e779827b 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 77f58ce592834a1daaf0b8fc7a12634dbed8f31c..b83839b90b6ef8c13415548f5c1d1f1871425157 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 f80dc2ca8c61e86d1e9f1c6d449708261bef5866..3f9ef4037f5a0ab6366ef217046e3457915d0877 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 e38ab4ecec2223c4f46f1cadc85022ce248c04a9..77e58168518ce292090a446881903565a0f46f8c 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 ef0ce5d149e88a7acfca3b415198efa5a4f8a1e7..e4af358e37b2cdd5b9e063004b4a2453b5885d62 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"
 )