Skip to content

wireform-bond

wireform-bond implements Microsoft Bond Compact Binary serialization. Bond uses explicit numeric field IDs for schema evolution, supports nullable types and struct inheritance in the IDL, and encodes with packed delta/type headers and ZigZag varints. Use this package when you need wire compatibility with Bond-based services (Bing, Cosmos DB, and other Microsoft systems) or a compact, ID-driven binary format with a rich schema language.

  • Typeclass API via ToBond and FromBond with Template Haskell deriving
  • Compact Binary v1 wire format with packed delta/type field headers
  • ZigZag varints for signed integer encoding
  • Bond IDL parser and codegen from .bond schema files
  • Schema AST with type parameters, field modifiers, and custom attributes
  • QuasiQuoter for inline [bond| ... |] schemas

Derive instances for your record types, then encode through the Compact Binary codec:

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE TemplateHaskell #-}
import Bond.Decode qualified as BD
import Bond.Derive (ToBond (..), FromBond (..), deriveBond)
import Bond.Encode qualified as BE
import Bond.Value qualified as BV
import Data.Int (Int32)
import Data.Text (Text)
import GHC.Generics (Generic)
data Person = Person
{ personName :: !Text
, personAge :: !Int32
, personEmail :: !Text
}
deriving stock (Show, Eq, Generic)
$(deriveBond ''Person)
encodePerson :: Person -> ByteString
encodePerson = BE.encode . toBond
decodePerson :: ByteString -> Either String Person
decodePerson bs = do
val <- BD.decode BV.BT_STRUCT bs
fromBond val
alice :: Person
alice = Person "Alice" 30 "alice@example.com"
roundTrip :: Either String Person
roundTrip = decodePerson (encodePerson alice)

For schema-first workflows, parse Bond IDL and generate Haskell types:

{-# LANGUAGE TemplateHaskell #-}
import Bond.QQ (bond)
[bond|
struct Person {
1: string name;
2: int32 age;
3: string email;
}
|]
Terminal window
wireform-gen bond -i schema.bond -o src/Gen/
wireform-bond encode + decode (Compact Binary, Person record) wireform-bond encode + decode (Compact Binary, Person record) lower is better · ns · ghc-9.8.4 on darwin-aarch64, criterion 1.6.5. Decode is structurally lazy at the Value layer; the [Person] x 100 number reflects only the outer container resolution. 0 5000 10000 15000 20000 168 192 15742 2140 single Person [Person] x 100 encode decode wireform-bond encode + decode (Compact Binary, Person record) lower is better · ns · ghc-9.8.4 on darwin-aarch64, criterion 1.6.5. Decode is structurally lazy at the Value layer; the [Person] x 100 number reflects only the outer container resolution. 0 5000 10000 15000 20000 168 192 15742 2140 single Person [Person] x 100 encode decode
Operationencodedecoderatio
single Person168 ns192 ns1.14x
[Person] x 10015742 ns2140 ns0.14x

Last run 2026-06-27 11:35:54 UTC. ghc-9.8.4 on darwin-aarch64, criterion 1.6.5. Decode is structurally lazy at the Value layer; the [Person] x 100 number reflects only the outer container resolution..

Decode is structurally lazy at the Value layer: the 100-element list decode resolves only the outer container, deferring per-element materialization until access. This makes random-access patterns fast for large payloads.

The chart and table above are regenerated by wireform-stats from wireform-bond/bench-results/summary/bond-encode-decode.json — the same source the README chart is built from.

ModulePurpose
Bond.DeriveToBond / FromBond classes and deriveBond
Bond.Encode / Bond.DecodeCompact Binary v1 encoder and decoder
Bond.ValueDynamic untyped Value ADT with Bond type tags
Bond.Schema / Bond.ParserSchema AST and .bond IDL parser
Bond.CodeGen / Bond.QQHaskell codegen and quasiquoter
Bond.RegistryRuntime schema registry