Runtime support library for Wire-generated Protocol Buffer classes in Kotlin multiplatform applications
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Wire Runtime provides core functionality for encoding, decoding, and working with Protocol Buffer messages in Kotlin multiplatform applications. It serves as the foundation for Wire-generated protobuf classes, offering cross-platform serialization capabilities, immutable message classes with builders, and efficient binary protobuf data handling.
implementation("com.squareup.wire:wire-runtime:4.9.11")import com.squareup.wire.*
import com.squareup.wire.ProtoAdapter.*
import okio.ByteString
import okio.BufferedSource
import okio.BufferedSinkimport com.squareup.wire.*
import okio.Buffer
// Create a message using generated Wire classes
val person = Person.Builder()
.name("John Doe")
.age(30)
.email("john@example.com")
.build()
// Encode message to binary format
val encoded: ByteArray = person.encode()
val encodedByteString: ByteString = person.encodeByteString()
// Decode message from binary format
val decoded: Person = Person.ADAPTER.decode(encoded)
// Work with protocol buffer I/O directly
val buffer = Buffer()
val writer = ProtoWriter(buffer)
ProtoAdapter.STRING.encodeWithTag(writer, 1, "Hello Wire!")
val reader = ProtoReader(buffer)
val tag = reader.nextTag() // Returns 1
val message = ProtoAdapter.STRING.decode(reader) // Returns "Hello Wire!"Wire Runtime is built around several key architectural components:
ProtoAdapter handles encoding/decoding for each type with built-in adapters for all protobuf typesProtoReader and ProtoWriter provide low-level protocol buffer reading and writingexpect classes, platform-specific implementationsCore message classes and builders that form the foundation of all Wire-generated protocol buffer classes.
abstract class Message<M : Message<M, B>, B : Message.Builder<M, B>>(
adapter: ProtoAdapter<M>,
unknownFields: ByteString
) {
val unknownFields: ByteString
val adapter: ProtoAdapter<M>
abstract fun newBuilder(): B
fun encode(sink: BufferedSink)
fun encode(): ByteArray
fun encodeByteString(): ByteString
}
abstract class Message.Builder<M : Message<M, B>, B : Builder<M, B>> {
fun addUnknownFields(unknownFields: ByteString): Builder<M, B>
fun addUnknownField(tag: Int, fieldEncoding: FieldEncoding, value: Any?): Builder<M, B>
fun clearUnknownFields(): Builder<M, B>
fun buildUnknownFields(): ByteString
abstract fun build(): M
}Low-level reading and writing of protocol buffer wire format data with support for all protobuf field types.
class ProtoReader(source: BufferedSource) {
fun beginMessage(): Long
fun endMessageAndGetUnknownFields(token: Long): ByteString
fun nextTag(): Int
fun peekFieldEncoding(): FieldEncoding?
fun readString(): String
fun readBytes(): ByteString
fun readVarint32(): Int
fun readVarint64(): Long
fun readFixed32(): Int
fun readFixed64(): Long
}
class ProtoWriter(sink: BufferedSink) {
fun writeTag(fieldNumber: Int, fieldEncoding: FieldEncoding)
fun writeString(value: String)
fun writeBytes(value: ByteString)
fun writeVarint32(value: Int)
fun writeVarint64(value: Long)
fun writeFixed32(value: Int)
fun writeFixed64(value: Long)
}Type-safe encoding and decoding adapters for all protocol buffer types, including built-in adapters for scalars, collections, and Google Well-Known Types.
abstract class ProtoAdapter<E>(
fieldEncoding: FieldEncoding,
type: KClass<*>?,
typeUrl: String?,
syntax: Syntax,
identity: E? = null,
sourceFile: String? = null
) {
abstract fun encodedSize(value: E): Int
abstract fun encode(writer: ProtoWriter, value: E)
abstract fun decode(reader: ProtoReader): E
fun encode(value: E): ByteArray
fun decode(bytes: ByteArray): E
fun asPacked(): ProtoAdapter<List<E>>
fun asRepeated(): ProtoAdapter<List<E>>
companion object {
val STRING: ProtoAdapter<String>
val BYTES: ProtoAdapter<ByteString>
val INT32: ProtoAdapter<Int>
val INT64: ProtoAdapter<Long>
val BOOL: ProtoAdapter<Boolean>
val FLOAT: ProtoAdapter<Float>
val DOUBLE: ProtoAdapter<Double>
// ... all built-in adapters
}
}Support for protocol buffer enums with proper value mapping and unknown value handling.
interface WireEnum {
val value: Int
}
abstract class EnumAdapter<E : WireEnum>(
type: KClass<E>,
syntax: Syntax,
identity: E?
) : ProtoAdapter<E> {
protected abstract fun fromValue(value: Int): E?
}Annotations for marking generated message fields with encoding metadata and serialization behavior.
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
annotation class WireField(
val tag: Int,
val adapter: String,
val label: Label = Label.OPTIONAL,
val redacted: Boolean = false,
val declaredName: String = "",
val jsonName: String = "",
val oneofName: String = "",
val schemaIndex: Int = -1
)
enum class Label {
REQUIRED, OPTIONAL, REPEATED, ONE_OF, PACKED, OMIT_IDENTITY
}Cross-platform time and duration types that map to Google Well-Known Types.
expect class Duration {
fun getSeconds(): Long
fun getNano(): Int
}
expect class Instant {
fun getEpochSecond(): Long
fun getNano(): Int
}
fun durationOfSeconds(seconds: Long, nano: Long): Duration
fun ofEpochSecond(epochSecond: Long, nano: Long): InstantSupport for google.protobuf.Any messages allowing type-safe packing and unpacking of arbitrary protocol buffer messages.
class AnyMessage(
val typeUrl: String,
val value: ByteString = ByteString.EMPTY
) : Message<AnyMessage, Nothing> {
fun <T> unpack(adapter: ProtoAdapter<T>): T
fun <T> unpackOrNull(adapter: ProtoAdapter<T>): T?
companion object {
fun pack(message: Message<*, *>): AnyMessage
val ADAPTER: ProtoAdapter<AnyMessage>
}
}enum class FieldEncoding(val value: Int) {
VARINT(0),
FIXED64(1),
LENGTH_DELIMITED(2),
FIXED32(5)
}
enum class Syntax {
PROTO_2,
PROTO_3
}