zio.blocks.schema.binding
Members list
Type members
Classlikes
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):
- Binding.Record: a Constructor and a Deconstructor that move a record's fields in and out of Registers.
- Binding.Variant: a Discriminator that returns the case index of a value, and Matchers that downcast a value to each case.
- Binding.Seq: a SeqConstructor and a SeqDeconstructor for a collection type constructor.
- Binding.Map: a MapConstructor and a MapDeconstructor for a map type constructor.
- Binding.Primitive: a marker without functions.
- Binding.Wrapper:
wrapandunwrapfunctions between a type and the type it wraps. - Binding.Dynamic: a marker without functions, for a node that holds a zio.blocks.schema.DynamicValue.
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
- Known subtypes
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
- 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
- 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:
- BindingResolver.Registry: A map-backed resolver for explicit bindings
- BindingResolver.reflection: A resolver that derives record bindings using runtime reflection (JVM only)
- BindingResolver.defaults: Pre-configured bindings for primitives, java.time, and common collections
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
- 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
- Self type
-
BindingResolver.type
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
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
- Self type
-
BindingType.type
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
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
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
- Known subtypes
-
class ConstantConstructor[A]
- Self type
-
Constructor[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
- Known subtypes
-
class ConstantDeconstructor[A]
- Self type
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
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
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
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
The map constructors for the standard maps.
The map constructors for the standard maps.
Attributes
- Companion
- trait
- Source
- MapConstructor.scala
- Supertypes
- Self type
-
MapConstructor.type
The map deconstructors for the standard maps.
The map deconstructors for the standard maps.
Attributes
- Companion
- trait
- Source
- MapDeconstructor.scala
- Supertypes
- Self type
-
MapDeconstructor.type
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
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
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
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
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
- Known subtypes
The register kinds of record fields.
The register kinds of record fields.
Attributes
- Companion
- trait
- Source
- Register.scala
- Supertypes
- 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
- Self type
-
RegisterOffset.type
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
- Known subtypes
The register kinds.
The register kinds.
Attributes
- Companion
- trait
- Source
- RegisterType.scala
- Supertypes
- Self type
-
RegisterType.type
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
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
- Known subtypes
-
object chunkConstructorobject indexedSeqConstructorobject listConstructorobject seqConstructorobject setConstructorobject vectorConstructorShow all
The sequence constructors for the standard collections.
The sequence constructors for the standard collections.
Attributes
- Companion
- trait
- Source
- SeqConstructor.scala
- Supertypes
- Self type
-
SeqConstructor.type
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
- Known subtypes
-
trait SpecializedIndexed[C]
The sequence deconstructors for the standard collections.
The sequence deconstructors for the standard collections.
Attributes
- Companion
- trait
- Source
- SeqDeconstructor.scala
- Supertypes
- Self type
-
SeqDeconstructor.type
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
The UnapplyMap instance for the immutable Map.
The UnapplyMap instance for the immutable Map.
Attributes
- Companion
- trait
- Source
- Unapply.scala
- Supertypes
- Self type
-
UnapplyMap.type
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
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
- 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
- Known subtypes
-
object UnapplySeq