or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

builtins.mdcore-api.mddescriptors.mdencoding.mdindex.mdmodules.md

encoding.mddocs/

0

# Encoding System

1

2

The encoding system provides format-agnostic interfaces for serializing and deserializing data. Format implementations use these interfaces to read and write data without being tied to specific serialization formats.

3

4

## Encoder Interfaces

5

6

### Encoder

7

8

Base interface for encoding primitive values and beginning structured encoding.

9

10

```kotlin { .api }

11

interface Encoder {

12

val serializersModule: SerializersModule

13

14

// Primitive encoding methods

15

fun encodeBoolean(value: Boolean)

16

fun encodeByte(value: Byte)

17

fun encodeShort(value: Short)

18

fun encodeInt(value: Int)

19

fun encodeLong(value: Long)

20

fun encodeFloat(value: Float)

21

fun encodeDouble(value: Double)

22

fun encodeChar(value: Char)

23

fun encodeString(value: String)

24

25

// Special encoding methods

26

fun encodeEnum(enumDescriptor: SerialDescriptor, index: Int)

27

fun encodeInline(descriptor: SerialDescriptor): Encoder

28

29

// Nullable handling (experimental)

30

@ExperimentalSerializationApi

31

fun encodeNotNullMark()

32

@ExperimentalSerializationApi

33

fun encodeNull()

34

35

// Structure encoding

36

fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder

37

fun beginCollection(descriptor: SerialDescriptor, collectionSize: Int): CompositeEncoder

38

39

// Serialization helpers

40

fun <T : Any?> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T)

41

42

@ExperimentalSerializationApi

43

fun <T : Any> encodeNullableSerializableValue(

44

serializer: SerializationStrategy<T>,

45

value: T?

46

)

47

}

48

```

49

50

### CompositeEncoder

51

52

Interface for encoding structured data with multiple elements.

53

54

```kotlin { .api }

55

interface CompositeEncoder {

56

val serializersModule: SerializersModule

57

58

// Element encoding methods for primitives

59

fun encodeBooleanElement(descriptor: SerialDescriptor, index: Int, value: Boolean)

60

fun encodeByteElement(descriptor: SerialDescriptor, index: Int, value: Byte)

61

fun encodeShortElement(descriptor: SerialDescriptor, index: Int, value: Short)

62

fun encodeIntElement(descriptor: SerialDescriptor, index: Int, value: Int)

63

fun encodeLongElement(descriptor: SerialDescriptor, index: Int, value: Long)

64

fun encodeFloatElement(descriptor: SerialDescriptor, index: Int, value: Float)

65

fun encodeDoubleElement(descriptor: SerialDescriptor, index: Int, value: Double)

66

fun encodeCharElement(descriptor: SerialDescriptor, index: Int, value: Char)

67

fun encodeStringElement(descriptor: SerialDescriptor, index: Int, value: String)

68

69

// Complex element encoding

70

fun <T : Any?> encodeSerializableElement(

71

descriptor: SerialDescriptor,

72

index: Int,

73

serializer: SerializationStrategy<T>,

74

value: T

75

)

76

77

@ExperimentalSerializationApi

78

fun <T : Any> encodeNullableSerializableElement(

79

descriptor: SerialDescriptor,

80

index: Int,

81

serializer: SerializationStrategy<T>,

82

value: T?

83

)

84

85

// Inline element encoding

86

fun encodeInlineElement(descriptor: SerialDescriptor, index: Int): Encoder

87

88

// Structure control

89

fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder

90

fun endStructure(descriptor: SerialDescriptor)

91

92

// Encoding behavior control

93

@ExperimentalSerializationApi

94

fun shouldEncodeElementDefault(descriptor: SerialDescriptor, index: Int): Boolean

95

}

96

```

97

98

## Decoder Interfaces

99

100

### Decoder

101

102

Base interface for decoding primitive values and beginning structured decoding.

103

104

```kotlin { .api }

105

interface Decoder {

106

val serializersModule: SerializersModule

107

108

// Primitive decoding methods

109

fun decodeBoolean(): Boolean

110

fun decodeByte(): Byte

111

fun decodeShort(): Short

112

fun decodeInt(): Int

113

fun decodeLong(): Long

114

fun decodeFloat(): Float

115

fun decodeDouble(): Double

116

fun decodeChar(): Char

117

fun decodeString(): String

118

119

// Special decoding methods

120

fun decodeEnum(enumDescriptor: SerialDescriptor): Int

121

fun decodeInline(descriptor: SerialDescriptor): Decoder

122

123

// Nullable handling (experimental)

124

@ExperimentalSerializationApi

125

fun decodeNotNullMark(): Boolean

126

@ExperimentalSerializationApi

127

fun decodeNull(): Nothing?

128

129

// Structure decoding

130

fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder

131

132

// Serialization helpers

133

fun <T : Any?> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T

134

135

@ExperimentalSerializationApi

136

fun <T : Any> decodeNullableSerializableValue(

137

deserializer: DeserializationStrategy<T?>

138

): T?

139

}

140

```

141

142

### CompositeDecoder

143

144

Interface for decoding structured data with multiple elements.

145

146

```kotlin { .api }

147

interface CompositeDecoder {

148

val serializersModule: SerializersModule

149

150

// Element discovery

151

fun decodeElementIndex(descriptor: SerialDescriptor): Int

152

fun decodeCollectionSize(descriptor: SerialDescriptor): Int

153

154

@ExperimentalSerializationApi

155

fun decodeSequentially(): Boolean

156

157

// Element decoding methods for primitives

158

fun decodeBooleanElement(descriptor: SerialDescriptor, index: Int): Boolean

159

fun decodeByteElement(descriptor: SerialDescriptor, index: Int): Byte

160

fun decodeShortElement(descriptor: SerialDescriptor, index: Int): Short

161

fun decodeIntElement(descriptor: SerialDescriptor, index: Int): Int

162

fun decodeLongElement(descriptor: SerialDescriptor, index: Int): Long

163

fun decodeFloatElement(descriptor: SerialDescriptor, index: Int): Float

164

fun decodeDoubleElement(descriptor: SerialDescriptor, index: Int): Double

165

fun decodeCharElement(descriptor: SerialDescriptor, index: Int): Char

166

fun decodeStringElement(descriptor: SerialDescriptor, index: Int): String

167

168

// Complex element decoding

169

fun <T : Any?> decodeSerializableElement(

170

descriptor: SerialDescriptor,

171

index: Int,

172

deserializer: DeserializationStrategy<T>,

173

previousValue: T? = null

174

): T

175

176

@ExperimentalSerializationApi

177

fun <T : Any> decodeNullableSerializableElement(

178

descriptor: SerialDescriptor,

179

index: Int,

180

deserializer: DeserializationStrategy<T?>,

181

previousValue: T? = null

182

): T?

183

184

// Inline element decoding

185

fun decodeInlineElement(descriptor: SerialDescriptor, index: Int): Decoder

186

187

// Structure control

188

fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder

189

fun endStructure(descriptor: SerialDescriptor)

190

191

companion object {

192

const val DECODE_DONE: Int = -1

193

const val UNKNOWN_NAME: Int = -3

194

}

195

}

196

```

197

198

## Encoding Usage Examples

199

200

### Basic Encoder Implementation

201

202

```kotlin

203

class CustomEncoder : Encoder {

204

override val serializersModule: SerializersModule = EmptySerializersModule()

205

206

override fun encodeString(value: String) {

207

// Custom string encoding logic

208

println("Encoding string: $value")

209

}

210

211

override fun encodeInt(value: Int) {

212

// Custom integer encoding logic

213

println("Encoding int: $value")

214

}

215

216

override fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder {

217

println("Beginning structure: ${descriptor.serialName}")

218

return CustomCompositeEncoder()

219

}

220

221

// ... implement other required methods

222

}

223

```

224

225

### Basic Decoder Implementation

226

227

```kotlin

228

class CustomDecoder(private val data: Map<String, Any>) : Decoder {

229

override val serializersModule: SerializersModule = EmptySerializersModule()

230

231

override fun decodeString(): String {

232

// Custom string decoding logic

233

return data["current"] as String

234

}

235

236

override fun decodeInt(): Int {

237

// Custom integer decoding logic

238

return data["current"] as Int

239

}

240

241

override fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder {

242

println("Beginning structure: ${descriptor.serialName}")

243

return CustomCompositeDecoder(data)

244

}

245

246

// ... implement other required methods

247

}

248

```

249

250

### Composite Encoding Pattern

251

252

```kotlin

253

class CustomCompositeEncoder : CompositeEncoder {

254

override val serializersModule: SerializersModule = EmptySerializersModule()

255

256

override fun encodeStringElement(

257

descriptor: SerialDescriptor,

258

index: Int,

259

value: String

260

) {

261

val elementName = descriptor.getElementName(index)

262

println("Encoding element '$elementName' at index $index: $value")

263

}

264

265

override fun <T> encodeSerializableElement(

266

descriptor: SerialDescriptor,

267

index: Int,

268

serializer: SerializationStrategy<T>,

269

value: T

270

) {

271

val elementName = descriptor.getElementName(index)

272

println("Encoding serializable element '$elementName' at index $index")

273

274

// Create nested encoder for the element

275

val elementEncoder = createNestedEncoder()

276

serializer.serialize(elementEncoder, value)

277

}

278

279

override fun endStructure(descriptor: SerialDescriptor) {

280

println("Ending structure: ${descriptor.serialName}")

281

}

282

283

// ... implement other required methods

284

}

285

```

286

287

### Composite Decoding Pattern

288

289

```kotlin

290

class CustomCompositeDecoder(

291

private val data: Map<String, Any>

292

) : CompositeDecoder {

293

override val serializersModule: SerializersModule = EmptySerializersModule()

294

private var currentIndex = 0

295

296

override fun decodeElementIndex(descriptor: SerialDescriptor): Int {

297

// Return next available element index or DECODE_DONE when finished

298

return if (currentIndex < descriptor.elementsCount) {

299

currentIndex++

300

} else {

301

CompositeDecoder.DECODE_DONE

302

}

303

}

304

305

override fun decodeStringElement(

306

descriptor: SerialDescriptor,

307

index: Int

308

): String {

309

val elementName = descriptor.getElementName(index)

310

return data[elementName] as String

311

}

312

313

override fun <T> decodeSerializableElement(

314

descriptor: SerialDescriptor,

315

index: Int,

316

deserializer: DeserializationStrategy<T>,

317

previousValue: T?

318

): T {

319

val elementName = descriptor.getElementName(index)

320

val elementData = data[elementName] as Map<String, Any>

321

322

// Create nested decoder for the element

323

val elementDecoder = CustomDecoder(elementData)

324

return deserializer.deserialize(elementDecoder)

325

}

326

327

// ... implement other required methods

328

}

329

```

330

331

## Advanced Encoding Features

332

333

### Inline Value Handling

334

335

```kotlin

336

// In custom encoder

337

override fun encodeInline(descriptor: SerialDescriptor): Encoder {

338

// Return encoder for inline value content

339

return this // or create specialized inline encoder

340

}

341

342

// In custom decoder

343

override fun decodeInline(descriptor: SerialDescriptor): Decoder {

344

// Return decoder for inline value content

345

return this // or create specialized inline decoder

346

}

347

```

348

349

### Null Handling

350

351

```kotlin

352

// Encoding nulls

353

override fun encodeNull() {

354

println("Encoding null value")

355

}

356

357

override fun encodeNotNullMark() {

358

println("Encoding not-null marker")

359

}

360

361

// Decoding nulls

362

override fun decodeNotNullMark(): Boolean {

363

// Return true if next value is not null

364

return true

365

}

366

367

override fun decodeNull(): Nothing? {

368

println("Decoding null value")

369

return null

370

}

371

```

372

373

### Default Value Handling

374

375

```kotlin

376

// In CompositeEncoder

377

override fun shouldEncodeElementDefault(

378

descriptor: SerialDescriptor,

379

index: Int

380

): Boolean {

381

// Control whether default values should be encoded

382

val elementName = descriptor.getElementName(index)

383

return !elementName.startsWith("optional")

384

}

385

```

386

387

## Extension Functions

388

389

### Encoder Extensions

390

391

```kotlin { .api }

392

// Structure encoding helpers

393

inline fun Encoder.encodeStructure(

394

descriptor: SerialDescriptor,

395

crossinline block: CompositeEncoder.() -> Unit

396

)

397

398

inline fun Encoder.encodeCollection(

399

descriptor: SerialDescriptor,

400

collectionSize: Int,

401

crossinline block: CompositeEncoder.() -> Unit

402

)

403

404

inline fun <E> Encoder.encodeCollection(

405

descriptor: SerialDescriptor,

406

collection: Collection<E>,

407

crossinline block: CompositeEncoder.(index: Int, E) -> Unit

408

)

409

```

410

411

### Decoder Extensions

412

413

```kotlin { .api }

414

// Structure decoding helpers

415

inline fun <T> Decoder.decodeStructure(

416

descriptor: SerialDescriptor,

417

crossinline block: CompositeDecoder.() -> T

418

): T

419

```

420

421

## Format Implementation Tips

422

423

1. **Stateful Encoders/Decoders**: Maintain state for tracking current position, nesting levels, etc.

424

2. **Error Handling**: Throw descriptive `SerializationException`s for format-specific errors

425

3. **Performance**: Cache frequently accessed data like element names and descriptors

426

4. **Validation**: Validate data structure matches descriptor expectations

427

5. **Null Safety**: Properly handle nullable types and null markers