zio.blocks.schema.binding

Members list

Type members

Classlikes

sealed trait Binding[T, +A]

A Binding holds the Scala functions that a zio.blocks.schema.Reflect node needs to work with values at run time: how to build a value, how to take it apart, and how to tell the cases of a sum type apart. A Reflect describes the shape of a type as plain data; its bindings make that description usable.

A Binding holds the Scala functions that a zio.blocks.schema.Reflect node needs to work with values at run time: how to build a value, how to take it apart, and how to tell the cases of a sum type apart. A Reflect describes the shape of a type as plain data; its bindings make that description usable.

A Reflect node keeps its binding in its metadata F[T, A]. A Reflect.Bound node, whose F is Binding, can construct and deconstruct values, and every zio.blocks.schema.Schema wraps one. A Reflect.Unbound node carries a NoBinding instead: it holds no functions, so it can be serialized, and DynamicSchema#rebind gets its bindings back from a BindingResolver.

There is one binding kind per node kind (a Reflect.Deferred node uses the binding of the node it defers to), and the phantom type T names it (see BindingType):

Schema.derived creates the bindings of a whole schema, and Binding.of derives the binding of one type. The example takes the record binding of a derived schema and moves a value through registers:

import zio.blocks.schema.binding._

case class Book(title: String, year: Int)
object Book {
 implicit val schema: Schema[Book] = Schema.derived
}

val record    = Book.schema.reflect.asRecord.get
val registers = Registers(record.usedRegisters)
record.deconstructor.deconstruct(registers, RegisterOffset.Zero, Book("Zionomicon", 2021))
val title = registers.getObject(RegisterOffset.Zero)                     // "Zionomicon"
val book  = record.constructor.construct(registers, RegisterOffset.Zero) // Book("Zionomicon", 2021)

Type parameters

A

the type whose values the binding works with

T

the binding kind, one of the BindingType members

Attributes

See also
Companion
object
Source
Binding.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
class Dynamic
class Map[M, K, V]
class Primitive[A]
class Record[A]
class Seq[C, A]
class Variant[A]
class Wrapper[A, B]
Show all

The binding kinds, ready-made bindings for standard types, and Binding.of, which derives a binding at compile time.

The binding kinds, ready-made bindings for standard types, and Binding.of, which derives a binding at compile time.

Attributes

Companion
trait
Source
Binding.scala
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Show all
Self type
Binding.type

The Binding.of methods, which differ between Scala 2 and Scala 3.

The Binding.of methods, which differ between Scala 2 and Scala 3.

Attributes

Source
BindingCompanionVersionSpecific.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
object Binding

A binding resolver provides bindings for types during schema rebinding.

A binding resolver provides bindings for types during schema rebinding.

BindingResolver is the read-only interface for looking up bindings by type identity. Multiple resolvers can be combined using ++ to form resolution chains with fallback behavior.

The library provides several resolver implementations:

Attributes

Example
import zio.blocks.schema.binding._
case class Person(name: String, age: Int)
val customRegistry = BindingResolver.empty.bind(Binding.of[Person])
// Use defaults for primitives and collections, with custom bindings
val resolver = customRegistry ++ BindingResolver.defaults
// Add reflection-based derivation as fallback
val withReflection = customRegistry ++ BindingResolver.reflection ++ BindingResolver.defaults
Companion
object
Source
BindingResolver.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
class Registry
Self type

The ready-made resolvers empty, defaults and reflection, and BindingResolver.Registry, the resolver that bind builds.

The ready-made resolvers empty, defaults and reflection, and BindingResolver.Registry, the resolver that bind builds.

Attributes

Companion
trait
Source
BindingResolver.scala
Supertypes
class Object
trait Matchable
class Any
Self type
final abstract class BindingType

The binding kinds: the phantom type T of Binding[T, A] and of a Reflect node's metadata F[T, A]. BindingType has no values; its members only name which kind of Binding a node carries.

The binding kinds: the phantom type T of Binding[T, A] and of a Reflect node's metadata F[T, A]. BindingType has no values; its members only name which kind of Binding a node carries.

Attributes

Companion
object
Source
BindingType.scala
Supertypes
class Object
trait Matchable
class Any
object BindingType

One binding kind per Reflect node kind (a Reflect.Deferred node uses the binding of the node it defers to).

One binding kind per Reflect node kind (a Reflect.Deferred node uses the binding of the node it defers to).

Attributes

Companion
class
Source
BindingType.scala
Supertypes
class Object
trait Matchable
class Any
Self type
class ConstantConstructor[A](constant: A) extends Constructor[A]

A constructor that uses no registers and always returns constant. Binding.of uses it for case objects and for Scala 3 enum cases without parameters.

A constructor that uses no registers and always returns constant. Binding.of uses it for case objects and for Scala 3 enum cases without parameters.

Attributes

Source
Constructor.scala
Supertypes
class Constructor[A]
class Object
trait Matchable
class Any
class ConstantDeconstructor[A] extends Deconstructor[A]

A deconstructor that uses no registers and writes nothing, for types without fields such as case objects.

A deconstructor that uses no registers and writes nothing, for types without fields such as case objects.

Attributes

Source
Deconstructor.scala
Supertypes
class Deconstructor[A]
class Object
trait Matchable
class Any
abstract class Constructor[+A]

A Constructor builds a value of type A from Registers: it is the construction half of a Binding.Record. To decode a record, a codec writes each field into registers, at the positions that Reflect.Record#registers gives, and then calls construct. Reading the fields from registers, instead of from a tuple or an array of boxed values, keeps primitive fields unboxed.

A Constructor builds a value of type A from Registers: it is the construction half of a Binding.Record. To decode a record, a codec writes each field into registers, at the positions that Reflect.Record#registers gives, and then calls construct. Reading the fields from registers, instead of from a tuple or an array of boxed values, keeps primitive fields unboxed.

construct reads at positions counted from its offset argument. A record decoded on its own starts at RegisterOffset.Zero; the JSON codec keeps one Registers as a stack and passes the start of the record's part of it. A RegisterOffset counts the registers before a field, so year below, which comes after one object field, is at RegisterOffset(objects = 1), whose byte position is 0:

import zio.blocks.schema.binding._
import zio.blocks.schema.binding.RegisterOffset.RegisterOffset

case class Book(title: String, year: Int)

val bookConstructor: Constructor[Book] = new Constructor[Book] {
 def usedRegisters: RegisterOffset = RegisterOffset(objects = 1, ints = 1)

 def construct(in: Registers, offset: RegisterOffset): Book =
   Book(in.getObject(offset).asInstanceOf[String], in.getInt(offset + RegisterOffset(objects = 1)))
}

val registers = Registers(bookConstructor.usedRegisters)
registers.setObject(RegisterOffset.Zero, "Zionomicon")
registers.setInt(RegisterOffset(objects = 1), 2021)
val book = bookConstructor.construct(registers, RegisterOffset.Zero) // Book("Zionomicon", 2021)

Type parameters

A

the type of the values it builds

Attributes

See also
Source
Constructor.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
Self type
abstract class Deconstructor[-A]

A Deconstructor writes the fields of a value of type A into Registers: it is the deconstruction half of a Binding.Record. To encode a record, a codec calls deconstruct and then reads each field from the registers, at the positions that Reflect.Record#registers gives. Writing the fields into registers, instead of into a tuple or an array of boxed values, keeps primitive fields unboxed.

A Deconstructor writes the fields of a value of type A into Registers: it is the deconstruction half of a Binding.Record. To encode a record, a codec calls deconstruct and then reads each field from the registers, at the positions that Reflect.Record#registers gives. Writing the fields into registers, instead of into a tuple or an array of boxed values, keeps primitive fields unboxed.

deconstruct writes at positions counted from its offset argument, with the same layout that the record's Constructor reads:

import zio.blocks.schema.binding._
import zio.blocks.schema.binding.RegisterOffset.RegisterOffset

case class Book(title: String, year: Int)

val bookDeconstructor: Deconstructor[Book] = new Deconstructor[Book] {
 def usedRegisters: RegisterOffset = RegisterOffset(objects = 1, ints = 1)

 def deconstruct(out: Registers, offset: RegisterOffset, in: Book): Unit = {
   out.setObject(offset, in.title)
   out.setInt(offset + RegisterOffset(objects = 1), in.year)
 }
}

val registers = Registers(bookDeconstructor.usedRegisters)
bookDeconstructor.deconstruct(registers, RegisterOffset.Zero, Book("Zionomicon", 2021))
val title = registers.getObject(RegisterOffset.Zero)     // "Zionomicon"
val year  = registers.getInt(RegisterOffset(objects = 1)) // 2021

Type parameters

A

the type of the values it takes apart

Attributes

See also
Source
Deconstructor.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
Self type
trait Discriminator[-A]

A Discriminator tells which case of a sum type a value belongs to: it is half of a Binding.Variant. It returns the index of the case in the order of the variant node's cases, and the Matcher at that index of the variant's Matchers downcasts the value to that case.

A Discriminator tells which case of a sum type a value belongs to: it is half of a Binding.Variant. It returns the index of the case in the order of the variant node's cases, and the Matcher at that index of the variant's Matchers downcasts the value to that case.

Type parameters

A

the sum type

Attributes

Source
Discriminator.scala
Supertypes
class Object
trait Matchable
class Any
trait FromBinding[F[_, _]]

Wraps a Binding as the metadata F[T, A] of a Reflect node. The Reflect constructors for standard types, such as Reflect.int and Reflect.option, take one to store the bindings they create. The library's instance is Binding.bindingFromBinding, for F = Binding.

Wraps a Binding as the metadata F[T, A] of a Reflect node. The Reflect constructors for standard types, such as Reflect.int and Reflect.option, take one to store the bindings they create. The library's instance is Binding.bindingFromBinding, for F = Binding.

Type parameters

F

the metadata type of the nodes

Attributes

Source
FromBinding.scala
Supertypes
class Object
trait Matchable
class Any
trait HasBinding[F[_, _]] extends OnlyMetadata[F, Binding]

Reads and replaces the Binding inside a Reflect node's metadata F[T, A]. The Reflect methods that need a binding, such as Reflect.Record#constructor and Reflect#fromDynamicValue, take one implicitly. The library provides instances for Binding itself (Binding.bindingHasBinding) and for BindingInstance, which pairs a binding with a derived type class instance.

Reads and replaces the Binding inside a Reflect node's metadata F[T, A]. The Reflect methods that need a binding, such as Reflect.Record#constructor and Reflect#fromDynamicValue, take one implicitly. The library provides instances for Binding itself (Binding.bindingHasBinding) and for BindingInstance, which pairs a binding with a derived type class instance.

A HasBinding is also a zio.blocks.schema.ReflectTransformer that turns every node's metadata into its Binding.

The typed accessors (record, constructor, seq and the others) check the binding's kind at run time and throw a RuntimeException naming the expected kind when it does not match.

Type parameters

F

the metadata type of the nodes

Attributes

Source
HasBinding.scala
Supertypes
class OnlyMetadata[F, Binding]
class Object
trait Matchable
class Any
trait MapConstructor[M[_, _]]

Builds a map of type M[K, V] entry by entry through a mutable builder: the construction half of a Binding.Map. A codec decodes a map by calling newObjectBuilder, addObject for each entry, and then resultObject.

Builds a map of type M[K, V] entry by entry through a mutable builder: the construction half of a Binding.Map. A codec decodes a map by calling newObjectBuilder, addObject for each entry, and then resultObject.

Type parameters

M

the map type constructor

Attributes

Companion
object
Source
MapConstructor.scala
Supertypes
class Object
trait Matchable
class Any

The map constructors for the standard maps.

The map constructors for the standard maps.

Attributes

Companion
trait
Source
MapConstructor.scala
Supertypes
class Object
trait Matchable
class Any
Self type

The map deconstructors for the standard maps.

The map deconstructors for the standard maps.

Attributes

Companion
trait
Source
MapDeconstructor.scala
Supertypes
class Object
trait Matchable
class Any
Self type
trait MapDeconstructor[M[_, _]]

Reads a map of type M[K, V] back as its entries: the deconstruction half of a Binding.Map.

Reads a map of type M[K, V] back as its entries: the deconstruction half of a Binding.Map.

Type parameters

M

the map type constructor

Attributes

Companion
object
Source
MapDeconstructor.scala
Supertypes
class Object
trait Matchable
class Any
trait Matcher[+A]

A Matcher downcasts a value of a sum type to one of its cases: a Binding.Variant has one per case, in Matchers.

A Matcher downcasts a value of a sum type to one of its cases: a Binding.Variant has one per case, in Matchers.

Type parameters

A

the case type

Attributes

Source
Matcher.scala
Supertypes
class Object
trait Matchable
class Any
final case class Matchers[+A](matchers: IndexedSeq[Matcher[_ <: A]])

The Matchers of a Binding.Variant, one per case, in the order of the variant node's cases.

The Matchers of a Binding.Variant, one per case, in the order of the variant node's cases.

Type parameters

A

the sum type

Attributes

Companion
object
Source
Matchers.scala
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
object Matchers

Creates Matchers.

Creates Matchers.

Attributes

Companion
class
Source
Matchers.scala
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
Matchers.type
sealed trait NoBinding[T, A]

The metadata of a Reflect.Unbound node: a marker that stands where a Binding would be. A node with NoBinding holds no functions, so it can be serialized; Reflect#noBinding produces one and DynamicSchema#rebind gives it bindings again.

The metadata of a Reflect.Unbound node: a marker that stands where a Binding would be. A node with NoBinding holds no functions, so it can be serialized; Reflect#noBinding produces one and DynamicSchema#rebind gives it bindings again.

Type parameters

A

the type the node describes

T

the binding kind, one of the BindingType members

Attributes

Companion
object
Source
NoBinding.scala
Supertypes
class Object
trait Matchable
class Any
object NoBinding

Creates NoBinding markers.

Creates NoBinding markers.

Attributes

Companion
trait
Source
NoBinding.scala
Supertypes
class Object
trait Matchable
class Any
Self type
NoBinding.type
sealed trait Register[A]

The position of one field of a record in Registers, and the kind of register that holds it. Reflect.Record#registers computes one per field, in field order, from the fields' types: a field stored as a Boolean, Byte, Short, Char, Int, Float, Long or Double (a primitive node of that type, or a wrapper node that Reflect treats as one, such as an opaque type over Int) gets the register of that type at the next free position of the byte area, a Unit field gets Register.Unit, and every other field gets a Register.Object at the next object slot. Lenses, Reflect.Record#fromDynamicValue and Reflect.Record#toDynamicValue use these registers to move a field's value in and out of registers without knowing its type.

The position of one field of a record in Registers, and the kind of register that holds it. Reflect.Record#registers computes one per field, in field order, from the fields' types: a field stored as a Boolean, Byte, Short, Char, Int, Float, Long or Double (a primitive node of that type, or a wrapper node that Reflect treats as one, such as an opaque type over Int) gets the register of that type at the next free position of the byte area, a Unit field gets Register.Unit, and every other field gets a Register.Object at the next object slot. Lenses, Reflect.Record#fromDynamicValue and Reflect.Record#toDynamicValue use these registers to move a field's value in and out of registers without knowing its type.

get and set take a base offset, which is added to the register's own offset, so the same register works for a record placed anywhere in a larger Registers.

import zio.blocks.schema.binding._

case class Book(title: String, year: Int)
object Book {
 implicit val schema: Schema[Book] = Schema.derived
}

val record    = Book.schema.reflect.asRecord.get
val year      = record.registers(1) // Int(1): byte 0, after the object slot of title
val registers = Registers(record.usedRegisters)
record.deconstructor.deconstruct(registers, RegisterOffset.Zero, Book("Zionomicon", 2021))
val value = year.get(registers, RegisterOffset.Zero) // 2021

Type parameters

A

the type of the field

Attributes

See also
Companion
object
Source
Register.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
class Boolean
class Byte
class Char
class Double
class Float
class Int
class Long
class Object[A]
class Short
object Unit
Show all
object Register

The register kinds of record fields.

The register kinds of record fields.

Attributes

Companion
trait
Source
Register.scala
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
Register.type

A RegisterOffset is a position in Registers, or an amount of space in them, packed into one Long. The high 32 bits count bytes of the byte area, which holds primitive values, and the low 32 bits count slots of the object area, which holds references. Offsets add up: the offset of a record field is the space taken by the fields before it, and offset + base places a record inside a larger Registers. Plain + is correct as long as neither total reaches 2^31; add checks that.

A RegisterOffset is a position in Registers, or an amount of space in them, packed into one Long. The high 32 bits count bytes of the byte area, which holds primitive values, and the low 32 bits count slots of the object area, which holds references. Offsets add up: the offset of a record field is the space taken by the fields before it, and offset + base places a record inside a larger Registers. Plain + is correct as long as neither total reaches 2^31; add checks that.

import zio.blocks.schema.binding._

val offset = RegisterOffset(objects = 3, bytes = 4, ints = 2)
val bytes  = RegisterOffset.getBytes(offset)   // 12
val slots  = RegisterOffset.getObjects(offset) // 3

Attributes

See also
Source
RegisterOffset.scala
Supertypes
class Object
trait Matchable
class Any
Self type
sealed trait RegisterType[A]

The kind of register that holds a value of type A: one case object for each of Unit, Char, Byte, Short, Int, Long, Float, Double and Boolean, and Object for reference types. SeqDeconstructor.SpecializedIndexed#elementType returns one to say how the elements of an array-backed collection are stored.

The kind of register that holds a value of type A: one case object for each of Unit, Char, Byte, Short, Int, Long, Float, Double and Boolean, and Object for reference types. SeqDeconstructor.SpecializedIndexed#elementType returns one to say how the elements of an array-backed collection are stored.

Type parameters

A

the type of the values

Attributes

Companion
object
Source
RegisterType.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
object Boolean
object Byte
object Char
object Double
object Float
object Int
object Long
trait Object[A]
object Short
object Unit
Show all
object RegisterType

The register kinds.

The register kinds.

Attributes

Companion
trait
Source
RegisterType.scala
Supertypes
class Object
trait Matchable
class Any
Self type
object Registers

Creates Registers.

Creates Registers.

Attributes

Companion
class
Source
Registers.scala
Supertypes
class Object
trait Matchable
class Any
Self type
Registers.type
class Registers

The mutable storage that Constructors and Deconstructors read and write: a byte area for primitive values and an object area for references. A value's position is a RegisterOffset: the getters and setters for primitives use its byte part as the index into the byte area, and getObject and setObject use its object part as the index into the object area. Primitives are stored as raw little-endian bytes, without boxing.

The mutable storage that Constructors and Deconstructors read and write: a byte area for primitive values and an object area for references. A value's position is a RegisterOffset: the getters and setters for primitives use its byte part as the index into the byte area, and getObject and setObject use its object part as the index into the object area. Primitives are stored as raw little-endian bytes, without boxing.

Registers(usedRegisters) allocates both areas at the sizes that usedRegisters gives. The setters grow an area when a value does not fit. The getters never grow an area: a position must be inside an area before it is read, and on the JVM reading beyond an area throws an IndexOutOfBoundsException. A position that was allocated but never written reads as 0, false or null.

A Registers is not thread-safe. The JSON reader and writer each keep one as a stack of record frames, so the JSON codec does not allocate registers for each record.

import zio.blocks.schema.binding._

val registers = Registers(RegisterOffset(objects = 1, ints = 1))
registers.setObject(RegisterOffset.Zero, "Zionomicon")
registers.setInt(RegisterOffset(objects = 1), 2021)
val title = registers.getObject(RegisterOffset.Zero)     // "Zionomicon"
val year  = registers.getInt(RegisterOffset(objects = 1)) // 2021

Attributes

See also
Companion
object
Source
Registers.scala
Supertypes
class Object
trait Matchable
class Any
trait SeqConstructor[C[_]]

Builds a collection of type C[A] element by element through a mutable builder: the construction half of a Binding.Seq. A codec decodes a sequence by calling newBuilder, one of the add methods for each element, and then result.

Builds a collection of type C[A] element by element through a mutable builder: the construction half of a Binding.Seq. A codec decodes a sequence by calling newBuilder, one of the add methods for each element, and then result.

The companion object has an instance for each standard collection. The array-backed ones (arraySeqConstructor, arrayConstructor and, on Scala 3 only, iArrayConstructor) store the elements in an array of the element type, so addInt and the other primitive adders write a primitive element without boxing it.

Type parameters

C

the collection type constructor

Attributes

Companion
object
Source
SeqConstructor.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes

The sequence constructors for the standard collections.

The sequence constructors for the standard collections.

Attributes

Companion
trait
Source
SeqConstructor.scala
Supertypes
class Object
trait Matchable
class Any
Self type
trait SeqDeconstructor[C[_]]

Reads a collection of type C[A] back as its elements and size: the deconstruction half of a Binding.Seq. The instances for array-backed collections are SeqDeconstructor.SpecializedIndexed, which also read an element by index; the JSON codec and the optics use that when they can.

Reads a collection of type C[A] back as its elements and size: the deconstruction half of a Binding.Seq. The instances for array-backed collections are SeqDeconstructor.SpecializedIndexed, which also read an element by index; the JSON codec and the optics use that when they can.

Type parameters

C

the collection type constructor

Attributes

Companion
object
Source
SeqDeconstructor.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes

The sequence deconstructors for the standard collections.

The sequence deconstructors for the standard collections.

Attributes

Companion
trait
Source
SeqDeconstructor.scala
Supertypes
class Object
trait Matchable
class Any
Self type
trait UnapplyMap[X]

Type class that witnesses that a type X is an applied map type M[K, V].

Type class that witnesses that a type X is an applied map type M[K, V].

This is used for Scala 2 compatibility when resolving map bindings in a BindingResolver, since Scala 2 cannot express higher-kinded type parameters directly in implicit parameters.

Type parameters

X

The applied type (e.g., Map[String, Int])

Attributes

Companion
object
Source
Unapply.scala
Supertypes
class Object
trait Matchable
class Any
object UnapplyMap

The UnapplyMap instance for the immutable Map.

The UnapplyMap instance for the immutable Map.

Attributes

Companion
trait
Source
Unapply.scala
Supertypes
class Object
trait Matchable
class Any
Self type
UnapplyMap.type
trait UnapplySeq[X]

Type class that witnesses that a type X is an applied sequence type C[A].

Type class that witnesses that a type X is an applied sequence type C[A].

This is used for Scala 2 compatibility when resolving sequence bindings in a BindingResolver, since Scala 2 cannot express higher-kinded type parameters directly in implicit parameters.

Type parameters

X

The applied type (e.g., List[Int])

Attributes

Companion
object
Source
Unapply.scala
Supertypes
class Object
trait Matchable
class Any

The UnapplySeq instances: Set, List, Vector, IndexedSeq and Chunk, and, in the lower-priority parent, the immutable Seq.

The UnapplySeq instances: Set, List, Vector, IndexedSeq and Chunk, and, in the lower-priority parent, the immutable Seq.

Attributes

Companion
trait
Source
Unapply.scala
Supertypes
class Object
trait Matchable
class Any
Self type
UnapplySeq.type

The lower-priority UnapplySeq instance for the immutable Seq.

The lower-priority UnapplySeq instance for the immutable Seq.

Attributes

Source
Unapply.scala
Supertypes
class Object
trait Matchable
class Any
Known subtypes
object UnapplySeq