From 00aa4fb38d2b461b0744ebeba40a72cb41fea454 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Sat, 6 Feb 2021 19:01:51 +0100
Subject: [PATCH] Implement more (de-)serializers

---
 .../kuschku/quasseldroid/ExampleUnitTest.kt   | 12 +--
 .../main/java/de/kuschku/bitflags/Flags.kt    | 22 ++++-
 .../main/java/de/kuschku/bitflags/toFlag.kt   | 16 ++--
 protocol/build.gradle.kts                     |  1 +
 .../protocol/features/FeatureSet.kt           |  6 +-
 .../handshake/ClientInitAckSerializer.kt      |  4 +-
 .../handshake/ClientInitSerializer.kt         |  4 +-
 .../primitive/BufferIdSerializer.kt           | 40 +++++++++
 .../primitive/BufferInfoSerializer.kt         | 57 +++++++++++++
 .../serializers/primitive/DateSerializer.kt   | 43 ++++++++++
 .../primitive/DateTimeSerializer.kt           | 81 +++++++++++++++++++
 .../primitive/IdentityIdSerializer.kt         | 41 ++++++++++
 .../primitive/MessageSerializer.kt            | 81 +++++++++++++++++++
 .../serializers/primitive/MsgIdSerializer.kt  | 49 +++++++++++
 .../primitive/NetworkIdSerializer.kt          | 42 ++++++++++
 .../primitive/PeerPtrSerializer.kt            | 39 +++++++++
 .../serializers/primitive/Serializers.kt      | 48 ++++++++---
 .../serializers/primitive/TimeSerializer.kt   | 41 ++++++++++
 .../serializers/primitive/VoidSerializer.kt   | 33 ++++++++
 .../protocol/types/BufferActivity.kt          | 40 +++++++++
 .../libquassel/protocol/types/BufferInfo.kt   | 30 +++++++
 .../libquassel/protocol/types/BufferType.kt   | 41 ++++++++++
 .../libquassel/protocol/types/Message.kt      | 39 +++++++++
 .../libquassel/protocol/types/MessageFlag.kt  | 41 ++++++++++
 .../libquassel/protocol/types/MessageType.kt  | 55 +++++++++++++
 .../libquassel/protocol/types/SignedId.kt     |  4 -
 .../libquassel/protocol/types/TimeSpec.kt     | 33 ++++++++
 .../handshake/ClientInitSerializerTest.kt     |  1 -
 28 files changed, 904 insertions(+), 40 deletions(-)
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BufferIdSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BufferInfoSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateTimeSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IdentityIdSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/MessageSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/MsgIdSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/NetworkIdSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/PeerPtrSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/TimeSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/VoidSerializer.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferActivity.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferInfo.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferType.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/types/Message.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/types/MessageFlag.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/types/MessageType.kt
 create mode 100644 protocol/src/main/java/de/kuschku/libquassel/protocol/types/TimeSpec.kt

diff --git a/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt b/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt
index 9663335fd..16bd7c90f 100644
--- a/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt
+++ b/app/src/test/java/de/kuschku/quasseldroid/ExampleUnitTest.kt
@@ -1,10 +1,11 @@
 package de.kuschku.quasseldroid
 
-import de.kuschku.bitflags.flags
+import de.kuschku.bitflags.of
 import de.kuschku.libquassel.protocol.connection.ProtocolInfoSerializer
 import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.features.LegacyFeature
+import de.kuschku.libquassel.protocol.features.QuasselFeature
 import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
-import de.kuschku.libquassel.protocol.io.print
 import de.kuschku.libquassel.protocol.messages.handshake.ClientInit
 import de.kuschku.libquassel.protocol.serializers.handshake.ClientInitAckSerializer
 import de.kuschku.libquassel.protocol.serializers.handshake.ClientInitRejectSerializer
@@ -15,7 +16,6 @@ import de.kuschku.libquassel.protocol.serializers.primitive.UIntSerializer
 import de.kuschku.libquassel.protocol.variant.into
 import de.kuschku.quasseldroid.protocol.io.CoroutineChannel
 import kotlinx.coroutines.runBlocking
-import org.junit.Assert.assertEquals
 import org.junit.Test
 import java.net.InetSocketAddress
 import java.nio.ByteBuffer
@@ -44,7 +44,7 @@ class ExampleUnitTest {
     }), null)
 
     runBlocking {
-      val connectionFeatureSet = FeatureSet.build()
+      val connectionFeatureSet = FeatureSet.all()
       val sizeBuffer = ByteBuffer.allocateDirect(4)
       val sendBuffer = ChainedByteBuffer(direct = true)
       val channel = CoroutineChannel()
@@ -105,8 +105,8 @@ class ExampleUnitTest {
           ClientInitSerializer.serialize(ClientInit(
             clientVersion = "Quasseldroid test",
             buildDate = "Never",
-            clientFeatures = flags(),
-            featureList = emptyList()
+            clientFeatures = connectionFeatureSet.legacyFeatures(),
+            featureList = connectionFeatureSet.featureList()
           )),
           connectionFeatureSet
         )
diff --git a/bitflags/src/main/java/de/kuschku/bitflags/Flags.kt b/bitflags/src/main/java/de/kuschku/bitflags/Flags.kt
index a06610add..e29c2b7cf 100644
--- a/bitflags/src/main/java/de/kuschku/bitflags/Flags.kt
+++ b/bitflags/src/main/java/de/kuschku/bitflags/Flags.kt
@@ -19,10 +19,26 @@
 
 package de.kuschku.bitflags
 
-interface Flags<T, U : Flag<T>> {
+import java.util.*
+
+interface Flags<T, U> where U: Flag<T>, U: Enum<U> {
   operator fun get(value: T): U?
   fun all(): Collection<U>
 }
 
-inline fun <reified T> flags(vararg values: T) where T : Flag<*>, T : Enum<T> = setOf(*values)
-inline fun <reified T> flags(values: Collection<T>) where T : Flag<*>, T : Enum<T> = values.toSet()
+inline fun <reified T> Flags<*, T>.of(
+  vararg values: T
+) where T: Flag<*>, T: Enum<T> = values.toEnumSet()
+inline fun <reified T> Flags<*, T>.of(
+  values: Collection<T>
+) where T: Flag<*>, T: Enum<T> = values.toEnumSet()
+
+inline fun <reified T: Enum<T>> Array<out T>.toEnumSet() =
+  EnumSet.noneOf(T::class.java).apply {
+    addAll(this@toEnumSet)
+  }
+
+inline fun <reified T: Enum<T>> Collection<T>.toEnumSet() =
+  EnumSet.noneOf(T::class.java).apply {
+    addAll(this@toEnumSet)
+  }
diff --git a/bitflags/src/main/java/de/kuschku/bitflags/toFlag.kt b/bitflags/src/main/java/de/kuschku/bitflags/toFlag.kt
index 12083c14f..8018a4444 100644
--- a/bitflags/src/main/java/de/kuschku/bitflags/toFlag.kt
+++ b/bitflags/src/main/java/de/kuschku/bitflags/toFlag.kt
@@ -22,42 +22,42 @@ 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> {
+inline fun <reified T> Flags<Byte, T>.of(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> {
+inline fun <reified T> Flags<UByte, T>.of(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> {
+inline fun <reified T> Flags<Short, T>.of(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> {
+inline fun <reified T> Flags<UShort, T>.of(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> {
+inline fun <reified T> Flags<Int, T>.of(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> {
+inline fun <reified T> Flags<UInt, T>.of(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> {
+inline fun <reified T> Flags<Long, T>.of(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> {
+inline fun <reified T> Flags<ULong, T>.of(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/protocol/build.gradle.kts b/protocol/build.gradle.kts
index f909252e7..2bfaa2a2f 100644
--- a/protocol/build.gradle.kts
+++ b/protocol/build.gradle.kts
@@ -4,6 +4,7 @@ plugins {
 
 dependencies {
   implementation(kotlin("stdlib"))
+  implementation("org.threeten", "threetenbp", "1.4.0")
   api(project(":bitflags"))
 
   testImplementation("junit", "junit", "4.13.1")
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/features/FeatureSet.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/FeatureSet.kt
index 9ea9379f5..3173028f8 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/features/FeatureSet.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/features/FeatureSet.kt
@@ -19,19 +19,19 @@
 
 package de.kuschku.libquassel.protocol.features
 
-import de.kuschku.bitflags.flags
+import de.kuschku.bitflags.of
 
 class FeatureSet internal constructor(
   private val features: Set<QuasselFeature>,
   private val additional: Set<QuasselFeatureName> = emptySet()
 ) {
-  fun enabled(feature: QuasselFeature) = features.contains(feature)
+  fun hasFeature(feature: QuasselFeature) = features.contains(feature)
 
   fun featureList(): List<QuasselFeatureName> =
     features.map(QuasselFeature::feature) + additional
 
   fun legacyFeatures(): LegacyFeatures =
-    flags(features.mapNotNull(LegacyFeature.Companion::get))
+    LegacyFeature.of(features.mapNotNull(LegacyFeature.Companion::get))
 
   companion object {
     fun parse(
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
index b9754ccff..80dc55499 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitAckSerializer.kt
@@ -20,7 +20,7 @@
 package de.kuschku.libquassel.protocol.serializers.handshake
 
 import de.kuschku.bitflags.toBits
-import de.kuschku.bitflags.toFlag
+import de.kuschku.bitflags.of
 import de.kuschku.libquassel.protocol.features.QuasselFeatureName
 import de.kuschku.libquassel.protocol.features.LegacyFeature
 import de.kuschku.libquassel.protocol.messages.handshake.ClientInitAck
@@ -37,7 +37,7 @@ object ClientInitAckSerializer : HandshakeSerializer<ClientInitAck> {
   )
 
   override fun deserialize(data: QVariantMap) = ClientInitAck(
-    coreFeatures = LegacyFeature.toFlag(data["CoreFeatures"].into<UInt>()),
+    coreFeatures = LegacyFeature.of(data["CoreFeatures"].into<UInt>()),
     backendInfo = data["StorageBackends"].into(emptyList()),
     authenticatorInfo = data["Authenticators"].into(emptyList()),
     coreConfigured = data["Configured"].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
index 91488db6f..3b3de6a12 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializer.kt
@@ -20,7 +20,7 @@
 package de.kuschku.libquassel.protocol.serializers.handshake
 
 import de.kuschku.bitflags.toBits
-import de.kuschku.bitflags.toFlag
+import de.kuschku.bitflags.of
 import de.kuschku.libquassel.protocol.features.QuasselFeatureName
 import de.kuschku.libquassel.protocol.features.LegacyFeature
 import de.kuschku.libquassel.protocol.messages.handshake.ClientInit
@@ -45,7 +45,7 @@ object ClientInitSerializer : HandshakeSerializer<ClientInit> {
     return ClientInit(
       clientVersion = data["ClientVersion"].into(),
       buildDate = data["ClientDate"].into(),
-      clientFeatures = LegacyFeature.toFlag(data["Features"].into<UInt>()),
+      clientFeatures = LegacyFeature.of(data["Features"].into<UInt>()),
       featureList = data["FeatureList"].into(emptyList<String>()).map(::QuasselFeatureName),
     )
   }
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BufferIdSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BufferIdSerializer.kt
new file mode 100644
index 000000000..23791d212
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BufferIdSerializer.kt
@@ -0,0 +1,40 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2021 Janne Mareike Koschinski
+ * Copyright (c) 2021 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.types.BufferId
+import de.kuschku.libquassel.protocol.variant.QuasselType
+import java.nio.ByteBuffer
+
+object BufferIdSerializer : QuasselSerializer<BufferId> {
+  override val quasselType: QuasselType = QuasselType.BufferId
+  override val javaType: Class<out BufferId> = BufferId::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: BufferId, featureSet: FeatureSet) {
+    IntSerializer.serialize(buffer, data.id, featureSet)
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): BufferId {
+    return BufferId(IntSerializer.deserialize(buffer, featureSet))
+  }
+
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BufferInfoSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BufferInfoSerializer.kt
new file mode 100644
index 000000000..062096780
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/BufferInfoSerializer.kt
@@ -0,0 +1,57 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2020 Janne Mareike Koschinski
+ * Copyright (c) 2020 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.bitflags.of
+import de.kuschku.bitflags.toBits
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.types.BufferInfo
+import de.kuschku.libquassel.protocol.types.BufferType
+import de.kuschku.libquassel.protocol.variant.QuasselType
+import java.nio.ByteBuffer
+
+object BufferInfoSerializer : QuasselSerializer<BufferInfo> {
+  override val quasselType: QuasselType = QuasselType.BufferInfo
+  override val javaType: Class<out BufferInfo> = BufferInfo::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: BufferInfo, featureSet: FeatureSet) {
+    BufferIdSerializer.serialize(buffer, data.bufferId, featureSet)
+    NetworkIdSerializer.serialize(buffer, data.networkId, featureSet)
+    UShortSerializer.serialize(buffer, data.type.toBits(), featureSet)
+    IntSerializer.serialize(buffer, data.groupId, featureSet)
+    StringSerializerUtf8.serialize(buffer, data.bufferName, featureSet)
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): BufferInfo {
+    val bufferId = BufferIdSerializer.deserialize(buffer, featureSet)
+    val networkId = NetworkIdSerializer.deserialize(buffer, featureSet)
+    val type = BufferType.of(UShortSerializer.deserialize(buffer, featureSet))
+    val groupId = IntSerializer.deserialize(buffer, featureSet)
+    val bufferName = StringSerializerUtf8.deserialize(buffer, featureSet)
+    return BufferInfo(
+      bufferId = bufferId,
+      networkId = networkId,
+      type = type,
+      groupId = groupId,
+      bufferName = bufferName
+    )
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateSerializer.kt
new file mode 100644
index 000000000..da03cc8e8
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateSerializer.kt
@@ -0,0 +1,43 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2020 Janne Mareike Koschinski
+ * Copyright (c) 2020 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
+import org.threeten.bp.LocalDate
+import org.threeten.bp.LocalTime
+import org.threeten.bp.temporal.JulianFields
+import java.nio.ByteBuffer
+
+object DateSerializer : QtSerializer<LocalDate> {
+  override val qtType: QtType = QtType.QDate
+  override val javaType: Class<out LocalDate> = LocalDate::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: LocalDate, featureSet: FeatureSet) {
+    val julianDay = data.getLong(JulianFields.JULIAN_DAY).toInt()
+    IntSerializer.serialize(buffer, julianDay, featureSet)
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): LocalDate {
+    val julianDay = IntSerializer.deserialize(buffer, featureSet).toLong()
+    return LocalDate.ofEpochDay(0).with(JulianFields.JULIAN_DAY, julianDay)
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateTimeSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateTimeSerializer.kt
new file mode 100644
index 000000000..450b01061
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/DateTimeSerializer.kt
@@ -0,0 +1,81 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2020 Janne Mareike Koschinski
+ * Copyright (c) 2020 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.types.TimeSpec
+import de.kuschku.libquassel.protocol.variant.QtType
+import org.threeten.bp.*
+import org.threeten.bp.temporal.Temporal
+import java.nio.ByteBuffer
+
+object DateTimeSerializer : QtSerializer<Temporal> {
+  override val qtType: QtType = QtType.QDateTime
+  override val javaType: Class<out Temporal> = Temporal::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: Temporal, featureSet: FeatureSet) {
+    fun serialize(data: LocalDateTime, timeSpec: TimeSpec, offset: ZoneOffset? = null) {
+      DateSerializer.serialize(buffer, data.toLocalDate(), featureSet)
+      TimeSerializer.serialize(buffer, data.toLocalTime(), featureSet)
+      ByteSerializer.serialize(buffer, timeSpec.value, featureSet)
+      if (offset != null) {
+        IntSerializer.serialize(buffer, offset.totalSeconds, featureSet)
+      }
+    }
+
+    when (data) {
+      is LocalDateTime ->
+        serialize(data, TimeSpec.LocalUnknown)
+      is OffsetDateTime ->
+        serialize(data.toLocalDateTime(), TimeSpec.OffsetFromUTC, data.offset)
+      is ZonedDateTime ->
+        serialize(data.toLocalDateTime(), TimeSpec.OffsetFromUTC, data.offset)
+      is Instant ->
+        serialize(data.atOffset(ZoneOffset.UTC).toLocalDateTime(), TimeSpec.OffsetFromUTC)
+      else ->
+        throw IllegalArgumentException("Unsupported Format: ${data::class.java.canonicalName}")
+    }
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): Temporal {
+    val julianDay = DateSerializer.deserialize(buffer, featureSet)
+    val localTime = TimeSerializer.deserialize(buffer, featureSet)
+    val localDateTime = LocalDateTime.of(julianDay, localTime)
+    val timeSpec = TimeSpec.of(ByteSerializer.deserialize(buffer, featureSet))
+      ?: TimeSpec.LocalUnknown
+    return when (timeSpec) {
+      TimeSpec.LocalStandard,
+      TimeSpec.LocalUnknown,
+      TimeSpec.LocalDST ->
+        localDateTime
+          .atZone(ZoneId.systemDefault())
+      TimeSpec.OffsetFromUTC ->
+        localDateTime
+          .atOffset(ZoneOffset.ofTotalSeconds(
+            IntSerializer.deserialize(buffer, featureSet)))
+          .toInstant()
+      TimeSpec.UTC ->
+        localDateTime
+          .atOffset(ZoneOffset.UTC)
+          .toInstant()
+    }
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IdentityIdSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IdentityIdSerializer.kt
new file mode 100644
index 000000000..3a27fb8c3
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/IdentityIdSerializer.kt
@@ -0,0 +1,41 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2021 Janne Mareike Koschinski
+ * Copyright (c) 2021 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.types.BufferId
+import de.kuschku.libquassel.protocol.types.IdentityId
+import de.kuschku.libquassel.protocol.variant.QuasselType
+import java.nio.ByteBuffer
+
+object IdentityIdSerializer : QuasselSerializer<IdentityId> {
+  override val quasselType: QuasselType = QuasselType.IdentityId
+  override val javaType: Class<out IdentityId> = IdentityId::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: IdentityId, featureSet: FeatureSet) {
+    IntSerializer.serialize(buffer, data.id, featureSet)
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): IdentityId {
+    return IdentityId(IntSerializer.deserialize(buffer, featureSet))
+  }
+
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/MessageSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/MessageSerializer.kt
new file mode 100644
index 000000000..ebc0427e2
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/MessageSerializer.kt
@@ -0,0 +1,81 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2020 Janne Mareike Koschinski
+ * Copyright (c) 2020 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.bitflags.of
+import de.kuschku.bitflags.toBits
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.features.QuasselFeature
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.types.Message
+import de.kuschku.libquassel.protocol.types.MessageFlag
+import de.kuschku.libquassel.protocol.types.MessageType
+import de.kuschku.libquassel.protocol.variant.QuasselType
+import org.threeten.bp.Instant
+import java.nio.ByteBuffer
+
+object MessageSerializer : QuasselSerializer<Message> {
+  override val quasselType: QuasselType = QuasselType.Message
+  override val javaType: Class<out Message> = Message::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: Message, featureSet: FeatureSet) {
+    MsgIdSerializer.serialize(buffer, data.messageId, featureSet)
+    if (featureSet.hasFeature(QuasselFeature.LongTime)) {
+      LongSerializer.serialize(buffer, data.time.toEpochMilli(), featureSet)
+    } else {
+      IntSerializer.serialize(buffer, data.time.epochSecond.toInt(), featureSet)
+    }
+    UIntSerializer.serialize(buffer, data.type.toBits(), featureSet)
+    UByteSerializer.serialize(buffer, data.flag.toBits().toUByte(), featureSet)
+    BufferInfoSerializer.serialize(buffer, data.bufferInfo, featureSet)
+    StringSerializerUtf8.serialize(buffer, data.sender, featureSet)
+    if (featureSet.hasFeature(QuasselFeature.SenderPrefixes)) {
+      StringSerializerUtf8.serialize(buffer, data.senderPrefixes, featureSet)
+    }
+    if (featureSet.hasFeature(QuasselFeature.RichMessages)) {
+      StringSerializerUtf8.serialize(buffer, data.realName, featureSet)
+      StringSerializerUtf8.serialize(buffer, data.avatarUrl, featureSet)
+    }
+    StringSerializerUtf8.serialize(buffer, data.content, featureSet)
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): Message {
+    return Message(
+      messageId = MsgIdSerializer.deserialize(buffer, featureSet),
+      time = if (featureSet.hasFeature(QuasselFeature.LongTime))
+        Instant.ofEpochMilli(LongSerializer.deserialize(buffer, featureSet))
+      else
+        Instant.ofEpochSecond(IntSerializer.deserialize(buffer, featureSet).toLong()),
+      type = MessageType.of(UIntSerializer.deserialize(buffer, featureSet)),
+      flag = MessageFlag.of(
+        UByteSerializer.deserialize(buffer, featureSet).toUInt() and 0xffu
+      ),
+      bufferInfo = BufferInfoSerializer.deserialize(buffer, featureSet),
+      sender = StringSerializerUtf8.deserialize(buffer, featureSet) ?: "",
+      senderPrefixes = if (featureSet.hasFeature(QuasselFeature.SenderPrefixes))
+        StringSerializerUtf8.deserialize(buffer, featureSet) ?: "" else "",
+      realName = if (featureSet.hasFeature(QuasselFeature.RichMessages))
+        StringSerializerUtf8.deserialize(buffer, featureSet) ?: "" else "",
+      avatarUrl = if (featureSet.hasFeature(QuasselFeature.RichMessages))
+        StringSerializerUtf8.deserialize(buffer, featureSet) ?: "" else "",
+      content = StringSerializerUtf8.deserialize(buffer, featureSet) ?: ""
+    )
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/MsgIdSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/MsgIdSerializer.kt
new file mode 100644
index 000000000..aab03d828
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/MsgIdSerializer.kt
@@ -0,0 +1,49 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2021 Janne Mareike Koschinski
+ * Copyright (c) 2021 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.features.QuasselFeature
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.types.MsgId
+import de.kuschku.libquassel.protocol.variant.QuasselType
+import java.nio.ByteBuffer
+
+object MsgIdSerializer : QuasselSerializer<MsgId> {
+  override val quasselType: QuasselType = QuasselType.MsgId
+  override val javaType: Class<out MsgId> = MsgId::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: MsgId, featureSet: FeatureSet) {
+    if (featureSet.hasFeature(QuasselFeature.LongMessageId)) {
+      LongSerializer.serialize(buffer, data.id, featureSet)
+    } else {
+      IntSerializer.serialize(buffer, data.id.toInt(), featureSet)
+    }
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): MsgId {
+    return if (featureSet.hasFeature(QuasselFeature.LongMessageId)) {
+      MsgId(LongSerializer.deserialize(buffer, featureSet))
+    } else {
+      MsgId(IntSerializer.deserialize(buffer, featureSet).toLong())
+    }
+  }
+
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/NetworkIdSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/NetworkIdSerializer.kt
new file mode 100644
index 000000000..62b6fe809
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/NetworkIdSerializer.kt
@@ -0,0 +1,42 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2021 Janne Mareike Koschinski
+ * Copyright (c) 2021 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.types.BufferId
+import de.kuschku.libquassel.protocol.types.IdentityId
+import de.kuschku.libquassel.protocol.types.NetworkId
+import de.kuschku.libquassel.protocol.variant.QuasselType
+import java.nio.ByteBuffer
+
+object NetworkIdSerializer : QuasselSerializer<NetworkId> {
+  override val quasselType: QuasselType = QuasselType.NetworkId
+  override val javaType: Class<out NetworkId> = NetworkId::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: NetworkId, featureSet: FeatureSet) {
+    IntSerializer.serialize(buffer, data.id, featureSet)
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): NetworkId {
+    return NetworkId(IntSerializer.deserialize(buffer, featureSet))
+  }
+
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/PeerPtrSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/PeerPtrSerializer.kt
new file mode 100644
index 000000000..9a927a077
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/PeerPtrSerializer.kt
@@ -0,0 +1,39 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2021 Janne Mareike Koschinski
+ * Copyright (c) 2021 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
+import de.kuschku.libquassel.protocol.variant.QuasselType
+import java.nio.ByteBuffer
+
+object PeerPtrSerializer : QuasselSerializer<ULong> {
+  override val quasselType: QuasselType = QuasselType.PeerPtr
+  override val javaType: Class<ULong> = ULong::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: ULong, featureSet: FeatureSet) {
+    buffer.putLong(data.toLong())
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): ULong {
+    return buffer.getLong().toULong()
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt
index e870e9a35..89b05757c 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/Serializers.kt
@@ -26,23 +26,49 @@ import de.kuschku.libquassel.protocol.variant.QuasselType
 import java.util.*
 
 object Serializers {
-  private val qtSerializers = listOf<QtSerializer<*>>(
+  private val qtSerializers = setOf<QtSerializer<*>>(
+    VoidSerializer,
     BoolSerializer,
-    UByteSerializer,
-    ByteSerializer,
-    ShortSerializer,
-    UShortSerializer,
     IntSerializer,
     UIntSerializer,
-    LongSerializer,
-    ULongSerializer,
-    ByteBufferSerializer,
-    StringSerializerUtf16,
+
     QCharSerializer,
+    QVariantMapSerializer,
+    QVariantListSerializer,
+
+    StringSerializerUtf16,
     QStringListSerializer,
+    ByteBufferSerializer,
+
+    DateSerializer,
+    TimeSerializer,
+    DateTimeSerializer,
+
+    LongSerializer,
+    ShortSerializer,
+    ByteSerializer,
+    ULongSerializer,
+
+    UShortSerializer,
+    UByteSerializer,
+
     QVariantSerializer,
-    QVariantListSerializer,
-    QVariantMapSerializer,
+
+    BufferIdSerializer,
+    BufferInfoSerializer,
+    //DccConfigIpDetectionModeSerializer,
+    //DccConfigPortSelectionModeSerializer,
+    //IrcUserSerializer,
+    //IrcChannelSerializer,
+    //IdentitySerializer,
+    IdentityIdSerializer,
+    MessageSerializer,
+    MsgIdSerializer,
+    NetworkIdSerializer,
+    //NetworkInfoSerializer,
+    //NetworkServerSerializer,
+    //QHostAddressSerializer,
+    PeerPtrSerializer,
   ).associateBy(QtSerializer<*>::qtType)
 
   private val quasselSerializers = listOf<QuasselSerializer<*>>(
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/TimeSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/TimeSerializer.kt
new file mode 100644
index 000000000..a93e623c9
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/TimeSerializer.kt
@@ -0,0 +1,41 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2020 Janne Mareike Koschinski
+ * Copyright (c) 2020 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
+import org.threeten.bp.LocalTime
+import java.nio.ByteBuffer
+
+object TimeSerializer : QtSerializer<LocalTime> {
+  override val qtType: QtType = QtType.QTime
+  override val javaType: Class<out LocalTime> = LocalTime::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: LocalTime, featureSet: FeatureSet) {
+    val millisecondOfDay = (data.toNanoOfDay() / 1000).toInt()
+    IntSerializer.serialize(buffer, millisecondOfDay, featureSet)
+  }
+
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet): LocalTime {
+    val millisecondOfDay = IntSerializer.deserialize(buffer, featureSet).toLong()
+    return LocalTime.ofNanoOfDay(millisecondOfDay * 1000)
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/VoidSerializer.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/VoidSerializer.kt
new file mode 100644
index 000000000..cc29434c6
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/serializers/primitive/VoidSerializer.kt
@@ -0,0 +1,33 @@
+/*
+ * Quasseldroid - Quassel client for Android
+ *
+ * Copyright (c) 2021 Janne Mareike Koschinski
+ * Copyright (c) 2021 The Quassel Project
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.libquassel.protocol.serializers.primitive
+
+import de.kuschku.libquassel.protocol.features.FeatureSet
+import de.kuschku.libquassel.protocol.io.ChainedByteBuffer
+import de.kuschku.libquassel.protocol.variant.QtType
+import java.nio.ByteBuffer
+
+object VoidSerializer : QtSerializer<Unit> {
+  override val qtType: QtType = QtType.Void
+  override val javaType: Class<out Unit> = Unit::class.java
+
+  override fun serialize(buffer: ChainedByteBuffer, data: Unit, featureSet: FeatureSet) = Unit
+  override fun deserialize(buffer: ByteBuffer, featureSet: FeatureSet)  = Unit
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferActivity.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferActivity.kt
new file mode 100644
index 000000000..8bd2dbe28
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferActivity.kt
@@ -0,0 +1,40 @@
+/*
+ * 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.types
+
+import de.kuschku.bitflags.Flag
+import de.kuschku.bitflags.Flags
+
+enum class BufferActivity(
+  override val value: UInt,
+): Flag<UInt> {
+  NoActivity(0x00u),
+  OtherActivity(0x01u),
+  NewMessage(0x02u),
+  Highlight(0x04u);
+
+  companion object : Flags<UInt, BufferActivity> {
+    private val values = values().associateBy(BufferActivity::value)
+    override fun get(value: UInt) = values[value]
+    override fun all() = values.values
+  }
+}
+
+typealias BufferActivities = Set<BufferActivity>
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferInfo.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferInfo.kt
new file mode 100644
index 000000000..91e0726c2
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferInfo.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.types
+
+import de.kuschku.bitflags.of
+
+data class BufferInfo(
+  val bufferId: BufferId = BufferId(-1),
+  val networkId: NetworkId = NetworkId(-1),
+  val type: BufferTypes = BufferType.of(),
+  val groupId: Int = -1,
+  val bufferName: String? = null,
+)
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferType.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferType.kt
new file mode 100644
index 000000000..ae609475c
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/BufferType.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.types
+
+import de.kuschku.bitflags.Flag
+import de.kuschku.bitflags.Flags
+
+enum class BufferType(
+  override val value: UShort,
+): Flag<UShort> {
+  Invalid(0x00u),
+  Status(0x01u),
+  Channel(0x02u),
+  Query(0x04u),
+  Group(0x08u);
+
+  companion object : Flags<UShort, BufferType> {
+    private val values = values().associateBy(BufferType::value)
+    override fun get(value: UShort) = values[value]
+    override fun all() = values.values
+  }
+}
+
+typealias BufferTypes = Set<BufferType>
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/Message.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/Message.kt
new file mode 100644
index 000000000..f9e85d450
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/Message.kt
@@ -0,0 +1,39 @@
+/*
+ * 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.types
+
+import org.threeten.bp.Instant
+
+data class Message(
+  val messageId: MsgId,
+  val time: Instant,
+  val type: MessageTypes,
+  val flag: MessageFlags,
+  val bufferInfo: BufferInfo,
+  val sender: String,
+  val senderPrefixes: String,
+  val realName: String,
+  val avatarUrl: String,
+  val content: String
+) {
+  override fun toString(): String {
+    return "Message(messageId=$messageId, time=$time, type=$type, flag=$flag, bufferInfo=$bufferInfo, sender='$sender', senderPrefixes='$senderPrefixes', content='$content')"
+  }
+}
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/MessageFlag.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/MessageFlag.kt
new file mode 100644
index 000000000..da916d387
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/MessageFlag.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.types
+
+import de.kuschku.bitflags.Flag
+import de.kuschku.bitflags.Flags
+
+enum class MessageFlag(
+  override val value: UInt,
+) : Flag<UInt> {
+  Self(0x01u),
+  Highlight(0x02u),
+  Redirected(0x04u),
+  ServerMsg(0x08u),
+  Backlog(0x80u);
+
+  companion object : Flags<UInt, MessageFlag> {
+    private val values = values().associateBy(MessageFlag::value)
+    override fun get(value: UInt) = values[value]
+    override fun all() = values.values
+  }
+}
+
+typealias MessageFlags = Set<MessageFlag>
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/MessageType.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/MessageType.kt
new file mode 100644
index 000000000..a5afb2c50
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/MessageType.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.types
+
+import de.kuschku.bitflags.Flag
+import de.kuschku.bitflags.Flags
+
+enum class MessageType(
+  override val value: UInt,
+) : Flag<UInt> {
+  Plain(0x00001u),
+  Notice(0x00002u),
+  Action(0x00004u),
+  Nick(0x00008u),
+  Mode(0x00010u),
+  Join(0x00020u),
+  Part(0x00040u),
+  Quit(0x00080u),
+  Kick(0x00100u),
+  Kill(0x00200u),
+  Server(0x00400u),
+  Info(0x00800u),
+  Error(0x01000u),
+  DayChange(0x02000u),
+  Topic(0x04000u),
+  NetsplitJoin(0x08000u),
+  NetsplitQuit(0x10000u),
+  Invite(0x20000u),
+  Markerline(0x40000u);
+
+  companion object : Flags<UInt, MessageType> {
+    private val values = values().associateBy(MessageType::value)
+    override fun get(value: UInt) = values[value]
+    override fun all() = values.values
+  }
+}
+
+typealias MessageTypes = Set<MessageType>
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/SignedId.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/SignedId.kt
index b1e1efdee..fb3f1bae8 100644
--- a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/SignedId.kt
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/SignedId.kt
@@ -40,7 +40,3 @@ inline fun SignedId<SignedIdType>.isValid() = id > 0
 @Suppress("NOTHING_TO_INLINE")
 @JvmName("isValidId64")
 inline fun SignedId<SignedId64Type>.isValid() = id > 0
-
-
-
-
diff --git a/protocol/src/main/java/de/kuschku/libquassel/protocol/types/TimeSpec.kt b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/TimeSpec.kt
new file mode 100644
index 000000000..52e07dffc
--- /dev/null
+++ b/protocol/src/main/java/de/kuschku/libquassel/protocol/types/TimeSpec.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.types
+
+enum class TimeSpec(val value: Byte) {
+  LocalUnknown(-1),
+  LocalStandard(0),
+  LocalDST(1),
+  UTC(2),
+  OffsetFromUTC(3);
+
+  companion object {
+    private val map = values().associateBy(TimeSpec::value)
+    fun of(type: Byte) = map[type]
+  }
+}
diff --git a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializerTest.kt b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializerTest.kt
index 753280936..c03ae034c 100644
--- a/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializerTest.kt
+++ b/protocol/src/test/kotlin/de/kuschku/libquassel/protocol/serializers/handshake/ClientInitSerializerTest.kt
@@ -19,7 +19,6 @@
 
 package de.kuschku.libquassel.protocol.serializers.handshake
 
-import de.kuschku.bitflags.flags
 import de.kuschku.libquassel.protocol.features.FeatureSet
 import de.kuschku.libquassel.protocol.messages.handshake.ClientInit
 import de.kuschku.libquassel.protocol.testutil.byteBufferOf
-- 
GitLab