Skip to content

wireform-flatbuffers

wireform-flatbuffers implements Google FlatBuffers, a zero-copy serialization format designed for game engines, mobile apps, and real-time inference serving. FlatBuffers lay out tables with vtables that index field offsets, keeping scalars inline and strings or sub-tables behind indirection. Use this package when you need to read large buffers without deserializing the entire message, or when sharing the builder infrastructure with Arrow IPC.

  • Typeclass API via ToFlatBuffers and FromFlatBuffers with Template Haskell deriving
  • FlatBuffers IDL parser and codegen from .fbs schema files
  • Vtable-based wire layout with inline scalars and offset-indirected collections
  • Zero-copy view/reader via FlatBuffers.View for schema-known access patterns
  • Shared builder with Arrow IPC for cross-format buffer construction
  • QuasiQuoter for inline [flatbuffers| ... |] schemas

Derive instances for your table types, then encode and decode through the value-level codec:

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE TemplateHaskell #-}
import FlatBuffers.Decode qualified as FBD
import FlatBuffers.Derive (ToFlatBuffers (..), FromFlatBuffers (..), deriveFlatBuffers, deriveView)
import FlatBuffers.Encode qualified as FBE
import Data.Int (Int32)
import Data.Text (Text)
import GHC.Generics (Generic)
data Widget = Widget
{ widgetName :: !Text
, widgetCount :: !Int32
, widgetPrice :: !Double
}
deriving stock (Show, Eq, Generic)
$(deriveFlatBuffers ''Widget)
$(deriveView ''Widget)
encodeWidget :: Widget -> ByteString
encodeWidget = FBE.encode . toFlatBuffers
decodeWidget :: ByteString -> Either String Widget
decodeWidget bs = do
val <- FBD.decode bs
fromFlatBuffers val
sample :: Widget
sample = Widget "wireform" 42 2.718
roundTrip :: Either String Widget
roundTrip = decodeWidget (encodeWidget sample)

For zero-copy reads on known schemas, use the view layer after encoding:

import FlatBuffers.View (decodeRoot)
readWidget :: ByteString -> Either String Widget
readWidget = decodeRoot

Generate types from .fbs files:

{-# LANGUAGE TemplateHaskell #-}
import FlatBuffers.QQ (fbs)
[fbs|
table Widget {
name:string;
count:int;
price:double;
}
root_type Widget;
|]
Terminal window
wireform-gen flatbuffers -i schema.fbs -o src/Gen/
wireform-flatbuffers encode + decode (zero-copy decode) wireform-flatbuffers encode + decode (zero-copy decode) lower is better · ns · ghc-9.8.4 on darwin-aarch64, criterion 1.6.5. Decode is a zero-copy cursor by design: only the outer envelope is resolved at decode time. Per-field reads happen lazily. 0 25000 50000 75000 100000 827 142 95352 75.7 Person table Person[100] vector encode decode wireform-flatbuffers encode + decode (zero-copy decode) lower is better · ns · ghc-9.8.4 on darwin-aarch64, criterion 1.6.5. Decode is a zero-copy cursor by design: only the outer envelope is resolved at decode time. Per-field reads happen lazily. 0 25000 50000 75000 100000 827 142 95352 75.7 Person table Person[100] vector encode decode
Operationencodedecoderatio
Person table827 ns142 ns0.17x
Person[100] vector95352 ns75.7 ns0.00x

Last run 2026-06-27 11:35:54 UTC. ghc-9.8.4 on darwin-aarch64, criterion 1.6.5. Decode is a zero-copy cursor by design: only the outer envelope is resolved at decode time. Per-field reads happen lazily..

Like Cap’n Proto, FlatBuffers decode is a zero-copy cursor. The decode cost is near-constant because only the root table offset is resolved; field access is lazy pointer arithmetic into the original buffer. Encode is proportional to the number of fields and vector elements.

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

ModulePurpose
FlatBuffers.DeriveToFlatBuffers / FromFlatBuffers and deriveFlatBuffers
FlatBuffers.Encode / FlatBuffers.DecodeHigh-level encoder and value-tree decoder
FlatBuffers.ViewZero-copy cursor access for schema-known tables
FlatBuffers.ReaderLow-level pointer-walking decoder
FlatBuffers.BuilderVtable and offset builder
FlatBuffers.ValueDynamic untyped Value ADT
FlatBuffers.Schema / FlatBuffers.ParserSchema AST and .fbs parser
FlatBuffers.CodeGen / FlatBuffers.QQHaskell codegen and quasiquoter
FlatBuffers.RegistryRuntime schema registry