diff --git a/README.md b/README.md index 6478993..0550e82 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,21 @@ -# mixtape • usagi +# Usagi -> a kotlin multi-platform [rabbitmq](https://rabbitmq.org) client +A kotlin multi-platform AMQP 0.9.1 client. -- ⚡ powered by [kotlin coroutines](https://github.com/kotlin/kotlinx.coroutines) -- 🚀 uses [ktor](https://ktor.io) -- 😎 modern api +- ⚡ Powered by [kotlin coroutines](https://github.com/kotlin/kotlinx.coroutines) +- 🚀 Uses [ktor](https://ktor.io) +- 😎 Idiomatic Kotlin API > **Warning** > Usagi is in Alpha, bugs may be ahead! -## installation +**We are looking for contributors! If you are looking for a kotlin multiplatform AMQP client please consider opening PRs and Issues, it is very appreciated.** + +## Installation current version: *coming soon* -#### 🐘 docker +#### 🐘 Gradle ```kotlin repositories { @@ -22,20 +24,23 @@ repositories { dependencies { // common: - implementation("mixtape.oss.usagi:usagi:{VERSION}") + implementation("dimensional.usagi:usagi:{VERSION}") } ``` -## usage +## Usage + +> **Note** +> This API is not final, it may change in the future. -**create a channel:** +**Create a Channel:** ```kotlin val connection = Usagi.connect("amqp://guest:guest@localhost:5672") val channel = connection.channels.create() ?: error("Unable to create channel") ``` -**using exchanges & queues** +**Using Exchanges & Queues** ```kotlin channel.exchange.declare { exchange = "my-exchange" @@ -49,7 +54,7 @@ channel.queue.bind { } ``` -**publishing messages:** +**Publishing Messages:** ```kotlin channel.basic.publish { data = "Hello, World!".decodeToString() @@ -65,7 +70,7 @@ channel.basic.publish { } ``` -**consuming messages:** +**Consuming Messages:** ```kotlin val consumer = channel.basic.consume { exchangeName = "my-exchange" @@ -78,8 +83,12 @@ consumer.on { } ``` -## acknowledgements +## Acknowledgements - a bit of the internal connection/channel code was adapted from the [official rabbitmq java client](https://github.com/rabbitmq/rabbitmq-java-client) - [amqp 0.9.1 spec](https://www.rabbitmq.com/resources/specs/amqp0-9-1.pdf) - [amqp 0.9.1 doc](https://www.rabbitmq.com/resources/specs/amqp-xml-doc0-9-1.pdf) + +--- + +[Dimensional Fun](https://dimensional.fun) diff --git a/TODO.md b/TODO.md index 5e5bd17..cdb3df0 100644 --- a/TODO.md +++ b/TODO.md @@ -6,4 +6,4 @@ - [ ] connections * [ ] handle consumer cancellation -probably more that i need to write down but ill do that later! +probably more that I need to write down but ill do that later! diff --git a/build.gradle.kts b/build.gradle.kts index 01d07b0..0a235ee 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,32 +1,32 @@ import codegen.GenerateAMQPClasses +import lol.dimensional.gradle.dsl.Version +import lol.dimensional.gradle.dsl.ReleaseType +import lol.dimensional.gradle.dsl.by plugins { - kotlin("multiplatform") + `maven-publish` - kotlin("plugin.serialization") version "1.7.10" + kotlin("multiplatform") + kotlin("plugin.serialization") version "1.8.0" } -allprojects { - group = "mixtape.oss.usagi" +val versionRef = Version(0, 0, 1, release = ReleaseType.Snapshot) +version = "$versionRef" +group = "dimensional.usagi" - repositories { - mavenCentral() +repositories { + mavenCentral() - maven(url = "https://maven.dimensional.fun/releases") - maven(url = "https://jitpack.io") - } -} - -tasks { - create("generateAmqpClasses") { - outputDirectory.set(file("src/commonGenerated")) - } + maven(url = "https://maven.dimensional.fun/releases") + maven(url = "https://jitpack.io") } kotlin { explicitApi() jvm { + withJava() + compilations.all { kotlinOptions.jvmTarget = compiler.jvm.target } @@ -37,7 +37,7 @@ kotlin { } jvmToolchain { - languageVersion.set(JavaLanguageVersion.of(11)) // "8" + languageVersion by JavaLanguageVersion.of(11) } linuxX64() @@ -51,15 +51,95 @@ kotlin { kotlin.srcDir("src/commonGenerated") dependencies { - implementation(libs.bundles.common) - implementation(libs.ktor.network) - implementation(libs.kyuso) + implementation(kotlin("stdlib")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.1") + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0") + + implementation("mixtape.oss:kyuso:1.0.2") + + implementation("io.github.microutils:kotlin-logging:2.1.23") + + implementation("io.ktor:ktor-network:2.2.2") + implementation("io.ktor:ktor-network-tls:2.2.2") + implementation("io.ktor:ktor-http:2.2.2") } } getByName("jvmTest").dependencies { - implementation(libs.logback) implementation("com.rabbitmq:amqp-client:5.15.0") + implementation("ch.qos.logback:logback-classic:1.2.11") } } } + +tasks { + val jvmMainClasses by named("jvmMainClasses") { + dependsOn("compileJava") + } + + val jvmTestClasses by named("jvmTestClasses") { + dependsOn("compileJava") + } + + create("generateAmqpClasses") { + outputDirectory by file("src/commonGenerated") + } + + publishing { + repositories { + dimensionalFun( + versionRef.repository, + System.getenv("REPO_ALIAS"), + System.getenv("REPO_TOKEN"), + true + ) + } + + publications.filterIsInstance().forEach { publication -> + publication.pom { + name by project.name + description by "\uD83D\uDC30 kotlin multi-platform rabbitmq client" + url by "https://github.com/dimensional-fun/usagi" + + organization { + name by "Dimensional Fun" + url by "https://www.dimensional.fun" + } + + developers { + developer { + name by "Dimensional Fun" + email by "opensource@dimensional.fun" + url by "https://opensource.dimensional.fun" + } + + developer { + name by "melike2d" + email by "hi@2d.gay" + url by "https://2d.gay" + } + } + + licenses { + license { + name by "Apache-2.0" + url by "https://opensource.org/licenses/Apache-2.0" + } + } + + issueManagement { + system by "GitHub" + url by "https://github.com/dimensional-fun/usagi/issues" + } + + scm { + connection by "scm:git:ssh://github.com/dimensional-fun/usagi.git" + developerConnection by "scm:git:ssh://git@github.com/dimensional-fun/usagi.git" + url by "https://github.com/dimensional-fun/usagi" + } + } + } + } +} + diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 8758ea6..00617c0 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -11,17 +11,16 @@ repositories { dependencies { /* gradle bullshit */ - implementation(kotlin("gradle-plugin", version = "1.7.10")) + implementation(kotlin("gradle-plugin", version = "1.8.0")) implementation(gradleApi()) implementation(localGroovy()) /* misc */ -// implementation("org.jetbrains.kotlinx:atomicfu-gradle-plugin:0.17.3") - implementation("fun.dimensional.gradle:gradle-tools:1.0.3") + implementation("fun.dimensional.gradle:gradle-tools:1.1.2") /* used for code-generation */ - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") implementation("com.squareup.okhttp3:okhttp:4.9.3") implementation("com.squareup:kotlinpoet:1.12.0") } diff --git a/buildSrc/src/main/kotlin/codegen/classes.kt b/buildSrc/src/main/kotlin/codegen/classes.kt index 70c0d2f..96fa285 100644 --- a/buildSrc/src/main/kotlin/codegen/classes.kt +++ b/buildSrc/src/main/kotlin/codegen/classes.kt @@ -17,7 +17,7 @@ fun generateAMQP(name: String, classes: List): FileSpec { fun generateAMQPObject(name: String, amqpClasses: List): TypeSpec { val classHolder = TypeSpec.objectBuilder(name) .addModifiers(KModifier.PUBLIC) - //.addKdoc("Container class for auto-generated AMQP classes & their methods.") +// .addKdoc("Container class for auto-generated AMQP classes & their methods.") for (amqpClass in amqpClasses) { val spec = generateAMQPClass(amqpClass) @@ -37,11 +37,10 @@ fun TypeSpec.Builder.amqpReadMethodFromFunction(amqpClasses: List): .returns(METHOD) spec.addCode( - """ - |val classId = reader.readShortUnsigned().toInt() - |val methodId = reader.readShortUnsigned().toInt() - |return when (classId) { - |""".trimMargin() + """|val classId = reader.readShortUnsigned().toInt() + |val methodId = reader.readShortUnsigned().toInt() + |return when (classId) { + |""".trimMargin() ) for (amqpClass in amqpClasses) { @@ -56,7 +55,10 @@ fun TypeSpec.Builder.amqpReadMethodFromFunction(amqpClasses: List): fun AMQP.Class.createWhenMethodId(): String = """when (methodId) { - ${methods.joinToString("\n") { "|$INDENT${it.id} -> ${normalizedName}.${it.normalizedName}(reader)" }} + ${methods.joinToString("\n") { + val expression = "${normalizedName}.${it.normalizedName}" + "|$INDENT${it.id} -> $expression${if (it.arguments.isNotEmpty()) "(reader)" else ""}" + }} |${INDENT}else -> error("Invalid method id ${"$"}methodId for class ${"$"}classId") |} """.replaceIndentByMargin(INDENT) diff --git a/buildSrc/src/main/kotlin/codegen/common.kt b/buildSrc/src/main/kotlin/codegen/common.kt index b31184a..6a18c2e 100644 --- a/buildSrc/src/main/kotlin/codegen/common.kt +++ b/buildSrc/src/main/kotlin/codegen/common.kt @@ -9,7 +9,7 @@ fun TypeSpec.Builder.amqpToBuilderFunction(parent: AMQP.Parent): TypeSpec.Builde toBuilder.addCode("return Builder()\n") for (child in parent.children) { - toBuilder.addCode(" .${child.normalizedName}(${child.normalizedName})\n") + toBuilder.addCode("$INDENT.${child.normalizedName}(${child.normalizedName})\n") } return addFunction(toBuilder.build()) @@ -21,14 +21,15 @@ fun amqpCompanionBuilderFunction(returnType: TypeName): FunSpec { .addModifiers(KModifier.PUBLIC, KModifier.INLINE, KModifier.OPERATOR) .addParameter( ParameterSpec - .builder("block", LambdaTypeName.get(ClassName("", "Builder"), returnType = UNIT)) - .defaultValue("{}") - .build()) - .addCode(""" - |return Builder() - | .apply(block) - | .build() - """.trimMargin()) + .builder("block", LambdaTypeName.get(ClassName("", "Builder"), returnType = UNIT)) + .defaultValue("{}") + .build() + ) + .addCode( + """|return Builder() + |$INDENT.apply(block) + |$INDENT.build()""".trimMargin() + ) .returns(returnType) .build() } diff --git a/buildSrc/src/main/kotlin/codegen/constants.kt b/buildSrc/src/main/kotlin/codegen/constants.kt index 44fd115..ecec6ab 100644 --- a/buildSrc/src/main/kotlin/codegen/constants.kt +++ b/buildSrc/src/main/kotlin/codegen/constants.kt @@ -5,7 +5,8 @@ import com.squareup.kotlinpoet.ClassName val protocolPackage = project.rootPackage + ".protocol" val channelPackage = project.rootPackage + ".channel" -val INDENT = " " +//val INDENT = " " +val INDENT = " " val DELEGATES = ClassName("kotlin.properties", "Delegates") diff --git a/buildSrc/src/main/kotlin/codegen/methods.kt b/buildSrc/src/main/kotlin/codegen/methods.kt index 4f9e7d6..40490ef 100644 --- a/buildSrc/src/main/kotlin/codegen/methods.kt +++ b/buildSrc/src/main/kotlin/codegen/methods.kt @@ -6,19 +6,21 @@ fun generateMethodClass( amqpClass: AMQP.Class, amqpMethod: AMQP.Method, ): TypeSpec { - val specBuilder = TypeSpec.classBuilder(amqpMethod.normalizedName) - .superclass(METHOD) - .addModifiers(KModifier.PUBLIC) - //.addKdoc("Represents the AMQP method `${amqpClass.name}.${amqpMethod.name}` (${amqpMethod.id})") - - if (amqpMethod.arguments.isNotEmpty()) { - specBuilder - .addModifiers(KModifier.DATA) + val specBuilder = if (amqpMethod.arguments.isNotEmpty()) { + TypeSpec.classBuilder(amqpMethod.normalizedName) + .superclass(METHOD) + .addModifiers(KModifier.PUBLIC, KModifier.DATA) .amqpMethodPrimaryConstructor(amqpMethod) + .amqpMethodCompanionObject(amqpMethod) + .amqpMethodBuilderClass(amqpMethod) + .amqpToBuilderFunction(amqpMethod) + } else { + TypeSpec.objectBuilder(amqpMethod.normalizedName) + .superclass(METHOD) + .addModifiers(KModifier.PUBLIC) } return specBuilder - .amqpMethodCompanionObject(amqpMethod) .overrideMethod("classId", SHORT) { addCode("return %L",amqpClass.id) } .overrideMethod("methodId", SHORT) { addCode("return %L", amqpMethod.id) } .overrideMethod("methodName", STRING) { addCode("return %S", "${amqpClass.name}.${amqpMethod.name}") } @@ -30,8 +32,6 @@ fun generateMethodClass( .amqpWriteArguments(amqpMethod) .build() ) - .amqpMethodBuilderClass(amqpMethod) - .amqpToBuilderFunction(amqpMethod) .build() } @@ -40,10 +40,14 @@ fun TypeSpec.Builder.amqpMethodBuilderClass(amqpMethod: AMQP.Method): TypeSpec.B //.addKdoc("Convenience class for constructing an instance of [${amqpMethod.normalizedName}]") .addModifiers(KModifier.PUBLIC) - val builder = FunSpec.builder("build") + val buildMethod = FunSpec.builder("build") .returns(ClassName("", amqpMethod.normalizedName)) .addCode("return ${amqpMethod.normalizedName}(") + val copyFromMethod = FunSpec.builder("copyFrom") + .addParameter("other", ClassName("", "Builder")) + .returns(ClassName("", "Builder")) + for (argument in amqpMethod.arguments) { val type = argument.type.exposedType @@ -79,18 +83,25 @@ fun TypeSpec.Builder.amqpMethodBuilderClass(amqpMethod: AMQP.Method): TypeSpec.B spec.addFunction(function.build()) - /* add parameter to constructor call in builder. */ + /* add parameter to constructor call in the build method. */ val constructorArgument = CodeBlock.of(argument.normalizedName) - builder.addCode( + buildMethod.addCode( argument.type.convert?.takeIf { argument.type.internalType != argument.type.exposedType } ?: "%L", constructorArgument ) - builder.addCode(", ") + buildMethod.addCode(", ") + + /* add copy instruction to copyFrom method. */ + copyFromMethod.addCode("%L = other.%L\n", constructorArgument, constructorArgument) } - spec.addFunction(builder + spec.addFunction(copyFromMethod + .addCode("return this") + .build()) + + spec.addFunction(buildMethod .addCode(")") .build()) @@ -117,7 +128,7 @@ fun TypeSpec.Builder.amqpMethodCompanionObject(amqpMethod: AMQP.Method): TypeSpe fun FunSpec.Builder.amqpReadArguments(amqpMethod: AMQP.Method): FunSpec.Builder { addCode(""" |return ${amqpMethod.normalizedName}( - ${amqpMethod.arguments.joinToString(",\n") { "| reader.${it.type.readerMethod}()" }} + ${amqpMethod.arguments.joinToString(",\n") { "|${INDENT}reader.${it.type.readerMethod}()" }} |) """.trimMargin()) diff --git a/buildSrc/src/main/kotlin/codegen/properties.kt b/buildSrc/src/main/kotlin/codegen/properties.kt index e2a9f8e..1a7d970 100644 --- a/buildSrc/src/main/kotlin/codegen/properties.kt +++ b/buildSrc/src/main/kotlin/codegen/properties.kt @@ -99,11 +99,9 @@ fun TypeSpec.Builder.amqpClassPropertiesWriter(amqpClass: AMQP.Class): TypeSpec. } ) writeTo.addCode( - """ - | - |writer.finishPresence() - | - """.trimMargin() + """| + |writer.finishPresence() + |""".trimMargin() ) writeTo.addCode( @@ -116,15 +114,19 @@ fun TypeSpec.Builder.amqpClassPropertiesWriter(amqpClass: AMQP.Class): TypeSpec. return addFunction(writeTo.build()) } +/* Simplified version of the builder for methods */ fun TypeSpec.Builder.amqpClassPropertiesBuilder(amqpClass: AMQP.Class): TypeSpec.Builder { val spec = TypeSpec.classBuilder("Builder") .addModifiers(KModifier.PUBLIC) - val builder = FunSpec.builder("build") + val buildMethod = FunSpec.builder("build") .returns(ClassName("", "Properties")) .addCode("return Properties(") - // Simplified version of the builder for methods + val copyFromMethod = FunSpec.builder("copyFrom") + .addParameter("other", ClassName("", "Builder")) + .returns(ClassName("", "Builder")) + for (prop in amqpClass.properties) { spec.addProperty( PropertySpec @@ -153,17 +155,24 @@ fun TypeSpec.Builder.amqpClassPropertiesBuilder(amqpClass: AMQP.Class): TypeSpec .build() ) - /* add parameter to constructor call in builder. */ - builder.addCode("%L", prop.normalizedName) + /* add parameter to constructor call in `build` method. */ + buildMethod.addCode("%L", prop.normalizedName) prop.type.convert ?.takeIf { prop.type.internalType != prop.type.exposedType } - ?.let { builder.addCode("?.let { %L }", CodeBlock.of(it, "it")) } + ?.let { buildMethod.addCode("?.let { %L }", CodeBlock.of(it, "it")) } + + buildMethod.addCode(", ") - builder.addCode(", ") + /* add copy instruction to `copyFrom` method. */ + copyFromMethod.addCode("%L = other.%L\n", prop.normalizedName, prop.normalizedName) } + spec.addFunction(copyFromMethod + .addCode("return this") + .build()) + spec.addFunction( - builder + buildMethod .addCode(")") .build() ) diff --git a/buildSrc/src/main/kotlin/codegen/task.kt b/buildSrc/src/main/kotlin/codegen/task.kt index 22e17e0..e6246df 100644 --- a/buildSrc/src/main/kotlin/codegen/task.kt +++ b/buildSrc/src/main/kotlin/codegen/task.kt @@ -54,8 +54,6 @@ abstract class GenerateAMQPClasses : DefaultTask() { } catch (e: IOException) { project.logger.error("Unable to request to $CODE_GEN_DATA") } - - } private fun generate(fileSpec: FileSpec) { diff --git a/buildSrc/src/main/kotlin/codegen/types.kt b/buildSrc/src/main/kotlin/codegen/types.kt index 209e220..6ae373f 100644 --- a/buildSrc/src/main/kotlin/codegen/types.kt +++ b/buildSrc/src/main/kotlin/codegen/types.kt @@ -6,7 +6,6 @@ import com.squareup.kotlinpoet.* import kotlinx.serialization.json.* val LONG_STRING = ClassName("$protocolPackage.type", "LongString") -val FIELD_TABLE = ClassName("$protocolPackage.type", "FieldTable") val INSTANT = ClassName("kotlinx.datetime", "Instant") enum class RequiredBehavior { @@ -66,11 +65,11 @@ object AMQP { /** used to find this type within the codegen json */ val id: String get() = name.toLowerCase() - /** method within the ProtoolReader used to read this type. */ + /** method within the ProtocolReader used to read this type. */ val readerMethod: String get() = "read$libraryName" - /** method within the ProtoolWriter used to write this type. */ + /** method within the ProtocolWriter used to write this type. */ val writerMethod: String get() = "write$libraryName" diff --git a/buildSrc/src/main/kotlin/project.kt b/buildSrc/src/main/kotlin/project.kt index 7865a79..b845a42 100644 --- a/buildSrc/src/main/kotlin/project.kt +++ b/buildSrc/src/main/kotlin/project.kt @@ -1,3 +1,3 @@ object project { - val rootPackage = "mixtape.oss.usagi" + val rootPackage = "dimensional.usagi" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661..070cb70 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index c96d98b..54de011 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,42 +1 @@ -rootProject.name = "usagi-root" - -enableFeaturePreview("VERSION_CATALOGS") -enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") - -dependencyResolutionManagement { - versionCatalogs { - create("libs") { - application() - net() - common() - } - } -} - -/* application-specific libraries */ -fun VersionCatalogBuilder.application() { - /* logging */ - library("kotlin-logging", "io.github.microutils", "kotlin-logging").version("2.1.23") - library("logback", "ch.qos.logback", "logback-classic").version("1.2.11") -} - -/* common libraries */ -fun VersionCatalogBuilder.common() { - library("kyuso", "mixtape.oss", "kyuso").version("1.0.2") - - library("kotlin-stdlib", "org.jetbrains.kotlin", "kotlin-stdlib").version("1.7.10") - library("kotlinx-datetime", "org.jetbrains.kotlinx", "kotlinx-datetime").version("0.4.0") - library("kotlinx-coroutines", "org.jetbrains.kotlinx", "kotlinx-coroutines-core").version("1.6.4") - - bundle("common", listOf( - "kotlin-stdlib", - "kotlinx-coroutines", - "kotlinx-datetime", - "kotlin-logging" - )) -} - -/* networking */ -fun VersionCatalogBuilder.net() { - library("ktor-network", "io.ktor", "ktor-network").version("2.1.0") -} +rootProject.name = "usagi" diff --git a/src/commonGenerated/dimensional/usagi/protocol/AMQP.kt b/src/commonGenerated/dimensional/usagi/protocol/AMQP.kt new file mode 100644 index 0000000..448ac5e --- /dev/null +++ b/src/commonGenerated/dimensional/usagi/protocol/AMQP.kt @@ -0,0 +1,3944 @@ +// DO NOT EDIT THIS FILE! This was generated by the `./gradlew :generateAmqpClasses` task.` +package dimensional.usagi.protocol + +import dimensional.usagi.channel.command.ContentHeader +import dimensional.usagi.protocol.reader.MethodProtocolReader +import dimensional.usagi.protocol.reader.ProtocolPropertiesReader +import dimensional.usagi.protocol.writer.MethodProtocolWriter +import dimensional.usagi.protocol.writer.ProtocolPropertiesWriter +import kotlinx.datetime.Instant + +public object AMQP { + public suspend fun readMethodFrom(reader: MethodProtocolReader): Method { + val classId = reader.readShortUnsigned().toInt() + val methodId = reader.readShortUnsigned().toInt() + return when (classId) { + 10 -> when (methodId) { + 10 -> Connection.Start(reader) + 11 -> Connection.StartOk(reader) + 20 -> Connection.Secure(reader) + 21 -> Connection.SecureOk(reader) + 30 -> Connection.Tune(reader) + 31 -> Connection.TuneOk(reader) + 40 -> Connection.Open(reader) + 41 -> Connection.OpenOk(reader) + 50 -> Connection.Close(reader) + 51 -> Connection.CloseOk + 60 -> Connection.Blocked(reader) + 61 -> Connection.Unblocked + 70 -> Connection.UpdateSecret(reader) + 71 -> Connection.UpdateSecretOk + else -> error("Invalid method id $methodId for class $classId") + } + 20 -> when (methodId) { + 10 -> Channel.Open(reader) + 11 -> Channel.OpenOk(reader) + 20 -> Channel.Flow(reader) + 21 -> Channel.FlowOk(reader) + 40 -> Channel.Close(reader) + 41 -> Channel.CloseOk + else -> error("Invalid method id $methodId for class $classId") + } + 30 -> when (methodId) { + 10 -> Access.Request(reader) + 11 -> Access.RequestOk(reader) + else -> error("Invalid method id $methodId for class $classId") + } + 40 -> when (methodId) { + 10 -> Exchange.Declare(reader) + 11 -> Exchange.DeclareOk + 20 -> Exchange.Delete(reader) + 21 -> Exchange.DeleteOk + 30 -> Exchange.Bind(reader) + 31 -> Exchange.BindOk + 40 -> Exchange.Unbind(reader) + 51 -> Exchange.UnbindOk + else -> error("Invalid method id $methodId for class $classId") + } + 50 -> when (methodId) { + 10 -> Queue.Declare(reader) + 11 -> Queue.DeclareOk(reader) + 20 -> Queue.Bind(reader) + 21 -> Queue.BindOk + 30 -> Queue.Purge(reader) + 31 -> Queue.PurgeOk(reader) + 40 -> Queue.Delete(reader) + 41 -> Queue.DeleteOk(reader) + 50 -> Queue.Unbind(reader) + 51 -> Queue.UnbindOk + else -> error("Invalid method id $methodId for class $classId") + } + 60 -> when (methodId) { + 10 -> Basic.Qos(reader) + 11 -> Basic.QosOk + 20 -> Basic.Consume(reader) + 21 -> Basic.ConsumeOk(reader) + 30 -> Basic.Cancel(reader) + 31 -> Basic.CancelOk(reader) + 40 -> Basic.Publish(reader) + 50 -> Basic.Return(reader) + 60 -> Basic.Deliver(reader) + 70 -> Basic.Get(reader) + 71 -> Basic.GetOk(reader) + 72 -> Basic.GetEmpty(reader) + 80 -> Basic.Ack(reader) + 90 -> Basic.Reject(reader) + 100 -> Basic.RecoverAsync(reader) + 110 -> Basic.Recover(reader) + 111 -> Basic.RecoverOk + 120 -> Basic.Nack(reader) + else -> error("Invalid method id $methodId for class $classId") + } + 90 -> when (methodId) { + 10 -> Tx.Select + 11 -> Tx.SelectOk + 20 -> Tx.Commit + 21 -> Tx.CommitOk + 30 -> Tx.Rollback + 31 -> Tx.RollbackOk + else -> error("Invalid method id $methodId for class $classId") + } + 85 -> when (methodId) { + 10 -> Confirm.Select(reader) + 11 -> Confirm.SelectOk + else -> error("Invalid method id $methodId for class $classId") + } + else -> error("Invalid class id: $classId") + } + } + + public suspend fun readPropertiesFrom(classId: Short, reader: ProtocolPropertiesReader): + ContentHeader.Properties = when (classId.toInt()) { + 60 -> Basic.Properties(reader) + else -> error("Invalid class id: $classId") + } + + public object Connection { + public data class Start( + public val versionMajor: Int, + public val versionMinor: Int, + public val serverProperties: Map, + public val mechanisms: LongString, + public val locales: LongString, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .versionMajor(versionMajor) + .versionMinor(versionMinor) + .serverProperties(serverProperties) + .mechanisms(mechanisms) + .locales(locales) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 10 + + public override fun methodName(): String = "connection.start" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeOctet(versionMajor) + writer.writeOctet(versionMinor) + writer.writeFieldTable(serverProperties) + writer.writeLongString(mechanisms) + writer.writeLongString(locales) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Start = Start( + reader.readOctet(), + reader.readOctet(), + reader.readFieldTable(), + reader.readLongString(), + reader.readLongString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Start = Builder() + .apply(block) + .build() + } + + public class Builder { + public var versionMajor: Int = 0 + + public var versionMinor: Int = 9 + + public lateinit var serverProperties: Map + + public var mechanisms: LongString = LongString("PLAIN") + + public var locales: LongString = LongString("en_US") + + public fun versionMajor(`value`: Int): Builder { + versionMajor = value + return this + } + + public fun versionMinor(`value`: Int): Builder { + versionMinor = value + return this + } + + public fun serverProperties(`value`: Map): Builder { + serverProperties = value + return this + } + + public fun mechanisms(`value`: LongString): Builder { + mechanisms = value + return this + } + + public fun locales(`value`: LongString): Builder { + locales = value + return this + } + + public fun copyFrom(other: Builder): Builder { + versionMajor = other.versionMajor + versionMinor = other.versionMinor + serverProperties = other.serverProperties + mechanisms = other.mechanisms + locales = other.locales + return this + } + + public fun build(): Start = Start(versionMajor, versionMinor, serverProperties, mechanisms, + locales, ) + } + } + + public data class StartOk( + public val clientProperties: Map, + public val mechanism: String, + public val response: LongString, + public val locale: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .clientProperties(clientProperties) + .mechanism(mechanism) + .response(response) + .locale(locale) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 11 + + public override fun methodName(): String = "connection.start-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeFieldTable(clientProperties) + writer.writeShortString(mechanism) + writer.writeLongString(response) + writer.writeShortString(locale) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): StartOk = StartOk( + reader.readFieldTable(), + reader.readShortString(), + reader.readLongString(), + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): StartOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public lateinit var clientProperties: Map + + public var mechanism: String = "PLAIN" + + public var response: LongString by kotlin.properties.Delegates.notNull() + + public var locale: String = "en_US" + + public fun clientProperties(`value`: Map): Builder { + clientProperties = value + return this + } + + public fun mechanism(`value`: String): Builder { + mechanism = value + return this + } + + public fun response(`value`: LongString): Builder { + response = value + return this + } + + public fun locale(`value`: String): Builder { + locale = value + return this + } + + public fun copyFrom(other: Builder): Builder { + clientProperties = other.clientProperties + mechanism = other.mechanism + response = other.response + locale = other.locale + return this + } + + public fun build(): StartOk = StartOk(clientProperties, mechanism, response, locale, ) + } + } + + public data class Secure( + public val challenge: LongString, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .challenge(challenge) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 20 + + public override fun methodName(): String = "connection.secure" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongString(challenge) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Secure = Secure( + reader.readLongString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Secure = Builder() + .apply(block) + .build() + } + + public class Builder { + public var challenge: LongString by kotlin.properties.Delegates.notNull() + + public fun challenge(`value`: LongString): Builder { + challenge = value + return this + } + + public fun copyFrom(other: Builder): Builder { + challenge = other.challenge + return this + } + + public fun build(): Secure = Secure(challenge, ) + } + } + + public data class SecureOk( + public val response: LongString, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .response(response) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 21 + + public override fun methodName(): String = "connection.secure-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongString(response) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): SecureOk = SecureOk( + reader.readLongString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): SecureOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public var response: LongString by kotlin.properties.Delegates.notNull() + + public fun response(`value`: LongString): Builder { + response = value + return this + } + + public fun copyFrom(other: Builder): Builder { + response = other.response + return this + } + + public fun build(): SecureOk = SecureOk(response, ) + } + } + + public data class Tune( + public val channelMax: Short, + public val frameMax: Int, + public val heartbeat: Short, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .channelMax(channelMax) + .frameMax(frameMax) + .heartbeat(heartbeat) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 30 + + public override fun methodName(): String = "connection.tune" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(channelMax) + writer.writeLongUnsigned(frameMax) + writer.writeShortUnsigned(heartbeat) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Tune = Tune( + reader.readShortUnsigned(), + reader.readLongUnsigned(), + reader.readShortUnsigned() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Tune = Builder() + .apply(block) + .build() + } + + public class Builder { + public var channelMax: Short = 0 + + public var frameMax: Int = 0 + + public var heartbeat: Short = 0 + + public fun channelMax(`value`: Short): Builder { + channelMax = value + return this + } + + public fun frameMax(`value`: Int): Builder { + frameMax = value + return this + } + + public fun heartbeat(`value`: Short): Builder { + heartbeat = value + return this + } + + public fun copyFrom(other: Builder): Builder { + channelMax = other.channelMax + frameMax = other.frameMax + heartbeat = other.heartbeat + return this + } + + public fun build(): Tune = Tune(channelMax, frameMax, heartbeat, ) + } + } + + public data class TuneOk( + public val channelMax: Short, + public val frameMax: Int, + public val heartbeat: Short, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .channelMax(channelMax) + .frameMax(frameMax) + .heartbeat(heartbeat) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 31 + + public override fun methodName(): String = "connection.tune-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(channelMax) + writer.writeLongUnsigned(frameMax) + writer.writeShortUnsigned(heartbeat) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): TuneOk = TuneOk( + reader.readShortUnsigned(), + reader.readLongUnsigned(), + reader.readShortUnsigned() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): TuneOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public var channelMax: Short = 0 + + public var frameMax: Int = 0 + + public var heartbeat: Short = 0 + + public fun channelMax(`value`: Short): Builder { + channelMax = value + return this + } + + public fun frameMax(`value`: Int): Builder { + frameMax = value + return this + } + + public fun heartbeat(`value`: Short): Builder { + heartbeat = value + return this + } + + public fun copyFrom(other: Builder): Builder { + channelMax = other.channelMax + frameMax = other.frameMax + heartbeat = other.heartbeat + return this + } + + public fun build(): TuneOk = TuneOk(channelMax, frameMax, heartbeat, ) + } + } + + public data class Open( + public val virtualHost: String, + public val capabilities: String, + public val insist: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .virtualHost(virtualHost) + .capabilities(capabilities) + .insist(insist) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 40 + + public override fun methodName(): String = "connection.open" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(virtualHost) + writer.writeShortString(capabilities) + writer.writeBit(insist) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Open = Open( + reader.readShortString(), + reader.readShortString(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Open = Builder() + .apply(block) + .build() + } + + public class Builder { + public var virtualHost: String = "/" + + public var capabilities: String = "" + + public var insist: Boolean = false + + public fun virtualHost(`value`: String): Builder { + virtualHost = value + return this + } + + public fun capabilities(`value`: String): Builder { + capabilities = value + return this + } + + public fun insist(`value`: Boolean): Builder { + insist = value + return this + } + + public fun copyFrom(other: Builder): Builder { + virtualHost = other.virtualHost + capabilities = other.capabilities + insist = other.insist + return this + } + + public fun build(): Open = Open(virtualHost, capabilities, insist, ) + } + } + + public data class OpenOk( + public val knownHosts: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .knownHosts(knownHosts) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 41 + + public override fun methodName(): String = "connection.open-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(knownHosts) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): OpenOk = OpenOk( + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): OpenOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public var knownHosts: String = "" + + public fun knownHosts(`value`: String): Builder { + knownHosts = value + return this + } + + public fun copyFrom(other: Builder): Builder { + knownHosts = other.knownHosts + return this + } + + public fun build(): OpenOk = OpenOk(knownHosts, ) + } + } + + public data class Close( + public val replyCode: Short, + public val replyText: String, + public val classId: Short, + public val methodId: Short, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .replyCode(replyCode) + .replyText(replyText) + .classId(classId) + .methodId(methodId) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 50 + + public override fun methodName(): String = "connection.close" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(replyCode) + writer.writeShortString(replyText) + writer.writeShortUnsigned(classId) + writer.writeShortUnsigned(methodId) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Close = Close( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortUnsigned(), + reader.readShortUnsigned() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Close = Builder() + .apply(block) + .build() + } + + public class Builder { + public var replyCode: Short by kotlin.properties.Delegates.notNull() + + public var replyText: String = "" + + public var classId: Short by kotlin.properties.Delegates.notNull() + + public var methodId: Short by kotlin.properties.Delegates.notNull() + + public fun replyCode(`value`: Short): Builder { + replyCode = value + return this + } + + public fun replyText(`value`: String): Builder { + replyText = value + return this + } + + public fun classId(`value`: Short): Builder { + classId = value + return this + } + + public fun methodId(`value`: Short): Builder { + methodId = value + return this + } + + public fun copyFrom(other: Builder): Builder { + replyCode = other.replyCode + replyText = other.replyText + classId = other.classId + methodId = other.methodId + return this + } + + public fun build(): Close = Close(replyCode, replyText, classId, methodId, ) + } + } + + public object CloseOk : Method() { + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 51 + + public override fun methodName(): String = "connection.close-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public data class Blocked( + public val reason: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .reason(reason) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 60 + + public override fun methodName(): String = "connection.blocked" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(reason) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Blocked = Blocked( + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Blocked = Builder() + .apply(block) + .build() + } + + public class Builder { + public var reason: String = "" + + public fun reason(`value`: String): Builder { + reason = value + return this + } + + public fun copyFrom(other: Builder): Builder { + reason = other.reason + return this + } + + public fun build(): Blocked = Blocked(reason, ) + } + } + + public object Unblocked : Method() { + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 61 + + public override fun methodName(): String = "connection.unblocked" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public data class UpdateSecret( + public val newSecret: LongString, + public val reason: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .newSecret(newSecret) + .reason(reason) + + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 70 + + public override fun methodName(): String = "connection.update-secret" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongString(newSecret) + writer.writeShortString(reason) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): UpdateSecret = + UpdateSecret( + reader.readLongString(), + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): UpdateSecret = Builder() + .apply(block) + .build() + } + + public class Builder { + public var newSecret: LongString by kotlin.properties.Delegates.notNull() + + public lateinit var reason: String + + public fun newSecret(`value`: LongString): Builder { + newSecret = value + return this + } + + public fun reason(`value`: String): Builder { + reason = value + return this + } + + public fun copyFrom(other: Builder): Builder { + newSecret = other.newSecret + reason = other.reason + return this + } + + public fun build(): UpdateSecret = UpdateSecret(newSecret, reason, ) + } + } + + public object UpdateSecretOk : Method() { + public override fun classId(): Short = 10 + + public override fun methodId(): Short = 71 + + public override fun methodName(): String = "connection.update-secret-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + } + + public object Channel { + public data class Open( + public val outOfBand: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .outOfBand(outOfBand) + + public override fun classId(): Short = 20 + + public override fun methodId(): Short = 10 + + public override fun methodName(): String = "channel.open" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(outOfBand) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Open = Open( + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Open = Builder() + .apply(block) + .build() + } + + public class Builder { + public var outOfBand: String = "" + + public fun outOfBand(`value`: String): Builder { + outOfBand = value + return this + } + + public fun copyFrom(other: Builder): Builder { + outOfBand = other.outOfBand + return this + } + + public fun build(): Open = Open(outOfBand, ) + } + } + + public data class OpenOk( + public val channelId: LongString, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .channelId(channelId) + + public override fun classId(): Short = 20 + + public override fun methodId(): Short = 11 + + public override fun methodName(): String = "channel.open-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongString(channelId) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): OpenOk = OpenOk( + reader.readLongString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): OpenOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public var channelId: LongString = LongString("") + + public fun channelId(`value`: LongString): Builder { + channelId = value + return this + } + + public fun copyFrom(other: Builder): Builder { + channelId = other.channelId + return this + } + + public fun build(): OpenOk = OpenOk(channelId, ) + } + } + + public data class Flow( + public val active: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .active(active) + + public override fun classId(): Short = 20 + + public override fun methodId(): Short = 20 + + public override fun methodName(): String = "channel.flow" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeBit(active) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Flow = Flow( + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Flow = Builder() + .apply(block) + .build() + } + + public class Builder { + public var active: Boolean by kotlin.properties.Delegates.notNull() + + public fun active(`value`: Boolean): Builder { + active = value + return this + } + + public fun copyFrom(other: Builder): Builder { + active = other.active + return this + } + + public fun build(): Flow = Flow(active, ) + } + } + + public data class FlowOk( + public val active: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .active(active) + + public override fun classId(): Short = 20 + + public override fun methodId(): Short = 21 + + public override fun methodName(): String = "channel.flow-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeBit(active) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): FlowOk = FlowOk( + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): FlowOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public var active: Boolean by kotlin.properties.Delegates.notNull() + + public fun active(`value`: Boolean): Builder { + active = value + return this + } + + public fun copyFrom(other: Builder): Builder { + active = other.active + return this + } + + public fun build(): FlowOk = FlowOk(active, ) + } + } + + public data class Close( + public val replyCode: Short, + public val replyText: String, + public val classId: Short, + public val methodId: Short, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .replyCode(replyCode) + .replyText(replyText) + .classId(classId) + .methodId(methodId) + + public override fun classId(): Short = 20 + + public override fun methodId(): Short = 40 + + public override fun methodName(): String = "channel.close" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(replyCode) + writer.writeShortString(replyText) + writer.writeShortUnsigned(classId) + writer.writeShortUnsigned(methodId) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Close = Close( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortUnsigned(), + reader.readShortUnsigned() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Close = Builder() + .apply(block) + .build() + } + + public class Builder { + public var replyCode: Short by kotlin.properties.Delegates.notNull() + + public var replyText: String = "" + + public var classId: Short by kotlin.properties.Delegates.notNull() + + public var methodId: Short by kotlin.properties.Delegates.notNull() + + public fun replyCode(`value`: Short): Builder { + replyCode = value + return this + } + + public fun replyText(`value`: String): Builder { + replyText = value + return this + } + + public fun classId(`value`: Short): Builder { + classId = value + return this + } + + public fun methodId(`value`: Short): Builder { + methodId = value + return this + } + + public fun copyFrom(other: Builder): Builder { + replyCode = other.replyCode + replyText = other.replyText + classId = other.classId + methodId = other.methodId + return this + } + + public fun build(): Close = Close(replyCode, replyText, classId, methodId, ) + } + } + + public object CloseOk : Method() { + public override fun classId(): Short = 20 + + public override fun methodId(): Short = 41 + + public override fun methodName(): String = "channel.close-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + } + + public object Access { + public data class Request( + public val realm: String, + public val exclusive: Boolean, + public val passive: Boolean, + public val active: Boolean, + public val write: Boolean, + public val read: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .realm(realm) + .exclusive(exclusive) + .passive(passive) + .active(active) + .write(write) + .read(read) + + public override fun classId(): Short = 30 + + public override fun methodId(): Short = 10 + + public override fun methodName(): String = "access.request" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(realm) + writer.writeBit(exclusive) + writer.writeBit(passive) + writer.writeBit(active) + writer.writeBit(write) + writer.writeBit(read) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Request = Request( + reader.readShortString(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Request = Builder() + .apply(block) + .build() + } + + public class Builder { + public var realm: String = "/data" + + public var exclusive: Boolean = false + + public var passive: Boolean = true + + public var active: Boolean = true + + public var write: Boolean = true + + public var read: Boolean = true + + public fun realm(`value`: String): Builder { + realm = value + return this + } + + public fun exclusive(`value`: Boolean): Builder { + exclusive = value + return this + } + + public fun passive(`value`: Boolean): Builder { + passive = value + return this + } + + public fun active(`value`: Boolean): Builder { + active = value + return this + } + + public fun write(`value`: Boolean): Builder { + write = value + return this + } + + public fun read(`value`: Boolean): Builder { + read = value + return this + } + + public fun copyFrom(other: Builder): Builder { + realm = other.realm + exclusive = other.exclusive + passive = other.passive + active = other.active + write = other.write + read = other.read + return this + } + + public fun build(): Request = Request(realm, exclusive, passive, active, write, read, ) + } + } + + public data class RequestOk( + public val ticket: Short, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + + public override fun classId(): Short = 30 + + public override fun methodId(): Short = 11 + + public override fun methodName(): String = "access.request-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): RequestOk = RequestOk( + reader.readShortUnsigned() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): RequestOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 1 + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + return this + } + + public fun build(): RequestOk = RequestOk(ticket, ) + } + } + } + + public object Exchange { + public data class Declare( + public val ticket: Short, + public val exchange: String, + public val type: String, + public val passive: Boolean, + public val durable: Boolean, + public val autoDelete: Boolean, + public val `internal`: Boolean, + public val nowait: Boolean, + public val arguments: Map, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .exchange(exchange) + .type(type) + .passive(passive) + .durable(durable) + .autoDelete(autoDelete) + .internal(internal) + .nowait(nowait) + .arguments(arguments) + + public override fun classId(): Short = 40 + + public override fun methodId(): Short = 10 + + public override fun methodName(): String = "exchange.declare" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(exchange) + writer.writeShortString(type) + writer.writeBit(passive) + writer.writeBit(durable) + writer.writeBit(autoDelete) + writer.writeBit(internal) + writer.writeBit(nowait) + writer.writeFieldTable(arguments) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Declare = Declare( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortString(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readFieldTable() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Declare = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public lateinit var exchange: String + + public var type: String = "direct" + + public var passive: Boolean = false + + public var durable: Boolean = false + + public var autoDelete: Boolean = false + + public var `internal`: Boolean = false + + public var nowait: Boolean = false + + public var arguments: Map = mapOf() + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun exchange(`value`: String): Builder { + exchange = value + return this + } + + public fun type(`value`: String): Builder { + type = value + return this + } + + public fun passive(`value`: Boolean): Builder { + passive = value + return this + } + + public fun durable(`value`: Boolean): Builder { + durable = value + return this + } + + public fun autoDelete(`value`: Boolean): Builder { + autoDelete = value + return this + } + + public fun `internal`(`value`: Boolean): Builder { + internal = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun arguments(`value`: Map): Builder { + arguments = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + exchange = other.exchange + type = other.type + passive = other.passive + durable = other.durable + autoDelete = other.autoDelete + internal = other.internal + nowait = other.nowait + arguments = other.arguments + return this + } + + public fun build(): Declare = Declare(ticket, exchange, type, passive, durable, autoDelete, + internal, nowait, arguments, ) + } + } + + public object DeclareOk : Method() { + public override fun classId(): Short = 40 + + public override fun methodId(): Short = 11 + + public override fun methodName(): String = "exchange.declare-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public data class Delete( + public val ticket: Short, + public val exchange: String, + public val ifUnused: Boolean, + public val nowait: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .exchange(exchange) + .ifUnused(ifUnused) + .nowait(nowait) + + public override fun classId(): Short = 40 + + public override fun methodId(): Short = 20 + + public override fun methodName(): String = "exchange.delete" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(exchange) + writer.writeBit(ifUnused) + writer.writeBit(nowait) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Delete = Delete( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readBit(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Delete = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public lateinit var exchange: String + + public var ifUnused: Boolean = false + + public var nowait: Boolean = false + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun exchange(`value`: String): Builder { + exchange = value + return this + } + + public fun ifUnused(`value`: Boolean): Builder { + ifUnused = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + exchange = other.exchange + ifUnused = other.ifUnused + nowait = other.nowait + return this + } + + public fun build(): Delete = Delete(ticket, exchange, ifUnused, nowait, ) + } + } + + public object DeleteOk : Method() { + public override fun classId(): Short = 40 + + public override fun methodId(): Short = 21 + + public override fun methodName(): String = "exchange.delete-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public data class Bind( + public val ticket: Short, + public val destination: String, + public val source: String, + public val routingKey: String, + public val nowait: Boolean, + public val arguments: Map, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .destination(destination) + .source(source) + .routingKey(routingKey) + .nowait(nowait) + .arguments(arguments) + + public override fun classId(): Short = 40 + + public override fun methodId(): Short = 30 + + public override fun methodName(): String = "exchange.bind" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(destination) + writer.writeShortString(source) + writer.writeShortString(routingKey) + writer.writeBit(nowait) + writer.writeFieldTable(arguments) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Bind = Bind( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortString(), + reader.readShortString(), + reader.readBit(), + reader.readFieldTable() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Bind = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public lateinit var destination: String + + public lateinit var source: String + + public var routingKey: String = "" + + public var nowait: Boolean = false + + public var arguments: Map = mapOf() + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun destination(`value`: String): Builder { + destination = value + return this + } + + public fun source(`value`: String): Builder { + source = value + return this + } + + public fun routingKey(`value`: String): Builder { + routingKey = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun arguments(`value`: Map): Builder { + arguments = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + destination = other.destination + source = other.source + routingKey = other.routingKey + nowait = other.nowait + arguments = other.arguments + return this + } + + public fun build(): Bind = Bind(ticket, destination, source, routingKey, nowait, arguments, + ) + } + } + + public object BindOk : Method() { + public override fun classId(): Short = 40 + + public override fun methodId(): Short = 31 + + public override fun methodName(): String = "exchange.bind-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public data class Unbind( + public val ticket: Short, + public val destination: String, + public val source: String, + public val routingKey: String, + public val nowait: Boolean, + public val arguments: Map, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .destination(destination) + .source(source) + .routingKey(routingKey) + .nowait(nowait) + .arguments(arguments) + + public override fun classId(): Short = 40 + + public override fun methodId(): Short = 40 + + public override fun methodName(): String = "exchange.unbind" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(destination) + writer.writeShortString(source) + writer.writeShortString(routingKey) + writer.writeBit(nowait) + writer.writeFieldTable(arguments) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Unbind = Unbind( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortString(), + reader.readShortString(), + reader.readBit(), + reader.readFieldTable() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Unbind = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public lateinit var destination: String + + public lateinit var source: String + + public var routingKey: String = "" + + public var nowait: Boolean = false + + public var arguments: Map = mapOf() + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun destination(`value`: String): Builder { + destination = value + return this + } + + public fun source(`value`: String): Builder { + source = value + return this + } + + public fun routingKey(`value`: String): Builder { + routingKey = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun arguments(`value`: Map): Builder { + arguments = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + destination = other.destination + source = other.source + routingKey = other.routingKey + nowait = other.nowait + arguments = other.arguments + return this + } + + public fun build(): Unbind = Unbind(ticket, destination, source, routingKey, nowait, + arguments, ) + } + } + + public object UnbindOk : Method() { + public override fun classId(): Short = 40 + + public override fun methodId(): Short = 51 + + public override fun methodName(): String = "exchange.unbind-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + } + + public object Queue { + public data class Declare( + public val ticket: Short, + public val queue: String, + public val passive: Boolean, + public val durable: Boolean, + public val exclusive: Boolean, + public val autoDelete: Boolean, + public val nowait: Boolean, + public val arguments: Map, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .queue(queue) + .passive(passive) + .durable(durable) + .exclusive(exclusive) + .autoDelete(autoDelete) + .nowait(nowait) + .arguments(arguments) + + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 10 + + public override fun methodName(): String = "queue.declare" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(queue) + writer.writeBit(passive) + writer.writeBit(durable) + writer.writeBit(exclusive) + writer.writeBit(autoDelete) + writer.writeBit(nowait) + writer.writeFieldTable(arguments) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Declare = Declare( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readFieldTable() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Declare = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public var queue: String = "" + + public var passive: Boolean = false + + public var durable: Boolean = false + + public var exclusive: Boolean = false + + public var autoDelete: Boolean = false + + public var nowait: Boolean = false + + public var arguments: Map = mapOf() + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun queue(`value`: String): Builder { + queue = value + return this + } + + public fun passive(`value`: Boolean): Builder { + passive = value + return this + } + + public fun durable(`value`: Boolean): Builder { + durable = value + return this + } + + public fun exclusive(`value`: Boolean): Builder { + exclusive = value + return this + } + + public fun autoDelete(`value`: Boolean): Builder { + autoDelete = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun arguments(`value`: Map): Builder { + arguments = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + queue = other.queue + passive = other.passive + durable = other.durable + exclusive = other.exclusive + autoDelete = other.autoDelete + nowait = other.nowait + arguments = other.arguments + return this + } + + public fun build(): Declare = Declare(ticket, queue, passive, durable, exclusive, + autoDelete, nowait, arguments, ) + } + } + + public data class DeclareOk( + public val queue: String, + public val messageCount: Int, + public val consumerCount: Int, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .queue(queue) + .messageCount(messageCount) + .consumerCount(consumerCount) + + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 11 + + public override fun methodName(): String = "queue.declare-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(queue) + writer.writeLongUnsigned(messageCount) + writer.writeLongUnsigned(consumerCount) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): DeclareOk = DeclareOk( + reader.readShortString(), + reader.readLongUnsigned(), + reader.readLongUnsigned() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): DeclareOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public lateinit var queue: String + + public var messageCount: Int by kotlin.properties.Delegates.notNull() + + public var consumerCount: Int by kotlin.properties.Delegates.notNull() + + public fun queue(`value`: String): Builder { + queue = value + return this + } + + public fun messageCount(`value`: Int): Builder { + messageCount = value + return this + } + + public fun consumerCount(`value`: Int): Builder { + consumerCount = value + return this + } + + public fun copyFrom(other: Builder): Builder { + queue = other.queue + messageCount = other.messageCount + consumerCount = other.consumerCount + return this + } + + public fun build(): DeclareOk = DeclareOk(queue, messageCount, consumerCount, ) + } + } + + public data class Bind( + public val ticket: Short, + public val queue: String, + public val exchange: String, + public val routingKey: String, + public val nowait: Boolean, + public val arguments: Map, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .queue(queue) + .exchange(exchange) + .routingKey(routingKey) + .nowait(nowait) + .arguments(arguments) + + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 20 + + public override fun methodName(): String = "queue.bind" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(queue) + writer.writeShortString(exchange) + writer.writeShortString(routingKey) + writer.writeBit(nowait) + writer.writeFieldTable(arguments) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Bind = Bind( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortString(), + reader.readShortString(), + reader.readBit(), + reader.readFieldTable() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Bind = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public var queue: String = "" + + public lateinit var exchange: String + + public var routingKey: String = "" + + public var nowait: Boolean = false + + public var arguments: Map = mapOf() + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun queue(`value`: String): Builder { + queue = value + return this + } + + public fun exchange(`value`: String): Builder { + exchange = value + return this + } + + public fun routingKey(`value`: String): Builder { + routingKey = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun arguments(`value`: Map): Builder { + arguments = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + queue = other.queue + exchange = other.exchange + routingKey = other.routingKey + nowait = other.nowait + arguments = other.arguments + return this + } + + public fun build(): Bind = Bind(ticket, queue, exchange, routingKey, nowait, arguments, ) + } + } + + public object BindOk : Method() { + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 21 + + public override fun methodName(): String = "queue.bind-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public data class Purge( + public val ticket: Short, + public val queue: String, + public val nowait: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .queue(queue) + .nowait(nowait) + + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 30 + + public override fun methodName(): String = "queue.purge" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(queue) + writer.writeBit(nowait) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Purge = Purge( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Purge = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public var queue: String = "" + + public var nowait: Boolean = false + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun queue(`value`: String): Builder { + queue = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + queue = other.queue + nowait = other.nowait + return this + } + + public fun build(): Purge = Purge(ticket, queue, nowait, ) + } + } + + public data class PurgeOk( + public val messageCount: Int, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .messageCount(messageCount) + + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 31 + + public override fun methodName(): String = "queue.purge-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongUnsigned(messageCount) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): PurgeOk = PurgeOk( + reader.readLongUnsigned() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): PurgeOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public var messageCount: Int by kotlin.properties.Delegates.notNull() + + public fun messageCount(`value`: Int): Builder { + messageCount = value + return this + } + + public fun copyFrom(other: Builder): Builder { + messageCount = other.messageCount + return this + } + + public fun build(): PurgeOk = PurgeOk(messageCount, ) + } + } + + public data class Delete( + public val ticket: Short, + public val queue: String, + public val ifUnused: Boolean, + public val ifEmpty: Boolean, + public val nowait: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .queue(queue) + .ifUnused(ifUnused) + .ifEmpty(ifEmpty) + .nowait(nowait) + + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 40 + + public override fun methodName(): String = "queue.delete" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(queue) + writer.writeBit(ifUnused) + writer.writeBit(ifEmpty) + writer.writeBit(nowait) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Delete = Delete( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readBit(), + reader.readBit(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Delete = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public var queue: String = "" + + public var ifUnused: Boolean = false + + public var ifEmpty: Boolean = false + + public var nowait: Boolean = false + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun queue(`value`: String): Builder { + queue = value + return this + } + + public fun ifUnused(`value`: Boolean): Builder { + ifUnused = value + return this + } + + public fun ifEmpty(`value`: Boolean): Builder { + ifEmpty = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + queue = other.queue + ifUnused = other.ifUnused + ifEmpty = other.ifEmpty + nowait = other.nowait + return this + } + + public fun build(): Delete = Delete(ticket, queue, ifUnused, ifEmpty, nowait, ) + } + } + + public data class DeleteOk( + public val messageCount: Int, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .messageCount(messageCount) + + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 41 + + public override fun methodName(): String = "queue.delete-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongUnsigned(messageCount) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): DeleteOk = DeleteOk( + reader.readLongUnsigned() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): DeleteOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public var messageCount: Int by kotlin.properties.Delegates.notNull() + + public fun messageCount(`value`: Int): Builder { + messageCount = value + return this + } + + public fun copyFrom(other: Builder): Builder { + messageCount = other.messageCount + return this + } + + public fun build(): DeleteOk = DeleteOk(messageCount, ) + } + } + + public data class Unbind( + public val ticket: Short, + public val queue: String, + public val exchange: String, + public val routingKey: String, + public val arguments: Map, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .queue(queue) + .exchange(exchange) + .routingKey(routingKey) + .arguments(arguments) + + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 50 + + public override fun methodName(): String = "queue.unbind" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(queue) + writer.writeShortString(exchange) + writer.writeShortString(routingKey) + writer.writeFieldTable(arguments) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Unbind = Unbind( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortString(), + reader.readShortString(), + reader.readFieldTable() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Unbind = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public var queue: String = "" + + public lateinit var exchange: String + + public var routingKey: String = "" + + public var arguments: Map = mapOf() + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun queue(`value`: String): Builder { + queue = value + return this + } + + public fun exchange(`value`: String): Builder { + exchange = value + return this + } + + public fun routingKey(`value`: String): Builder { + routingKey = value + return this + } + + public fun arguments(`value`: Map): Builder { + arguments = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + queue = other.queue + exchange = other.exchange + routingKey = other.routingKey + arguments = other.arguments + return this + } + + public fun build(): Unbind = Unbind(ticket, queue, exchange, routingKey, arguments, ) + } + } + + public object UnbindOk : Method() { + public override fun classId(): Short = 50 + + public override fun methodId(): Short = 51 + + public override fun methodName(): String = "queue.unbind-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + } + + public object Basic { + public data class Qos( + public val prefetchSize: Int, + public val prefetchCount: Short, + public val global: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .prefetchSize(prefetchSize) + .prefetchCount(prefetchCount) + .global(global) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 10 + + public override fun methodName(): String = "basic.qos" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongUnsigned(prefetchSize) + writer.writeShortUnsigned(prefetchCount) + writer.writeBit(global) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Qos = Qos( + reader.readLongUnsigned(), + reader.readShortUnsigned(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Qos = Builder() + .apply(block) + .build() + } + + public class Builder { + public var prefetchSize: Int = 0 + + public var prefetchCount: Short = 0 + + public var global: Boolean = false + + public fun prefetchSize(`value`: Int): Builder { + prefetchSize = value + return this + } + + public fun prefetchCount(`value`: Short): Builder { + prefetchCount = value + return this + } + + public fun global(`value`: Boolean): Builder { + global = value + return this + } + + public fun copyFrom(other: Builder): Builder { + prefetchSize = other.prefetchSize + prefetchCount = other.prefetchCount + global = other.global + return this + } + + public fun build(): Qos = Qos(prefetchSize, prefetchCount, global, ) + } + } + + public object QosOk : Method() { + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 11 + + public override fun methodName(): String = "basic.qos-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public data class Consume( + public val ticket: Short, + public val queue: String, + public val consumerTag: String, + public val noLocal: Boolean, + public val noAck: Boolean, + public val exclusive: Boolean, + public val nowait: Boolean, + public val arguments: Map, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .queue(queue) + .consumerTag(consumerTag) + .noLocal(noLocal) + .noAck(noAck) + .exclusive(exclusive) + .nowait(nowait) + .arguments(arguments) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 20 + + public override fun methodName(): String = "basic.consume" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(queue) + writer.writeShortString(consumerTag) + writer.writeBit(noLocal) + writer.writeBit(noAck) + writer.writeBit(exclusive) + writer.writeBit(nowait) + writer.writeFieldTable(arguments) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Consume = Consume( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortString(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readBit(), + reader.readFieldTable() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Consume = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public var queue: String = "" + + public var consumerTag: String = "" + + public var noLocal: Boolean = false + + public var noAck: Boolean = false + + public var exclusive: Boolean = false + + public var nowait: Boolean = false + + public var arguments: Map = mapOf() + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun queue(`value`: String): Builder { + queue = value + return this + } + + public fun consumerTag(`value`: String): Builder { + consumerTag = value + return this + } + + public fun noLocal(`value`: Boolean): Builder { + noLocal = value + return this + } + + public fun noAck(`value`: Boolean): Builder { + noAck = value + return this + } + + public fun exclusive(`value`: Boolean): Builder { + exclusive = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun arguments(`value`: Map): Builder { + arguments = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + queue = other.queue + consumerTag = other.consumerTag + noLocal = other.noLocal + noAck = other.noAck + exclusive = other.exclusive + nowait = other.nowait + arguments = other.arguments + return this + } + + public fun build(): Consume = Consume(ticket, queue, consumerTag, noLocal, noAck, exclusive, + nowait, arguments, ) + } + } + + public data class ConsumeOk( + public val consumerTag: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .consumerTag(consumerTag) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 21 + + public override fun methodName(): String = "basic.consume-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(consumerTag) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): ConsumeOk = ConsumeOk( + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): ConsumeOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public lateinit var consumerTag: String + + public fun consumerTag(`value`: String): Builder { + consumerTag = value + return this + } + + public fun copyFrom(other: Builder): Builder { + consumerTag = other.consumerTag + return this + } + + public fun build(): ConsumeOk = ConsumeOk(consumerTag, ) + } + } + + public data class Cancel( + public val consumerTag: String, + public val nowait: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .consumerTag(consumerTag) + .nowait(nowait) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 30 + + public override fun methodName(): String = "basic.cancel" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(consumerTag) + writer.writeBit(nowait) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Cancel = Cancel( + reader.readShortString(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Cancel = Builder() + .apply(block) + .build() + } + + public class Builder { + public lateinit var consumerTag: String + + public var nowait: Boolean = false + + public fun consumerTag(`value`: String): Builder { + consumerTag = value + return this + } + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun copyFrom(other: Builder): Builder { + consumerTag = other.consumerTag + nowait = other.nowait + return this + } + + public fun build(): Cancel = Cancel(consumerTag, nowait, ) + } + } + + public data class CancelOk( + public val consumerTag: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .consumerTag(consumerTag) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 31 + + public override fun methodName(): String = "basic.cancel-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(consumerTag) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): CancelOk = CancelOk( + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): CancelOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public lateinit var consumerTag: String + + public fun consumerTag(`value`: String): Builder { + consumerTag = value + return this + } + + public fun copyFrom(other: Builder): Builder { + consumerTag = other.consumerTag + return this + } + + public fun build(): CancelOk = CancelOk(consumerTag, ) + } + } + + public data class Publish( + public val ticket: Short, + public val exchange: String, + public val routingKey: String, + public val mandatory: Boolean, + public val immediate: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .exchange(exchange) + .routingKey(routingKey) + .mandatory(mandatory) + .immediate(immediate) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 40 + + public override fun methodName(): String = "basic.publish" + + public override fun hasContent(): Boolean = true + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(exchange) + writer.writeShortString(routingKey) + writer.writeBit(mandatory) + writer.writeBit(immediate) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Publish = Publish( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortString(), + reader.readBit(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Publish = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public var exchange: String = "" + + public var routingKey: String = "" + + public var mandatory: Boolean = false + + public var immediate: Boolean = false + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun exchange(`value`: String): Builder { + exchange = value + return this + } + + public fun routingKey(`value`: String): Builder { + routingKey = value + return this + } + + public fun mandatory(`value`: Boolean): Builder { + mandatory = value + return this + } + + public fun immediate(`value`: Boolean): Builder { + immediate = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + exchange = other.exchange + routingKey = other.routingKey + mandatory = other.mandatory + immediate = other.immediate + return this + } + + public fun build(): Publish = Publish(ticket, exchange, routingKey, mandatory, immediate, ) + } + } + + public data class Return( + public val replyCode: Short, + public val replyText: String, + public val exchange: String, + public val routingKey: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .replyCode(replyCode) + .replyText(replyText) + .exchange(exchange) + .routingKey(routingKey) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 50 + + public override fun methodName(): String = "basic.return" + + public override fun hasContent(): Boolean = true + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(replyCode) + writer.writeShortString(replyText) + writer.writeShortString(exchange) + writer.writeShortString(routingKey) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Return = Return( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readShortString(), + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Return = Builder() + .apply(block) + .build() + } + + public class Builder { + public var replyCode: Short by kotlin.properties.Delegates.notNull() + + public var replyText: String = "" + + public lateinit var exchange: String + + public lateinit var routingKey: String + + public fun replyCode(`value`: Short): Builder { + replyCode = value + return this + } + + public fun replyText(`value`: String): Builder { + replyText = value + return this + } + + public fun exchange(`value`: String): Builder { + exchange = value + return this + } + + public fun routingKey(`value`: String): Builder { + routingKey = value + return this + } + + public fun copyFrom(other: Builder): Builder { + replyCode = other.replyCode + replyText = other.replyText + exchange = other.exchange + routingKey = other.routingKey + return this + } + + public fun build(): Return = Return(replyCode, replyText, exchange, routingKey, ) + } + } + + public data class Deliver( + public val consumerTag: String, + public val deliveryTag: Long, + public val redelivered: Boolean, + public val exchange: String, + public val routingKey: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .consumerTag(consumerTag) + .deliveryTag(deliveryTag) + .redelivered(redelivered) + .exchange(exchange) + .routingKey(routingKey) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 60 + + public override fun methodName(): String = "basic.deliver" + + public override fun hasContent(): Boolean = true + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(consumerTag) + writer.writeLongLongUnsigned(deliveryTag) + writer.writeBit(redelivered) + writer.writeShortString(exchange) + writer.writeShortString(routingKey) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Deliver = Deliver( + reader.readShortString(), + reader.readLongLongUnsigned(), + reader.readBit(), + reader.readShortString(), + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Deliver = Builder() + .apply(block) + .build() + } + + public class Builder { + public lateinit var consumerTag: String + + public var deliveryTag: Long by kotlin.properties.Delegates.notNull() + + public var redelivered: Boolean = false + + public lateinit var exchange: String + + public lateinit var routingKey: String + + public fun consumerTag(`value`: String): Builder { + consumerTag = value + return this + } + + public fun deliveryTag(`value`: Long): Builder { + deliveryTag = value + return this + } + + public fun redelivered(`value`: Boolean): Builder { + redelivered = value + return this + } + + public fun exchange(`value`: String): Builder { + exchange = value + return this + } + + public fun routingKey(`value`: String): Builder { + routingKey = value + return this + } + + public fun copyFrom(other: Builder): Builder { + consumerTag = other.consumerTag + deliveryTag = other.deliveryTag + redelivered = other.redelivered + exchange = other.exchange + routingKey = other.routingKey + return this + } + + public fun build(): Deliver = Deliver(consumerTag, deliveryTag, redelivered, exchange, + routingKey, ) + } + } + + public data class Get( + public val ticket: Short, + public val queue: String, + public val noAck: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .ticket(ticket) + .queue(queue) + .noAck(noAck) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 70 + + public override fun methodName(): String = "basic.get" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortUnsigned(ticket) + writer.writeShortString(queue) + writer.writeBit(noAck) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Get = Get( + reader.readShortUnsigned(), + reader.readShortString(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Get = Builder() + .apply(block) + .build() + } + + public class Builder { + public var ticket: Short = 0 + + public var queue: String = "" + + public var noAck: Boolean = false + + public fun ticket(`value`: Short): Builder { + ticket = value + return this + } + + public fun queue(`value`: String): Builder { + queue = value + return this + } + + public fun noAck(`value`: Boolean): Builder { + noAck = value + return this + } + + public fun copyFrom(other: Builder): Builder { + ticket = other.ticket + queue = other.queue + noAck = other.noAck + return this + } + + public fun build(): Get = Get(ticket, queue, noAck, ) + } + } + + public data class GetOk( + public val deliveryTag: Long, + public val redelivered: Boolean, + public val exchange: String, + public val routingKey: String, + public val messageCount: Int, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .deliveryTag(deliveryTag) + .redelivered(redelivered) + .exchange(exchange) + .routingKey(routingKey) + .messageCount(messageCount) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 71 + + public override fun methodName(): String = "basic.get-ok" + + public override fun hasContent(): Boolean = true + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongLongUnsigned(deliveryTag) + writer.writeBit(redelivered) + writer.writeShortString(exchange) + writer.writeShortString(routingKey) + writer.writeLongUnsigned(messageCount) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): GetOk = GetOk( + reader.readLongLongUnsigned(), + reader.readBit(), + reader.readShortString(), + reader.readShortString(), + reader.readLongUnsigned() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): GetOk = Builder() + .apply(block) + .build() + } + + public class Builder { + public var deliveryTag: Long by kotlin.properties.Delegates.notNull() + + public var redelivered: Boolean = false + + public lateinit var exchange: String + + public lateinit var routingKey: String + + public var messageCount: Int by kotlin.properties.Delegates.notNull() + + public fun deliveryTag(`value`: Long): Builder { + deliveryTag = value + return this + } + + public fun redelivered(`value`: Boolean): Builder { + redelivered = value + return this + } + + public fun exchange(`value`: String): Builder { + exchange = value + return this + } + + public fun routingKey(`value`: String): Builder { + routingKey = value + return this + } + + public fun messageCount(`value`: Int): Builder { + messageCount = value + return this + } + + public fun copyFrom(other: Builder): Builder { + deliveryTag = other.deliveryTag + redelivered = other.redelivered + exchange = other.exchange + routingKey = other.routingKey + messageCount = other.messageCount + return this + } + + public fun build(): GetOk = GetOk(deliveryTag, redelivered, exchange, routingKey, + messageCount, ) + } + } + + public data class GetEmpty( + public val clusterId: String, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .clusterId(clusterId) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 72 + + public override fun methodName(): String = "basic.get-empty" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeShortString(clusterId) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): GetEmpty = GetEmpty( + reader.readShortString() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): GetEmpty = Builder() + .apply(block) + .build() + } + + public class Builder { + public var clusterId: String = "" + + public fun clusterId(`value`: String): Builder { + clusterId = value + return this + } + + public fun copyFrom(other: Builder): Builder { + clusterId = other.clusterId + return this + } + + public fun build(): GetEmpty = GetEmpty(clusterId, ) + } + } + + public data class Ack( + public val deliveryTag: Long, + public val multiple: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .deliveryTag(deliveryTag) + .multiple(multiple) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 80 + + public override fun methodName(): String = "basic.ack" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongLongUnsigned(deliveryTag) + writer.writeBit(multiple) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Ack = Ack( + reader.readLongLongUnsigned(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Ack = Builder() + .apply(block) + .build() + } + + public class Builder { + public var deliveryTag: Long = 0 + + public var multiple: Boolean = false + + public fun deliveryTag(`value`: Long): Builder { + deliveryTag = value + return this + } + + public fun multiple(`value`: Boolean): Builder { + multiple = value + return this + } + + public fun copyFrom(other: Builder): Builder { + deliveryTag = other.deliveryTag + multiple = other.multiple + return this + } + + public fun build(): Ack = Ack(deliveryTag, multiple, ) + } + } + + public data class Reject( + public val deliveryTag: Long, + public val requeue: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .deliveryTag(deliveryTag) + .requeue(requeue) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 90 + + public override fun methodName(): String = "basic.reject" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongLongUnsigned(deliveryTag) + writer.writeBit(requeue) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Reject = Reject( + reader.readLongLongUnsigned(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Reject = Builder() + .apply(block) + .build() + } + + public class Builder { + public var deliveryTag: Long by kotlin.properties.Delegates.notNull() + + public var requeue: Boolean = true + + public fun deliveryTag(`value`: Long): Builder { + deliveryTag = value + return this + } + + public fun requeue(`value`: Boolean): Builder { + requeue = value + return this + } + + public fun copyFrom(other: Builder): Builder { + deliveryTag = other.deliveryTag + requeue = other.requeue + return this + } + + public fun build(): Reject = Reject(deliveryTag, requeue, ) + } + } + + public data class RecoverAsync( + public val requeue: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .requeue(requeue) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 100 + + public override fun methodName(): String = "basic.recover-async" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeBit(requeue) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): RecoverAsync = + RecoverAsync( + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): RecoverAsync = Builder() + .apply(block) + .build() + } + + public class Builder { + public var requeue: Boolean = false + + public fun requeue(`value`: Boolean): Builder { + requeue = value + return this + } + + public fun copyFrom(other: Builder): Builder { + requeue = other.requeue + return this + } + + public fun build(): RecoverAsync = RecoverAsync(requeue, ) + } + } + + public data class Recover( + public val requeue: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .requeue(requeue) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 110 + + public override fun methodName(): String = "basic.recover" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeBit(requeue) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Recover = Recover( + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Recover = Builder() + .apply(block) + .build() + } + + public class Builder { + public var requeue: Boolean = false + + public fun requeue(`value`: Boolean): Builder { + requeue = value + return this + } + + public fun copyFrom(other: Builder): Builder { + requeue = other.requeue + return this + } + + public fun build(): Recover = Recover(requeue, ) + } + } + + public object RecoverOk : Method() { + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 111 + + public override fun methodName(): String = "basic.recover-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public data class Nack( + public val deliveryTag: Long, + public val multiple: Boolean, + public val requeue: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .deliveryTag(deliveryTag) + .multiple(multiple) + .requeue(requeue) + + public override fun classId(): Short = 60 + + public override fun methodId(): Short = 120 + + public override fun methodName(): String = "basic.nack" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeLongLongUnsigned(deliveryTag) + writer.writeBit(multiple) + writer.writeBit(requeue) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Nack = Nack( + reader.readLongLongUnsigned(), + reader.readBit(), + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Nack = Builder() + .apply(block) + .build() + } + + public class Builder { + public var deliveryTag: Long = 0 + + public var multiple: Boolean = false + + public var requeue: Boolean = true + + public fun deliveryTag(`value`: Long): Builder { + deliveryTag = value + return this + } + + public fun multiple(`value`: Boolean): Builder { + multiple = value + return this + } + + public fun requeue(`value`: Boolean): Builder { + requeue = value + return this + } + + public fun copyFrom(other: Builder): Builder { + deliveryTag = other.deliveryTag + multiple = other.multiple + requeue = other.requeue + return this + } + + public fun build(): Nack = Nack(deliveryTag, multiple, requeue, ) + } + } + + public data class Properties( + public val contentType: String?, + public val contentEncoding: String?, + public val headers: Map?, + public val deliveryMode: Int?, + public val priority: Int?, + public val correlationId: String?, + public val replyTo: String?, + public val expiration: String?, + public val messageId: String?, + public val timestamp: Instant?, + public val type: String?, + public val userId: String?, + public val appId: String?, + public val clusterId: String?, + ) : ContentHeader.Properties { + public override suspend fun writeTo(writer: ProtocolPropertiesWriter): Unit { + writer.writePresence(contentType != null) + writer.writePresence(contentEncoding != null) + writer.writePresence(headers != null) + writer.writePresence(deliveryMode != null) + writer.writePresence(priority != null) + writer.writePresence(correlationId != null) + writer.writePresence(replyTo != null) + writer.writePresence(expiration != null) + writer.writePresence(messageId != null) + writer.writePresence(timestamp != null) + writer.writePresence(type != null) + writer.writePresence(userId != null) + writer.writePresence(appId != null) + writer.writePresence(clusterId != null) + writer.finishPresence() + contentType?.let { writer.writeShortString(it) } + contentEncoding?.let { writer.writeShortString(it) } + headers?.let { writer.writeFieldTable(it) } + deliveryMode?.let { writer.writeOctet(it) } + priority?.let { writer.writeOctet(it) } + correlationId?.let { writer.writeShortString(it) } + replyTo?.let { writer.writeShortString(it) } + expiration?.let { writer.writeShortString(it) } + messageId?.let { writer.writeShortString(it) } + timestamp?.let { writer.writeTimestamp(it) } + type?.let { writer.writeShortString(it) } + userId?.let { writer.writeShortString(it) } + appId?.let { writer.writeShortString(it) } + clusterId?.let { writer.writeShortString(it) } + } + + public fun toBuilder(): Builder = Builder() + .contentType(contentType) + .contentEncoding(contentEncoding) + .headers(headers) + .deliveryMode(deliveryMode) + .priority(priority) + .correlationId(correlationId) + .replyTo(replyTo) + .expiration(expiration) + .messageId(messageId) + .timestamp(timestamp) + .type(type) + .userId(userId) + .appId(appId) + .clusterId(clusterId) + + public override fun classId(): Short = 60 + + public companion object { + public suspend operator fun invoke(reader: ProtocolPropertiesReader): Properties { + val contentTypePresent = reader.readPresence() + val contentEncodingPresent = reader.readPresence() + val headersPresent = reader.readPresence() + val deliveryModePresent = reader.readPresence() + val priorityPresent = reader.readPresence() + val correlationIdPresent = reader.readPresence() + val replyToPresent = reader.readPresence() + val expirationPresent = reader.readPresence() + val messageIdPresent = reader.readPresence() + val timestampPresent = reader.readPresence() + val typePresent = reader.readPresence() + val userIdPresent = reader.readPresence() + val appIdPresent = reader.readPresence() + val clusterIdPresent = reader.readPresence() + reader.finishPresence() + return Properties( + if (contentTypePresent) reader.readShortString() else null, + if (contentEncodingPresent) reader.readShortString() else null, + if (headersPresent) reader.readFieldTable() else null, + if (deliveryModePresent) reader.readOctet() else null, + if (priorityPresent) reader.readOctet() else null, + if (correlationIdPresent) reader.readShortString() else null, + if (replyToPresent) reader.readShortString() else null, + if (expirationPresent) reader.readShortString() else null, + if (messageIdPresent) reader.readShortString() else null, + if (timestampPresent) reader.readTimestamp() else null, + if (typePresent) reader.readShortString() else null, + if (userIdPresent) reader.readShortString() else null, + if (appIdPresent) reader.readShortString() else null, + if (clusterIdPresent) reader.readShortString() else null + ) + } + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Properties = Builder() + .apply(block) + .build() + } + + public class Builder { + public var contentType: String? = null + + public var contentEncoding: String? = null + + public var headers: Map? = null + + public var deliveryMode: Int? = null + + public var priority: Int? = null + + public var correlationId: String? = null + + public var replyTo: String? = null + + public var expiration: String? = null + + public var messageId: String? = null + + public var timestamp: Instant? = null + + public var type: String? = null + + public var userId: String? = null + + public var appId: String? = null + + public var clusterId: String? = null + + public fun contentType(`value`: String?): Builder { + contentType = value + return this + } + + public fun contentEncoding(`value`: String?): Builder { + contentEncoding = value + return this + } + + public fun headers(`value`: Map?): Builder { + headers = value + return this + } + + public fun deliveryMode(`value`: Int?): Builder { + deliveryMode = value + return this + } + + public fun priority(`value`: Int?): Builder { + priority = value + return this + } + + public fun correlationId(`value`: String?): Builder { + correlationId = value + return this + } + + public fun replyTo(`value`: String?): Builder { + replyTo = value + return this + } + + public fun expiration(`value`: String?): Builder { + expiration = value + return this + } + + public fun messageId(`value`: String?): Builder { + messageId = value + return this + } + + public fun timestamp(`value`: Instant?): Builder { + timestamp = value + return this + } + + public fun type(`value`: String?): Builder { + type = value + return this + } + + public fun userId(`value`: String?): Builder { + userId = value + return this + } + + public fun appId(`value`: String?): Builder { + appId = value + return this + } + + public fun clusterId(`value`: String?): Builder { + clusterId = value + return this + } + + public fun copyFrom(other: Builder): Builder { + contentType = other.contentType + contentEncoding = other.contentEncoding + headers = other.headers + deliveryMode = other.deliveryMode + priority = other.priority + correlationId = other.correlationId + replyTo = other.replyTo + expiration = other.expiration + messageId = other.messageId + timestamp = other.timestamp + type = other.type + userId = other.userId + appId = other.appId + clusterId = other.clusterId + return this + } + + public fun build(): Properties = Properties(contentType, contentEncoding, headers, + deliveryMode, priority, correlationId, replyTo, expiration, messageId, timestamp, type, + userId, appId, clusterId, ) + } + } + } + + public object Tx { + public object Select : Method() { + public override fun classId(): Short = 90 + + public override fun methodId(): Short = 10 + + public override fun methodName(): String = "tx.select" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public object SelectOk : Method() { + public override fun classId(): Short = 90 + + public override fun methodId(): Short = 11 + + public override fun methodName(): String = "tx.select-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public object Commit : Method() { + public override fun classId(): Short = 90 + + public override fun methodId(): Short = 20 + + public override fun methodName(): String = "tx.commit" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public object CommitOk : Method() { + public override fun classId(): Short = 90 + + public override fun methodId(): Short = 21 + + public override fun methodName(): String = "tx.commit-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public object Rollback : Method() { + public override fun classId(): Short = 90 + + public override fun methodId(): Short = 30 + + public override fun methodName(): String = "tx.rollback" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + + public object RollbackOk : Method() { + public override fun classId(): Short = 90 + + public override fun methodId(): Short = 31 + + public override fun methodName(): String = "tx.rollback-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + } + + public object Confirm { + public data class Select( + public val nowait: Boolean, + ) : Method() { + public fun toBuilder(): Builder = Builder() + .nowait(nowait) + + public override fun classId(): Short = 85 + + public override fun methodId(): Short = 10 + + public override fun methodName(): String = "confirm.select" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + writer.writeBit(nowait) + } + + public companion object { + public suspend operator fun invoke(reader: MethodProtocolReader): Select = Select( + reader.readBit() + ) + + public inline operator fun invoke(block: Builder.() -> Unit = {}): Select = Builder() + .apply(block) + .build() + } + + public class Builder { + public var nowait: Boolean = false + + public fun nowait(`value`: Boolean): Builder { + nowait = value + return this + } + + public fun copyFrom(other: Builder): Builder { + nowait = other.nowait + return this + } + + public fun build(): Select = Select(nowait, ) + } + } + + public object SelectOk : Method() { + public override fun classId(): Short = 85 + + public override fun methodId(): Short = 11 + + public override fun methodName(): String = "confirm.select-ok" + + public override fun hasContent(): Boolean = false + + public override suspend fun writeTo(writer: MethodProtocolWriter): Unit { + } + } + } +} diff --git a/src/commonMain/kotlin/dimensional/usagi/Usagi.kt b/src/commonMain/kotlin/dimensional/usagi/Usagi.kt new file mode 100644 index 0000000..a705253 --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/Usagi.kt @@ -0,0 +1,28 @@ +package dimensional.usagi + +import dimensional.usagi.connection.Connection +import dimensional.usagi.connection.ConnectionResources +import dimensional.usagi.connection.ConnectionResourcesBuilder +import dimensional.usagi.protocol.Uri +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +public suspend inline fun Usagi( + uri: String, + build: ConnectionResourcesBuilder.() -> Unit = {} +): Connection = Usagi(Uri(uri), build) + +public suspend inline fun Usagi( + uri: Uri, + build: ConnectionResourcesBuilder.() -> Unit = {} +): Connection { + contract { + callsInPlace(build, InvocationKind.EXACTLY_ONCE) + } + + val resources = ConnectionResourcesBuilder() + .apply(build) + .build() + + return Connection.connect(uri, resources) +} diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/BaseChannel.kt b/src/commonMain/kotlin/dimensional/usagi/channel/BaseChannel.kt similarity index 90% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/BaseChannel.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/BaseChannel.kt index f06bda0..e2ec35e 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/BaseChannel.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/BaseChannel.kt @@ -1,17 +1,17 @@ -package mixtape.oss.usagi.channel - +package dimensional.usagi.channel + +import dimensional.usagi.channel.command.Command +import dimensional.usagi.channel.command.CommandAssembler +import dimensional.usagi.connection.Connection +import dimensional.usagi.connection.frame.Frame +import dimensional.usagi.protocol.AMQP +import dimensional.usagi.protocol.Method +import dimensional.usagi.tools.measure import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import mixtape.oss.usagi.channel.command.Command -import mixtape.oss.usagi.channel.command.CommandAssembler -import mixtape.oss.usagi.connection.Connection -import mixtape.oss.usagi.connection.frame.Frame -import mixtape.oss.usagi.protocol.AMQP -import mixtape.oss.usagi.protocol.Method -import mixtape.oss.usagi.tools.measure import mu.KotlinLogging import kotlin.time.Duration @@ -35,13 +35,13 @@ public abstract class BaseChannel( private val assembler = CommandAssembler() /** Shared flow of incoming [Command]s */ private val commandFlow = MutableSharedFlow() - /** The current RPC being performed */ - private var rpc: Deferred? = null /** Whether sending of content-frames is being done, see [AMQP.Channel.Flow] */ private var active: Boolean = true /** Mutex used for sending commands */ private val mutex = Mutex() + /** The current RPC being performed */ + internal var rpc: Deferred? = null /** Whether this channel is performing an RPC call */ internal val inRPC: Boolean get() = rpc != null @@ -114,9 +114,8 @@ public abstract class BaseChannel( * */ public suspend fun rpc(command: Command): Command { - send(command) - rpc = scope.async { receiveCommand() } + send(command) return log.measure("[Channel $id] RPC took", log::debug) { rpc!!.await() } } diff --git a/src/commonMain/kotlin/dimensional/usagi/channel/Channel.kt b/src/commonMain/kotlin/dimensional/usagi/channel/Channel.kt new file mode 100644 index 0000000..d93fc34 --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/channel/Channel.kt @@ -0,0 +1,98 @@ +package dimensional.usagi.channel + +import dimensional.usagi.channel.command.Command +import dimensional.usagi.channel.consumer.Consumer +import dimensional.usagi.channel.consumer.Delivery +import dimensional.usagi.channel.event.ChannelEvent +import dimensional.usagi.channel.event.MessagePublishedEvent +import dimensional.usagi.connection.Connection +import dimensional.usagi.protocol.AMQP +import dimensional.usagi.tools.into +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import mu.KotlinLogging + +public class Channel( + connection: Connection, + id: Int +) : BaseChannel(connection, id) { + public companion object { + private val log = KotlinLogging.logger { } + } + + private val consumerMap = hashMapOf() + private val eventFlow = MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE) + + /** */ + public val consumers: Map get() = object : Map by consumerMap {} + /** */ + public val events: SharedFlow get() = eventFlow + + override suspend fun processIncomingCommand(command: Command): Boolean { + if (command.method is AMQP.Channel.Close) { + processShutdown(command.method) + return true + } + + return when (command.method) { + + /* consumer-specific commands */ + is AMQP.Basic.Deliver -> { + val consumer = consumerMap[command.method.consumerTag] + if (consumer != null) { + val delivery = Delivery( + consumer, + Delivery.Envelope( + command.method.deliveryTag, + command.method.redelivered, + command.method.exchange, + command.method.routingKey, + ), + command.header?.properties.into(), + command.body!!.asBytes() + ) + + eventFlow.emit(MessagePublishedEvent(consumer, delivery)) + } + + true + } + + is AMQP.Basic.Cancel -> { + true + } + + is AMQP.Basic.CancelOk -> { + !inRPC // forward this to RPC + } + + is AMQP.Basic.RecoverOk -> { + !inRPC // forward this to RPC + } + + /* everything else */ + else -> false + } + } + + internal suspend fun createConsumer(method: AMQP.Basic.Consume): Consumer { + val ok = rpc(method) + require(ok.method is AMQP.Basic.ConsumeOk) { "Expected `basic.consume-ok`, not ${ok.method.methodName()}" } + + val consumer = Consumer(this, ok.method.consumerTag) + consumerMap[consumer.tag] = consumer + + return consumer + } + + private suspend fun processShutdown(method: AMQP.Channel.Close) { + log.debug { "[Channel $id] Server requested close: $method" } + + try { + send(AMQP.Channel.CloseOk) + } finally { + connection.channels.free(this) + rpc?.cancel() + } + } +} diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/ChannelManager.kt b/src/commonMain/kotlin/dimensional/usagi/channel/ChannelManager.kt similarity index 96% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/ChannelManager.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/ChannelManager.kt index 65e909d..8753c35 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/ChannelManager.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/ChannelManager.kt @@ -1,11 +1,11 @@ -package mixtape.oss.usagi.channel +package dimensional.usagi.channel +import dimensional.usagi.connection.Connection +import dimensional.usagi.tools.IntAllocator import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withTimeout -import mixtape.oss.usagi.connection.Connection -import mixtape.oss.usagi.tools.IntAllocator import mu.KotlinLogging import kotlin.time.Duration.Companion.seconds diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/command/Command.kt b/src/commonMain/kotlin/dimensional/usagi/channel/command/Command.kt similarity index 86% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/command/Command.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/command/Command.kt index 79daa60..93fca83 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/command/Command.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/command/Command.kt @@ -1,12 +1,11 @@ -package mixtape.oss.usagi.channel.command +package dimensional.usagi.channel.command -import mixtape.oss.usagi.channel.BaseChannel -import mixtape.oss.usagi.channel.Channel -import mixtape.oss.usagi.protocol.Method -import mixtape.oss.usagi.connection.frame.Frame -import mixtape.oss.usagi.connection.frame.FrameHeader -import mixtape.oss.usagi.connection.frame.FrameType -import mixtape.oss.usagi.tools.arraycopy +import dimensional.usagi.channel.BaseChannel +import dimensional.usagi.connection.frame.Frame +import dimensional.usagi.connection.frame.FrameHeader +import dimensional.usagi.connection.frame.FrameType +import dimensional.usagi.protocol.Method +import dimensional.usagi.tools.arraycopy /** * diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/command/CommandAssembler.kt b/src/commonMain/kotlin/dimensional/usagi/channel/command/CommandAssembler.kt similarity index 91% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/command/CommandAssembler.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/command/CommandAssembler.kt index 59a6d81..160b85c 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/command/CommandAssembler.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/command/CommandAssembler.kt @@ -1,10 +1,10 @@ -package mixtape.oss.usagi.channel.command +package dimensional.usagi.channel.command +import dimensional.usagi.connection.frame.Frame +import dimensional.usagi.connection.frame.FrameType +import dimensional.usagi.protocol.Method +import dimensional.usagi.protocol.reader.amqp import io.ktor.utils.io.core.* -import mixtape.oss.usagi.protocol.Method -import mixtape.oss.usagi.connection.frame.Frame -import mixtape.oss.usagi.connection.frame.FrameType -import mixtape.oss.usagi.protocol.reader.amqp public class CommandAssembler { private var state: State = State.ExpectingMethod diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/command/ContentBody.kt b/src/commonMain/kotlin/dimensional/usagi/channel/command/ContentBody.kt similarity index 91% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/command/ContentBody.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/command/ContentBody.kt index 352879d..236e587 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/command/ContentBody.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/command/ContentBody.kt @@ -1,8 +1,8 @@ -package mixtape.oss.usagi.channel.command +package dimensional.usagi.channel.command -import mixtape.oss.usagi.connection.frame.Frame -import mixtape.oss.usagi.connection.frame.FrameType -import mixtape.oss.usagi.tools.arraycopy +import dimensional.usagi.connection.frame.Frame +import dimensional.usagi.connection.frame.FrameType +import dimensional.usagi.tools.arraycopy public sealed class ContentBody { /** diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/command/ContentHeader.kt b/src/commonMain/kotlin/dimensional/usagi/channel/command/ContentHeader.kt similarity index 71% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/command/ContentHeader.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/command/ContentHeader.kt index b416856..0817b3d 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/command/ContentHeader.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/command/ContentHeader.kt @@ -1,14 +1,14 @@ -package mixtape.oss.usagi.channel.command +package dimensional.usagi.channel.command +import dimensional.usagi.connection.frame.Frame +import dimensional.usagi.connection.frame.FrameHeader +import dimensional.usagi.connection.frame.FrameType +import dimensional.usagi.protocol.AMQP +import dimensional.usagi.protocol.reader.ProtocolPropertiesReader +import dimensional.usagi.protocol.reader.ProtocolReader +import dimensional.usagi.protocol.writer.ProtocolPropertiesWriter +import dimensional.usagi.protocol.writer.amqp import io.ktor.utils.io.core.* -import mixtape.oss.usagi.connection.frame.Frame -import mixtape.oss.usagi.connection.frame.FrameHeader -import mixtape.oss.usagi.connection.frame.FrameType -import mixtape.oss.usagi.protocol.AMQP -import mixtape.oss.usagi.protocol.reader.ProtocolPropertiesReader -import mixtape.oss.usagi.protocol.reader.ProtocolReader -import mixtape.oss.usagi.protocol.writer.ProtocolPropertiesWriter -import mixtape.oss.usagi.protocol.writer.amqp public data class ContentHeader( public val bodySize: Long, diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/consumer/Consumer.kt b/src/commonMain/kotlin/dimensional/usagi/channel/consumer/Consumer.kt similarity index 65% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/consumer/Consumer.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/consumer/Consumer.kt index b2e20da..d29719a 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/consumer/Consumer.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/consumer/Consumer.kt @@ -1,14 +1,14 @@ -package mixtape.oss.usagi.channel.consumer +package dimensional.usagi.channel.consumer +import dimensional.usagi.channel.Channel +import dimensional.usagi.channel.event.ConsumerEvent +import dimensional.usagi.channel.method.basic import kotlinx.coroutines.* import kotlinx.coroutines.flow.* -import kotlinx.coroutines.channels.Channel as CoroutineChannel -import mixtape.oss.usagi.channel.Channel -import mixtape.oss.usagi.channel.event.ConsumerEvent -import mixtape.oss.usagi.channel.method.basic import mu.KLogger import mu.KotlinLogging import kotlin.coroutines.CoroutineContext +import kotlinx.coroutines.channels.Channel as CoroutineChannel public data class Consumer( val channel: Channel, @@ -31,15 +31,13 @@ public data class Consumer( } @PublishedApi -internal val consumerOnLog: KLogger = KotlinLogging.logger("mixtape.oss.usagi.channel.consumer.Consumer#on") +internal val consumerOnLog: KLogger = KotlinLogging.logger("dimensional.usagi.Consumer#on") public inline fun Consumer.on( scope: CoroutineScope = this, noinline block: suspend T.() -> Unit -): Job { - return events - .buffer(CoroutineChannel.UNLIMITED) - .filterIsInstance() - .onEach { scope.launch { runCatching { block(it) }.onFailure { consumerOnLog.catching(it) } } } - .launchIn(scope) -} +): Job = events + .buffer(CoroutineChannel.UNLIMITED) + .filterIsInstance() + .onEach { scope.launch { runCatching { block(it) }.onFailure { consumerOnLog.catching(it) } } } + .launchIn(scope) diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/consumer/Delivery.kt b/src/commonMain/kotlin/dimensional/usagi/channel/consumer/Delivery.kt similarity index 86% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/consumer/Delivery.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/consumer/Delivery.kt index d2b378a..435dc58 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/consumer/Delivery.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/consumer/Delivery.kt @@ -1,7 +1,7 @@ -package mixtape.oss.usagi.channel.consumer +package dimensional.usagi.channel.consumer -import mixtape.oss.usagi.channel.method.basic -import mixtape.oss.usagi.protocol.AMQP +import dimensional.usagi.channel.method.basic +import dimensional.usagi.protocol.AMQP public data class Delivery( val consumer: Consumer, diff --git a/src/commonMain/kotlin/dimensional/usagi/channel/event/ChannelEvent.kt b/src/commonMain/kotlin/dimensional/usagi/channel/event/ChannelEvent.kt new file mode 100644 index 0000000..d6c741a --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/channel/event/ChannelEvent.kt @@ -0,0 +1,7 @@ +package dimensional.usagi.channel.event + +import dimensional.usagi.channel.Channel + +public interface ChannelEvent { + public val channel: Channel +} diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/event/ConsumerEvent.kt b/src/commonMain/kotlin/dimensional/usagi/channel/event/ConsumerEvent.kt similarity index 53% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/event/ConsumerEvent.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/event/ConsumerEvent.kt index dc391c5..80a8d77 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/event/ConsumerEvent.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/event/ConsumerEvent.kt @@ -1,7 +1,7 @@ -package mixtape.oss.usagi.channel.event +package dimensional.usagi.channel.event -import mixtape.oss.usagi.channel.Channel -import mixtape.oss.usagi.channel.consumer.Consumer +import dimensional.usagi.channel.Channel +import dimensional.usagi.channel.consumer.Consumer public interface ConsumerEvent : ChannelEvent { public val consumer: Consumer diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/event/MessagePublishedEvent.kt b/src/commonMain/kotlin/dimensional/usagi/channel/event/MessagePublishedEvent.kt similarity index 64% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/event/MessagePublishedEvent.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/event/MessagePublishedEvent.kt index c1396d4..1c71cb7 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/event/MessagePublishedEvent.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/event/MessagePublishedEvent.kt @@ -1,7 +1,7 @@ -package mixtape.oss.usagi.channel.event +package dimensional.usagi.channel.event -import mixtape.oss.usagi.channel.consumer.Consumer -import mixtape.oss.usagi.channel.consumer.Delivery +import dimensional.usagi.channel.consumer.Consumer +import dimensional.usagi.channel.consumer.Delivery /** * Emitted whenever a message has been published. diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/method/BasicMethods.kt b/src/commonMain/kotlin/dimensional/usagi/channel/method/BasicMethods.kt similarity index 82% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/method/BasicMethods.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/method/BasicMethods.kt index a4d29f7..2c0dc43 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/method/BasicMethods.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/method/BasicMethods.kt @@ -1,11 +1,11 @@ -package mixtape.oss.usagi.channel.method - -import mixtape.oss.usagi.channel.Channel -import mixtape.oss.usagi.channel.command.Command -import mixtape.oss.usagi.channel.command.ContentBody -import mixtape.oss.usagi.channel.command.ContentHeader -import mixtape.oss.usagi.channel.consumer.Consumer -import mixtape.oss.usagi.protocol.AMQP +package dimensional.usagi.channel.method + +import dimensional.usagi.channel.Channel +import dimensional.usagi.channel.command.Command +import dimensional.usagi.channel.command.ContentBody +import dimensional.usagi.channel.command.ContentHeader +import dimensional.usagi.channel.consumer.Consumer +import dimensional.usagi.protocol.AMQP import kotlin.jvm.JvmInline public val Channel.basic: BasicMethods get() = BasicMethods(this) @@ -15,7 +15,7 @@ public value class BasicMethods(private val channel: Channel) { /** * @param method */ - public suspend fun qos(method: AMQP.Basic.Qos): AMQP.Basic.QosOk { + public suspend fun qos(method: AMQP.Basic.Qos): AMQP.Basic.QosOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Basic.QosOk) { "Expected `basic.qos-ok`, not ${ok.method.methodName()}" } return ok.method @@ -41,7 +41,7 @@ public value class BasicMethods(private val channel: Channel) { /** * @param method */ - public suspend fun cancel(method: AMQP.Basic.Cancel): AMQP.Basic.CancelOk { + public suspend fun cancel(method: AMQP.Basic.Cancel): AMQP.Basic.CancelOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Basic.CancelOk) { "Expected `basic.cancel-ok`, not ${ok.method.methodName()}" } return ok.method @@ -52,7 +52,9 @@ public value class BasicMethods(private val channel: Channel) { } /** - * @param method + * Publish a message + * + * @param block Function used for building the message to publish. */ public suspend fun publish( block: Publish.() -> Unit, @@ -61,13 +63,13 @@ public value class BasicMethods(private val channel: Channel) { .apply(block) .build() - channel.send(command) + /*channel.mutex.withLock { */channel.send(command)/* }*/ } /** * @param method */ - public suspend fun get(method: AMQP.Basic.Get): AMQP.Basic.GetOk { + public suspend fun get(method: AMQP.Basic.Get): AMQP.Basic.GetOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Basic.GetOk) { "Expected `basic.get-ok`, not ${ok.method.methodName()}" } return ok.method @@ -81,7 +83,7 @@ public value class BasicMethods(private val channel: Channel) { * @param method */ public suspend fun ack(method: AMQP.Basic.Ack) { - channel.send(method) + /*channel.mutex.withLock { */channel.send(method)/* }*/ } public suspend fun ack(block: AMQP.Basic.Ack.Builder.() -> Unit) { @@ -91,7 +93,7 @@ public value class BasicMethods(private val channel: Channel) { /** * @param method */ - public suspend fun recover(method: AMQP.Basic.Recover): AMQP.Basic.RecoverOk { + public suspend fun recover(method: AMQP.Basic.Recover): AMQP.Basic.RecoverOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Basic.RecoverOk) { "Expected `basic.recover-ok`, not ${ok.method.methodName()}" } return ok.method @@ -105,7 +107,7 @@ public value class BasicMethods(private val channel: Channel) { * @param method */ public suspend fun nack(method: AMQP.Basic.Nack) { - channel.send(method) + /*channel.mutex.withLock { */channel.send(method)/* }*/ } public suspend fun nack(block: AMQP.Basic.Nack.Builder.() -> Unit) { diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/method/ExchangeMethods.kt b/src/commonMain/kotlin/dimensional/usagi/channel/method/ExchangeMethods.kt similarity index 86% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/method/ExchangeMethods.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/method/ExchangeMethods.kt index c6ed1d2..b8f78cc 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/method/ExchangeMethods.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/method/ExchangeMethods.kt @@ -1,7 +1,7 @@ -package mixtape.oss.usagi.channel.method +package dimensional.usagi.channel.method -import mixtape.oss.usagi.channel.Channel -import mixtape.oss.usagi.protocol.AMQP +import dimensional.usagi.channel.Channel +import dimensional.usagi.protocol.AMQP import kotlin.jvm.JvmInline public val Channel.exchange: ExchangeMethods get() = ExchangeMethods(this) @@ -11,7 +11,7 @@ public value class ExchangeMethods(private val channel: Channel) { /** * @param method */ - public suspend fun declare(method: AMQP.Exchange.Declare): AMQP.Exchange.DeclareOk { + public suspend fun declare(method: AMQP.Exchange.Declare): AMQP.Exchange.DeclareOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Exchange.DeclareOk) { "Expected `exchange.declare-ok`, not ${ok.method.methodName()}" } return ok.method @@ -24,7 +24,7 @@ public value class ExchangeMethods(private val channel: Channel) { /** * @param method */ - public suspend fun delete(method: AMQP.Exchange.Delete): AMQP.Exchange.DeleteOk { + public suspend fun delete(method: AMQP.Exchange.Delete): AMQP.Exchange.DeleteOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Exchange.DeleteOk) { "Expected `exchange.delete-ok`, not ${ok.method.methodName()}" } return ok.method @@ -37,7 +37,7 @@ public value class ExchangeMethods(private val channel: Channel) { /** * @param method */ - public suspend fun bind(method: AMQP.Exchange.Bind): AMQP.Exchange.BindOk { + public suspend fun bind(method: AMQP.Exchange.Bind): AMQP.Exchange.BindOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Exchange.BindOk) { "Expected `exchange.bind-ok`, not ${ok.method.methodName()}" } return ok.method @@ -50,7 +50,7 @@ public value class ExchangeMethods(private val channel: Channel) { /** * @param method */ - public suspend fun unbind(method: AMQP.Exchange.Unbind): AMQP.Exchange.UnbindOk { + public suspend fun unbind(method: AMQP.Exchange.Unbind): AMQP.Exchange.UnbindOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Exchange.UnbindOk) { "Expected `exchange.unbind-ok`, not ${ok.method.methodName()}" } return ok.method diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/method/QueueMethods.kt b/src/commonMain/kotlin/dimensional/usagi/channel/method/QueueMethods.kt similarity index 87% rename from src/commonMain/kotlin/mixtape/oss/usagi/channel/method/QueueMethods.kt rename to src/commonMain/kotlin/dimensional/usagi/channel/method/QueueMethods.kt index af89097..3224d91 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/method/QueueMethods.kt +++ b/src/commonMain/kotlin/dimensional/usagi/channel/method/QueueMethods.kt @@ -1,7 +1,7 @@ -package mixtape.oss.usagi.channel.method +package dimensional.usagi.channel.method -import mixtape.oss.usagi.channel.Channel -import mixtape.oss.usagi.protocol.AMQP +import dimensional.usagi.channel.Channel +import dimensional.usagi.protocol.AMQP import kotlin.jvm.JvmInline public val Channel.queue: QueueMethods get() = QueueMethods(this) @@ -11,7 +11,7 @@ public value class QueueMethods(public val channel: Channel) { /** * @param method */ - public suspend fun declare(method: AMQP.Queue.Declare): AMQP.Queue.DeclareOk { + public suspend fun declare(method: AMQP.Queue.Declare): AMQP.Queue.DeclareOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Queue.DeclareOk) { "Expected `queue.declare-ok`, not ${ok.method.methodName()}" } return ok.method @@ -24,7 +24,7 @@ public value class QueueMethods(public val channel: Channel) { /** * @param method */ - public suspend fun bind(method: AMQP.Queue.Bind): AMQP.Queue.BindOk { + public suspend fun bind(method: AMQP.Queue.Bind): AMQP.Queue.BindOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Queue.BindOk) { "Expected `queue.bind-ok`, not ${ok.method.methodName()}" } return ok.method @@ -37,7 +37,7 @@ public value class QueueMethods(public val channel: Channel) { /** * @param method */ - public suspend fun purge(method: AMQP.Queue.Purge): AMQP.Queue.PurgeOk { + public suspend fun purge(method: AMQP.Queue.Purge): AMQP.Queue.PurgeOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Queue.PurgeOk) { "Expected `queue.purge-ok`, not ${ok.method.methodName()}" } return ok.method @@ -50,7 +50,7 @@ public value class QueueMethods(public val channel: Channel) { /** * @param method */ - public suspend fun delete(method: AMQP.Queue.Delete): AMQP.Queue.DeleteOk { + public suspend fun delete(method: AMQP.Queue.Delete): AMQP.Queue.DeleteOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Queue.DeleteOk) { "Expected `queue.delete-ok`, not ${ok.method.methodName()}" } return ok.method @@ -63,7 +63,7 @@ public value class QueueMethods(public val channel: Channel) { /** * @param method */ - public suspend fun unbind(method: AMQP.Queue.Unbind): AMQP.Queue.UnbindOk { + public suspend fun unbind(method: AMQP.Queue.Unbind): AMQP.Queue.UnbindOk /*= channel.mutex.withLock */{ val ok = channel.rpc(method) require(ok.method is AMQP.Queue.UnbindOk) { "Expected `queue.unbind-ok`, not ${ok.method.methodName()}" } return ok.method diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/Channel0.kt b/src/commonMain/kotlin/dimensional/usagi/connection/Channel0.kt similarity index 78% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/Channel0.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/Channel0.kt index 3b0e0c4..f2f4af6 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/Channel0.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/Channel0.kt @@ -1,10 +1,10 @@ -package mixtape.oss.usagi.connection +package dimensional.usagi.connection -import mixtape.oss.usagi.channel.BaseChannel -import mixtape.oss.usagi.channel.command.Command -import mixtape.oss.usagi.connection.event.ConnectionBlockedEvent -import mixtape.oss.usagi.connection.event.ConnectionUnblockedEvent -import mixtape.oss.usagi.protocol.AMQP +import dimensional.usagi.channel.BaseChannel +import dimensional.usagi.channel.command.Command +import dimensional.usagi.connection.event.ConnectionBlockedEvent +import dimensional.usagi.connection.event.ConnectionUnblockedEvent +import dimensional.usagi.protocol.AMQP import mu.KotlinLogging internal class Channel0(connection: Connection) : BaseChannel(connection, 0) { @@ -37,7 +37,7 @@ internal class Channel0(connection: Connection) : BaseChannel(connection, 0) { } else { when (command.method) { is AMQP.Connection.Close -> { - send(AMQP.Connection.CloseOk()) + send(AMQP.Connection.CloseOk) true } diff --git a/src/commonMain/kotlin/dimensional/usagi/connection/ClientProperties.kt b/src/commonMain/kotlin/dimensional/usagi/connection/ClientProperties.kt new file mode 100644 index 0000000..8343369 --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/connection/ClientProperties.kt @@ -0,0 +1,47 @@ +package dimensional.usagi.connection + +public class ClientProperties { + public companion object { + /** The capabilities of this AMQP client */ + public val CAPABILITIES: Map = mapOf( + "authentication_failure_close" to true, + "basic.nack" to true, + "connection.blocked" to true, + "consumer_cancel_notify" to true, + "exchange_exchange_bindings" to true, + "per_consumer_qos" to true, + "publisher_confirms" to true, + ) + } + + public var product: String = "usagi" + + public var information: String = "https://github.com/dimensional-fun/usagi" + + public var platform: String = "Kotlin ${KotlinVersion.CURRENT}" + + public var version: String = "0.0.0" + + public var copyright: String = "Copyright (c) 2019 - 2023 Dimensional Fun" + + public var connectionName: String? = null + + public val extra: MutableMap = mutableMapOf() + + public fun build(): Map { + val properties: MutableMap = (extra + mapOf( + "product" to product, + "information" to information, + "platform" to platform, + "version" to version, + "copyright" to copyright, + "capabilities" to CAPABILITIES, + )).toMutableMap() + + if (connectionName != null) { + properties["connection_name"] = connectionName + } + + return properties + } +} diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/Connection.kt b/src/commonMain/kotlin/dimensional/usagi/connection/Connection.kt similarity index 84% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/Connection.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/Connection.kt index 00b1bde..7bc3247 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/Connection.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/Connection.kt @@ -1,25 +1,27 @@ -package mixtape.oss.usagi.connection - +package dimensional.usagi.connection + +import dimensional.usagi.channel.ChannelManager +import dimensional.usagi.connection.event.ConnectionEvent +import dimensional.usagi.connection.frame.Frame +import dimensional.usagi.connection.frame.FrameTooLargeException +import dimensional.usagi.connection.frame.FrameType +import dimensional.usagi.protocol.AMQP +import dimensional.usagi.protocol.Method +import dimensional.usagi.protocol.ProtocolVersion +import dimensional.usagi.protocol.Uri +import dimensional.usagi.protocol.reader.amqp +import dimensional.usagi.protocol.LongString +import dimensional.usagi.protocol.writer.amqp import io.ktor.network.selector.* import io.ktor.network.sockets.* +import io.ktor.network.tls.* import io.ktor.utils.io.* -import io.ktor.utils.io.CancellationException -import kotlinx.coroutines.* +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import mixtape.oss.kyuso.Kyuso import mixtape.oss.kyuso.task.Task -import mixtape.oss.usagi.channel.ChannelManager -import mixtape.oss.usagi.connection.event.ConnectionEvent -import mixtape.oss.usagi.connection.frame.Frame -import mixtape.oss.usagi.connection.frame.FrameTooLargeException -import mixtape.oss.usagi.connection.frame.FrameType -import mixtape.oss.usagi.protocol.AMQP -import mixtape.oss.usagi.protocol.Method -import mixtape.oss.usagi.protocol.ProtocolVersion -import mixtape.oss.usagi.protocol.reader.amqp -import mixtape.oss.usagi.protocol.type.LongString -import mixtape.oss.usagi.protocol.writer.amqp import mu.KotlinLogging import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @@ -33,18 +35,23 @@ public class Connection(private val socket: Socket, internal val resources: Conn * */ public suspend fun connect( - brokerAddress: SocketAddress, + uri: Uri, resources: ConnectionResources, ): Connection { /* create a new TCP socket connection to the specified broker address */ val (connection, took) = measureTimedValue { val socket = aSocket(SelectorManager(resources.scope.coroutineContext)) .tcp() - .connect(brokerAddress) + .connect(InetSocketAddress(uri.host, uri.port)) + + val connection = if (uri.secure) { + Connection(socket.tls(resources.scope.coroutineContext), resources) + } else { + Connection(socket, resources) + } /* create a new AMQP connection instance and negotiate with the broker. */ - val connection = Connection(socket, resources) - connection.initialize() + connection.initialize(uri) } log.debug { "Initialized connection in $took" } @@ -176,7 +183,7 @@ public class Connection(private val socket: Socket, internal val resources: Conn /** * Initializes this AMQP connection. */ - public suspend fun initialize(): Connection { + public suspend fun initialize(uri: Uri): Connection { running = true /* write the protocol frame header. */ @@ -210,17 +217,19 @@ public class Connection(private val socket: Socket, internal val resources: Conn ?: error("No compatible auth mechanisms found, server offered: $serverAuthMechanisms.") /* start authentication sequence */ - val (username, password) = resources.credentials // TODO: support dynamic credentials - var challenge: LongString? = null while (tune == null) { val startOk = AMQP.Connection.StartOk { if (challenge == null) { - clientProperties = resources.connectionProperties + clientProperties = resources.clientProperties mechanism = authMechanism.name } - response = authMechanism.handleChallenge(challenge, username, password) + response = authMechanism.handleChallenge( + challenge, + uri.username, + uri.password + ) } val response = channel0.rpc(startOk) @@ -241,16 +250,16 @@ public class Connection(private val socket: Socket, internal val resources: Conn throw ex } - /* negotiate the connection preferences. */ + /* negotiate the client preferences. */ preferences = preferences.negotiate(tune) - channel0.send(preferences.tuneOk()) - - /* start heart-beating. */ + /* "The client should start sending heartbeats after receiving a connection.tune method" */ heartbeatDispatcher.start(preferences.heartbeat.seconds) - /* send connection.open and wait for ok */ - val ok = channel0.rpc(AMQP.Connection.Open(resources.virtualHost, "", false)).method + channel0.send(preferences.tuneOk()) + + /* send `connection.open` */ + val ok = channel0.rpc(AMQP.Connection.Open(uri.virtualHost, "", false)).method require(ok is AMQP.Connection.OpenOk) { "Expected connection.open-ok but got: $ok" } @@ -260,7 +269,7 @@ public class Connection(private val socket: Socket, internal val resources: Conn /** Handle a close method */ internal suspend fun handleConnectionClose(method: AMQP.Connection.Close) { - channel0.send(AMQP.Connection.CloseOk()) + channel0.send(AMQP.Connection.CloseOk) cancelCause = ConnectionCancelledException(method, null, false) dispose() } diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/ConnectionCancelledException.kt b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionCancelledException.kt similarity index 80% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/ConnectionCancelledException.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/ConnectionCancelledException.kt index 5ec01c5..42a84af 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/ConnectionCancelledException.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionCancelledException.kt @@ -1,7 +1,7 @@ -package mixtape.oss.usagi.connection +package dimensional.usagi.connection +import dimensional.usagi.protocol.AMQP import kotlinx.coroutines.CancellationException -import mixtape.oss.usagi.protocol.AMQP public class ConnectionCancelledException( reason: AMQP.Connection.Close, diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/ConnectionPreferences.kt b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionPreferences.kt similarity index 83% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/ConnectionPreferences.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/ConnectionPreferences.kt index a8c47eb..20d4a4f 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/ConnectionPreferences.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionPreferences.kt @@ -1,23 +1,14 @@ -package mixtape.oss.usagi.connection +package dimensional.usagi.connection -import mixtape.oss.usagi.protocol.AMQP -import mixtape.oss.usagi.tools.RANGE +import dimensional.usagi.protocol.AMQP +import dimensional.usagi.tools.RANGE /** * Preferences for an [Connection] */ public data class ConnectionPreferences( - /** - * The max number of channels that can be created by this connection. - */ - val maxChannelCount: Int = UShort.RANGE.endInclusive - 1, - /** - * The max number of bytes that a frame can take up. - */ + val maxChannelCount: Int = DEFAULT_MAX_CHANNEL_COUNT, val maxFrameSize: Int = 0, - /** - * The interval to send heartbeats at, in seconds. - */ val heartbeat: Int = 60 ) { public companion object { @@ -25,7 +16,7 @@ public data class ConnectionPreferences( * The default max number of channels that can be allocated * to a single connection. */ - public const val DEFAULT_MAX_CHANNEL_COUNT: Int = 2047 + public const val DEFAULT_MAX_CHANNEL_COUNT: Int = 65534 /** * Negotiate between two values, the preferred [client] value diff --git a/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionPreferencesBuilder.kt b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionPreferencesBuilder.kt new file mode 100644 index 0000000..73e9028 --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionPreferencesBuilder.kt @@ -0,0 +1,22 @@ +package dimensional.usagi.connection + +public class ConnectionPreferencesBuilder { + /** + * The max number of channels that can be created by this connection. + */ + public var maxChannelCount: Int = ConnectionPreferences.DEFAULT_MAX_CHANNEL_COUNT + + /** + * The max number of bytes that a frame can take up. 0 means no limit. + */ + public var maxFrameSize: Int = 0 + + /** + * The interval to send heartbeats at, in seconds. + */ + public var heartbeatInterval: Int = 60 + + public fun build(): ConnectionPreferences = ConnectionPreferences( + maxChannelCount, maxFrameSize, heartbeatInterval + ) +} \ No newline at end of file diff --git a/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionResources.kt b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionResources.kt new file mode 100644 index 0000000..0a9ec5d --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionResources.kt @@ -0,0 +1,22 @@ +package dimensional.usagi.connection + +import dimensional.usagi.connection.auth.AuthMechanism +import dimensional.usagi.connection.auth.AuthMechanisms +import dimensional.usagi.connection.event.ConnectionEvent +import dimensional.usagi.protocol.Protocol +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds + +public data class ConnectionResources( + val scope: CoroutineScope = CoroutineScope(Dispatchers.Default + Job()), + val protocol: Protocol, + val handshakeTimeout: Duration , + val authMechanisms: List, + val preferences: ConnectionPreferences, + val clientProperties: Map, + val eventFlow: MutableSharedFlow +) diff --git a/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionResourcesBuilder.kt b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionResourcesBuilder.kt new file mode 100644 index 0000000..f86ef73 --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/connection/ConnectionResourcesBuilder.kt @@ -0,0 +1,79 @@ +package dimensional.usagi.connection + +import dimensional.usagi.connection.auth.AuthMechanism +import dimensional.usagi.connection.auth.AuthMechanisms +import dimensional.usagi.connection.event.ConnectionEvent +import dimensional.usagi.protocol.Protocol +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds + +public class ConnectionResourcesBuilder { + public var dispatcher: CoroutineDispatcher = Dispatchers.Default + + /** + * The protocol information to use when creating the connection. + * + * **Only change this if you know what you're doing.** + */ + public var protocol: Protocol = Protocol.DEFAULT + + /** + * Duration to wait after starting a connection handshake. + */ + public var handshakeTimeout: Duration = 10.seconds + + /** + * The auth mechanisms to attempt. Defaults to `PLAIN` if none are provided. + */ + public var authMechanism: List? = null + + /** + * The preferences to use. + */ + public var preferences: ConnectionPreferencesBuilder.() -> Unit = {} + + /** + * The properties of this client. + */ + public var properties: ClientProperties.() -> Unit = {} + + /** + * + */ + public var eventFlow: MutableSharedFlow = MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE) + + public inline fun preferences(crossinline block: ConnectionPreferencesBuilder.() -> Unit) { + val old = preferences + preferences = { + old() + block() + } + } + + public inline fun properties(crossinline block: ClientProperties.() -> Unit) { + val old = properties + properties = { + old() + block() + } + } + + public fun build(): ConnectionResources = ConnectionResources( + CoroutineScope(dispatcher + Job()), + protocol, + handshakeTimeout, + authMechanism ?: listOf(AuthMechanisms.Plain), + ConnectionPreferencesBuilder() + .apply(preferences) + .build(), + ClientProperties() + .apply(properties) + .build(), + eventFlow + ) +} \ No newline at end of file diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/HeartbeatDispatcher.kt b/src/commonMain/kotlin/dimensional/usagi/connection/HeartbeatDispatcher.kt similarity index 93% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/HeartbeatDispatcher.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/HeartbeatDispatcher.kt index 2a3fca1..340f8ac 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/HeartbeatDispatcher.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/HeartbeatDispatcher.kt @@ -1,5 +1,7 @@ -package mixtape.oss.usagi.connection +package dimensional.usagi.connection +import dimensional.usagi.connection.frame.Frame +import dimensional.usagi.connection.frame.FrameType import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.datetime.Clock import kotlinx.datetime.Instant @@ -7,8 +9,6 @@ import mixtape.oss.kyuso.Kyuso import mixtape.oss.kyuso.task.Task import mixtape.oss.kyuso.tools.Runnable import mixtape.oss.kyuso.tools.calculatingDelay -import mixtape.oss.usagi.connection.frame.Frame -import mixtape.oss.usagi.connection.frame.FrameType import mu.KotlinLogging import kotlin.time.Duration import kotlin.time.TimeMark diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/auth/AuthMechanism.kt b/src/commonMain/kotlin/dimensional/usagi/connection/auth/AuthMechanism.kt similarity index 85% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/auth/AuthMechanism.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/auth/AuthMechanism.kt index 02536ae..0c5c9d2 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/auth/AuthMechanism.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/auth/AuthMechanism.kt @@ -1,6 +1,6 @@ -package mixtape.oss.usagi.connection.auth +package dimensional.usagi.connection.auth -import mixtape.oss.usagi.protocol.type.LongString +import dimensional.usagi.protocol.LongString /** * Represents an authentication mechanism. diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/auth/AuthMechanisms.kt b/src/commonMain/kotlin/dimensional/usagi/connection/auth/AuthMechanisms.kt similarity index 79% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/auth/AuthMechanisms.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/auth/AuthMechanisms.kt index d9fa93f..0181bfb 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/auth/AuthMechanisms.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/auth/AuthMechanisms.kt @@ -1,6 +1,8 @@ -package mixtape.oss.usagi.connection.auth +package dimensional.usagi.connection.auth -import mixtape.oss.usagi.protocol.type.LongString +import dimensional.usagi.connection.auth.AuthMechanisms.External +import dimensional.usagi.connection.auth.AuthMechanisms.Plain +import dimensional.usagi.protocol.LongString /** * Some of our built-in auth mechanisms. diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/event/ConnectionBlockedEvent.kt b/src/commonMain/kotlin/dimensional/usagi/connection/event/ConnectionBlockedEvent.kt similarity index 74% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/event/ConnectionBlockedEvent.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/event/ConnectionBlockedEvent.kt index ef38178..d58cac9 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/event/ConnectionBlockedEvent.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/event/ConnectionBlockedEvent.kt @@ -1,6 +1,6 @@ -package mixtape.oss.usagi.connection.event +package dimensional.usagi.connection.event -import mixtape.oss.usagi.connection.Connection +import dimensional.usagi.connection.Connection /** * The connection has been blocked for the provided [reason] diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/event/ConnectionEvent.kt b/src/commonMain/kotlin/dimensional/usagi/connection/event/ConnectionEvent.kt similarity index 68% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/event/ConnectionEvent.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/event/ConnectionEvent.kt index c1b12dd..cbb2988 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/event/ConnectionEvent.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/event/ConnectionEvent.kt @@ -1,6 +1,6 @@ -package mixtape.oss.usagi.connection.event +package dimensional.usagi.connection.event -import mixtape.oss.usagi.connection.Connection +import dimensional.usagi.connection.Connection /** * An event relating to an AMQP connection. diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/event/ConnectionUnblockedEvent.kt b/src/commonMain/kotlin/dimensional/usagi/connection/event/ConnectionUnblockedEvent.kt similarity index 61% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/event/ConnectionUnblockedEvent.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/event/ConnectionUnblockedEvent.kt index 17bfee9..2ecb6e7 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/event/ConnectionUnblockedEvent.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/event/ConnectionUnblockedEvent.kt @@ -1,6 +1,6 @@ -package mixtape.oss.usagi.connection.event +package dimensional.usagi.connection.event -import mixtape.oss.usagi.connection.Connection +import dimensional.usagi.connection.Connection /** * The connection has been unblocked diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/Frame.kt b/src/commonMain/kotlin/dimensional/usagi/connection/frame/Frame.kt similarity index 92% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/Frame.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/frame/Frame.kt index 8005e23..2681d34 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/Frame.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/frame/Frame.kt @@ -1,8 +1,8 @@ -package mixtape.oss.usagi.connection.frame +package dimensional.usagi.connection.frame +import dimensional.usagi.protocol.reader.ProtocolReader +import dimensional.usagi.protocol.writer.ProtocolWriter import io.ktor.utils.io.core.* -import mixtape.oss.usagi.protocol.reader.ProtocolReader -import mixtape.oss.usagi.protocol.writer.ProtocolWriter public data class Frame( val header: FrameHeader, diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/FrameHeader.kt b/src/commonMain/kotlin/dimensional/usagi/connection/frame/FrameHeader.kt similarity index 79% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/FrameHeader.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/frame/FrameHeader.kt index cd0addd..b946238 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/FrameHeader.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/frame/FrameHeader.kt @@ -1,7 +1,7 @@ -package mixtape.oss.usagi.connection.frame +package dimensional.usagi.connection.frame -import mixtape.oss.usagi.protocol.reader.ProtocolReader -import mixtape.oss.usagi.protocol.writer.ProtocolWriter +import dimensional.usagi.protocol.reader.ProtocolReader +import dimensional.usagi.protocol.writer.ProtocolWriter public data class FrameHeader( val type: FrameType, diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/FrameTooLargeException.kt b/src/commonMain/kotlin/dimensional/usagi/connection/frame/FrameTooLargeException.kt similarity index 78% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/FrameTooLargeException.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/frame/FrameTooLargeException.kt index 16b645f..f64f98a 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/FrameTooLargeException.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/frame/FrameTooLargeException.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.connection.frame +package dimensional.usagi.connection.frame public class FrameTooLargeException(public val frame: Frame, public val maxSize: Int) : Exception( "Frame exceeds max size of $maxSize: ${frame.size}" diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/FrameType.kt b/src/commonMain/kotlin/dimensional/usagi/connection/frame/FrameType.kt similarity index 91% rename from src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/FrameType.kt rename to src/commonMain/kotlin/dimensional/usagi/connection/frame/FrameType.kt index b91dd9a..0470999 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/frame/FrameType.kt +++ b/src/commonMain/kotlin/dimensional/usagi/connection/frame/FrameType.kt @@ -1,6 +1,6 @@ -package mixtape.oss.usagi.connection.frame +package dimensional.usagi.connection.frame -import mixtape.oss.usagi.protocol.reader.ProtocolReader +import dimensional.usagi.protocol.reader.ProtocolReader /** must be in this order, see [id] */ public sealed class FrameType(public val id: Int) { diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/type/LongString.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/LongString.kt similarity index 87% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/type/LongString.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/LongString.kt index b53d054..8a7a84f 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/type/LongString.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/LongString.kt @@ -1,7 +1,7 @@ -package mixtape.oss.usagi.protocol.type +package dimensional.usagi.protocol +import dimensional.usagi.protocol.reader.ProtocolReader import io.ktor.utils.io.core.* -import mixtape.oss.usagi.protocol.reader.ProtocolReader import kotlin.jvm.JvmInline @JvmInline diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/Method.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/Method.kt similarity index 78% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/Method.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/Method.kt index af9207d..76c2c90 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/Method.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/Method.kt @@ -1,13 +1,13 @@ -package mixtape.oss.usagi.protocol +package dimensional.usagi.protocol +import dimensional.usagi.connection.frame.Frame +import dimensional.usagi.connection.frame.FrameHeader +import dimensional.usagi.connection.frame.FrameType +import dimensional.usagi.protocol.reader.MethodProtocolReader +import dimensional.usagi.protocol.reader.amqp +import dimensional.usagi.protocol.writer.MethodProtocolWriter +import dimensional.usagi.protocol.writer.amqp import io.ktor.utils.io.core.* -import mixtape.oss.usagi.connection.frame.Frame -import mixtape.oss.usagi.connection.frame.FrameHeader -import mixtape.oss.usagi.connection.frame.FrameType -import mixtape.oss.usagi.protocol.reader.MethodProtocolReader -import mixtape.oss.usagi.protocol.reader.amqp -import mixtape.oss.usagi.protocol.writer.MethodProtocolWriter -import mixtape.oss.usagi.protocol.writer.amqp public abstract class Method { public companion object { diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/Protocol.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/Protocol.kt similarity index 94% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/Protocol.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/Protocol.kt index 8e90fde..50e9e44 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/Protocol.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/Protocol.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol +package dimensional.usagi.protocol public data class Protocol( val version: ProtocolVersion diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/ProtocolVersion.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/ProtocolVersion.kt similarity index 96% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/ProtocolVersion.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/ProtocolVersion.kt index 624b63b..8973d69 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/ProtocolVersion.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/ProtocolVersion.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol +package dimensional.usagi.protocol public data class ProtocolVersion(val major: Int, val minor: Int, val revision: Int = 0) { public companion object { diff --git a/src/commonMain/kotlin/dimensional/usagi/protocol/URIBuilder.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/URIBuilder.kt new file mode 100644 index 0000000..7bf8776 --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/URIBuilder.kt @@ -0,0 +1,14 @@ +package dimensional.usagi.protocol + +import dimensional.usagi.tools.AMQP +import io.ktor.http.* + +/** + */ +public class URIBuilder( + public var host: String = "", + public var port: Int = URLProtocol.AMQP.defaultPort, + public var username: String = "guest", + public var password: String = "guest", + public var virtualHost: String = "/" +) diff --git a/src/commonMain/kotlin/dimensional/usagi/protocol/Uri.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/Uri.kt new file mode 100644 index 0000000..07e6d30 --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/Uri.kt @@ -0,0 +1,10 @@ +package dimensional.usagi.protocol + +public data class Uri( + val virtualHost: String, + val username: String, + val password: String, + val host: String, + val port: Int, + val secure: Boolean +) diff --git a/src/commonMain/kotlin/dimensional/usagi/protocol/dsl.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/dsl.kt new file mode 100644 index 0000000..d21da3f --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/dsl.kt @@ -0,0 +1,42 @@ +package dimensional.usagi.protocol + +import dimensional.usagi.tools.AMQP +import dimensional.usagi.tools.AMQPS +import io.ktor.http.* + +public fun Uri(url: String): Uri { + return Uri(Url(url)) +} + +public fun Uri(url: Url): Uri { + val normalized = url.normalizeProtocol() + + /* get vhost from path segments. */ + val vhost = url.pathSegments + .drop(1) + .firstOrNull() + ?: "" + + /* return amqp uri */ + return Uri( + vhost.ifBlank { "/" }, + normalized.user ?: "guest", + normalized.password ?: "guest", + normalized.host, + normalized.port, + normalized.protocol == URLProtocol.AMQPS + ) +} + +private fun Url.normalizeProtocol(): Url { + val protocol: URLProtocol = when (protocol.name) { + "amqp" -> URLProtocol.AMQP + "amqps" -> URLProtocol.AMQPS + else -> error("Invalid Protocol: ${protocol.name}") + } + + val url = URLBuilder(this) + url.protocol = protocol + + return url.build() +} diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/ChannelProtocolReader.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/ChannelProtocolReader.kt similarity index 96% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/ChannelProtocolReader.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/reader/ChannelProtocolReader.kt index 99fac03..b517fec 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/ChannelProtocolReader.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/ChannelProtocolReader.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol.reader +package dimensional.usagi.protocol.reader import io.ktor.utils.io.* import io.ktor.utils.io.core.* diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/InputProtocolReader.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/InputProtocolReader.kt similarity index 95% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/InputProtocolReader.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/reader/InputProtocolReader.kt index 02d9a3e..ccb0eea 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/InputProtocolReader.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/InputProtocolReader.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol.reader +package dimensional.usagi.protocol.reader import io.ktor.utils.io.core.* diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/MethodProtocolReader.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/MethodProtocolReader.kt similarity index 98% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/MethodProtocolReader.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/reader/MethodProtocolReader.kt index daacb6c..fdcc946 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/MethodProtocolReader.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/MethodProtocolReader.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol.reader +package dimensional.usagi.protocol.reader import io.ktor.utils.io.core.* diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/ProtocolPropertiesReader.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/ProtocolPropertiesReader.kt similarity index 95% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/ProtocolPropertiesReader.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/reader/ProtocolPropertiesReader.kt index 8e5740c..a1084b7 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/ProtocolPropertiesReader.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/ProtocolPropertiesReader.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol.reader +package dimensional.usagi.protocol.reader public class ProtocolPropertiesReader(reader: ProtocolReader): ProtocolReader by reader { private var flagWord = 1 diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/ProtocolReader.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/ProtocolReader.kt similarity index 95% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/ProtocolReader.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/reader/ProtocolReader.kt index f8a8235..83a8762 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/reader/ProtocolReader.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/reader/ProtocolReader.kt @@ -1,8 +1,8 @@ -package mixtape.oss.usagi.protocol.reader +package dimensional.usagi.protocol.reader +import dimensional.usagi.protocol.LongString import io.ktor.utils.io.core.* import kotlinx.datetime.Instant -import mixtape.oss.usagi.protocol.type.LongString public interface ProtocolReader { public suspend fun readOctet(): Int { @@ -29,7 +29,7 @@ public interface ProtocolReader { public suspend fun readArray(): List { val packet = readPacket(n = readLongSigned()) - /* read array values from packet */ + /* read array values from the packet */ val array = mutableListOf() while (packet.isNotEmpty) { array += packet.amqp.readFieldValue() diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/ChannelProtocolWriter.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/ChannelProtocolWriter.kt similarity index 96% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/ChannelProtocolWriter.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/writer/ChannelProtocolWriter.kt index 60c8516..a94a382 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/ChannelProtocolWriter.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/ChannelProtocolWriter.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol.writer +package dimensional.usagi.protocol.writer import io.ktor.utils.io.* import io.ktor.utils.io.core.* diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/MethodProtocolWriter.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/MethodProtocolWriter.kt similarity index 97% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/MethodProtocolWriter.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/writer/MethodProtocolWriter.kt index 751dc50..7428d64 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/MethodProtocolWriter.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/MethodProtocolWriter.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol.writer +package dimensional.usagi.protocol.writer import io.ktor.utils.io.core.* diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/OutputProtocolWriter.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/OutputProtocolWriter.kt similarity index 96% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/OutputProtocolWriter.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/writer/OutputProtocolWriter.kt index 9821e16..77f833b 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/OutputProtocolWriter.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/OutputProtocolWriter.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol.writer +package dimensional.usagi.protocol.writer import io.ktor.utils.io.core.* diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/ProtocolPropertiesWriter.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/ProtocolPropertiesWriter.kt similarity index 94% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/ProtocolPropertiesWriter.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/writer/ProtocolPropertiesWriter.kt index add5b36..7305c6d 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/ProtocolPropertiesWriter.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/ProtocolPropertiesWriter.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.protocol.writer +package dimensional.usagi.protocol.writer public class ProtocolPropertiesWriter(writer: ProtocolWriter): ProtocolWriter by writer { private var flagWord = 0 diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/ProtocolWriter.kt b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/ProtocolWriter.kt similarity index 96% rename from src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/ProtocolWriter.kt rename to src/commonMain/kotlin/dimensional/usagi/protocol/writer/ProtocolWriter.kt index 92ec177..3e2eaf7 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/protocol/writer/ProtocolWriter.kt +++ b/src/commonMain/kotlin/dimensional/usagi/protocol/writer/ProtocolWriter.kt @@ -1,9 +1,9 @@ -package mixtape.oss.usagi.protocol.writer +package dimensional.usagi.protocol.writer +import dimensional.usagi.protocol.LongString +import dimensional.usagi.tools.into import io.ktor.utils.io.core.* import kotlinx.datetime.Instant -import mixtape.oss.usagi.protocol.type.LongString -import mixtape.oss.usagi.tools.into public interface ProtocolWriter { public suspend fun writeOctet(value: Int) { diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/tools/BitSet.kt b/src/commonMain/kotlin/dimensional/usagi/tools/BitSet.kt similarity index 91% rename from src/commonMain/kotlin/mixtape/oss/usagi/tools/BitSet.kt rename to src/commonMain/kotlin/dimensional/usagi/tools/BitSet.kt index 78c341a..85cd324 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/tools/BitSet.kt +++ b/src/commonMain/kotlin/dimensional/usagi/tools/BitSet.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.tools +package dimensional.usagi.tools public expect class BitSet public constructor(size: Int) { diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/tools/IntAllocator.kt b/src/commonMain/kotlin/dimensional/usagi/tools/IntAllocator.kt similarity index 98% rename from src/commonMain/kotlin/mixtape/oss/usagi/tools/IntAllocator.kt rename to src/commonMain/kotlin/dimensional/usagi/tools/IntAllocator.kt index 86bd139..c50df8c 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/tools/IntAllocator.kt +++ b/src/commonMain/kotlin/dimensional/usagi/tools/IntAllocator.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.tools +package dimensional.usagi.tools /** * A class for allocating integers from a given range that uses a diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/tools/KLogger.kt b/src/commonMain/kotlin/dimensional/usagi/tools/KLogger.kt similarity index 90% rename from src/commonMain/kotlin/mixtape/oss/usagi/tools/KLogger.kt rename to src/commonMain/kotlin/dimensional/usagi/tools/KLogger.kt index e054154..80a914a 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/tools/KLogger.kt +++ b/src/commonMain/kotlin/dimensional/usagi/tools/KLogger.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.tools +package dimensional.usagi.tools import mu.KLogger import kotlin.time.measureTimedValue diff --git a/src/commonMain/kotlin/dimensional/usagi/tools/URLProtocol.kt b/src/commonMain/kotlin/dimensional/usagi/tools/URLProtocol.kt new file mode 100644 index 0000000..0edf2f0 --- /dev/null +++ b/src/commonMain/kotlin/dimensional/usagi/tools/URLProtocol.kt @@ -0,0 +1,11 @@ +package dimensional.usagi.tools + +import io.ktor.http.* + +/** AMQP with port 5672 */ +public val URLProtocol.Companion.AMQP: URLProtocol + get() = URLProtocol("amqp", 5672) + +/** secure AMQP with port 5671 */ +public val URLProtocol.Companion.AMQPS: URLProtocol + get() = URLProtocol("amqps", 5671) diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/tools/extensions.kt b/src/commonMain/kotlin/dimensional/usagi/tools/extensions.kt similarity index 95% rename from src/commonMain/kotlin/mixtape/oss/usagi/tools/extensions.kt rename to src/commonMain/kotlin/dimensional/usagi/tools/extensions.kt index 4356722..227644a 100644 --- a/src/commonMain/kotlin/mixtape/oss/usagi/tools/extensions.kt +++ b/src/commonMain/kotlin/dimensional/usagi/tools/extensions.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.tools +package dimensional.usagi.tools /** * The range of the values a UShort can hold. diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/Usagi.kt b/src/commonMain/kotlin/mixtape/oss/usagi/Usagi.kt deleted file mode 100644 index c41e196..0000000 --- a/src/commonMain/kotlin/mixtape/oss/usagi/Usagi.kt +++ /dev/null @@ -1,5 +0,0 @@ -package mixtape.oss.usagi - -public object Usagi { - -} diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/Channel.kt b/src/commonMain/kotlin/mixtape/oss/usagi/channel/Channel.kt deleted file mode 100644 index 9d87611..0000000 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/Channel.kt +++ /dev/null @@ -1,87 +0,0 @@ -package mixtape.oss.usagi.channel - -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.sync.withLock -import mixtape.oss.usagi.channel.command.Command -import mixtape.oss.usagi.channel.consumer.Consumer -import mixtape.oss.usagi.channel.consumer.Delivery -import mixtape.oss.usagi.channel.event.MessagePublishedEvent -import mixtape.oss.usagi.channel.event.ChannelEvent -import mixtape.oss.usagi.connection.Connection -import mixtape.oss.usagi.protocol.AMQP -import mixtape.oss.usagi.tools.into -import mu.KotlinLogging - -public class Channel( - connection: Connection, - id: Int -) : BaseChannel(connection, id) { - public companion object { - private val log = KotlinLogging.logger { } - } - - private val consumerMap = hashMapOf() - private val eventFlow = MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE) - - /** */ - public val consumers: Map get() = object : Map by consumerMap {} - /** */ - public val events: SharedFlow get() = eventFlow - - override suspend fun processIncomingCommand(command: Command): Boolean = when (command.method) { - // TODO: handle channel related shit here. - /* channel-specific commands. */ - is AMQP.Channel.Close -> { - log.warn { "[Channel $id] Server requested close..." } - true - } - - /* consumer-specific commands */ - is AMQP.Basic.Deliver -> { - val consumer = consumerMap[command.method.consumerTag] - if (consumer != null) { - val delivery = Delivery( - consumer, - Delivery.Envelope( - command.method.deliveryTag, - command.method.redelivered, - command.method.exchange, - command.method.routingKey, - ), - command.header?.properties.into(), - command.body!!.asBytes() - ) - - eventFlow.emit(MessagePublishedEvent(consumer, delivery)) - } - - true - } - - is AMQP.Basic.Cancel -> { - true - } - - is AMQP.Basic.CancelOk -> { - false // forward this to RPC - } - - is AMQP.Basic.RecoverOk -> { - false // forward this to RPC - } - - /* everything else */ - else -> false - } - - internal suspend fun createConsumer(method: AMQP.Basic.Consume): Consumer { - val ok = rpc(method) - require(ok.method is AMQP.Basic.ConsumeOk) { "Expected `basic.consume-ok`, not ${ok.method.methodName()}" } - - val consumer = Consumer(this, ok.method.consumerTag) - consumerMap[consumer.tag] = consumer - - return consumer - } -} diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/channel/event/ChannelEvent.kt b/src/commonMain/kotlin/mixtape/oss/usagi/channel/event/ChannelEvent.kt deleted file mode 100644 index 1a4cd89..0000000 --- a/src/commonMain/kotlin/mixtape/oss/usagi/channel/event/ChannelEvent.kt +++ /dev/null @@ -1,7 +0,0 @@ -package mixtape.oss.usagi.channel.event - -import mixtape.oss.usagi.channel.Channel - -public interface ChannelEvent { - public val channel: Channel -} diff --git a/src/commonMain/kotlin/mixtape/oss/usagi/connection/ConnectionResources.kt b/src/commonMain/kotlin/mixtape/oss/usagi/connection/ConnectionResources.kt deleted file mode 100644 index 3cd9f8a..0000000 --- a/src/commonMain/kotlin/mixtape/oss/usagi/connection/ConnectionResources.kt +++ /dev/null @@ -1,44 +0,0 @@ -package mixtape.oss.usagi.connection - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.flow.MutableSharedFlow -import mixtape.oss.usagi.connection.auth.AuthMechanism -import mixtape.oss.usagi.connection.auth.AuthMechanisms -import mixtape.oss.usagi.connection.event.ConnectionEvent -import mixtape.oss.usagi.protocol.Protocol -import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds - -public data class ConnectionResources( - val credentials: Pair, - val virtualHost: String = "/", - val scope: CoroutineScope = CoroutineScope(Dispatchers.Default + Job()), - val protocol: Protocol = Protocol.DEFAULT, - val handshakeTimeout: Duration = 10.seconds, - val authMechanisms: List = listOf(AuthMechanisms.Plain), - val preferences: ConnectionPreferences = ConnectionPreferences(), - val connectionProperties: Map = DEFAULT_CONNECTION_PROPERTIES, - val eventFlow: MutableSharedFlow = MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE) -) { - public companion object { - public val DEFAULT_CONNECTION_PROPERTIES: Map = mapOf( - "product" to "usagi", - "information" to "https://github.com/mixtape-bot/usagi", - "platform" to "Kotlin ${KotlinVersion.CURRENT}", - "version" to "0.0.0", - "copyright" to "Copyright (c) 2019 - 2022 Dimensional Fun", - "capabilities" to mapOf( - "authentication_failure_close" to true, - "basic.nack" to true, - "connection.blocked" to true, - "consumer_cancel_notify" to true, - "exchange_exchange_bindings" to true, - "per_consumer_qos" to true, - "publisher_confirms" to true, - ) - ) - } -} diff --git a/src/jvmMain/kotlin/mixtape/oss/usagi/tools/BitSet.kt b/src/jvmMain/kotlin/mixtape/oss/usagi/tools/BitSet.kt index 5e82180..7ec88b4 100644 --- a/src/jvmMain/kotlin/mixtape/oss/usagi/tools/BitSet.kt +++ b/src/jvmMain/kotlin/mixtape/oss/usagi/tools/BitSet.kt @@ -1,3 +1,3 @@ -package mixtape.oss.usagi.tools +package dimensional.usagi.tools public actual typealias BitSet = java.util.BitSet diff --git a/src/jvmTest/kotlin/usagi.kt b/src/jvmTest/kotlin/usagi.kt new file mode 100644 index 0000000..a9b2986 --- /dev/null +++ b/src/jvmTest/kotlin/usagi.kt @@ -0,0 +1,112 @@ +import com.rabbitmq.client.AMQP +import com.rabbitmq.client.CancelCallback +import com.rabbitmq.client.ConnectionFactory +import com.rabbitmq.client.DeliverCallback +import dimensional.usagi.Usagi +import dimensional.usagi.channel.consumer.on +import dimensional.usagi.channel.event.MessagePublishedEvent +import dimensional.usagi.channel.method.basic +import dimensional.usagi.channel.method.exchange +import dimensional.usagi.channel.method.queue +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.job +import mixtape.oss.kyuso.Kyuso +import mixtape.oss.kyuso.tools.calculatingDelay +import kotlin.time.Duration.Companion.seconds + +val publishData = "lol".encodeToByteArray() +val publishHeaders = mapOf("X-Testing" to true) + +suspend fun main() { + usagi() +} + +suspend fun javaRabbitMq() { + val connectionFactory = ConnectionFactory() + connectionFactory.useNio() + connectionFactory.setUri("amqp://localhost") + + /* create connection & channel */ + val connection = connectionFactory.newConnection() + val channel = connection.createChannel() + + /* declare exchange */ + channel.exchangeDeclare("test", "direct", false, true, emptyMap()) + + /* declare & bind queue */ + channel.queueDeclare("test", true, false, true, emptyMap()) + channel.queueBind("", "test", "test") + + /* consume messages */ + channel.basicConsume( + "", + DeliverCallback { _, message -> + println(message.body.decodeToString()); + println(message.properties); + println(message.envelope) + }, + CancelCallback { } + ) + + /* publish messages every 20ms */ + val kyuso = Kyuso(Dispatchers.IO.limitedParallelism(1)) + kyuso.dispatchEvery(calculatingDelay(1.seconds)) { + val properties = AMQP.BasicProperties.Builder() + .headers(publishHeaders) + .build() + + channel.basicPublish("test", "test", properties, publishData) + } + + kyuso.scope.coroutineContext.job.join() +} + +suspend fun usagi() { + val connection = Usagi("amqp://localhost") { + properties { + connectionName = "testing thing idk" + } + } + + val channel = connection.channels.create()!! + + channel.queue.declare { + queue = "test" + durable = true + autoDelete = true + } + + channel.exchange.declare { + exchange = "test" + autoDelete = true + } + + channel.queue.bind { + exchange = "test" + routingKey = "test" + } + + val consumer = channel.basic.consume { + queue = "test" + } + + consumer.on { + println(delivery.data.decodeToString()) + println(delivery.properties) + println(delivery.envelope) + + delivery.ack() + } + + val kyuso = Kyuso(Dispatchers.IO.limitedParallelism(1)) + kyuso.dispatchEvery(calculatingDelay(1.seconds)) { + channel.basic.publish { + data = publishData + options { routingKey = "test"; exchange = "test" } + properties { headers = publishHeaders } + } + } + + connection.resources.scope.coroutineContext[Job]!!.join() +} diff --git a/src/jvmTest/resources/logback.xml b/src/jvmTest/resources/logback.xml new file mode 100644 index 0000000..e820d45 --- /dev/null +++ b/src/jvmTest/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + + %gray(%d{yyyy-MM-dd HH:mm:ss.SSS}) %magenta(%-15.-15thread) %cyan(%-30.-30logger{30}) %highlight(%-6level) %msg%n + + + + + + + diff --git a/src/linuxX64Main/kotlin/mixtape/oss/usagi/tools/BitSet.kt b/src/linuxX64Main/kotlin/mixtape/oss/usagi/tools/BitSet.kt index 201a4f7..524dfc7 100644 --- a/src/linuxX64Main/kotlin/mixtape/oss/usagi/tools/BitSet.kt +++ b/src/linuxX64Main/kotlin/mixtape/oss/usagi/tools/BitSet.kt @@ -1,4 +1,4 @@ -package mixtape.oss.usagi.tools +package dimensional.usagi.tools /** * Simplified version of java.util.BitSet