Skip to content
Snippets Groups Projects
Verified Commit de68668c authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Prepare for implementing common syncable objects

parent 40d68cd3
Branches
Tags
No related merge requests found
Showing
with 270 additions and 35 deletions
......@@ -125,15 +125,15 @@ class RpcModelProcessor : RpcModelVisitor<ProtocolSide, KotlinModel?> {
companion object {
private val TYPENAME_INVOKER = ClassName(
"de.justjanne.libquassel.state.invoker",
"de.justjanne.libquassel.protocol.syncables.invoker",
"Invoker"
)
private val TYPENAME_UNKNOWN_METHOD_EXCEPTION = ClassName(
"de.justjanne.libquassel.state.exceptions",
"de.justjanne.libquassel.protocol.exceptions",
"UnknownMethodException"
)
private val TYPENAME_WRONG_OBJECT_TYPE_EXCEPTION = ClassName(
"de.justjanne.libquassel.state.exceptions",
"de.justjanne.libquassel.protocol.exceptions",
"WrongObjectTypeException"
)
private val TYPENAME_QVARIANTLIST = ClassName(
......
......@@ -10,6 +10,7 @@
plugins {
id("com.vanniktech.maven.publish")
id("com.google.devtools.ksp") version "1.4.30-1.0.0-alpha02"
}
dependencies {
......@@ -17,4 +18,5 @@ dependencies {
val kotlinBitflagsVersion: String by project
api("de.justjanne", "kotlin-bitflags", kotlinBitflagsVersion)
api(project(":libquassel-annotations"))
ksp(project(":libquassel-generator"))
}
......@@ -8,7 +8,7 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.exceptions
package de.justjanne.libquassel.protocol.exceptions
data class UnknownMethodException(
val className: String,
......
......@@ -8,7 +8,7 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.exceptions
package de.justjanne.libquassel.protocol.exceptions
data class WrongObjectTypeException(
val obj: Any?,
......
/*
* libquassel
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* 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.syncables
import de.justjanne.libquassel.protocol.models.Alias
import de.justjanne.libquassel.protocol.models.BufferInfo
import de.justjanne.libquassel.protocol.models.Command
import de.justjanne.libquassel.protocol.models.QStringList
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.syncables.stubs.AliasManagerStub
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.into
import de.justjanne.libquassel.protocol.variant.qVariant
class AliasManager constructor(
session: Session
) : SyncableObject(session, "AliasManager"), AliasManagerStub {
override fun toVariantMap(): QVariantMap = mapOf(
"Aliases" to qVariant(initAliases(), QtType.QVariantMap)
)
override fun fromVariantMap(properties: QVariantMap) {
initSetAliases(properties["Aliases"].into<QVariantMap>().orEmpty())
}
private fun initAliases(): QVariantMap = mapOf(
"names" to qVariant(aliases.map(Alias::name), QtType.QStringList),
"expansions" to qVariant(aliases.map(Alias::expansion), QtType.QStringList)
)
private fun initSetAliases(aliases: QVariantMap) {
val names = aliases["names"].into<QStringList>().orEmpty()
val expansions = aliases["expansions"].into<List<String>>().orEmpty()
require(names.size == expansions.size) {
"Sizes do not match: names=${names.size}, expansions=${expansions.size}"
}
this.aliases = names.zip(expansions, ::Alias)
}
override fun addAlias(name: String, expansion: String) {
if (contains(name)) {
return
}
aliases += Alias(name, expansion)
super.addAlias(name, expansion)
}
fun indexOf(name: String?) = aliases.map(Alias::name).indexOf(name)
fun contains(name: String?) = aliases.map(Alias::name).contains(name)
fun processInput(
info: BufferInfo,
message: String
) = mutableListOf<Command>().also {
processInput(info, message, it)
}
fun processInput(
info: BufferInfo,
message: String,
previousCommands: MutableList<Command>
) {
val (command, arguments) = determineMessageCommand(message)
if (command == null) {
// If no command is found, this means the message should be treated as
// pure text. To ensure this won’t be unescaped twice it’s sent with /SAY.
previousCommands.add(Command(info, "/SAY $arguments"))
} else {
val found = aliases.firstOrNull { it.name.equals(command, true) }
if (found != null) {
expand(found.expansion ?: "", info, arguments, previousCommands)
} else {
previousCommands.add(Command(info, message))
}
}
}
fun expand(
expansion: String,
bufferInfo: BufferInfo,
msg: String,
previousCommands: MutableList<Command>
) {
}
fun copy() = AliasManager(session).also {
it.fromVariantMap(toVariantMap())
}
var aliases = listOf<Alias>()
companion object {
private fun determineMessageCommand(message: String) = when {
// Only messages starting with a forward slash are commands
!message.startsWith("/") ->
Pair(null, message)
// If a message starts with //, we consider that an escaped slash
message.startsWith("//") ->
Pair(null, message.substring(1))
// If the first word of a message contains more than one slash, it is
// usually a regex of format /[a-z][a-z0-9]*/g, or a path of format
// /usr/bin/powerline-go. In that case we also pass it right through
message.startsWith("/") &&
message.substringBefore(' ').indexOf('/', 1) != -1
-> Pair(null, message)
// If the first word is purely a /, we won’t consider it a command either
message.substringBefore(' ') == "/" ->
Pair(null, message)
// Otherwise we treat the first word as a command, and all further words as
// arguments
else -> Pair(
message.trimStart('/').substringBefore(' '),
message.substringAfter(' ')
)
}
}
}
......@@ -8,12 +8,18 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
plugins {
id("com.vanniktech.maven.publish")
id("com.google.devtools.ksp") version "1.4.30-1.0.0-alpha02"
}
package de.justjanne.libquassel.protocol.syncables
import de.justjanne.libquassel.protocol.variant.QVariantMap
dependencies {
api(project(":libquassel-protocol"))
ksp(project(":libquassel-generator"))
interface ObjectRepository {
fun register(syncable: SyncableStub, batch: Boolean)
fun init(syncable: SyncableStub, data: QVariantMap)
fun rename(syncable: SyncableStub, newName: String)
fun remove(syncable: SyncableStub)
fun <T : SyncableStub> find(type: Class<T>, objectName: String): T
}
inline fun <reified T : SyncableStub> ObjectRepository.find(objectName: String): T =
find(T::class.java, objectName)
......@@ -8,15 +8,25 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.protocol.models.SignalProxyMessage
import de.justjanne.libquassel.protocol.models.ids.IdentityId
import de.justjanne.libquassel.protocol.models.ids.NetworkId
import de.justjanne.libquassel.protocol.syncables.stubs.IdentityStub
import de.justjanne.libquassel.protocol.syncables.stubs.NetworkStub
import de.justjanne.libquassel.protocol.syncables.stubs.RpcHandlerStub
import de.justjanne.libquassel.protocol.variant.QVariantList
interface SignalProxy {
interface Session : RpcHandlerStub {
val protocolSide: ProtocolSide
val objectRepository: ObjectRepository
fun network(id: NetworkId): NetworkStub
fun identity(id: IdentityId): IdentityStub
fun sync(
target: ProtocolSide,
className: String,
......@@ -52,4 +62,11 @@ interface SignalProxy {
}
fun emit(message: SignalProxyMessage)
fun dispatch(message: SignalProxyMessage)
fun dispatch(message: SignalProxyMessage.Sync)
fun dispatch(message: SignalProxyMessage.Rpc)
fun dispatch(message: SignalProxyMessage.InitRequest)
fun dispatch(message: SignalProxyMessage.InitData)
fun dispatch(message: SignalProxyMessage.HeartBeat)
fun dispatch(message: SignalProxyMessage.HeartBeatReply)
}
/*
* libquassel
* Copyright (c) 2021 Janne Mareike Koschinski
* Copyright (c) 2021 The Quassel Project
*
* 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.syncables
import de.justjanne.libquassel.protocol.serializers.qt.StringSerializerUtf8
abstract class SyncableObject(
override var session: Session,
override val className: String
) : SyncableStub {
final override var objectName: String = ""
internal set
final override var initialized: Boolean = false
internal set
protected fun renameObject(
newName: String
) {
val oldName = objectName
if (!initialized) {
objectName = newName
} else if (oldName != newName) {
objectName = newName
session.objectRepository.rename(this, newName)
session.objectRenamed(
StringSerializerUtf8.serializeRaw(className),
oldName,
newName
)
}
}
override fun init() {
initialized = true
}
override fun deinit() {
initialized = false
}
}
......@@ -8,7 +8,7 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.protocol.models.types.QtType
......@@ -16,24 +16,27 @@ import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.QVariant_
import de.justjanne.libquassel.protocol.variant.qVariant
interface SyncableProtocol {
interface SyncableStub {
val className: String
val objectName: String
val initialized: Boolean
val proxy: SignalProxy
val session: Session
fun fromVariantMap(properties: QVariantMap)
fun toVariantMap(): QVariantMap
fun init()
fun deinit()
fun sync(target: ProtocolSide, function: String, vararg arg: QVariant_) {
if (initialized) {
proxy.sync(target, className, objectName, function, arg.toList())
session.sync(target, className, objectName, function, arg.toList())
}
}
fun rpc(target: ProtocolSide, function: String, vararg arg: QVariant_) {
if (initialized) {
proxy.rpc(target, function, arg.toList())
session.rpc(target, function, arg.toList())
}
}
......
......@@ -8,14 +8,15 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.invoker
package de.justjanne.libquassel.protocol.syncables.invoker
import de.justjanne.libquassel.protocol.exceptions.UnknownMethodException
import de.justjanne.libquassel.protocol.exceptions.WrongObjectTypeException
import de.justjanne.libquassel.protocol.variant.QVariantList
import de.justjanne.libquassel.state.exceptions.UnknownMethodException
import de.justjanne.libquassel.state.exceptions.WrongObjectTypeException
interface Invoker<out T> {
val className: String
@Throws(WrongObjectTypeException::class, UnknownMethodException::class)
fun invoke(on: Any?, method: String, params: QVariantList)
}
......@@ -8,17 +8,18 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
import de.justjanne.libquassel.annotations.SyncedObject
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.qVariant
@SyncedObject("AliasManager")
interface AliasManager : SyncableProtocol {
interface AliasManagerStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CORE)
fun addAlias(name: String, expansion: String) {
sync(
......
......@@ -8,7 +8,7 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
......@@ -17,10 +17,11 @@ import de.justjanne.libquassel.protocol.models.ids.BufferId
import de.justjanne.libquassel.protocol.models.ids.MsgId
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.models.types.QuasselType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.qVariant
@SyncedObject("BacklogManager")
interface BacklogManagerProtocol : SyncableProtocol {
interface BacklogManagerStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CORE)
fun requestBacklog(
bufferId: BufferId,
......
......@@ -8,7 +8,7 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
......@@ -17,11 +17,12 @@ import de.justjanne.libquassel.protocol.models.ids.BufferId
import de.justjanne.libquassel.protocol.models.ids.MsgId
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.models.types.QuasselType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.qVariant
@SyncedObject("BufferSyncer")
interface BufferSyncerProtocol : SyncableProtocol {
interface BufferSyncerStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CLIENT)
fun markBufferAsRead(buffer: BufferId) {
sync(
......
......@@ -8,7 +8,7 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
......@@ -17,11 +17,12 @@ import de.justjanne.libquassel.protocol.models.ids.BufferId
import de.justjanne.libquassel.protocol.models.ids.NetworkId
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.models.types.QuasselType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.qVariant
@SyncedObject("BufferViewConfig")
interface BufferViewConfigProtocol : SyncableProtocol {
interface BufferViewConfigStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CLIENT)
fun addBuffer(buffer: BufferId, pos: Int) {
sync(
......
......@@ -8,18 +8,19 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
import de.justjanne.libquassel.annotations.SyncedObject
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.QVariantList
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.qVariant
@SyncedObject("BufferViewManager")
interface BufferViewManagerProtocol : SyncableProtocol {
interface BufferViewManagerStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CLIENT)
fun addBufferViewConfig(bufferViewConfigId: Int) {
sync(
......
......@@ -8,18 +8,19 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
import de.justjanne.libquassel.annotations.SyncedObject
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.qVariant
import java.nio.ByteBuffer
@SyncedObject("CertManager")
interface CertManagerProtocol : SyncableProtocol {
interface CertManagerStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CLIENT)
fun setSslCert(encoded: ByteBuffer) {
sync(
......
......@@ -8,17 +8,18 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
import de.justjanne.libquassel.annotations.SyncedObject
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.qVariant
@SyncedObject("CoreInfo")
interface CoreInfoProtocol : SyncableProtocol {
interface CoreInfoStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CLIENT)
fun setCoreData(data: QVariantMap) {
sync(
......
......@@ -8,7 +8,7 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
......@@ -17,12 +17,13 @@ import de.justjanne.libquassel.protocol.models.DccIpDetectionMode
import de.justjanne.libquassel.protocol.models.DccPortSelectionMode
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.models.types.QuasselType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.qVariant
import java.net.InetAddress
@SyncedObject("DccConfig")
interface DccConfigProtocol : SyncableProtocol {
interface DccConfigStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CLIENT)
fun setDccEnabled(enabled: Boolean) {
sync(
......
......@@ -8,17 +8,18 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
import de.justjanne.libquassel.annotations.SyncedObject
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.qVariant
@SyncedObject("HighlightRuleManager")
interface HighlightRuleManagerProtocol : SyncableProtocol {
interface HighlightRuleManagerStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CORE)
fun requestRemoveHighlightRule(highlightRule: Int) {
sync(
......
......@@ -8,7 +8,7 @@
* obtain one at https://mozilla.org/MPL/2.0/.
*/
package de.justjanne.libquassel.state.protocol
package de.justjanne.libquassel.protocol.syncables.stubs
import de.justjanne.libquassel.annotations.ProtocolSide
import de.justjanne.libquassel.annotations.SyncedCall
......@@ -17,11 +17,12 @@ import de.justjanne.libquassel.protocol.models.QStringList
import de.justjanne.libquassel.protocol.models.ids.IdentityId
import de.justjanne.libquassel.protocol.models.types.QtType
import de.justjanne.libquassel.protocol.models.types.QuasselType
import de.justjanne.libquassel.protocol.syncables.SyncableStub
import de.justjanne.libquassel.protocol.variant.QVariantMap
import de.justjanne.libquassel.protocol.variant.qVariant
@SyncedObject("Identity")
interface IdentityProtocol : SyncableProtocol {
interface IdentityStub : SyncableStub {
@SyncedCall(target = ProtocolSide.CLIENT)
fun setAutoAwayEnabled(enabled: Boolean) {
sync(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment