From 92ec89b4043c086665253ff35084d76da9c2f466 Mon Sep 17 00:00:00 2001
From: Janne Mareike Koschinski <janne@kuschku.de>
Date: Fri, 4 Mar 2022 00:56:52 +0100
Subject: [PATCH] feat: extract irc functionality into irc module

---
 .../libquassel}/irc/HostmaskHelper.kt         |   2 +-
 .../libquassel}/irc/IrcCapability.kt          |   2 +-
 .../libquassel}/irc/IrcCaseMapper.kt          |   4 +-
 .../justjanne/libquassel}/irc/IrcISupport.kt  |   2 +-
 libquassel-protocol/build.gradle.kts          |   1 +
 .../protocol/syncables/common/IrcUser.kt      |   2 +-
 .../protocol/syncables/common/Network.kt      |   2 +-
 .../state/HighlightRuleManagerState.kt        |   7 +-
 .../protocol/util/irc/FormatInfo.kt           |  15 -
 .../protocol/util/irc/FormatInfoBuilder.kt    |  15 -
 .../libquassel/protocol/util/irc/IrcFormat.kt |  34 --
 .../util/irc/IrcFormatDeserializer.kt         | 369 ------------------
 .../testutil/mocks/RealisticSession.kt        |   2 +-
 13 files changed, 14 insertions(+), 443 deletions(-)
 rename {libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util => libquassel-irc/src/main/kotlin/de/justjanne/libquassel}/irc/HostmaskHelper.kt (95%)
 rename {libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util => libquassel-irc/src/main/kotlin/de/justjanne/libquassel}/irc/IrcCapability.kt (94%)
 rename {libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util => libquassel-irc/src/main/kotlin/de/justjanne/libquassel}/irc/IrcCaseMapper.kt (95%)
 rename {libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util => libquassel-irc/src/main/kotlin/de/justjanne/libquassel}/irc/IrcISupport.kt (99%)
 delete mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/FormatInfo.kt
 delete mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/FormatInfoBuilder.kt
 delete mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcFormat.kt
 delete mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcFormatDeserializer.kt

diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/HostmaskHelper.kt b/libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/HostmaskHelper.kt
similarity index 95%
rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/HostmaskHelper.kt
rename to libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/HostmaskHelper.kt
index 5c37cd1..0d64701 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/HostmaskHelper.kt
+++ b/libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/HostmaskHelper.kt
@@ -7,7 +7,7 @@
  * obtain one at https://mozilla.org/MPL/2.0/.
  */
 
-package de.justjanne.libquassel.protocol.util.irc
+package de.justjanne.libquassel.irc
 
 object HostmaskHelper {
   fun nick(mask: String) = mask
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcCapability.kt b/libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/IrcCapability.kt
similarity index 94%
rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcCapability.kt
rename to libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/IrcCapability.kt
index 13e6125..02b3108 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcCapability.kt
+++ b/libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/IrcCapability.kt
@@ -7,7 +7,7 @@
  * obtain one at https://mozilla.org/MPL/2.0/.
  */
 
-package de.justjanne.libquassel.protocol.util.irc
+package de.justjanne.libquassel.irc
 
 object IrcCapability {
   const val ACCOUNT_NOTIFY = "account-notify"
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcCaseMapper.kt b/libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/IrcCaseMapper.kt
similarity index 95%
rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcCaseMapper.kt
rename to libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/IrcCaseMapper.kt
index 9ce7a21..69908a1 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcCaseMapper.kt
+++ b/libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/IrcCaseMapper.kt
@@ -1,13 +1,13 @@
 /*
  * libquassel
- * Copyright (c) 2021 Janne Mareike Koschinski
+ * Copyright (c) 2022 Janne Mareike Koschinski
  *
  * This Source Code Form is subject to the terms of the Mozilla Public License,
  * v. 2.0. If a copy of the MPL was not distributed with this file, You can
  * obtain one at https://mozilla.org/MPL/2.0/.
  */
 
-package de.justjanne.libquassel.protocol.util.irc
+package de.justjanne.libquassel.irc
 
 import java.util.Locale
 
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcISupport.kt b/libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/IrcISupport.kt
similarity index 99%
rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcISupport.kt
rename to libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/IrcISupport.kt
index ea31b90..c9fdf7f 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcISupport.kt
+++ b/libquassel-irc/src/main/kotlin/de/justjanne/libquassel/irc/IrcISupport.kt
@@ -7,7 +7,7 @@
  * obtain one at https://mozilla.org/MPL/2.0/.
  */
 
-package de.justjanne.libquassel.protocol.util.irc
+package de.justjanne.libquassel.irc
 
 object IrcISupport {
   /**
diff --git a/libquassel-protocol/build.gradle.kts b/libquassel-protocol/build.gradle.kts
index 4ecbe55..05daeaf 100644
--- a/libquassel-protocol/build.gradle.kts
+++ b/libquassel-protocol/build.gradle.kts
@@ -15,6 +15,7 @@ plugins {
 dependencies {
   api(project(":libquassel-annotations"))
   ksp(project(":libquassel-generator"))
+  implementation(project(":libquassel-irc"))
   api(libs.threetenbp)
   api(libs.kotlin.bitflags)
   implementation(libs.bouncycastle)
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcUser.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcUser.kt
index 6498c54..b282ffa 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcUser.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcUser.kt
@@ -9,12 +9,12 @@
 
 package de.justjanne.libquassel.protocol.syncables.common
 
+import de.justjanne.libquassel.irc.HostmaskHelper
 import de.justjanne.libquassel.protocol.models.types.QtType
 import de.justjanne.libquassel.protocol.session.Session
 import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject
 import de.justjanne.libquassel.protocol.syncables.state.IrcUserState
 import de.justjanne.libquassel.protocol.syncables.stubs.IrcUserStub
-import de.justjanne.libquassel.protocol.util.irc.HostmaskHelper
 import de.justjanne.libquassel.protocol.util.update
 import de.justjanne.libquassel.protocol.variant.QVariantMap
 import de.justjanne.libquassel.protocol.variant.indexed
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Network.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Network.kt
index 703337e..cf9b3fb 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Network.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Network.kt
@@ -9,6 +9,7 @@
 
 package de.justjanne.libquassel.protocol.syncables.common
 
+import de.justjanne.libquassel.irc.HostmaskHelper
 import de.justjanne.libquassel.protocol.models.QStringList
 import de.justjanne.libquassel.protocol.models.ids.IdentityId
 import de.justjanne.libquassel.protocol.models.network.ConnectionState
@@ -24,7 +25,6 @@ import de.justjanne.libquassel.protocol.syncables.state.IrcUserState
 import de.justjanne.libquassel.protocol.syncables.state.NetworkState
 import de.justjanne.libquassel.protocol.syncables.stubs.NetworkStub
 import de.justjanne.libquassel.protocol.util.collections.transpose
-import de.justjanne.libquassel.protocol.util.irc.HostmaskHelper
 import de.justjanne.libquassel.protocol.util.update
 import de.justjanne.libquassel.protocol.variant.QVariantList
 import de.justjanne.libquassel.protocol.variant.QVariantMap
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/HighlightRuleManagerState.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/HighlightRuleManagerState.kt
index e475462..b4b09da 100644
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/HighlightRuleManagerState.kt
+++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/HighlightRuleManagerState.kt
@@ -9,6 +9,8 @@
 
 package de.justjanne.libquassel.protocol.syncables.state
 
+import de.justjanne.libquassel.irc.IrcFormat
+import de.justjanne.libquassel.irc.IrcFormatDeserializer
 import de.justjanne.libquassel.protocol.models.flags.MessageFlag
 import de.justjanne.libquassel.protocol.models.flags.MessageFlags
 import de.justjanne.libquassel.protocol.models.flags.MessageType
@@ -16,7 +18,6 @@ import de.justjanne.libquassel.protocol.models.flags.MessageTypes
 import de.justjanne.libquassel.protocol.models.rules.HighlightNickType
 import de.justjanne.libquassel.protocol.models.rules.HighlightRule
 import de.justjanne.libquassel.protocol.util.expression.ExpressionMatch
-import de.justjanne.libquassel.protocol.util.irc.IrcFormatDeserializer
 
 data class HighlightRuleManagerState(
   val rules: List<HighlightRule> = emptyList(),
@@ -32,7 +33,9 @@ data class HighlightRuleManagerState(
     currentNick: String,
     identityNicks: List<String>
   ): Boolean {
-    val messageContent = IrcFormatDeserializer.stripColors(message)
+    val messageContent = IrcFormatDeserializer.parse(message)
+      .map(IrcFormat.Span::content)
+      .joinToString()
 
     if (!type.contains(MessageType.Action) &&
       !type.contains(MessageType.Notice) &&
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/FormatInfo.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/FormatInfo.kt
deleted file mode 100644
index bb39cf9..0000000
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/FormatInfo.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * libquassel
- * Copyright (c) 2021 Janne Mareike Koschinski
- *
- * This Source Code Form is subject to the terms of the Mozilla Public License,
- * v. 2.0. If a copy of the MPL was not distributed with this file, You can
- * obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package de.justjanne.libquassel.protocol.util.irc
-
-data class FormatInfo<T : IrcFormat>(
-  val range: IntRange,
-  val format: T
-)
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/FormatInfoBuilder.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/FormatInfoBuilder.kt
deleted file mode 100644
index f4b5b0c..0000000
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/FormatInfoBuilder.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * libquassel
- * Copyright (c) 2021 Janne Mareike Koschinski
- *
- * This Source Code Form is subject to the terms of the Mozilla Public License,
- * v. 2.0. If a copy of the MPL was not distributed with this file, You can
- * obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package de.justjanne.libquassel.protocol.util.irc
-
-data class FormatInfoBuilder<T : IrcFormat>(
-  val start: Int,
-  val format: T
-)
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcFormat.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcFormat.kt
deleted file mode 100644
index 1d5d265..0000000
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcFormat.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * libquassel
- * Copyright (c) 2021 Janne Mareike Koschinski
- *
- * This Source Code Form is subject to the terms of the Mozilla Public License,
- * v. 2.0. If a copy of the MPL was not distributed with this file, You can
- * obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package de.justjanne.libquassel.protocol.util.irc
-
-sealed class IrcFormat {
-  object Italic : IrcFormat()
-
-  object Underline : IrcFormat()
-
-  object Strikethrough : IrcFormat()
-
-  object Monospace : IrcFormat()
-
-  object Bold : IrcFormat()
-
-  data class HexColor(
-    val foreground: UInt,
-    val background: UInt
-  ) : IrcFormat()
-
-  data class IrcColor(
-    val foreground: UByte,
-    val background: UByte
-  ) : IrcFormat() {
-    fun copySwapped() = copy(foreground = background, background = foreground)
-  }
-}
diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcFormatDeserializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcFormatDeserializer.kt
deleted file mode 100644
index 141889f..0000000
--- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/irc/IrcFormatDeserializer.kt
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * libquassel
- * Copyright (c) 2021 Janne Mareike Koschinski
- *
- * This Source Code Form is subject to the terms of the Mozilla Public License,
- * v. 2.0. If a copy of the MPL was not distributed with this file, You can
- * obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-package de.justjanne.libquassel.protocol.util.irc
-
-object IrcFormatDeserializer {
-  fun stripColors(
-    str: String
-  ) = formatString(str, false, mutableListOf())
-
-  fun formatString(
-    str: String,
-    colorize: Boolean
-  ): Pair<String, List<FormatInfo<IrcFormat>>> {
-    val list = mutableListOf<FormatInfo<IrcFormat>>()
-    val content = formatString(str, colorize, list)
-    return Pair(content, list)
-  }
-
-  fun formatString(
-    str: String?,
-    colorize: Boolean,
-    output: MutableList<FormatInfo<IrcFormat>>
-  ): String {
-    if (str == null) return ""
-
-    val plainText = StringBuilder()
-    var bold: FormatInfoBuilder<IrcFormat.Bold>? = null
-    var italic: FormatInfoBuilder<IrcFormat.Italic>? = null
-    var underline: FormatInfoBuilder<IrcFormat.Underline>? = null
-    var strikethrough: FormatInfoBuilder<IrcFormat.Strikethrough>? = null
-    var monospace: FormatInfoBuilder<IrcFormat.Monospace>? = null
-    var color: FormatInfoBuilder<IrcFormat.IrcColor>? = null
-    var hexColor: FormatInfoBuilder<IrcFormat.HexColor>? = null
-
-    fun applyFormat(desc: FormatInfoBuilder<*>) {
-      output.add(FormatInfo(desc.start..plainText.length, desc.format))
-    }
-
-    // Iterating over every character
-    var normalCount = 0
-    var i = 0
-    while (i < str.length) {
-      val character = str[i]
-      when (character) {
-        CODE_BOLD -> {
-          plainText.append(str.substring(i - normalCount, i))
-          normalCount = 0
-
-          // If there is an element on stack with the same code, close it
-          bold = if (bold != null) {
-            if (colorize) applyFormat(bold)
-            null
-            // Otherwise create a new one
-          } else {
-            FormatInfoBuilder(
-              plainText.length,
-              IrcFormat.Bold
-            )
-          }
-        }
-        CODE_ITALIC -> {
-          plainText.append(str.substring(i - normalCount, i))
-          normalCount = 0
-
-          // If there is an element on stack with the same code, close it
-          italic = if (italic != null) {
-            if (colorize) applyFormat(italic)
-            null
-            // Otherwise create a new one
-          } else {
-            FormatInfoBuilder(
-              plainText.length,
-              IrcFormat.Italic
-            )
-          }
-        }
-        CODE_UNDERLINE -> {
-          plainText.append(str.substring(i - normalCount, i))
-          normalCount = 0
-
-          // If there is an element on stack with the same code, close it
-          underline = if (underline != null) {
-            if (colorize) applyFormat(underline)
-            null
-            // Otherwise create a new one
-          } else {
-            FormatInfoBuilder(
-              plainText.length,
-              IrcFormat.Underline
-            )
-          }
-        }
-        CODE_STRIKETHROUGH -> {
-          plainText.append(str.substring(i - normalCount, i))
-          normalCount = 0
-
-          // If there is an element on stack with the same code, close it
-          strikethrough = if (strikethrough != null) {
-            if (colorize) applyFormat(strikethrough)
-            null
-            // Otherwise create a new one
-          } else {
-            FormatInfoBuilder(
-              plainText.length,
-              IrcFormat.Strikethrough
-            )
-          }
-        }
-        CODE_MONOSPACE -> {
-          plainText.append(str.substring(i - normalCount, i))
-          normalCount = 0
-
-          // If there is an element on stack with the same code, close it
-          monospace = if (monospace != null) {
-            if (colorize) applyFormat(monospace)
-            null
-            // Otherwise create a new one
-          } else {
-            FormatInfoBuilder(
-              plainText.length,
-              IrcFormat.Monospace
-            )
-          }
-        }
-        CODE_COLOR -> {
-          plainText.append(str.substring(i - normalCount, i))
-          normalCount = 0
-
-          val foregroundStart = i + 1
-          val foregroundEnd = findEndOfNumber(str, foregroundStart)
-          // If we have a foreground element
-          if (foregroundEnd > foregroundStart) {
-            val foreground = readNumber(str, foregroundStart, foregroundEnd)
-
-            var background: UByte? = null
-            var backgroundEnd = -1
-            // If we have a background code, read it
-            if (str.length > foregroundEnd && str[foregroundEnd] == ',') {
-              backgroundEnd = findEndOfNumber(str, foregroundEnd + 1)
-              background = readNumber(str, foregroundEnd + 1, backgroundEnd)
-            }
-            // If previous element was also a color element, try to reuse background
-            if (color != null) {
-              // Apply old format
-              if (colorize) applyFormat(color)
-              // Reuse old background, if possible
-              if (background == null)
-                background = color.format.background
-            }
-            // Add new format
-            color = FormatInfoBuilder(
-              plainText.length,
-              IrcFormat.IrcColor(
-                foreground ?: 0xFFu,
-                background ?: 0xFFu
-              )
-            )
-
-            // i points in front of the next character
-            i = (if (backgroundEnd == -1) foregroundEnd else backgroundEnd) - 1
-
-            // Otherwise assume this is a closing tag
-          } else if (color != null) {
-            if (colorize) applyFormat(color)
-            color = null
-          }
-        }
-        CODE_HEXCOLOR -> {
-          plainText.append(str.substring(i - normalCount, i))
-          normalCount = 0
-
-          val foregroundStart = i + 1
-          val foregroundEnd = findEndOfHexNumber(str, foregroundStart)
-          // If we have a foreground element
-          if (foregroundEnd > foregroundStart) {
-            val foreground = readHexNumber(str, foregroundStart, foregroundEnd)
-
-            var background: UInt? = null
-            var backgroundEnd = -1
-            // If we have a background code, read it
-            if (str.length > foregroundEnd && str[foregroundEnd] == ',') {
-              backgroundEnd = findEndOfHexNumber(str, foregroundEnd + 1)
-              background = readHexNumber(str, foregroundEnd + 1, backgroundEnd)
-            }
-            // If previous element was also a color element, try to reuse background
-            if (hexColor != null) {
-              // Apply old format
-              if (colorize) applyFormat(hexColor)
-              // Reuse old background, if possible
-              if (background == null)
-                background = hexColor.format.background
-            }
-            // Add new format
-            hexColor = FormatInfoBuilder(
-              plainText.length,
-              IrcFormat.HexColor(
-                foreground ?: 0xFFFFFFFFu,
-                background ?: 0xFFFFFFFFu
-              )
-            )
-
-            // i points in front of the next character
-            i = (if (backgroundEnd == -1) foregroundEnd else backgroundEnd) - 1
-
-            // Otherwise assume this is a closing tag
-          } else if (hexColor != null) {
-            if (colorize) applyFormat(hexColor)
-            hexColor = null
-          }
-        }
-        CODE_SWAP -> {
-          plainText.append(str.substring(i - normalCount, i))
-          normalCount = 0
-
-          // If we have a color tag before, apply it, and create a new one with swapped colors
-          if (color != null) {
-            if (colorize) applyFormat(color)
-            color = FormatInfoBuilder(
-              plainText.length, color.format.copySwapped()
-            )
-          }
-        }
-        CODE_RESET -> {
-          plainText.append(str.substring(i - normalCount, i))
-          normalCount = 0
-
-          // End all formatting tags
-          if (bold != null) {
-            if (colorize) applyFormat(bold)
-            bold = null
-          }
-          if (italic != null) {
-            if (colorize) applyFormat(italic)
-            italic = null
-          }
-          if (underline != null) {
-            if (colorize) applyFormat(underline)
-            underline = null
-          }
-          if (color != null) {
-            if (colorize) applyFormat(color)
-            color = null
-          }
-          if (hexColor != null) {
-            if (colorize) applyFormat(hexColor)
-            hexColor = null
-          }
-        }
-        else -> {
-          // Just append it, if it’s not special
-          normalCount++
-        }
-      }
-      i++
-    }
-
-    plainText.append(str.substring(str.length - normalCount, str.length))
-
-    // End all formatting tags
-    if (bold != null) {
-      if (colorize) applyFormat(bold)
-    }
-    if (italic != null) {
-      if (colorize) applyFormat(italic)
-    }
-    if (underline != null) {
-      if (colorize) applyFormat(underline)
-    }
-    if (strikethrough != null) {
-      if (colorize) applyFormat(strikethrough)
-    }
-    if (monospace != null) {
-      if (colorize) applyFormat(monospace)
-    }
-    if (color != null) {
-      if (colorize) applyFormat(color)
-    }
-    if (hexColor != null) {
-      if (colorize) applyFormat(hexColor)
-    }
-    return plainText.toString()
-  }
-
-  private const val CODE_BOLD = 0x02.toChar()
-  private const val CODE_COLOR = 0x03.toChar()
-  private const val CODE_HEXCOLOR = 0x04.toChar()
-  private const val CODE_ITALIC = 0x1D.toChar()
-  private const val CODE_UNDERLINE = 0x1F.toChar()
-  private const val CODE_STRIKETHROUGH = 0x1E.toChar()
-  private const val CODE_MONOSPACE = 0x11.toChar()
-  private const val CODE_SWAP = 0x16.toChar()
-  private const val CODE_RESET = 0x0F.toChar()
-
-  /**
-   * Try to read a number from a String in specified bounds
-   *
-   * @param str   String to be read from
-   * @param start Start index (inclusive)
-   * @param end   End index (exclusive)
-   * @return The byte represented by the digits read from the string
-   */
-  fun readNumber(str: String, start: Int, end: Int): UByte? {
-    val result = str.substring(start, end)
-    return if (result.isEmpty()) null
-    else result.toUByteOrNull(10)
-  }
-
-  /**
-   * Try to read a number from a String in specified bounds
-   *
-   * @param str   String to be read from
-   * @param start Start index (inclusive)
-   * @param end   End index (exclusive)
-   * @return The byte represented by the digits read from the string
-   */
-  fun readHexNumber(str: String, start: Int, end: Int): UInt? {
-    val result = str.substring(start, end)
-    return if (result.isEmpty()) null
-    else result.toUIntOrNull(16)
-  }
-
-  /**
-   * @param str   String to be searched in
-   * @param start Start position (inclusive)
-   * @return Index of first character that is not a digit
-   */
-  private fun findEndOfNumber(str: String, start: Int): Int {
-    val searchFrame = str.substring(start)
-    var i = 0
-    loop@ while (i < 2 && i < searchFrame.length) {
-      when (searchFrame[i]) {
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> {
-          // Do nothing
-        }
-        else -> break@loop
-      }
-      i++
-    }
-    return start + i
-  }
-
-  /**
-   * @param str   String to be searched in
-   * @param start Start position (inclusive)
-   * @return Index of first character that is not a digit
-   */
-  private fun findEndOfHexNumber(str: String, start: Int): Int {
-    val searchFrame = str.substring(start)
-    var i = 0
-    loop@ while (i < 6 && i < searchFrame.length) {
-      when (searchFrame[i]) {
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b',
-        'c', 'd', 'e', 'f' -> {
-          // Do nothing
-        }
-        else -> break@loop
-      }
-      i++
-    }
-    return start + i
-  }
-}
diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/mocks/RealisticSession.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/mocks/RealisticSession.kt
index f2a2337..fe768e0 100644
--- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/mocks/RealisticSession.kt
+++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/mocks/RealisticSession.kt
@@ -10,6 +10,7 @@
 package de.justjanne.libquassel.protocol.testutil.mocks
 
 import de.justjanne.bitflags.of
+import de.justjanne.libquassel.irc.IrcCaseMapper
 import de.justjanne.libquassel.protocol.models.BufferInfo
 import de.justjanne.libquassel.protocol.models.flags.BufferType
 import de.justjanne.libquassel.protocol.models.ids.BufferId
@@ -27,7 +28,6 @@ import de.justjanne.libquassel.protocol.syncables.state.BufferSyncerState
 import de.justjanne.libquassel.protocol.syncables.state.IrcChannelState
 import de.justjanne.libquassel.protocol.syncables.state.IrcUserState
 import de.justjanne.libquassel.protocol.syncables.state.NetworkState
-import de.justjanne.libquassel.protocol.util.irc.IrcCaseMapper
 
 class RealisticSession : EmptySession() {
   private val networks = setOf(
-- 
GitLab