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 FlatBuffers.Parser (parseFlatBuffers)
import FlatBuffers.Codec (CompiledSchema, compileSchema)
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)
widgetSchema :: Either String CompiledSchema
widgetSchema = parseFlatBuffers "table Widget { name:string; count:int; price:double; } root_type Widget;" >>= compileSchema
encodeWidget :: Widget -> Either String ByteString
encodeWidget widget = widgetSchema >>= (\schema -> FBE.encodeWith schema (toFlatBuffers widget))
decodeWidget :: ByteString -> Either String Widget
decodeWidget bs = do
schema <- widgetSchema
val <- FBD.decodeWith schema bs
fromFlatBuffers val
sample :: Widget
sample = Widget "wireform" 42 2.718
roundTrip :: Either String Widget
roundTrip = encodeWidget sample >>= decodeWidget

Dynamic encode/decode require a parsed or compiled schema; values follow declaration order. decodeWith materializes a typed Value tree and validates references, alignment, and required fields. Defaults and optional scalar presence come from that schema.

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 schema-directed dynamic encode + decode wireform-flatbuffers schema-directed dynamic encode + decode lower is better · ns · GHC 9.10.3, Apple Silicon, criterion 1.6.5. Full Value materialization; compiled schemas reused 0 25000 50000 75000 100000 1222 185 99387 17627 Person table Person[100] vector encode decode wireform-flatbuffers schema-directed dynamic encode + decode lower is better · ns · GHC 9.10.3, Apple Silicon, criterion 1.6.5. Full Value materialization; compiled schemas reused 0 25000 50000 75000 100000 1222 185 99387 17627 Person table Person[100] vector encode decode
Operationencodedecoderatio
Person table1222 ns185 ns0.15x
Person[100] vector99387 ns17627 ns0.18x

Last run 2026-11-06 10:08:02 UTC. GHC 9.10.3, Apple Silicon, criterion 1.6.5. Full Value materialization; compiled schemas reused.

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