Summary

This PR introduces the schema-thrift module, porting Thrift serialization support to ZIO Schema 2. It provides a fully functional ThriftDeriver that automatically generates type-safe ThriftBinaryCodec instances for any ZIO Schema type, ensuring feature parity with the existing Avro implementation.

This is a direct port of the logic from the original zio-schema-thrift implementation, adapted for the new modular structure and ZIO Schema 2 APIs.

Key Changes

1. New Module: schema-thrift

  • Established a new sbt project, schema-thrift, within the build configuration.
  • Integrating org.apache.thrift:libthrift:0.20.0 and jakarta.annotation:jakarta.annotation-api:3.0.0 as core dependencies.
  • Added a dependency on the chunk module to facilitate efficient, zero-copy byte handling.

2. Implementation: ThriftDeriver & ThriftFormat

  • ZIO Schema 2 Migration: Completely re-engineered the derivation logic to leverage the modern Deriver and Reflect APIs inherent to ZIO Schema 2.
  • Robust Recursion Handling: Implemented a thread-safe caching mechanism (using ThreadLocal) to handle recursive schemas for both Records and Variants (including DynamicValue), effectively preventing StackOverflowError during derivation.
  • DynamicValue Support: Enabled comprehensive support for DynamicValue, allowing for flexible, schema-less serialization and deserialization via Thrift.

3. Optimized Transport Layer

  • ThriftTransport: Developed a custom TTransport implementation backed by zio.Chunk. This allows for efficient serialization directly to and from ZIO Chunks, minimizing unnecessary array inclusions and buffer copying.

4. Comprehensive Type Support

The codec enables Thrift serialization for the full spectrum of ZIO Schema primitives:

  • Standard Primitives: Mapped to their native Thrift counterparts (Boolean -> BOOL, Int -> I32, Long -> I64, etc.) or appropriate fallbacks (Char -> STRING).
  • Extended Numerics: BigInt (serialized as STRING) and BigDecimal (serialized as a structured STRUCT).
  • Miscellaneous: UUID and Currency (serialized as STRING).
  • Java Time: Complete support for the java.time suite (e.g., Instant, LocalDate, ZonedDateTime), using standardized String or Struct representations.

5. Complex Structure Handling

  • Collections: Native support for List, Vector, Set (via TType.LIST/TType.SET), and Map (via TType.MAP).
  • Records: Case classes and nested records are seamlessly mapped to TType.STRUCT.
  • Variants:
    • Option: Encoded using a specialized structure (Field 1: None, Field 2: Some) for reliable presence detection.
    • Either: Handled as a union-like structure.
    • Sealed Traits: fully supported as Thrift structs with discriminator fields for Enums and ADTs.

Testing & Verification

  • Test Suite: Introduced ThriftCodecSpec, mirroring the rigorous coverage of AvroFormatSpec.
  • Coverage: 43 comprehensive tests validate functionality across all supported primitives, deep recursive structures, and DynamicValue.
  • Result: All tests passed successfully.

Integration

  • The module is fully integrated into the root build.sbt structure.
  • Public API exposed via zio.blocks.schema.thrift.ThriftFormat.

Example Usage

import zio.schema.Schema
import zio.blocks.schema.thrift.ThriftFormat
import zio.Chunk
case class Person(name: String, age: Int)
object Person {
implicit val schema: Schema[Person] = Schema.gen
}
val person = Person("Alice", 30)
// Encodes directly to a ZIO Chunk[Byte]
val binary: Chunk[Byte] = ThriftFormat.encode(person)
// Decodes back to a Person case class
val result: Either[String, Person] = ThriftFormat.decode[Person](binary)

/claim #681 Fixes: #681

Claim

Total prize pool $1,000
Total paid $0
Status Pending
Submitted January 15, 2026
Last updated January 15, 2026

Contributors

PR

Pranjal Negi

@Pranjal6955

100%

Sponsors

ZI

ZIO

@ZIO

$1,000