blob: 36d867a3c33e35e3905f9f2990ff7ca360982f2e [file] [log] [blame] [edit]
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://flatbuffers.dev/evolution/">
<link rel="prev" href="../schema/">
<link rel="next" href="../grammar/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.16">
<title>Evolution - FlatBuffers Docs</title>
<link rel="stylesheet" href="../assets/stylesheets/main.7e37652d.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#evolution" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="FlatBuffers Docs" class="md-header__button md-logo" aria-label="FlatBuffers Docs" data-md-component="logo">
<img src="../assets/flatbuffers_logo.svg" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
FlatBuffers Docs
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Evolution
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<div class="md-header__source">
<a href="https://github.com/google/flatbuffers" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg>
</div>
<div class="md-source__repository">
google/FlatBuffers
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="FlatBuffers Docs" class="md-nav__button md-logo" aria-label="FlatBuffers Docs" data-md-component="logo">
<img src="../assets/flatbuffers_logo.svg" alt="logo">
</a>
FlatBuffers Docs
</label>
<div class="md-nav__source">
<a href="https://github.com/google/flatbuffers" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg>
</div>
<div class="md-source__repository">
google/FlatBuffers
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../quick_start/" class="md-nav__link">
<span class="md-ellipsis">
Quick Start
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tutorial/" class="md-nav__link">
<span class="md-ellipsis">
Tutorial
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_4" >
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
Compiler (flatc)
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Compiler (flatc)
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../building/" class="md-nav__link">
<span class="md-ellipsis">
Building
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../flatc/" class="md-nav__link">
<span class="md-ellipsis">
Using
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Schema (.fbs)
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Schema (.fbs)
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../schema/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Evolution
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Evolution
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#rules" class="md-nav__link">
<span class="md-ellipsis">
Rules
</span>
</a>
<nav class="md-nav" aria-label="Rules">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#addition" class="md-nav__link">
<span class="md-ellipsis">
Addition
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#removal" class="md-nav__link">
<span class="md-ellipsis">
Removal
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#name-changes" class="md-nav__link">
<span class="md-ellipsis">
Name Changes
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#examples" class="md-nav__link">
<span class="md-ellipsis">
Examples
</span>
</a>
<nav class="md-nav" aria-label="Examples">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#table-evolution" class="md-nav__link">
<span class="md-ellipsis">
Table Evolution
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#union-evolution" class="md-nav__link">
<span class="md-ellipsis">
Union Evolution
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#version-control" class="md-nav__link">
<span class="md-ellipsis">
Version Control
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#checking-conformity" class="md-nav__link">
<span class="md-ellipsis">
Checking Conformity
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../grammar/" class="md-nav__link">
<span class="md-ellipsis">
Grammar
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_6" >
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
Language Guides
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
Language Guides
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../languages/c/" class="md-nav__link">
<span class="md-ellipsis">
C
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/cpp/" class="md-nav__link">
<span class="md-ellipsis">
C++
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/c_sharp/" class="md-nav__link">
<span class="md-ellipsis">
C#
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/dart/" class="md-nav__link">
<span class="md-ellipsis">
Dart
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/go/" class="md-nav__link">
<span class="md-ellipsis">
Go
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/java/" class="md-nav__link">
<span class="md-ellipsis">
Java
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/javascript/" class="md-nav__link">
<span class="md-ellipsis">
JavaScript
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/kotlin/" class="md-nav__link">
<span class="md-ellipsis">
Kotlin
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/lobster/" class="md-nav__link">
<span class="md-ellipsis">
Lobster
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/lua/" class="md-nav__link">
<span class="md-ellipsis">
Lua
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/php/" class="md-nav__link">
<span class="md-ellipsis">
PHP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/python/" class="md-nav__link">
<span class="md-ellipsis">
Python
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/rust/" class="md-nav__link">
<span class="md-ellipsis">
Rust
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/swift/" class="md-nav__link">
<span class="md-ellipsis">
Swift
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../languages/typescript/" class="md-nav__link">
<span class="md-ellipsis">
TypeScript
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../support/" class="md-nav__link">
<span class="md-ellipsis">
Supported Configurations
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../white_paper/" class="md-nav__link">
<span class="md-ellipsis">
White Paper
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_9" >
<label class="md-nav__link" for="__nav_9" id="__nav_9_label" tabindex="0">
<span class="md-ellipsis">
Advanced
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_9_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_9">
<span class="md-nav__icon md-icon"></span>
Advanced
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../internals/" class="md-nav__link">
<span class="md-ellipsis">
FlatBuffers Internals
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../intermediate_representation/" class="md-nav__link">
<span class="md-ellipsis">
Intermediate Representation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../annotation/" class="md-nav__link">
<span class="md-ellipsis">
Annotating Buffers (.afb)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../benchmarks/" class="md-nav__link">
<span class="md-ellipsis">
Benchmarks
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../flexbuffers/" class="md-nav__link">
<span class="md-ellipsis">
FlexBuffers (Schema-less version)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../contributing/" class="md-nav__link">
<span class="md-ellipsis">
Contributing
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#rules" class="md-nav__link">
<span class="md-ellipsis">
Rules
</span>
</a>
<nav class="md-nav" aria-label="Rules">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#addition" class="md-nav__link">
<span class="md-ellipsis">
Addition
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#removal" class="md-nav__link">
<span class="md-ellipsis">
Removal
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#name-changes" class="md-nav__link">
<span class="md-ellipsis">
Name Changes
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#examples" class="md-nav__link">
<span class="md-ellipsis">
Examples
</span>
</a>
<nav class="md-nav" aria-label="Examples">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#table-evolution" class="md-nav__link">
<span class="md-ellipsis">
Table Evolution
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#union-evolution" class="md-nav__link">
<span class="md-ellipsis">
Union Evolution
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#version-control" class="md-nav__link">
<span class="md-ellipsis">
Version Control
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#checking-conformity" class="md-nav__link">
<span class="md-ellipsis">
Checking Conformity
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/google/flatbuffers/edit/master/docs/source/evolution.md" title="Edit this page" class="md-content__button md-icon" rel="edit">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10 20H6V4h7v5h5v3.1l2-2V8l-6-6H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h4zm10.2-7c.1 0 .3.1.4.2l1.3 1.3c.2.2.2.6 0 .8l-1 1-2.1-2.1 1-1c.1-.1.2-.2.4-.2m0 3.9L14.1 23H12v-2.1l6.1-6.1z"/></svg>
</a>
<h1 id="evolution">Evolution</h1>
<p>FlatBuffers enables the <a href="../schema/">schema</a> to evolve over time while still
maintaining forwards and backwards compatibility with old flatbuffers.</p>
<p>Some rules must be followed to ensure the evolution of a schema is valid.</p>
<h2 id="rules">Rules</h2>
<p>Adding new tables, vectors, structs to the schema is always allowed. Its only
when you add a new field to a <a href="../schema/#tables"><code>table</code></a> that certain rules
must be followed.</p>
<h3 id="addition">Addition</h3>
<p><strong>New fields MUST be added to the end of the table definition.</strong></p>
<p>This allows older data to still be read correctly (giving you the default value
of the added field if accessed).</p>
<p>Older code will simply ignore the new field in the flatbuffer.</p>
<p>You can ignore this rule if you use the <code>id</code> attribute on all the fields of a
table.</p>
<h3 id="removal">Removal</h3>
<p><strong>You MUST not remove a field from the schema, even if you don't use it
anymore.</strong> You simply stop writing them to the buffer.</p>
<p>Its encouraged to mark the field deprecated by adding the <code>deprecated</code>
attribute. This will skip the generation of accessors and setters in the code,
to enforce the field not to be used any more.</p>
<h3 id="name-changes">Name Changes</h3>
<p>Its generally OK to change the name of tables and fields, as these are not
serialized to the buffer. It may break code that would have to be refactored
with the updated name.</p>
<h2 id="examples">Examples</h2>
<p>The following examples uses a base schema and attempts to evolve it a few times.
The versions are tracked by <code>V1</code>, <code>V2</code>, etc.. and <code>CodeV1</code> means code compiled
against the <code>V1</code> schema.</p>
<h3 id="table-evolution">Table Evolution</h3>
<p>Lets start with a simple table <code>T</code> with two fields.</p>
<div class="highlight"><span class="filename">Schema V1</span><pre><span></span><code><span class="n">table</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">a</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="w"> </span><span class="nl">b</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<div class="tabbed-set tabbed-alternate" data-tabs="1:7"><input checked="checked" id="well-evolved" name="__tabbed_1" type="radio" /><input id="improper-addition" name="__tabbed_1" type="radio" /><input id="improper-deletion" name="__tabbed_1" type="radio" /><input id="proper-reordering" name="__tabbed_1" type="radio" /><input id="changing-types" name="__tabbed_1" type="radio" /><input id="changing-defaults" name="__tabbed_1" type="radio" /><input id="renaming-fields" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="well-evolved">Well Evolved</label><label for="improper-addition">Improper Addition</label><label for="improper-deletion">Improper Deletion</label><label for="proper-reordering">Proper Reordering</label><label for="changing-types">Changing Types</label><label for="changing-defaults">Changing Defaults</label><label for="renaming-fields">Renaming Fields</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<p>First lets extend the table with a new field.</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="n">table</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">a</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="w"> </span><span class="nl">b</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="w"> </span><span class="nl">c</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>This is OK. <code>CodeV1</code> reading <code>V2</code> data will simply ignore the presence of the
new field <code>c</code>. <code>CodeV2</code> reading <code>V1</code> data will get a default value (0) when
reading <code>c</code>.</p>
<div class="highlight"><span class="filename">Schema V3</span><pre><span></span><code><span class="n">table</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">a</span><span class="p">:</span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="n">deprecated</span><span class="p">);</span>
<span class="w"> </span><span class="nl">b</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="w"> </span><span class="nl">c</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>This is OK, removing field <code>a</code> via deprecation. <code>CodeV1</code>, <code>CodeV2</code> and <code>CodeV3</code>
reading <code>V3</code> data will now always get the default value of <code>a</code>, since it is not
present. <code>CodeV3</code> cannot write <code>a</code> anymore. <code>CodeV3</code> reading old data (<code>V1</code> or
<code>V2</code>) will not be able to access the field anymore, since no generated accessors
are omitted.</p>
</div>
<div class="tabbed-block">
<p>Add a new field, but this time at the beginning.</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="n">table</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">c</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="w"> </span><span class="nl">a</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="w"> </span><span class="nl">b</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>This is NOT OK, as it makes <code>V2</code> incompatible. <code>CodeV1</code> reading <code>V2</code> data
will access <code>a</code> but will read <code>c</code> data.</p>
<p><code>CodeV2</code> reading <code>V1</code> data will access <code>c</code> but will read <code>a</code> data.</p>
</div>
<div class="tabbed-block">
<p>Remove a field from the schema.</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="n">table</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">b</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>This is NOT OK. <code>CodeV1</code> reading <code>V2</code> data will access <code>a</code> but read <code>b</code> data.</p>
<p><code>CodeV2</code> reading <code>V1</code> data will access <code>b</code> but will read <code>a</code> data.</p>
</div>
<div class="tabbed-block">
<p>Lets add a new field to the beginning, but use <code>id</code> attributes.</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="n">table</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">c</span><span class="p">:</span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="o">:</span><span class="w"> </span><span class="mi">2</span><span class="p">);</span>
<span class="w"> </span><span class="nl">a</span><span class="p">:</span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="o">:</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="nl">b</span><span class="p">:</span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="o">:</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>This is OK. This adds the a new field in the beginning, but because all the
<code>id</code> attributes were added, it is OK.</p>
</div>
<div class="tabbed-block">
<p>Let change the types of the fields.</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="n">table</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">a</span><span class="p">:</span><span class="n">uint</span><span class="p">;</span>
<span class="w"> </span><span class="nl">b</span><span class="p">:</span><span class="n">uint</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>This is MAYBE OK, and only in the case where the type change is the same
width. This is tricky if the <code>V1</code> data contained any negative numbers. So
this should be done with care.</p>
</div>
<div class="tabbed-block">
<p>Lets change the default values of the existing fields.</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="n">table</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">a</span><span class="p">:</span><span class="kt">int</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="nl">b</span><span class="p">:</span><span class="kt">int</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>This is NOT OK. Any <code>V1</code> data that did not have a value written to the
buffer relied on generated code to provide the default value.</p>
<p>There MAY be cases where this is OK, if you control all the producers and
consumers, and you can update them in tandem.</p>
</div>
<div class="tabbed-block">
<p>Lets change the name of the fields</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="n">table</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nl">aa</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="w"> </span><span class="nl">bb</span><span class="p">:</span><span class="kt">int</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>This is generally OK. You've renamed fields will break all code and JSON
files that use this schema, but you can refactor those without affecting the
binary data, since the binary only address fields by id and offset, not by
names.</p>
</div>
</div>
</div>
<h3 id="union-evolution">Union Evolution</h3>
<p>Lets start with a simple union <code>U</code> with two members.</p>
<div class="highlight"><span class="filename">Schema V1</span><pre><span></span><code><span class="k">union</span><span class="w"> </span><span class="nc">U</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">A</span><span class="p">,</span>
<span class="w"> </span><span class="n">B</span>
<span class="p">}</span>
</code></pre></div>
<div class="tabbed-set tabbed-alternate" data-tabs="2:3"><input checked="checked" id="well-evolved_1" name="__tabbed_2" type="radio" /><input id="improper-evolved" name="__tabbed_2" type="radio" /><input id="evolved-with-discriminant" name="__tabbed_2" type="radio" /><div class="tabbed-labels"><label for="well-evolved_1">Well Evolved</label><label for="improper-evolved">Improper Evolved</label><label for="evolved-with-discriminant">Evolved With Discriminant</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<p>Lets add a another variant to the end.</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="k">union</span><span class="w"> </span><span class="nc">U</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">A</span><span class="p">,</span>
<span class="w"> </span><span class="n">B</span><span class="p">,</span>
<span class="w"> </span><span class="nl">another_a</span><span class="p">:</span><span class="w"> </span><span class="n">A</span>
<span class="p">}</span>
</code></pre></div>
<p>This is OK. <code>CodeV1</code> will not recognize the <code>another_a</code>.</p>
</div>
<div class="tabbed-block">
<p>Lets add a another variant to the middle.</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="k">union</span><span class="w"> </span><span class="nc">U</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">A</span><span class="p">,</span>
<span class="w"> </span><span class="nl">another_a</span><span class="p">:</span><span class="w"> </span><span class="n">A</span><span class="p">,</span>
<span class="w"> </span><span class="n">B</span>
<span class="p">}</span>
</code></pre></div>
<p>This is NOT OK. <code>CodeV1</code> reading <code>V2</code> data will interpret <code>B</code> as <code>another_a</code>.
<code>CodeV2</code> reading <code>V1</code> data will interpret <code>another_a</code> as <code>B</code>.</p>
</div>
<div class="tabbed-block">
<p>Lets add a another variant to the middle, this time adding a union "discriminant".</p>
<div class="highlight"><span class="filename">Schema V2</span><pre><span></span><code><span class="k">union</span><span class="w"> </span><span class="nc">U</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nl">another_a</span><span class="p">:</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span>
<span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span>
<span class="p">}</span>
</code></pre></div>
<p>This is OK. Its like you added it to the end, but using the discriminant
value to physically place it elsewhere in the union.</p>
</div>
</div>
</div>
<h2 id="version-control">Version Control</h2>
<p>FlatBuffers relies on new field declarations being added at the end, and earlier
declarations to not be removed, but be marked deprecated when needed. We think
this is an improvement over the manual number assignment that happens in
Protocol Buffers (and which is still an option using the <code>id</code> attribute
mentioned above).</p>
<p>One place where this is possibly problematic however is source control. If user
<code>A</code> adds a field, generates new binary data with this new schema, then tries to
commit both to source control after user <code>B</code> already committed a new field also,
and just auto-merges the schema, the binary files are now invalid compared to
the new schema.</p>
<p>The solution of course is that you should not be generating binary data before
your schema changes have been committed, ensuring consistency with the rest of
the world. If this is not practical for you, use explicit field <code>id</code>s, which
should always generate a merge conflict if two people try to allocate the same
id.</p>
<h2 id="checking-conformity">Checking Conformity</h2>
<p>To check that schema are properly evolved, the <a href="../flatc/"><code>flatc</code></a> compiler has
a <a href="../flatc/#additional-options">option</a> to do just that:</p>
<div class="highlight"><pre><span></span><code>--conform<span class="w"> </span>FILE
</code></pre></div>
<p>Where <code>FILE</code> is the base schema the rest of the input schemas must evolve from.
It returns <code>0</code> if they are properly evolved, otherwise returns a non-zero value
and provides errors on the reason why the schema are not properly evolved.</p>
<p>As an example, the following checks if <code>schema_v2.fbs</code> is properly evolved from
<code>schema_v1.fbs</code>.</p>
<div class="highlight"><pre><span></span><code>flatc<span class="w"> </span>--conform<span class="w"> </span>schema_v1.fbs<span class="w"> </span>schema_v2.fbs
</code></pre></div>
</article>
</div>
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../schema/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Overview">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</div>
<div class="md-footer__title">
<span class="md-footer__direction">
Previous
</span>
<div class="md-ellipsis">
Overview
</div>
</div>
</a>
<a href="../grammar/" class="md-footer__link md-footer__link--next" aria-label="Next: Grammar">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Grammar
</div>
</div>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg>
</div>
</a>
</nav>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
<div class="md-copyright__highlight">
Copyright &copy; 2025 Google
</div>
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
<div class="md-social">
<a href="https://github.com/google/flatbuffers" target="_blank" rel="noopener" title="github.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8M105.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg>
</a>
<a href="https:///discord.gg/6qgKs3R" target="_blank" rel="noopener" title="" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M492.5 69.8c-.2-.3-.4-.6-.8-.7-38.1-17.5-78.4-30-119.7-37.1-.4-.1-.8 0-1.1.1s-.6.4-.8.8c-5.5 9.9-10.5 20.2-14.9 30.6-44.6-6.8-89.9-6.8-134.4 0-4.5-10.5-9.5-20.7-15.1-30.6-.2-.3-.5-.6-.8-.8s-.7-.2-1.1-.2C162.5 39 122.2 51.5 84.1 69c-.3.1-.6.4-.8.7C7.1 183.5-13.8 294.6-3.6 404.2c0 .3.1.5.2.8s.3.4.5.6c44.4 32.9 94 58 146.8 74.2.4.1.8.1 1.1 0s.7-.4.9-.7c11.3-15.4 21.4-31.8 30-48.8.1-.2.2-.5.2-.8s0-.5-.1-.8-.2-.5-.4-.6-.4-.3-.7-.4c-15.8-6.1-31.2-13.4-45.9-21.9-.3-.2-.5-.4-.7-.6s-.3-.6-.3-.9 0-.6.2-.9.3-.5.6-.7c3.1-2.3 6.2-4.7 9.1-7.1.3-.2.6-.4.9-.4s.7 0 1 .1c96.2 43.9 200.4 43.9 295.5 0 .3-.1.7-.2 1-.2s.7.2.9.4c2.9 2.4 6 4.9 9.1 7.2.2.2.4.4.6.7s.2.6.2.9-.1.6-.3.9-.4.5-.6.6c-14.7 8.6-30 15.9-45.9 21.8-.2.1-.5.2-.7.4s-.3.4-.4.7-.1.5-.1.8.1.5.2.8c8.8 17 18.8 33.3 30 48.8.2.3.6.6.9.7s.8.1 1.1 0c52.9-16.2 102.6-41.3 147.1-74.2.2-.2.4-.4.5-.6s.2-.5.2-.8c12.3-126.8-20.5-236.9-86.9-334.5zm-302 267.7c-29 0-52.8-26.6-52.8-59.2s23.4-59.2 52.8-59.2c29.7 0 53.3 26.8 52.8 59.2 0 32.7-23.4 59.2-52.8 59.2m195.4 0c-29 0-52.8-26.6-52.8-59.2s23.4-59.2 52.8-59.2c29.7 0 53.3 26.8 52.8 59.2 0 32.7-23.2 59.2-52.8 59.2"/></svg>
</a>
<a href="https://twitter.com/dbaileychess" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path fill="currentColor" d="M357.2 48h70.6L273.6 224.2 455 464H313L201.7 318.6 74.5 464H3.8l164.9-188.5L-5.2 48h145.6l100.5 132.9zm-24.8 373.8h39.1L119.1 88h-42z"/></svg>
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": ["content.code.annotate", "content.tabs.link", "navigation.expand", "navigation.footer", "header.autohide", "content.action.edit"], "search": "../assets/javascripts/workers/search.d50fe291.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="../assets/javascripts/bundle.50899def.min.js"></script>
</body>
</html>