CustomStructSchema

class CustomStructSchema<T : Any>(val type: String, val componentNames: List<String>, val componentSchemas: List<FateSchema<*>>, val encoder: (T) -> List<Any>) : FateSchema<T>

A schema you define by hand. You name the components and supply a function that produces them.

Nothing is reflected. Use it for a class you can't modify, or to write fewer bytes than reflection would. You can drop fields you never plot, round a double, convert units, or emit a computed value that isn't a field.

How it works

encoder turns one object into a list of components. Each component has a name from componentNames and a schema from componentSchemas at the same index. They are written in that order after a leading type string.

Binary format

The schema:

[4 bytes: tag] [4 bytes: component count]
[4 bytes: ".type" length] [".type" bytes] [StringSchema]
[4 bytes: name1 length] [name1 bytes] [schema1]
[4 bytes: name2 length] [name2 bytes] [schema2]
...

An encoded object:

[4 bytes: type length] [type string bytes]
[component1 data] [component2 data] ...

Examples

Basic usage

data class Person(val name: String, val age: Int, val email: String)

val personSchema = CustomStructSchema<Person>(
type = "Person",
componentNames = listOf("name", "age", "email"),
componentSchemas = listOf(StringSchema, IntSchema, StringSchema),
encoder = { person -> listOf(person.name, person.age, person.email) }
)

Transforming values

val transformedSchema = CustomStructSchema<Person>(
type = "NormalizedPerson",
componentNames = listOf("displayName", "ageCategory"),
componentSchemas = listOf(StringSchema, StringSchema),
encoder = { person ->
listOf(
person.name.uppercase(),
when {
person.age < 18 -> "MINOR"
person.age < 65 -> "ADULT"
else -> "SENIOR"
}
)
}
)

Logging a subset of fields

val minimalSchema = CustomStructSchema<ComplexObject>(
type = "Essential",
componentNames = listOf("id", "status"),
componentSchemas = listOf(LongSchema, StringSchema),
encoder = { obj -> listOf(obj.id, obj.currentStatus.name) }
)

Parameters

T

The type of objects this schema serializes

type

Identifier for this object type, written to the log as the first value

componentNames

Names of the components, in the order they are written

componentSchemas

Schemas for each component, in the same order as componentNames

encoder

Converts an object into its list of components

Throws

if componentNames and componentSchemas have different sizes

Constructors

Link copied to clipboard
constructor(type: String, componentNames: List<String>, componentSchemas: List<FateSchema<*>>, encoder: (T) -> List<Any>)

Types

Link copied to clipboard
object Companion

The name and schema of the leading type string.

Properties

Link copied to clipboard

Names of the components, in the order they are written. They go into the schema entry.

Link copied to clipboard

Schemas for each component, in the same order as componentNames.

Link copied to clipboard
val encoder: (T) -> List<Any>

Converts an object into the values that componentSchemas encode.

Link copied to clipboard
open override val schema: ByteArray

The schema definition as bytes, which the writer puts in the log.

Link copied to clipboard
open override val schemaSize: Int

Number of bytes in this schema's definition.

Link copied to clipboard
open override val tag: Int

The integer that identifies this schema's type in the log.

Link copied to clipboard

Identifier for this object type, written before the components in every encoded object.

Functions

Link copied to clipboard
open override fun encodeObject(buffer: ByteBuffer, obj: T)

Writes the given object into the buffer.

Link copied to clipboard
open fun encodeSchema(buffer: ByteBuffer)

Writes the whole schema definition, starting with the tag, into the buffer.

Link copied to clipboard
open override fun objSize(obj: T): Int

Returns the number of bytes encodeObject writes for the given object.