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.
Key features
Section titled “Key features”- Typeclass API via
ToBondandFromBondwith 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
.bondschema files - Schema AST with type parameters, field modifiers, and custom attributes
- QuasiQuoter for inline
[bond| ... |]schemas
Basic usage
Section titled “Basic usage”Derive instances for your record types, then encode through the Compact Binary codec:
{-# LANGUAGE DerivingStrategies #-}{-# LANGUAGE TemplateHaskell #-}
import Bond.Decode qualified as BDimport Bond.Derive (ToBond (..), FromBond (..), deriveBond)import Bond.Encode qualified as BEimport Bond.Value qualified as BVimport 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 -> ByteStringencodePerson = BE.encode . toBond
decodePerson :: ByteString -> Either String PersondecodePerson bs = do val <- BD.decode BV.BT_STRUCT bs fromBond val
alice :: Personalice = Person "Alice" 30 "alice@example.com"
roundTrip :: Either String PersonroundTrip = 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; }|]wireform-gen bond -i schema.bond -o src/Gen/Performance
Section titled “Performance”Compact Binary encode/decode
Section titled “Compact Binary encode/decode”| Operation | encode | decode | ratio |
|---|---|---|---|
| single Person | 168 ns | 192 ns | 1.14x |
| [Person] x 100 | 15742 ns | 2140 ns | 0.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.
Notable modules
Section titled “Notable modules”| Module | Purpose |
|---|---|
Bond.Derive | ToBond / FromBond classes and deriveBond |
Bond.Encode / Bond.Decode | Compact Binary v1 encoder and decoder |
Bond.Value | Dynamic untyped Value ADT with Bond type tags |
Bond.Schema / Bond.Parser | Schema AST and .bond IDL parser |
Bond.CodeGen / Bond.QQ | Haskell codegen and quasiquoter |
Bond.Registry | Runtime schema registry |