{"id":16192231,"url":"https://github.com/cretz/pb-and-k","last_synced_at":"2025-10-24T00:06:07.431Z","repository":{"id":33888742,"uuid":"135504546","full_name":"cretz/pb-and-k","owner":"cretz","description":"Kotlin Code Generator and Runtime for Protocol Buffers","archived":false,"fork":false,"pushed_at":"2022-03-17T16:55:10.000Z","size":254,"stargazers_count":139,"open_issues_count":8,"forks_count":15,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-02-27T07:48:58.511Z","etag":null,"topics":["kotlin","protobuf","protoc","protocol-buffers"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cretz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-30T22:40:02.000Z","updated_at":"2025-02-19T17:56:01.000Z","dependencies_parsed_at":"2022-08-07T23:30:30.159Z","dependency_job_id":null,"html_url":"https://github.com/cretz/pb-and-k","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cretz%2Fpb-and-k","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cretz%2Fpb-and-k/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cretz%2Fpb-and-k/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cretz%2Fpb-and-k/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cretz","download_url":"https://codeload.github.com/cretz/pb-and-k/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243814907,"owners_count":20352037,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kotlin","protobuf","protoc","protocol-buffers"],"created_at":"2024-10-10T08:09:21.609Z","updated_at":"2025-10-24T00:06:01.975Z","avatar_url":"https://github.com/cretz.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"### This product is not actively maintained. See [streem/pbandk](https://github.com/streem/pbandk) for a more actively maintained fork.\n\n# PBAndK\n\nPBAndK is a Kotlin code generator and runtime for [Protocol Buffers](https://developers.google.com/protocol-buffers/).\nIt is built to work across multiple Kotlin platforms.\n\n**Features**\n\n* Clean data class generation\n* Works for JVM and JS\n* Support for proto2 and proto3 syntaxes\n* Oneof's are properly handled as sealed classes\n* JVM platform leverages [Protobuf's Java library](https://developers.google.com/protocol-buffers/docs/javatutorial) for\n  best performance\n* JS platform leverages [protobuf.js](https://github.com/dcodeIO/ProtoBuf.js/) for best performance\n* Support for custom service/gRPC code generator\n\n**Not Yet Implemented**\n\n* Kotlin Native runtime support\n* Protobuf code generator in Kotlin Native for easier importing\n* Specialized support for well known types instead of just referencing them\n* Code comments on generated code\n* JSON support\n\nRead below for more information and see the [examples](examples).\n\n### Beta\n\nThis project is currently in beta yet has the features needed to solve the author's original goals. The \"Not Yet\nImplemented\" features above will be implemented only if this project garners reasonable interest. If the features are\nimplemented, it is possible they may be done in a backwards incompatible way.\n\n**NOTE:** This product is not actively maintained. See https://github.com/streem/pbandk for a more actively maintained fork.\n\n### Generated Code\n\nFor the following `addressbook.proto` file:\n\n```protobuf\nsyntax = \"proto3\";\npackage tutorial;\n\nimport \"google/protobuf/timestamp.proto\";\n\nmessage Person {\n    string name = 1;\n    int32 id = 2;\n    string email = 3;\n\n    enum PhoneType {\n        MOBILE = 0;\n        HOME = 1;\n        WORK = 2;\n    }\n\n    message PhoneNumber {\n        string number = 1;\n        PhoneType type = 2;\n    }\n\n    repeated PhoneNumber phones = 4;\n\n    google.protobuf.Timestamp last_updated = 5;\n}\n\nmessage AddressBook {\n    repeated Person people = 1;\n}\n```\n\nThe following file will be generated at `tutorial/addressbook.kt`:\n\n```kotlin\npackage tutorial\n\ndata class Person(\n    val name: String = \"\",\n    val id: Int = 0,\n    val email: String = \"\",\n    val phones: List\u003ctutorial.Person.PhoneNumber\u003e = emptyList(),\n    val lastUpdated: pbandk.wkt.Timestamp? = null,\n    val unknownFields: Map\u003cInt, pbandk.UnknownField\u003e = emptyMap()\n) : pbandk.Message\u003cPerson\u003e {\n    override operator fun plus(other: Person?) = protoMergeImpl(other)\n    override val protoSize by lazy { protoSizeImpl() }\n    override fun protoMarshal(m: pbandk.Marshaller) = protoMarshalImpl(m)\n    companion object : pbandk.Message.Companion\u003cPerson\u003e {\n        override fun protoUnmarshal(u: pbandk.Unmarshaller) = Person.protoUnmarshalImpl(u)\n    }\n\n    data class PhoneType(override val value: Int) : pbandk.Message.Enum {\n        companion object : pbandk.Message.Enum.Companion\u003cPhoneType\u003e {\n            val MOBILE = PhoneType(0)\n            val HOME = PhoneType(1)\n            val WORK = PhoneType(2)\n\n            override fun fromValue(value: Int) = when (value) {\n                0 -\u003e MOBILE\n                1 -\u003e HOME\n                2 -\u003e WORK\n                else -\u003e PhoneType(value)\n            }\n        }\n    }\n\n    data class PhoneNumber(\n        val number: String = \"\",\n        val type: tutorial.Person.PhoneType = tutorial.Person.PhoneType.fromValue(0),\n        val unknownFields: Map\u003cInt, pbandk.UnknownField\u003e = emptyMap()\n    ) : pbandk.Message\u003cPhoneNumber\u003e {\n        override operator fun plus(other: PhoneNumber?) = protoMergeImpl(other)\n        override val protoSize by lazy { protoSizeImpl() }\n        override fun protoMarshal(m: pbandk.Marshaller) = protoMarshalImpl(m)\n        companion object : pbandk.Message.Companion\u003cPhoneNumber\u003e {\n            override fun protoUnmarshal(u: pbandk.Unmarshaller) = PhoneNumber.protoUnmarshalImpl(u)\n        }\n    }\n}\n\ndata class AddressBook(\n    val people: List\u003ctutorial.Person\u003e = emptyList(),\n    val unknownFields: Map\u003cInt, pbandk.UnknownField\u003e = emptyMap()\n) : pbandk.Message\u003cAddressBook\u003e {\n    override operator fun plus(other: AddressBook?) = protoMergeImpl(other)\n    override val protoSize by lazy { protoSizeImpl() }\n    override fun protoMarshal(m: pbandk.Marshaller) = protoMarshalImpl(m)\n    companion object : pbandk.Message.Companion\u003cAddressBook\u003e {\n        override fun protoUnmarshal(u: pbandk.Unmarshaller) = AddressBook.protoUnmarshalImpl(u)\n    }\n}\n\n// Omitted multiple supporting private extension methods\n```\n\nTo see a full version of the file, see\n[here](examples/gradle-and-jvm/src/main/kotlin/pbandk/examples/addressbook/pb/addressbook.kt). See the \"Generated Code\"\nsection below under \"Usage\" for more details.\n\n### Usage\n\n#### Generating Code\n\nPBAndK's code generator leverages `protoc`. Download the\n[latest protoc](https://github.com/google/protobuf/releases/latest) and make sure `protoc` is on the `PATH`. Then\ndownload the [latest protoc-gen-kotlin](https://github.com/cretz/pb-and-k/releases/latest) and make sure\n`protoc-gen-kotlin` is on the `PATH`. To generate code from `sample.proto` and put in `src/main/kotlin`, run:\n\n    protoc --kotlin_out=src/main/kotlin sample.proto\n\nFor Windows however, `protoc` doesn't support finding `protoc-gen-kotlin.bat` on the `PATH`. So it has to be specified\nexplicitly as a plugin:\n\n    protoc --kotlin_out=src/main/kotlin --plugin=protoc-gen-kotlin=path/to/protoc-gen-kotlin.bat sample.proto\n\nThe file is generated as `sample.kt` in the subdirectories specified by the package. Like other `X_out` arguments,\ncomma-separated options can be added to `--kotlin_out` before the colon and out dir path. To explicitly set the Kotlin\npackage to `my.pkg`, use the `kotlin_package` option like so:\n\n    protoc --kotlin_out=kotlin_package=my.pkg:src/main/kotlin sample.proto\n\nTo log debug logs during generation, `log=debug` can be set as well.\n\nIn addition to running `protoc` manually, the\n[Protobuf Plugin for Gradle](https://github.com/google/protobuf-gradle-plugin) can be used. See\n[this example](examples/gradle-and-jvm) to see how.\n\n#### Runtime Library\n\nPBAndK's runtime library is a thin layer over the preferred Protobuf library for each platform. The libraries are\npresent on [Maven Central](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.github.cretz.pbandk%22). Using Gradle\nand assuming `mavenCentral()` is one of the `repositories`, the dependency can be added for JVM libraries:\n\n```\ndependencies {\n    compile 'com.github.cretz.pbandk:pbandk-runtime-jvm:0.3.0'\n}\n```\n\nIt has a dependency on the Google Protobuf Java library. The code targets Java 1.6 to be Android friendly. For Kotlin\nJS, change `pbandk-runtime-jvm` to `pbandk-runtime-js` and for common multiplatform code, change `pbandk-runtime-jvm` to\n`pbandk-runtime-common`.\n\n#### Service Code Generation\n\nPBAndK does not generate gRPC code itself, but offers a `pbandk.gen.ServiceGenerator` interface in the\n`protoc-gen-kotlin-jvm` project (really in the `protoc-gen-kotlin-common` project and inherited) with a single method\nthat can be implemented to generate the code.\n\nTo do this, first depend on the project but it will only be needed at compile time because it's already there at\nruntime:\n\n```\ndependencies {\n    compileOnly 'com.github.cretz.pbandk:protoc-gen-kotlin-jvm:0.3.0'\n}\n```\n\nThen, the `kotlin_service_gen` option can be given to `protoc` to use the generator. The option is a path-separated\ncollection of JAR files to put on the classpath. It can end with a pipe (i.e. `|`) following by the fully-qualified\nclass name of the implementation of the `ServiceGenerator` to use. If the last part is not present, it will use the\n`ServiceLoader` mechanism to find the first implementation to use. For example, to gen with `my.Generator` from\n`gen.jar`, it might look like:\n\n    protoc --kotlin_out=kotlin_service_gen=gen.jar|my.Generator,kotlin_package=my.pkg:src/main/kotlin some.proto\n    \nFor more details, see the [custom-service-gen](examples/custom-service-gen) example.\n\n#### Generated Code\n\n**Package**\n\nThe package is either the `kotlin_package` plugin option or the package set in the message. If the `google.protobuf`\npackage is referenced, it is assumed to be a well-known type and is changed to reference `pbandk.wkt`.\n\n**Message**\n\nEach Protobuf message extends `pbandk.Message` and has two overloaded `protoMarshal` methods, the most useful of which\nmarshals to a byte array. The companion object of every message has two overloaded `protoUnmarshal` methods, the most\nuseful of which accepts a byte array and returns an instance of the class. The other `protoMarshal` and `protoUnmarshal`\nmethods accept `Marshaller` and `Unmarshaller` instances respectively which are different for each platform. For\nexample, the JVM `Marshaller` uses `com.google.protobuf.CodedOutputStream`.\n\nMessages are immutable Kotlin data classes. This means they automatically implement `hashCode`, `equals`, and\n`toString`. Each class has an `unknownFields` map which contains information about extra fields the unmarshaller didn't\nrecognize. If there are values in this map, they will be marshalled on output. The `Unmarshaller` instances have a\nconstructor option to discard unknown fields when reading.\n\nFor proto3, the only nullable fields are other messages and oneof fields. Other values have defaults. For proto2,\noptional fields are nullable and defaulted as such. Types are basically the same as they would be in Java. However,\n`bytes` fields actually use a `pbandk.ByteArr` class which is a simple wrapper around a byte array. This was done\nbecause Kotlin does not handle array fields in data classes predictably and it wasn't worth overriding `equals` and\n`hashCode` every time.\n\nRegardless of `optimize_for` options, the generated code is always the same. Each message has a `protoSize` field that\nlazily calculates the size of the message when first invoked. Also, each message has the `plus` operator defined which\nfollows protobuf merge semantics.\n\n**Oneof**\n\nOneof fields are generated as nested classes of a common sealed base class. Each oneof inner field is a data class that\nwraps a single value.\n\n**Enum**\n\nEnum fields are generated as single-integer-value immutable data classes with known values as vals on the companion\nobject. This is preferred over traditional enum classes because enums in protobuf are open ended and may not be one of\nthe specific known values. Traditional enum classes would not be able to capture this state and using data classes this\nway requires the user to do explicit checks for unknown ordinals during exhaustive when clauses. This does come at very\nnegligible cost during equality checks. Although there is the normal single-integer-value constructor on the data class,\ndevelopers should use the `fromValue` method present on the companion object. This will return an existing val if known.\nIt is possible in future versions that the generated data class constructor will become private.\n\nNote, there is no reflection outside of normal Kotlin reflection. This means Kotlin reflection has to be used to get\nstring values of the enums currently. This may change as the JSON format is developed which requires the string form.\n\n**Repeated and Map**\n\nRepeated fields are normal lists. Developers should make no assumptions about which list implementation is used. Maps\nare represented by Kotlin maps. In proto2, due to how map entries are serialized, both the key and the value are\nconsidered nullable.\n\n**Well-Known Types**\n\nWell known types (i.e. those in the `google/protobuf` imports) are shipped with the runtime. At this early stage,\nspecialized support (e.g. using Kotlin `Any` for `google.protobuf.Any`) is not implemented.\n\n**Services**\n\nServices can be handled with a custom service generator. See the \"Service Code Generation\" section above and the \n[custom-service-gen](examples/custom-service-gen) example.\n\n### Building\n\nThe project is built with Gradle and has several sub projects. In alphabetical order, they are:\n\n* `conformance/conformance-common` - Multiplatform common code for conformance tests\n* `conformance/conformance-js` - JS code for conformance tests\n* `conformance/conformance-jvm` - JVM code for conformance tests\n* `conformance/conformance-native` - Native code for conformance tests (not built yet)\n* `protoc-gen-kotlin/protoc-gen-kotlin-common` - Multiplatform common code for the code generator\n* `protoc-gen-kotlin/protoc-gen-kotlin-jvm` - JVM code for the code generator\n* `protoc-gen-kotlin/protoc-gen-kotlin-native` - Native code for the code generator (not built yet)\n* `runtime/runtime-common` - Multiplatform common code for runtime Protobuf support\n* `runtime/runtime-js` - JS code for runtime Protobuf support\n* `runtime/runtime-jvm` - JVM code for runtime Protobuf support\n* `runtime/runtime-native` - Native code for runtime Protobuf support\n\nDue to current issues, Gradle must be version 4.7 in the steps below.\n\n#### Code Generator\n\nTo generate the `protoc-gen-kotlin` distribution, run:\n\n    path/to/gradle :protoc-gen-kotlin:protoc-gen-kotlin-jvm:assembleDist\n\nOr use `installDist` to just put it locally and it will be in the `build/install` folder.\n\n#### Runtime Library\n\nTo build the runtime library for both JS and the JVM, run:\n\n    path/to/gradle :runtime:runtime-js:assemble\n    path/to/gradle :runtime:runtime-jvm:assemble\n\n#### Conformance Tests\n\nTo run conformance tests, the [conformance-test-runner](https://github.com/google/protobuf/tree/master/conformance) must\nbe built (does not work on Windows). Then both the JS and JVM projects must be built via:\n\n    path/to/gradle :conformance:conformance-js:assemble\n    path/to/gradle :conformance:conformance-jvm:installDist\n\nSet the `CONF_TEST_PATH` environment variable to the full path to\n`path/to/protobuf/conformance/conformance-test-runner`. The JS tests need to have `npm install` run in\n`conformance/conformance-js`. Then simply run `conformance/test-conformance.sh`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcretz%2Fpb-and-k","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcretz%2Fpb-and-k","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcretz%2Fpb-and-k/lists"}