or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

any-message.mdenum-support.mdfield-annotations.mdindex.mdmessage-framework.mdproto-adapters.mdprotobuf-io.mdtime-types.md

message-framework.mddocs/

0

# Message Framework

1

2

The Message Framework provides the foundational classes for all Wire-generated protocol buffer messages. It implements the builder pattern for immutable message construction and handles unknown field preservation for forward compatibility.

3

4

## Capabilities

5

6

### Message Base Class

7

8

Abstract base class for all protocol buffer messages providing encoding, unknown field management, and builder creation.

9

10

```kotlin { .api }

11

/**

12

* Abstract base class for protocol buffer messages

13

* @param M The message type

14

* @param B The builder type for this message

15

*/

16

expect abstract class Message<M : Message<M, B>, B : Message.Builder<M, B>> protected constructor(

17

adapter: ProtoAdapter<M>,

18

unknownFields: ByteString

19

) {

20

/** If non-zero, the hash code of this message */

21

protected var hashCode: Int

22

23

/** Returns unknown fields from proto encoding as ByteString */

24

val unknownFields: ByteString

25

26

/** The ProtoAdapter for encoding and decoding messages of this type */

27

val adapter: ProtoAdapter<M>

28

29

/** Returns a new builder initialized with the data in this message */

30

abstract fun newBuilder(): B

31

32

/** Encode this message and write it to stream */

33

fun encode(sink: BufferedSink)

34

35

/** Encode this message as a byte array */

36

fun encode(): ByteArray

37

38

/** Encode this message as a ByteString */

39

fun encodeByteString(): ByteString

40

}

41

```

42

43

**Usage Examples:**

44

45

```kotlin

46

import com.squareup.wire.*

47

import okio.Buffer

48

49

// Assuming generated Person class extends Message

50

val person = Person.Builder()

51

.name("Alice")

52

.age(30)

53

.build()

54

55

// Encode to different formats

56

val bytes: ByteArray = person.encode()

57

val byteString: ByteString = person.encodeByteString()

58

59

// Write to a buffered sink

60

val buffer = Buffer()

61

person.encode(buffer)

62

63

// Access unknown fields (for forward compatibility)

64

val unknownFields: ByteString = person.unknownFields

65

66

// Create a modified copy using builder

67

val updatedPerson = person.newBuilder()

68

.age(31)

69

.build()

70

```

71

72

### Message Builder

73

74

Abstract base class for message builders implementing the builder pattern for immutable message construction.

75

76

```kotlin { .api }

77

/**

78

* Superclass for protocol buffer message builders

79

* @param M The message type this builder creates

80

* @param B The builder type (self-reference for fluent interface)

81

*/

82

abstract class Message.Builder<M : Message<M, B>, B : Builder<M, B>> protected constructor() {

83

/** Cached unknown fields as ByteString */

84

internal var unknownFieldsByteString: ByteString

85

86

/** Buffer for unknown fields (lazily instantiated) */

87

internal var unknownFieldsBuffer: Buffer?

88

89

/** Writer for unknown fields */

90

internal var unknownFieldsWriter: ProtoWriter?

91

92

/** Add unknown fields from another message or source */

93

fun addUnknownFields(unknownFields: ByteString): Builder<M, B>

94

95

/** Add a single unknown field with specified encoding */

96

fun addUnknownField(

97

tag: Int,

98

fieldEncoding: FieldEncoding,

99

value: Any?

100

): Builder<M, B>

101

102

/** Clear all accumulated unknown fields */

103

fun clearUnknownFields(): Builder<M, B>

104

105

/** Build unknown fields to ByteString */

106

fun buildUnknownFields(): ByteString

107

108

/** Returns an immutable Message based on fields set in this builder */

109

abstract fun build(): M

110

}

111

```

112

113

**Usage Examples:**

114

115

```kotlin

116

import com.squareup.wire.*

117

118

// Create message using builder pattern

119

val person = Person.Builder()

120

.name("Bob")

121

.email("bob@example.com")

122

.age(25)

123

.build()

124

125

// Builder with unknown field handling

126

val builder = Person.Builder()

127

.name("Charlie")

128

129

// Add unknown fields (useful for proxy/gateway scenarios)

130

builder.addUnknownField(999, FieldEncoding.VARINT, 42)

131

builder.addUnknownField(998, FieldEncoding.LENGTH_DELIMITED, "custom_data")

132

133

val personWithUnknownFields = builder.build()

134

135

// Unknown fields are preserved when encoding/decoding

136

val encoded = personWithUnknownFields.encode()

137

val decoded = Person.ADAPTER.decode(encoded)

138

// decoded.unknownFields contains the unknown fields

139

140

// Clear unknown fields if needed

141

val cleanBuilder = decoded.newBuilder()

142

.clearUnknownFields()

143

val cleanPerson = cleanBuilder.build()

144

```

145

146

### Unknown Field Management

147

148

Wire Runtime preserves unknown fields to maintain forward compatibility when older clients receive messages with newer fields.

149

150

```kotlin { .api }

151

// Unknown fields are automatically preserved during decode/encode cycles

152

val messageWithUnknownFields = SomeMessage.ADAPTER.decode(bytesFromNewerVersion)

153

154

// Unknown fields are maintained

155

val reencoded = messageWithUnknownFields.encode()

156

// reencoded contains both known and unknown fields

157

158

// Access unknown fields directly

159

val unknownFieldsBytes: ByteString = messageWithUnknownFields.unknownFields

160

161

// Copy message while preserving unknown fields

162

val modified = messageWithUnknownFields.newBuilder()

163

.someKnownField("new value")

164

.build()

165

// modified.unknownFields still contains the unknown fields

166

```

167

168

## Builder Pattern Benefits

169

170

The builder pattern in Wire Runtime provides several advantages:

171

172

1. **Immutability**: Messages are immutable after construction

173

2. **Type Safety**: Compile-time validation of required fields

174

3. **Fluent Interface**: Chainable method calls for readable construction

175

4. **Unknown Field Preservation**: Automatic handling of forward compatibility

176

5. **Null Safety**: Kotlin's null safety integrated with optional fields

177

178

## Platform-Specific Implementations

179

180

The Message and Builder classes use Kotlin's `expect`/`actual` mechanism for multiplatform support:

181

182

- **JVM**: Full reflection-based implementation with Java interoperability

183

- **JavaScript**: Optimized for browser and Node.js environments

184

- **Native**: Compiled implementations for iOS, macOS, Linux, and Windows

185

- **Android**: Android-specific optimizations and Parcelable support