Squashed 'third_party/autocxx/' content from commit 629e8fa53

git-subtree-dir: third_party/autocxx
git-subtree-split: 629e8fa531a633164c0b52e2a3cab536d4cd0849
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: I62a03b0049f49adf029e0204639cdb5468dde1a1
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..3c52212
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,16 @@
+## Expected Behavior
+
+
+## Actual Behavior
+
+
+## Steps to Reproduce the Problem
+
+1.
+1.
+1.
+
+## Specifications
+
+- Version:
+- Platform:
\ No newline at end of file
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..0787bd9
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,6 @@
+Fixes #<issue_number_goes_here>
+
+> It's a good idea to open an issue first for discussion.
+
+- [ ] Tests pass
+- [ ] Appropriate changes to README are included in PR
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..3eb54d1
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,218 @@
+name: CI
+
+on:
+  push:
+    branches: [main]
+  pull_request:
+  schedule: [cron: "40 1 * * *"]
+  workflow_dispatch:
+
+env:
+  RUST_BACKTRACE: short
+  # CI builds don't benefit very much from this and it has bugs
+  CARGO_INCREMENTAL: 0
+  # We can't use a debugger in CI, and this makes builds faster and the cache
+  # smaller. (TODO: use -Cdebuginfo=0 if it doesn't make backtraces useless)
+  RUSTFLAGS: -Cdebuginfo=1
+  CARGO_TERM_COLOR: always
+
+jobs:
+  test:
+    name: Test ${{matrix.name || format('Rust {0}', matrix.rust)}}
+    runs-on: ${{matrix.os || 'ubuntu'}}-latest
+
+    strategy:
+      fail-fast: false
+
+      matrix:
+        include:
+          - rust: nightly
+          - rust: beta
+          - rust: stable
+          - name: macOS
+            rust: nightly
+            os: macos
+          - name: Windows (gnu)
+            rust: nightly-x86_64-pc-windows-gnu
+            os: windows
+          - name: Windows (msvc)
+            rust: nightly-x86_64-pc-windows-msvc
+            os: windows
+            flags: /EHsc
+    env:
+      CXXFLAGS: ${{matrix.flags}}
+      RUSTFLAGS: --cfg deny_warnings -Dwarnings
+
+    steps:
+      - uses: actions/checkout@v2
+        with:
+          submodules: recursive
+      - uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: ${{matrix.rust}}
+          components: rustfmt
+      # The `{ sharedKey: ... }` allows different actions to share the cache.
+      - uses: Swatinem/rust-cache@v1
+        with: { sharedKey: fullBuild }
+      # For operating systems that have it packaged, install creduce
+      - name: Install creduce (Linux)
+        if: matrix.os == ''
+        run: sudo apt-get install creduce
+      - name: Install creduce (MacOS)
+        if: matrix.os == 'macOS'
+        run: brew install creduce
+      - name: Set LIBCLANG_PATH (Windows)
+        # Windows github action doesn't set the path for clang, so set it
+        # See https://github.com/rust-lang/rust-bindgen/issues/1797
+        if: matrix.os == 'windows'
+        run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV
+      - name: Exclude failing targets and tests
+        # no creduce on Windows, so exclude tests needing creduce there
+        run: |
+          echo RUSTFLAGS=$RUSTFLAGS >> $GITHUB_ENV
+          echo ::set-output name=exclude::${{runner.os == 'Windows' && '--exclude autocxx-reduce --exclude autocxx-gen' || ''}}
+        env:
+          # non-linux failures https://github.com/google/autocxx/issues/819
+          # beta failing tests https://github.com/google/autocxx/issues/818
+          RUSTFLAGS: ${{matrix.name == 'Windows (msvc)' && '--cfg skip_windows_msvc_failing_tests' || ''}} ${{matrix.name == 'Windows (gnu)' && '--cfg skip_windows_gnu_failing_tests' || ''}}
+        id: testsuite
+        shell: bash
+      - run: cargo test --workspace ${{steps.testsuite.outputs.exclude}}
+
+  examples:
+    name: Examples ${{matrix.name || format('Rust {0}', matrix.rust)}}
+    runs-on: ${{matrix.os || 'ubuntu'}}-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - rust: nightly
+          - rust: beta
+          - rust: stable
+          - name: macOS
+            rust: nightly
+            os: macos
+          - name: Windows (gnu)
+            rust: nightly-x86_64-pc-windows-gnu
+            os: windows
+          - name: Windows (msvc)
+            rust: nightly-x86_64-pc-windows-msvc
+            os: windows
+            flags: /EHsc
+    env:
+      CXXFLAGS: ${{matrix.flags}}
+      RUSTFLAGS: --cfg deny_warnings -Dwarnings
+    steps:
+      - uses: actions/checkout@v2
+        with:
+          submodules: recursive
+      - uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: ${{matrix.rust}}
+          components: rustfmt
+      - uses: Swatinem/rust-cache@v1
+        with: { sharedKey: fullBuild }
+      - name: Set LIBCLANG_PATH (Windows)
+        # Windows github action doesn't set the path for clang, so set it
+        # See https://github.com/rust-lang/rust-bindgen/issues/1797
+        if: matrix.os == 'windows'
+        run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV
+      - name: Build s2 example
+        working-directory: ./examples/s2
+        # s2 doesn't link on Windows
+        if: matrix.os != 'windows'
+        run: cargo build
+      - name: Build steam example
+        working-directory: ./examples/steam-mini
+        run: cargo build
+      - name: Build subclass example
+        working-directory: ./examples/subclass
+        run: cargo build
+      - name: Build pod example
+        working-directory: ./examples/pod
+        run: cargo build
+      - name: Build chromium render-frame-host example
+        working-directory: ./examples/chromium-fake-render-frame-host
+        # chromium-fake-render-frame-host doesn't link on Windows
+        if: matrix.os != 'windows'
+        run: cargo build
+      - name: Build non-trivial-type-on-stack example
+        working-directory: ./examples/non-trivial-type-on-stack
+        run: cargo build
+        # We do not build the LLVM example because even 'apt-get install llvm-13-dev'
+        # does not work to install the LLVM 13 headers.
+
+  sanitizer:
+    name: Address Sanitizer
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      # Need nightly rust.
+      - uses: hecrj/setup-rust-action@v1
+        with:
+          rust-version: nightly
+          components: rust-src
+      - uses: Swatinem/rust-cache@v1
+      - name: Tests with asan
+        env:
+          AUTOCXX_ASAN: 1
+          RUSTFLAGS: -Zsanitizer=address -Cdebuginfo=0
+          RUSTDOCFLAGS: -Zsanitizer=address
+          ASAN_OPTIONS: "detect_stack_use_after_return=1:detect_leaks=0"
+          # Work around https://github.com/rust-lang/rust/issues/59125 by
+          # disabling backtraces. In an ideal world we'd probably suppress the
+          # leak sanitization, but we don't care about backtraces here, so long
+          # as the other tests have them.
+          RUST_BACKTRACE: "0"
+        run: cargo -Z build-std test --workspace --target x86_64-unknown-linux-gnu
+
+  # Clippy check
+  clippy:
+    name: Clippy
+    runs-on: ubuntu-latest
+    env:
+      CARGO_TERM_COLOR: always
+    steps:
+      - uses: actions/checkout@v2
+      - uses: hecrj/setup-rust-action@v1
+        with:
+          components: clippy
+      - uses: Swatinem/rust-cache@v1
+      - run: cargo clippy --workspace --tests -- -Dclippy::all
+
+  # Mention outdated dependencies
+  outdated:
+    name: Outdated
+    runs-on: ubuntu-latest
+    env:
+      CARGO_TERM_COLOR: always
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/install@cargo-outdated
+      - run: cargo outdated -R -w
+
+  # Check rustfmt is good
+  fmt:
+    name: Format
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: hecrj/setup-rust-action@v1
+        with:
+          components: rustfmt
+      - run: cargo fmt --all -- --check
+
+  # Detect cases where documentation links don't resolve and such.
+  doc:
+    name: Docs
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: hecrj/setup-rust-action@v1
+      - uses: Swatinem/rust-cache@v1
+        with: { sharedKey: fullBuild }
+      - run: |
+          for package in $(cargo metadata --no-deps --format-version=1 | jq -r '.packages[] | .name'); do
+            cargo rustdoc --color always -p "$package" -- -D warnings
+          done
+        env: { RUSTDOCFLAGS: -Dwarnings }
diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
new file mode 100644
index 0000000..0dd4237
--- /dev/null
+++ b/.github/workflows/site.yml
@@ -0,0 +1,43 @@
+name: github pages
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+
+jobs:
+  deploy:
+    runs-on: ubuntu-20.04
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Build preprocessor
+        run: cargo build
+        working-directory: tools/mdbook-preprocessor
+
+      - name: Setup mdBook
+        uses: peaceiris/actions-mdbook@v1
+        with:
+          mdbook-version: 'latest'
+
+      - name: Install mdbook-linkcheck
+        run: cargo install mdbook-linkcheck
+    
+      - name: Install mdbook-mermaid
+        run: |
+          curl -LSfs https://japaric.github.io/trust/install.sh | \
+            sh -s -- --git badboy/mdbook-mermaid
+    
+      - run: mdbook build
+        working-directory: book
+
+      - name: Deploy
+        uses: peaceiris/actions-gh-pages@v3
+        if: ${{ github.ref == 'refs/heads/main' }}
+        with:
+          github_token: ${{ secrets.GITHUB_TOKEN }}
+          publish_dir: ./book/build/html
+          #cname: autocxx.rs
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..af6bc43
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+target
+.vscode/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..642a67a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "examples/s2/s2geometry"]
+	path = examples/s2/s2geometry
+	url = https://github.com/google/s2geometry.git
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..a5bfc0a
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,1650 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
+
+[[package]]
+name = "aquamarine"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96e14cb2a51c8b45d26a4219981985c7350fc05eacb7b5b2939bceb2ffefdf3e"
+dependencies = [
+ "itertools 0.9.0",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "assert_cmd"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c98233c6673d8601ab23e77eb38f999c51100d46c5703b17288c57fddf3a1ffe"
+dependencies = [
+ "bstr",
+ "doc-comment",
+ "predicates",
+ "predicates-core",
+ "predicates-tree",
+ "wait-timeout",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "autocxx"
+version = "0.22.0"
+dependencies = [
+ "aquamarine",
+ "autocxx-macro",
+ "cxx",
+ "moveit",
+]
+
+[[package]]
+name = "autocxx-bindgen"
+version = "0.59.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435723e14bf88f198322f8555a4fdb108363021d97a47bb6492891ca86055e79"
+dependencies = [
+ "bitflags",
+ "cexpr",
+ "clang-sys",
+ "clap 2.34.0",
+ "env_logger 0.9.0",
+ "itertools 0.10.3",
+ "lazy_static",
+ "lazycell",
+ "log",
+ "peeking_take_while",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "which",
+]
+
+[[package]]
+name = "autocxx-build"
+version = "0.22.0"
+dependencies = [
+ "autocxx-engine",
+ "env_logger 0.9.0",
+ "indexmap",
+ "syn",
+]
+
+[[package]]
+name = "autocxx-demo"
+version = "0.22.0"
+dependencies = [
+ "autocxx",
+ "autocxx-build",
+ "cxx",
+ "miette",
+]
+
+[[package]]
+name = "autocxx-engine"
+version = "0.22.0"
+dependencies = [
+ "aquamarine",
+ "autocxx-bindgen",
+ "autocxx-parser",
+ "cc",
+ "cxx-gen",
+ "indexmap",
+ "indoc",
+ "itertools 0.10.3",
+ "log",
+ "miette",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "serde_json",
+ "strum_macros",
+ "syn",
+ "tempfile",
+ "thiserror",
+ "version_check",
+]
+
+[[package]]
+name = "autocxx-gen"
+version = "0.22.0"
+dependencies = [
+ "assert_cmd",
+ "autocxx",
+ "autocxx-engine",
+ "autocxx-integration-tests",
+ "clap 3.1.9",
+ "cxx",
+ "env_logger 0.9.0",
+ "indexmap",
+ "itertools 0.10.3",
+ "miette",
+ "pathdiff",
+ "proc-macro2",
+ "tempdir",
+]
+
+[[package]]
+name = "autocxx-integration-tests"
+version = "0.22.0"
+dependencies = [
+ "autocxx",
+ "autocxx-engine",
+ "cc",
+ "cxx",
+ "env_logger 0.9.0",
+ "indoc",
+ "itertools 0.10.3",
+ "link-cplusplus",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "rust_info",
+ "syn",
+ "tempfile",
+ "test-log",
+ "trybuild",
+]
+
+[[package]]
+name = "autocxx-macro"
+version = "0.22.0"
+dependencies = [
+ "autocxx-parser",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "autocxx-mdbook-preprocessor"
+version = "0.22.0"
+dependencies = [
+ "anyhow",
+ "autocxx-integration-tests",
+ "clap 3.1.9",
+ "env_logger 0.9.0",
+ "gag",
+ "itertools 0.10.3",
+ "mdbook",
+ "proc-macro2",
+ "rayon",
+ "regex",
+ "serde_json",
+ "syn",
+]
+
+[[package]]
+name = "autocxx-parser"
+version = "0.22.0"
+dependencies = [
+ "indexmap",
+ "itertools 0.10.3",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_json",
+ "syn",
+ "thiserror",
+]
+
+[[package]]
+name = "autocxx-reduce"
+version = "0.22.0"
+dependencies = [
+ "assert_cmd",
+ "autocxx-engine",
+ "autocxx-parser",
+ "clap 3.1.9",
+ "cxx-gen",
+ "indexmap",
+ "indoc",
+ "itertools 0.10.3",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "syn",
+ "tempdir",
+ "tempfile",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "block-buffer"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
+dependencies = [
+ "block-padding",
+ "byte-tools",
+ "byteorder",
+ "generic-array",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
+dependencies = [
+ "byte-tools",
+]
+
+[[package]]
+name = "bstr"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
+dependencies = [
+ "lazy_static",
+ "memchr",
+ "regex-automata",
+]
+
+[[package]]
+name = "byte-tools"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cc"
+version = "1.0.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+
+[[package]]
+name = "cexpr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
+dependencies = [
+ "libc",
+ "num-integer",
+ "num-traits",
+ "time",
+ "winapi",
+]
+
+[[package]]
+name = "clang-sys"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
+[[package]]
+name = "clap"
+version = "2.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim 0.8.0",
+ "textwrap 0.11.0",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "clap"
+version = "3.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6aad2534fad53df1cc12519c5cda696dd3e20e6118a027e24054aea14a0bdcbe"
+dependencies = [
+ "atty",
+ "bitflags",
+ "clap_lex",
+ "indexmap",
+ "lazy_static",
+ "strsim 0.10.0",
+ "termcolor",
+ "textwrap 0.15.0",
+]
+
+[[package]]
+name = "clap_complete"
+version = "3.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
+dependencies = [
+ "clap 3.1.9",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669"
+dependencies = [
+ "os_str_bytes",
+]
+
+[[package]]
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+dependencies = [
+ "termcolor",
+ "unicode-width",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "lazy_static",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
+dependencies = [
+ "cfg-if",
+ "lazy_static",
+]
+
+[[package]]
+name = "cxx"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce2295fe8865279f404147e9b2328e5af0ad11a2c016e58c13acfd48a07d8a55"
+dependencies = [
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-gen"
+version = "0.7.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bba249c8ea90cff9c647cd76928efc82f1e8684da0a6cedb4416cc79478050d"
+dependencies = [
+ "codespan-reporting",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a670224c6686471df12560a0b97a08145082e70bd38e2b0b5383b79e46c3da7"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b700096ca0dece28d9535fdb17ab784a8ae155d7f29d39c273643e6292c9620"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "difflib"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
+
+[[package]]
+name = "digest"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "doc-comment"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "env_logger"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
+dependencies = [
+ "atty",
+ "humantime 1.3.0",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
+dependencies = [
+ "atty",
+ "humantime 2.1.0",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "fake-simd"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
+
+[[package]]
+name = "fastrand"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "filedescriptor"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e"
+dependencies = [
+ "libc",
+ "thiserror",
+ "winapi",
+]
+
+[[package]]
+name = "fuchsia-cprng"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
+
+[[package]]
+name = "gag"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a713bee13966e9fbffdf7193af71d54a6b35a0bb34997cd6c9519ebeb5005972"
+dependencies = [
+ "filedescriptor",
+ "tempfile",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "gimli"
+version = "0.26.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "handlebars"
+version = "4.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d6a30320f094710245150395bc763ad23128d6a1ebbad7594dc4164b62c56b"
+dependencies = [
+ "log",
+ "pest",
+ "pest_derive",
+ "quick-error 2.0.1",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
+name = "heck"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "humantime"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+dependencies = [
+ "quick-error 1.2.3",
+]
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "indexmap"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+ "serde",
+]
+
+[[package]]
+name = "indoc"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7906a9fababaeacb774f72410e497a1d18de916322e33797bb2cd29baa23c9e"
+dependencies = [
+ "unindent",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "is_ci"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
+
+[[package]]
+name = "itertools"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "libc"
+version = "0.2.123"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb691a747a7ab48abc15c5b42066eaafde10dc427e3b6ee2a1cf43db04c763bd"
+
+[[package]]
+name = "libloading"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+dependencies = [
+ "cfg-if",
+ "winapi",
+]
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cae2cd7ba2f3f63938b9c724475dfb7b9861b545a90324476324ed21dbc8c8"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "log"
+version = "0.4.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "maplit"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+
+[[package]]
+name = "mdbook"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74612ae81a3e5ee509854049dfa4c7975ae033c06f5fc4735c7dfbe60ee2a39d"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "clap 3.1.9",
+ "clap_complete",
+ "env_logger 0.7.1",
+ "handlebars",
+ "lazy_static",
+ "log",
+ "memchr",
+ "opener",
+ "pulldown-cmark",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "shlex",
+ "tempfile",
+ "toml",
+ "topological-sort",
+]
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "memoffset"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "miette"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a097de91d72c13382f60213ed9f7f7a26afd8bee0ea320b47f886a9a67ca5a1"
+dependencies = [
+ "atty",
+ "backtrace",
+ "miette-derive",
+ "once_cell",
+ "owo-colors",
+ "supports-color",
+ "supports-hyperlinks",
+ "supports-unicode",
+ "terminal_size",
+ "textwrap 0.15.0",
+ "thiserror",
+ "unicode-width",
+]
+
+[[package]]
+name = "miette-derive"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45a95a48d0bc28f9af628286e8a4da09f96f34a97744a2e9a5a4db9814ad527d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+dependencies = [
+ "adler",
+ "autocfg",
+]
+
+[[package]]
+name = "moveit"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "815d5988a1dd22f08bad572a83ee654563bb422ece5d5bce41f31ec49399dcb5"
+dependencies = [
+ "cxx",
+]
+
+[[package]]
+name = "nom"
+version = "7.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
+
+[[package]]
+name = "opaque-debug"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
+
+[[package]]
+name = "opener"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952"
+dependencies = [
+ "bstr",
+ "winapi",
+]
+
+[[package]]
+name = "os_str_bytes"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
+
+[[package]]
+name = "owo-colors"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e72e30578e0d0993c8ae20823dd9cff2bc5517d2f586a8aef462a581e8a03eb"
+
+[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
+name = "peeking_take_while"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
+
+[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
+dependencies = [
+ "maplit",
+ "pest",
+ "sha-1",
+]
+
+[[package]]
+name = "predicates"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c"
+dependencies = [
+ "difflib",
+ "itertools 0.10.3",
+ "predicates-core",
+]
+
+[[package]]
+name = "predicates-core"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb"
+
+[[package]]
+name = "predicates-tree"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032"
+dependencies = [
+ "predicates-core",
+ "termtree",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "pulldown-cmark"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
+dependencies = [
+ "bitflags",
+ "memchr",
+ "unicase",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quick-error"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
+
+[[package]]
+name = "quote"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
+dependencies = [
+ "fuchsia-cprng",
+ "libc",
+ "rand_core 0.3.1",
+ "rdrand",
+ "winapi",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
+dependencies = [
+ "rand_core 0.4.2",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
+
+[[package]]
+name = "rayon"
+version = "1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221"
+dependencies = [
+ "autocfg",
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "rdrand"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
+dependencies = [
+ "rand_core 0.3.1",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "rust_info"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "821495e93d15e4433347b3a72e97005f1d8a620dc88d46637fecfcb16e98043d"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "rustversion"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
+
+[[package]]
+name = "ryu"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "serde"
+version = "1.0.136"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.136"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha-1"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
+dependencies = [
+ "block-buffer",
+ "digest",
+ "fake-simd",
+ "opaque-debug",
+]
+
+[[package]]
+name = "shlex"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
+
+[[package]]
+name = "smawk"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "strum_macros"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
+[[package]]
+name = "supports-color"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4872ced36b91d47bae8a214a683fe54e7078875b399dfa251df346c9b547d1f9"
+dependencies = [
+ "atty",
+ "is_ci",
+]
+
+[[package]]
+name = "supports-hyperlinks"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "590b34f7c5f01ecc9d78dba4b3f445f31df750a67621cf31626f3b7441ce6406"
+dependencies = [
+ "atty",
+]
+
+[[package]]
+name = "supports-unicode"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8b945e45b417b125a8ec51f1b7df2f8df7920367700d1f98aedd21e5735f8b2"
+dependencies = [
+ "atty",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "tempdir"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
+dependencies = [
+ "rand",
+ "remove_dir_all",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "libc",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "terminal_size"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "termtree"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b"
+
+[[package]]
+name = "test-log"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4235dbf7ea878b3ef12dea20a59c134b405a66aafc4fc2c7b9935916e289e735"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
+dependencies = [
+ "smawk",
+ "unicode-linebreak",
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "time"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
+dependencies = [
+ "libc",
+ "wasi",
+ "winapi",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "topological-sort"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c"
+
+[[package]]
+name = "trybuild"
+version = "1.0.59"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "606ab3fe0065741fdbb51f64bcb6ba76f13fad49f1723030041826c631782764"
+dependencies = [
+ "glob",
+ "once_cell",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "termcolor",
+ "toml",
+]
+
+[[package]]
+name = "typenum"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
+
+[[package]]
+name = "unicase"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a52dcaab0c48d931f7cc8ef826fa51690a08e1ea55117ef26f89864f532383f"
+dependencies = [
+ "regex",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "unindent"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "514672a55d7380da379785a4d70ca8386c8883ff7eaae877be4d2081cebe73d8"
+
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "wait-timeout"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+
+[[package]]
+name = "which"
+version = "4.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
+dependencies = [
+ "either",
+ "lazy_static",
+ "libc",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..5c24af8
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,41 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx"
+version = "0.22.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+license = "MIT OR Apache-2.0"
+description = "Safe autogenerated interop between Rust and C++"
+repository = "https://github.com/google/autocxx"
+homepage = "https://autocxx.rs"
+edition = "2021"
+keywords = ["ffi"]
+categories = ["development-tools::ffi", "api-bindings"]
+exclude = [ ".github", "book", "tools" ]
+
+# This is stricter about avoiding optional features in dependencies
+# such as 'syn'. We build this way such that CI spots any mistakes
+# where we are depending on such features.
+resolver = "2"
+
+[dependencies]
+autocxx-macro = { path="macro", version="0.22.0" }
+cxx = "1.0.54" # ... also needed because expansion of type_id refers to ::cxx
+aquamarine = "0.1" # docs
+moveit = { version = "0.5", features = [ "cxx" ] }
+
+[workspace]
+members = ["parser", "engine", "gen/cmd", "gen/build", "macro", "demo", "tools/reduce", "tools/mdbook-preprocessor", "integration-tests"]
+exclude = ["examples/s2", "examples/steam-mini", "examples/subclass", "examples/chromium-fake-render-frame-host", "examples/pod", "examples/non-trivial-type-on-stack", "examples/llvm", "tools/stress-test"]
+
+#[patch.crates-io]
+#cxx = { path="../cxx" }
+#cxx-gen = { path="../cxx/gen/lib" }
+#autocxx-bindgen = { path="../bindgen" }
+#moveit = { path="../moveit" }
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..31aa793
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..99a68b4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,37 @@
+# Autocxx
+
+[![GitHub](https://img.shields.io/crates/l/autocxx)](https://github.com/google/autocxx)
+[![crates.io](https://img.shields.io/crates/d/autocxx)](https://crates.io/crates/autocxx)
+[![docs.rs](https://docs.rs/autocxx/badge.svg)](https://docs.rs/autocxx)
+
+This project is a tool for calling C++ from Rust in a heavily automated, but safe, fashion.
+
+The intention is that it has all the fluent safety from [cxx](https://cxx.rs) whilst generating interfaces automatically from existing C++ headers using a variant of [bindgen](https://docs.rs/bindgen/latest/bindgen/). Think of autocxx as glue which plugs bindgen into cxx.
+
+For full documentation, see [the manual](https://google.github.io/autocxx/).
+
+# Overview
+
+```rust,ignore
+autocxx::include_cpp! {
+    #include "url/origin.h"
+    generate!("url::Origin")
+    safety!(unsafe_ffi)
+}
+
+fn main() {
+    let o = ffi::url::Origin::CreateFromNormalizedTuple("https",
+        "google.com", 443);
+    let uri = o.Serialize();
+    println!("URI is {}", uri.to_str().unwrap());
+}
+```
+
+#### License and usage notes
+
+This is not an officially supported Google product.
+
+<sup>
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+</sup>
diff --git a/book/.gitignore b/book/.gitignore
new file mode 100644
index 0000000..378eac2
--- /dev/null
+++ b/book/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/book/README.md b/book/README.md
new file mode 100644
index 0000000..c883a45
--- /dev/null
+++ b/book/README.md
@@ -0,0 +1,10 @@
+Published automatically to https://autocxx.rs from master branch.
+
+To build and view locally:
+
+- Install [mdBook] and some preprocessors: `cargo install mdbook mdbook-mermaid mdbook-linkcheck`.
+- Build our custom preprocessor: run `cargo build` in `tools/mdbook-preprocessor`
+- Run `mdbook build` in this directory.
+- Open the generated *build/html/index.html*.
+
+[mdBook]: https://github.com/rust-lang/mdBook
diff --git a/book/book.toml b/book/book.toml
new file mode 100644
index 0000000..b557cc6
--- /dev/null
+++ b/book/book.toml
@@ -0,0 +1,25 @@
+[book]
+title = "Rust ♡ Existing C++"
+authors = ["Adrian Taylor"]
+description = "autocxx — safe interop between Rust and existing C++"
+
+[rust]
+edition = "2018"
+
+[build]
+build-dir = "build"
+create-missing = false
+
+[preprocessor.autocxx]
+command = "../target/debug/autocxx-mdbook-preprocessor"
+
+[preprocessor.mermaid]
+command = "mdbook-mermaid"
+
+[output.html]
+cname = "google.github.io/autocxx"
+git-repository-url = "https://github.com/google/autocxx"
+additional-js = ["mermaid.min.js", "mermaid-init.js"]
+
+[output.linkcheck]
+warning-policy = "error"
diff --git a/book/mermaid-init.js b/book/mermaid-init.js
new file mode 100644
index 0000000..313a6e8
--- /dev/null
+++ b/book/mermaid-init.js
@@ -0,0 +1 @@
+mermaid.initialize({startOnLoad:true});
diff --git a/book/mermaid.min.js b/book/mermaid.min.js
new file mode 100644
index 0000000..d45942f
--- /dev/null
+++ b/book/mermaid.min.js
@@ -0,0 +1,4 @@
+/* MIT Licensed. Copyright (c) 2014 - 2021 Knut Sveidqvist */
+/*! For license information please see https://github.com/mermaid-js/mermaid/blob/8.13.10/LICENSE */
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.mermaid=e():t.mermaid=e()}("undefined"!=typeof self?self:this,(function(){return(()=>{var t={1362:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,6],n=[1,7],r=[1,8],i=[1,9],a=[1,12],o=[1,11],s=[1,15,24],c=[1,19],u=[1,31],l=[1,34],h=[1,32],f=[1,33],d=[1,35],p=[1,36],y=[1,37],g=[1,38],m=[1,41],v=[1,42],b=[1,43],_=[1,44],x=[15,24],w=[1,56],k=[1,57],T=[1,58],E=[1,59],C=[1,60],S=[1,61],A=[15,24,31,38,39,47,50,51,52,53,54,55,60,62],M=[15,24,29,31,38,39,43,47,50,51,52,53,54,55,60,62,77,78,79,80],N=[7,8,9,10,15,18,22,24],D=[47,77,78,79,80],O=[47,54,55,77,78,79,80],B=[47,50,51,52,53,77,78,79,80],L=[15,24,31],I=[1,93],R={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,direction:5,directive:6,direction_tb:7,direction_bt:8,direction_rl:9,direction_lr:10,graphConfig:11,openDirective:12,typeDirective:13,closeDirective:14,NEWLINE:15,":":16,argDirective:17,open_directive:18,type_directive:19,arg_directive:20,close_directive:21,CLASS_DIAGRAM:22,statements:23,EOF:24,statement:25,className:26,alphaNumToken:27,classLiteralName:28,GENERICTYPE:29,relationStatement:30,LABEL:31,classStatement:32,methodStatement:33,annotationStatement:34,clickStatement:35,cssClassStatement:36,CLASS:37,STYLE_SEPARATOR:38,STRUCT_START:39,members:40,STRUCT_STOP:41,ANNOTATION_START:42,ANNOTATION_END:43,MEMBER:44,SEPARATOR:45,relation:46,STR:47,relationType:48,lineType:49,AGGREGATION:50,EXTENSION:51,COMPOSITION:52,DEPENDENCY:53,LINE:54,DOTTED_LINE:55,CALLBACK:56,LINK:57,LINK_TARGET:58,CLICK:59,CALLBACK_NAME:60,CALLBACK_ARGS:61,HREF:62,CSSCLASS:63,commentToken:64,textToken:65,graphCodeTokens:66,textNoTagsToken:67,TAGSTART:68,TAGEND:69,"==":70,"--":71,PCT:72,DEFAULT:73,SPACE:74,MINUS:75,keywords:76,UNICODE_TEXT:77,NUM:78,ALPHA:79,BQUOTE_STR:80,$accept:0,$end:1},terminals_:{2:"error",7:"direction_tb",8:"direction_bt",9:"direction_rl",10:"direction_lr",15:"NEWLINE",16:":",18:"open_directive",19:"type_directive",20:"arg_directive",21:"close_directive",22:"CLASS_DIAGRAM",24:"EOF",29:"GENERICTYPE",31:"LABEL",37:"CLASS",38:"STYLE_SEPARATOR",39:"STRUCT_START",41:"STRUCT_STOP",42:"ANNOTATION_START",43:"ANNOTATION_END",44:"MEMBER",45:"SEPARATOR",47:"STR",50:"AGGREGATION",51:"EXTENSION",52:"COMPOSITION",53:"DEPENDENCY",54:"LINE",55:"DOTTED_LINE",56:"CALLBACK",57:"LINK",58:"LINK_TARGET",59:"CLICK",60:"CALLBACK_NAME",61:"CALLBACK_ARGS",62:"HREF",63:"CSSCLASS",66:"graphCodeTokens",68:"TAGSTART",69:"TAGEND",70:"==",71:"--",72:"PCT",73:"DEFAULT",74:"SPACE",75:"MINUS",76:"keywords",77:"UNICODE_TEXT",78:"NUM",79:"ALPHA",80:"BQUOTE_STR"},productions_:[0,[3,1],[3,1],[3,2],[5,1],[5,1],[5,1],[5,1],[4,1],[6,4],[6,6],[12,1],[13,1],[17,1],[14,1],[11,4],[23,1],[23,2],[23,3],[26,1],[26,1],[26,2],[26,2],[26,2],[25,1],[25,2],[25,1],[25,1],[25,1],[25,1],[25,1],[25,1],[25,1],[32,2],[32,4],[32,5],[32,7],[34,4],[40,1],[40,2],[33,1],[33,2],[33,1],[33,1],[30,3],[30,4],[30,4],[30,5],[46,3],[46,2],[46,2],[46,1],[48,1],[48,1],[48,1],[48,1],[49,1],[49,1],[35,3],[35,4],[35,3],[35,4],[35,4],[35,5],[35,3],[35,4],[35,4],[35,5],[35,3],[35,4],[35,4],[35,5],[36,3],[64,1],[64,1],[65,1],[65,1],[65,1],[65,1],[65,1],[65,1],[65,1],[67,1],[67,1],[67,1],[67,1],[27,1],[27,1],[27,1],[28,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:r.setDirection("TB");break;case 5:r.setDirection("BT");break;case 6:r.setDirection("RL");break;case 7:r.setDirection("LR");break;case 11:r.parseDirective("%%{","open_directive");break;case 12:r.parseDirective(a[s],"type_directive");break;case 13:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 14:r.parseDirective("}%%","close_directive","class");break;case 19:case 20:this.$=a[s];break;case 21:this.$=a[s-1]+a[s];break;case 22:case 23:this.$=a[s-1]+"~"+a[s];break;case 24:r.addRelation(a[s]);break;case 25:a[s-1].title=r.cleanupLabel(a[s]),r.addRelation(a[s-1]);break;case 33:r.addClass(a[s]);break;case 34:r.addClass(a[s-2]),r.setCssClass(a[s-2],a[s]);break;case 35:r.addClass(a[s-3]),r.addMembers(a[s-3],a[s-1]);break;case 36:r.addClass(a[s-5]),r.setCssClass(a[s-5],a[s-3]),r.addMembers(a[s-5],a[s-1]);break;case 37:r.addAnnotation(a[s],a[s-2]);break;case 38:this.$=[a[s]];break;case 39:a[s].push(a[s-1]),this.$=a[s];break;case 40:case 42:case 43:break;case 41:r.addMember(a[s-1],r.cleanupLabel(a[s]));break;case 44:this.$={id1:a[s-2],id2:a[s],relation:a[s-1],relationTitle1:"none",relationTitle2:"none"};break;case 45:this.$={id1:a[s-3],id2:a[s],relation:a[s-1],relationTitle1:a[s-2],relationTitle2:"none"};break;case 46:this.$={id1:a[s-3],id2:a[s],relation:a[s-2],relationTitle1:"none",relationTitle2:a[s-1]};break;case 47:this.$={id1:a[s-4],id2:a[s],relation:a[s-2],relationTitle1:a[s-3],relationTitle2:a[s-1]};break;case 48:this.$={type1:a[s-2],type2:a[s],lineType:a[s-1]};break;case 49:this.$={type1:"none",type2:a[s],lineType:a[s-1]};break;case 50:this.$={type1:a[s-1],type2:"none",lineType:a[s]};break;case 51:this.$={type1:"none",type2:"none",lineType:a[s]};break;case 52:this.$=r.relationType.AGGREGATION;break;case 53:this.$=r.relationType.EXTENSION;break;case 54:this.$=r.relationType.COMPOSITION;break;case 55:this.$=r.relationType.DEPENDENCY;break;case 56:this.$=r.lineType.LINE;break;case 57:this.$=r.lineType.DOTTED_LINE;break;case 58:case 64:this.$=a[s-2],r.setClickEvent(a[s-1],a[s]);break;case 59:case 65:this.$=a[s-3],r.setClickEvent(a[s-2],a[s-1]),r.setTooltip(a[s-2],a[s]);break;case 60:case 68:this.$=a[s-2],r.setLink(a[s-1],a[s]);break;case 61:case 69:this.$=a[s-3],r.setLink(a[s-2],a[s-1],a[s]);break;case 62:case 70:this.$=a[s-3],r.setLink(a[s-2],a[s-1]),r.setTooltip(a[s-2],a[s]);break;case 63:case 71:this.$=a[s-4],r.setLink(a[s-3],a[s-2],a[s]),r.setTooltip(a[s-3],a[s-1]);break;case 66:this.$=a[s-3],r.setClickEvent(a[s-2],a[s-1],a[s]);break;case 67:this.$=a[s-4],r.setClickEvent(a[s-3],a[s-2],a[s-1]),r.setTooltip(a[s-3],a[s]);break;case 72:r.setCssClass(a[s-1],a[s])}},table:[{3:1,4:2,5:3,6:4,7:e,8:n,9:r,10:i,11:5,12:10,18:a,22:o},{1:[3]},{1:[2,1]},{1:[2,2]},{3:13,4:2,5:3,6:4,7:e,8:n,9:r,10:i,11:5,12:10,18:a,22:o},{1:[2,8]},t(s,[2,4]),t(s,[2,5]),t(s,[2,6]),t(s,[2,7]),{13:14,19:[1,15]},{15:[1,16]},{19:[2,11]},{1:[2,3]},{14:17,16:[1,18],21:c},t([16,21],[2,12]),{5:29,6:28,7:e,8:n,9:r,10:i,12:10,18:a,23:20,25:21,26:30,27:39,28:40,30:22,32:23,33:24,34:25,35:26,36:27,37:u,42:l,44:h,45:f,56:d,57:p,59:y,63:g,77:m,78:v,79:b,80:_},{15:[1,45]},{17:46,20:[1,47]},{15:[2,14]},{24:[1,48]},{15:[1,49],24:[2,16]},t(x,[2,24],{31:[1,50]}),t(x,[2,26]),t(x,[2,27]),t(x,[2,28]),t(x,[2,29]),t(x,[2,30]),t(x,[2,31]),t(x,[2,32]),t(x,[2,40],{46:51,48:54,49:55,31:[1,53],47:[1,52],50:w,51:k,52:T,53:E,54:C,55:S}),{26:62,27:39,28:40,77:m,78:v,79:b,80:_},t(x,[2,42]),t(x,[2,43]),{27:63,77:m,78:v,79:b},{26:64,27:39,28:40,77:m,78:v,79:b,80:_},{26:65,27:39,28:40,77:m,78:v,79:b,80:_},{26:66,27:39,28:40,77:m,78:v,79:b,80:_},{47:[1,67]},t(A,[2,19],{27:39,28:40,26:68,29:[1,69],77:m,78:v,79:b,80:_}),t(A,[2,20],{29:[1,70]}),t(M,[2,86]),t(M,[2,87]),t(M,[2,88]),t([15,24,29,31,38,39,47,50,51,52,53,54,55,60,62],[2,89]),t(N,[2,9]),{14:71,21:c},{21:[2,13]},{1:[2,15]},{5:29,6:28,7:e,8:n,9:r,10:i,12:10,18:a,23:72,24:[2,17],25:21,26:30,27:39,28:40,30:22,32:23,33:24,34:25,35:26,36:27,37:u,42:l,44:h,45:f,56:d,57:p,59:y,63:g,77:m,78:v,79:b,80:_},t(x,[2,25]),{26:73,27:39,28:40,47:[1,74],77:m,78:v,79:b,80:_},{46:75,48:54,49:55,50:w,51:k,52:T,53:E,54:C,55:S},t(x,[2,41]),{49:76,54:C,55:S},t(D,[2,51],{48:77,50:w,51:k,52:T,53:E}),t(O,[2,52]),t(O,[2,53]),t(O,[2,54]),t(O,[2,55]),t(B,[2,56]),t(B,[2,57]),t(x,[2,33],{38:[1,78],39:[1,79]}),{43:[1,80]},{47:[1,81]},{47:[1,82]},{60:[1,83],62:[1,84]},{27:85,77:m,78:v,79:b},t(A,[2,21]),t(A,[2,22]),t(A,[2,23]),{15:[1,86]},{24:[2,18]},t(L,[2,44]),{26:87,27:39,28:40,77:m,78:v,79:b,80:_},{26:88,27:39,28:40,47:[1,89],77:m,78:v,79:b,80:_},t(D,[2,50],{48:90,50:w,51:k,52:T,53:E}),t(D,[2,49]),{27:91,77:m,78:v,79:b},{40:92,44:I},{26:94,27:39,28:40,77:m,78:v,79:b,80:_},t(x,[2,58],{47:[1,95]}),t(x,[2,60],{47:[1,97],58:[1,96]}),t(x,[2,64],{47:[1,98],61:[1,99]}),t(x,[2,68],{47:[1,101],58:[1,100]}),t(x,[2,72]),t(N,[2,10]),t(L,[2,46]),t(L,[2,45]),{26:102,27:39,28:40,77:m,78:v,79:b,80:_},t(D,[2,48]),t(x,[2,34],{39:[1,103]}),{41:[1,104]},{40:105,41:[2,38],44:I},t(x,[2,37]),t(x,[2,59]),t(x,[2,61]),t(x,[2,62],{58:[1,106]}),t(x,[2,65]),t(x,[2,66],{47:[1,107]}),t(x,[2,69]),t(x,[2,70],{58:[1,108]}),t(L,[2,47]),{40:109,44:I},t(x,[2,35]),{41:[2,39]},t(x,[2,63]),t(x,[2,67]),t(x,[2,71]),{41:[1,110]},t(x,[2,36])],defaultActions:{2:[2,1],3:[2,2],5:[2,8],12:[2,11],13:[2,3],19:[2,14],47:[2,13],48:[2,15],72:[2,18],105:[2,39]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},F={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),18;case 1:return 7;case 2:return 8;case 3:return 9;case 4:return 10;case 5:return this.begin("type_directive"),19;case 6:return this.popState(),this.begin("arg_directive"),16;case 7:return this.popState(),this.popState(),21;case 8:return 20;case 9:case 10:case 12:case 19:break;case 11:return 15;case 13:case 14:return 22;case 15:return this.begin("struct"),39;case 16:return"EOF_IN_STRUCT";case 17:return"OPEN_IN_STRUCT";case 18:return this.popState(),41;case 20:return"MEMBER";case 21:return 37;case 22:return 63;case 23:return 56;case 24:return 57;case 25:return 59;case 26:return 42;case 27:return 43;case 28:this.begin("generic");break;case 29:case 32:case 35:case 38:case 41:case 44:this.popState();break;case 30:return"GENERICTYPE";case 31:this.begin("string");break;case 33:return"STR";case 34:this.begin("bqstring");break;case 36:return"BQUOTE_STR";case 37:this.begin("href");break;case 39:return 62;case 40:this.begin("callback_name");break;case 42:this.popState(),this.begin("callback_args");break;case 43:return 60;case 45:return 61;case 46:case 47:case 48:case 49:return 58;case 50:case 51:return 51;case 52:case 53:return 53;case 54:return 52;case 55:return 50;case 56:return 54;case 57:return 55;case 58:return 31;case 59:return 38;case 60:return 75;case 61:return"DOT";case 62:return"PLUS";case 63:return 72;case 64:case 65:return"EQUALS";case 66:return 79;case 67:return"PUNCTUATION";case 68:return 78;case 69:return 77;case 70:return 74;case 71:return 24}},rules:[/^(?:%%\{)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:((?:(?!\}%%)[^:.])*))/,/^(?::)/,/^(?:\}%%)/,/^(?:((?:(?!\}%%).|\n)*))/,/^(?:%%(?!\{)*[^\n]*(\r?\n?)+)/,/^(?:%%[^\n]*(\r?\n)*)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:classDiagram-v2\b)/,/^(?:classDiagram\b)/,/^(?:[{])/,/^(?:$)/,/^(?:[{])/,/^(?:[}])/,/^(?:[\n])/,/^(?:[^{}\n]*)/,/^(?:class\b)/,/^(?:cssClass\b)/,/^(?:callback\b)/,/^(?:link\b)/,/^(?:click\b)/,/^(?:<<)/,/^(?:>>)/,/^(?:[~])/,/^(?:[~])/,/^(?:[^~]*)/,/^(?:["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:[`])/,/^(?:[`])/,/^(?:[^`]+)/,/^(?:href[\s]+["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:\s*<\|)/,/^(?:\s*\|>)/,/^(?:\s*>)/,/^(?:\s*<)/,/^(?:\s*\*)/,/^(?:\s*o\b)/,/^(?:--)/,/^(?:\.\.)/,/^(?::{1}[^:\n;]+)/,/^(?::{3})/,/^(?:-)/,/^(?:\.)/,/^(?:\+)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:\w+)/,/^(?:[!"#$%&'*+,-.`?\\/])/,/^(?:[0-9]+)/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\s)/,/^(?:$)/],conditions:{arg_directive:{rules:[7,8],inclusive:!1},type_directive:{rules:[6,7],inclusive:!1},open_directive:{rules:[5],inclusive:!1},callback_args:{rules:[44,45],inclusive:!1},callback_name:{rules:[41,42,43],inclusive:!1},href:{rules:[38,39],inclusive:!1},struct:{rules:[16,17,18,19,20],inclusive:!1},generic:{rules:[29,30],inclusive:!1},bqstring:{rules:[35,36],inclusive:!1},string:{rules:[32,33],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,9,10,11,12,13,14,15,21,22,23,24,25,26,27,28,31,34,37,40,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71],inclusive:!0}}};function P(){this.yy={}}return R.lexer=F,P.prototype=R,R.Parser=P,new P}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8218).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},5890:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,5],r=[6,9,11,23,41],i=[1,17],a=[1,20],o=[1,25],s=[1,26],c=[1,27],u=[1,28],l=[1,37],h=[23,38,39],f=[4,6,9,11,23,41],d=[34,35,36,37],p=[22,29],y=[1,55],g={trace:function(){},yy:{},symbols_:{error:2,start:3,ER_DIAGRAM:4,document:5,EOF:6,directive:7,line:8,SPACE:9,statement:10,NEWLINE:11,openDirective:12,typeDirective:13,closeDirective:14,":":15,argDirective:16,entityName:17,relSpec:18,role:19,BLOCK_START:20,attributes:21,BLOCK_STOP:22,ALPHANUM:23,attribute:24,attributeType:25,attributeName:26,attributeKeyType:27,attributeComment:28,ATTRIBUTE_WORD:29,ATTRIBUTE_KEY:30,COMMENT:31,cardinality:32,relType:33,ZERO_OR_ONE:34,ZERO_OR_MORE:35,ONE_OR_MORE:36,ONLY_ONE:37,NON_IDENTIFYING:38,IDENTIFYING:39,WORD:40,open_directive:41,type_directive:42,arg_directive:43,close_directive:44,$accept:0,$end:1},terminals_:{2:"error",4:"ER_DIAGRAM",6:"EOF",9:"SPACE",11:"NEWLINE",15:":",20:"BLOCK_START",22:"BLOCK_STOP",23:"ALPHANUM",29:"ATTRIBUTE_WORD",30:"ATTRIBUTE_KEY",31:"COMMENT",34:"ZERO_OR_ONE",35:"ZERO_OR_MORE",36:"ONE_OR_MORE",37:"ONLY_ONE",38:"NON_IDENTIFYING",39:"IDENTIFYING",40:"WORD",41:"open_directive",42:"type_directive",43:"arg_directive",44:"close_directive"},productions_:[0,[3,3],[3,2],[5,0],[5,2],[8,2],[8,1],[8,1],[8,1],[7,4],[7,6],[10,1],[10,5],[10,4],[10,3],[10,1],[17,1],[21,1],[21,2],[24,2],[24,3],[24,3],[24,4],[25,1],[26,1],[27,1],[28,1],[18,3],[32,1],[32,1],[32,1],[32,1],[33,1],[33,1],[19,1],[19,1],[12,1],[13,1],[16,1],[14,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 1:break;case 3:case 7:case 8:this.$=[];break;case 4:a[s-1].push(a[s]),this.$=a[s-1];break;case 5:case 6:case 16:case 23:case 24:case 25:case 35:this.$=a[s];break;case 12:r.addEntity(a[s-4]),r.addEntity(a[s-2]),r.addRelationship(a[s-4],a[s],a[s-2],a[s-3]);break;case 13:r.addEntity(a[s-3]),r.addAttributes(a[s-3],a[s-1]);break;case 14:r.addEntity(a[s-2]);break;case 15:r.addEntity(a[s]);break;case 17:this.$=[a[s]];break;case 18:a[s].push(a[s-1]),this.$=a[s];break;case 19:this.$={attributeType:a[s-1],attributeName:a[s]};break;case 20:this.$={attributeType:a[s-2],attributeName:a[s-1],attributeKeyType:a[s]};break;case 21:this.$={attributeType:a[s-2],attributeName:a[s-1],attributeComment:a[s]};break;case 22:this.$={attributeType:a[s-3],attributeName:a[s-2],attributeKeyType:a[s-1],attributeComment:a[s]};break;case 26:case 34:this.$=a[s].replace(/"/g,"");break;case 27:this.$={cardA:a[s],relType:a[s-1],cardB:a[s-2]};break;case 28:this.$=r.Cardinality.ZERO_OR_ONE;break;case 29:this.$=r.Cardinality.ZERO_OR_MORE;break;case 30:this.$=r.Cardinality.ONE_OR_MORE;break;case 31:this.$=r.Cardinality.ONLY_ONE;break;case 32:this.$=r.Identification.NON_IDENTIFYING;break;case 33:this.$=r.Identification.IDENTIFYING;break;case 36:r.parseDirective("%%{","open_directive");break;case 37:r.parseDirective(a[s],"type_directive");break;case 38:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 39:r.parseDirective("}%%","close_directive","er")}},table:[{3:1,4:e,7:3,12:4,41:n},{1:[3]},t(r,[2,3],{5:6}),{3:7,4:e,7:3,12:4,41:n},{13:8,42:[1,9]},{42:[2,36]},{6:[1,10],7:15,8:11,9:[1,12],10:13,11:[1,14],12:4,17:16,23:i,41:n},{1:[2,2]},{14:18,15:[1,19],44:a},t([15,44],[2,37]),t(r,[2,8],{1:[2,1]}),t(r,[2,4]),{7:15,10:21,12:4,17:16,23:i,41:n},t(r,[2,6]),t(r,[2,7]),t(r,[2,11]),t(r,[2,15],{18:22,32:24,20:[1,23],34:o,35:s,36:c,37:u}),t([6,9,11,15,20,23,34,35,36,37,41],[2,16]),{11:[1,29]},{16:30,43:[1,31]},{11:[2,39]},t(r,[2,5]),{17:32,23:i},{21:33,22:[1,34],24:35,25:36,29:l},{33:38,38:[1,39],39:[1,40]},t(h,[2,28]),t(h,[2,29]),t(h,[2,30]),t(h,[2,31]),t(f,[2,9]),{14:41,44:a},{44:[2,38]},{15:[1,42]},{22:[1,43]},t(r,[2,14]),{21:44,22:[2,17],24:35,25:36,29:l},{26:45,29:[1,46]},{29:[2,23]},{32:47,34:o,35:s,36:c,37:u},t(d,[2,32]),t(d,[2,33]),{11:[1,48]},{19:49,23:[1,51],40:[1,50]},t(r,[2,13]),{22:[2,18]},t(p,[2,19],{27:52,28:53,30:[1,54],31:y}),t([22,29,30,31],[2,24]),{23:[2,27]},t(f,[2,10]),t(r,[2,12]),t(r,[2,34]),t(r,[2,35]),t(p,[2,20],{28:56,31:y}),t(p,[2,21]),t([22,29,31],[2,25]),t(p,[2,26]),t(p,[2,22])],defaultActions:{5:[2,36],7:[2,2],20:[2,39],31:[2,38],37:[2,23],44:[2,18],47:[2,27]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},m={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),41;case 1:return this.begin("type_directive"),42;case 2:return this.popState(),this.begin("arg_directive"),15;case 3:return this.popState(),this.popState(),44;case 4:return 43;case 5:case 6:case 8:case 13:case 17:break;case 7:return 11;case 9:return 9;case 10:return 40;case 11:return 4;case 12:return this.begin("block"),20;case 14:return 30;case 15:return 29;case 16:return 31;case 18:return this.popState(),22;case 19:case 32:return e.yytext[0];case 20:case 24:return 34;case 21:case 25:return 35;case 22:case 26:return 36;case 23:return 37;case 27:case 29:case 30:return 38;case 28:return 39;case 31:return 23;case 33:return 6}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:[\s]+)/i,/^(?:"[^"]*")/i,/^(?:erDiagram\b)/i,/^(?:\{)/i,/^(?:\s+)/i,/^(?:(?:PK)|(?:FK))/i,/^(?:[A-Za-z][A-Za-z0-9\-_]*)/i,/^(?:"[^"]*")/i,/^(?:[\n]+)/i,/^(?:\})/i,/^(?:.)/i,/^(?:\|o\b)/i,/^(?:\}o\b)/i,/^(?:\}\|)/i,/^(?:\|\|)/i,/^(?:o\|)/i,/^(?:o\{)/i,/^(?:\|\{)/i,/^(?:\.\.)/i,/^(?:--)/i,/^(?:\.-)/i,/^(?:-\.)/i,/^(?:[A-Za-z][A-Za-z0-9\-_]*)/i,/^(?:.)/i,/^(?:$)/i],conditions:{open_directive:{rules:[1],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},block:{rules:[13,14,15,16,17,18,19],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,20,21,22,23,24,25,26,27,28,29,30,31,32,33],inclusive:!0}}};function v(){this.yy={}}return g.lexer=m,v.prototype=g,g.Parser=v,new v}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8009).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},3602:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,9],n=[1,7],r=[1,6],i=[1,8],a=[1,20,21,22,23,38,47,59,60,79,80,81,82,83,84,88,98,99,102,104,105,111,112,113,114,115,116,117,118,119,120],o=[2,10],s=[1,20],c=[1,21],u=[1,22],l=[1,23],h=[1,30],f=[1,59],d=[1,45],p=[1,49],y=[1,33],g=[1,34],m=[1,35],v=[1,36],b=[1,37],_=[1,53],x=[1,60],w=[1,48],k=[1,50],T=[1,52],E=[1,56],C=[1,57],S=[1,38],A=[1,39],M=[1,40],N=[1,41],D=[1,58],O=[1,47],B=[1,51],L=[1,54],I=[1,55],R=[1,46],F=[1,63],P=[1,68],j=[1,20,21,22,23,38,42,47,59,60,79,80,81,82,83,84,88,98,99,102,104,105,111,112,113,114,115,116,117,118,119,120],Y=[1,72],z=[1,71],U=[1,73],q=[20,21,23,74,75],H=[1,94],$=[1,99],W=[1,102],V=[1,103],G=[1,96],X=[1,101],Z=[1,104],Q=[1,97],K=[1,109],J=[1,108],tt=[1,98],et=[1,100],nt=[1,105],rt=[1,106],it=[1,107],at=[1,110],ot=[20,21,22,23,74,75],st=[20,21,22,23,48,74,75],ct=[20,21,22,23,40,47,48,50,52,54,56,58,59,60,62,64,66,67,69,74,75,84,88,98,99,102,104,105,115,116,117,118,119,120],ut=[20,21,23],lt=[20,21,23,47,59,60,74,75,84,88,98,99,102,104,105,115,116,117,118,119,120],ht=[1,12,20,21,22,23,24,38,42,47,59,60,79,80,81,82,83,84,88,98,99,102,104,105,111,112,113,114,115,116,117,118,119,120],ft=[47,59,60,84,88,98,99,102,104,105,115,116,117,118,119,120],dt=[1,143],pt=[1,151],yt=[1,152],gt=[1,153],mt=[1,154],vt=[1,138],bt=[1,139],_t=[1,135],xt=[1,146],wt=[1,147],kt=[1,148],Tt=[1,149],Et=[1,150],Ct=[1,155],St=[1,156],At=[1,141],Mt=[1,144],Nt=[1,140],Dt=[1,137],Ot=[20,21,22,23,38,42,47,59,60,79,80,81,82,83,84,88,98,99,102,104,105,111,112,113,114,115,116,117,118,119,120],Bt=[1,159],Lt=[20,21,22,23,26,47,59,60,84,98,99,102,104,105,115,116,117,118,119,120],It=[20,21,22,23,24,26,38,40,41,42,47,51,53,55,57,59,60,61,63,65,66,68,70,74,75,79,80,81,82,83,84,85,88,98,99,102,104,105,106,107,115,116,117,118,119,120],Rt=[12,21,22,24],Ft=[22,99],Pt=[1,242],jt=[1,237],Yt=[1,238],zt=[1,246],Ut=[1,243],qt=[1,240],Ht=[1,239],$t=[1,241],Wt=[1,244],Vt=[1,245],Gt=[1,247],Xt=[1,265],Zt=[20,21,23,99],Qt=[20,21,22,23,59,60,79,95,98,99,102,103,104,105,106],Kt={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,directive:5,openDirective:6,typeDirective:7,closeDirective:8,separator:9,":":10,argDirective:11,open_directive:12,type_directive:13,arg_directive:14,close_directive:15,graphConfig:16,document:17,line:18,statement:19,SEMI:20,NEWLINE:21,SPACE:22,EOF:23,GRAPH:24,NODIR:25,DIR:26,FirstStmtSeperator:27,ending:28,endToken:29,spaceList:30,spaceListNewline:31,verticeStatement:32,styleStatement:33,linkStyleStatement:34,classDefStatement:35,classStatement:36,clickStatement:37,subgraph:38,text:39,SQS:40,SQE:41,end:42,direction:43,link:44,node:45,vertex:46,AMP:47,STYLE_SEPARATOR:48,idString:49,PS:50,PE:51,"(-":52,"-)":53,STADIUMSTART:54,STADIUMEND:55,SUBROUTINESTART:56,SUBROUTINEEND:57,VERTEX_WITH_PROPS_START:58,ALPHA:59,COLON:60,PIPE:61,CYLINDERSTART:62,CYLINDEREND:63,DIAMOND_START:64,DIAMOND_STOP:65,TAGEND:66,TRAPSTART:67,TRAPEND:68,INVTRAPSTART:69,INVTRAPEND:70,linkStatement:71,arrowText:72,TESTSTR:73,START_LINK:74,LINK:75,textToken:76,STR:77,keywords:78,STYLE:79,LINKSTYLE:80,CLASSDEF:81,CLASS:82,CLICK:83,DOWN:84,UP:85,textNoTags:86,textNoTagsToken:87,DEFAULT:88,stylesOpt:89,alphaNum:90,CALLBACKNAME:91,CALLBACKARGS:92,HREF:93,LINK_TARGET:94,HEX:95,numList:96,INTERPOLATE:97,NUM:98,COMMA:99,style:100,styleComponent:101,MINUS:102,UNIT:103,BRKT:104,DOT:105,PCT:106,TAGSTART:107,alphaNumToken:108,idStringToken:109,alphaNumStatement:110,direction_tb:111,direction_bt:112,direction_rl:113,direction_lr:114,PUNCTUATION:115,UNICODE_TEXT:116,PLUS:117,EQUALS:118,MULT:119,UNDERSCORE:120,graphCodeTokens:121,ARROW_CROSS:122,ARROW_POINT:123,ARROW_CIRCLE:124,ARROW_OPEN:125,QUOTE:126,$accept:0,$end:1},terminals_:{2:"error",10:":",12:"open_directive",13:"type_directive",14:"arg_directive",15:"close_directive",20:"SEMI",21:"NEWLINE",22:"SPACE",23:"EOF",24:"GRAPH",25:"NODIR",26:"DIR",38:"subgraph",40:"SQS",41:"SQE",42:"end",47:"AMP",48:"STYLE_SEPARATOR",50:"PS",51:"PE",52:"(-",53:"-)",54:"STADIUMSTART",55:"STADIUMEND",56:"SUBROUTINESTART",57:"SUBROUTINEEND",58:"VERTEX_WITH_PROPS_START",59:"ALPHA",60:"COLON",61:"PIPE",62:"CYLINDERSTART",63:"CYLINDEREND",64:"DIAMOND_START",65:"DIAMOND_STOP",66:"TAGEND",67:"TRAPSTART",68:"TRAPEND",69:"INVTRAPSTART",70:"INVTRAPEND",73:"TESTSTR",74:"START_LINK",75:"LINK",77:"STR",79:"STYLE",80:"LINKSTYLE",81:"CLASSDEF",82:"CLASS",83:"CLICK",84:"DOWN",85:"UP",88:"DEFAULT",91:"CALLBACKNAME",92:"CALLBACKARGS",93:"HREF",94:"LINK_TARGET",95:"HEX",97:"INTERPOLATE",98:"NUM",99:"COMMA",102:"MINUS",103:"UNIT",104:"BRKT",105:"DOT",106:"PCT",107:"TAGSTART",111:"direction_tb",112:"direction_bt",113:"direction_rl",114:"direction_lr",115:"PUNCTUATION",116:"UNICODE_TEXT",117:"PLUS",118:"EQUALS",119:"MULT",120:"UNDERSCORE",122:"ARROW_CROSS",123:"ARROW_POINT",124:"ARROW_CIRCLE",125:"ARROW_OPEN",126:"QUOTE"},productions_:[0,[3,1],[3,2],[5,4],[5,6],[6,1],[7,1],[11,1],[8,1],[4,2],[17,0],[17,2],[18,1],[18,1],[18,1],[18,1],[18,1],[16,2],[16,2],[16,2],[16,3],[28,2],[28,1],[29,1],[29,1],[29,1],[27,1],[27,1],[27,2],[31,2],[31,2],[31,1],[31,1],[30,2],[30,1],[19,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,9],[19,6],[19,4],[19,1],[9,1],[9,1],[9,1],[32,3],[32,4],[32,2],[32,1],[45,1],[45,5],[45,3],[46,4],[46,6],[46,4],[46,4],[46,4],[46,8],[46,4],[46,4],[46,4],[46,6],[46,4],[46,4],[46,4],[46,4],[46,4],[46,1],[44,2],[44,3],[44,3],[44,1],[44,3],[71,1],[72,3],[39,1],[39,2],[39,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[78,1],[86,1],[86,2],[35,5],[35,5],[36,5],[37,2],[37,4],[37,3],[37,5],[37,2],[37,4],[37,4],[37,6],[37,2],[37,4],[37,2],[37,4],[37,4],[37,6],[33,5],[33,5],[34,5],[34,5],[34,9],[34,9],[34,7],[34,7],[96,1],[96,3],[89,1],[89,3],[100,1],[100,2],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[101,1],[76,1],[76,1],[76,1],[76,1],[76,1],[76,1],[87,1],[87,1],[87,1],[87,1],[49,1],[49,2],[90,1],[90,2],[110,1],[110,1],[110,1],[110,1],[43,1],[43,1],[43,1],[43,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[109,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1],[121,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 5:r.parseDirective("%%{","open_directive");break;case 6:r.parseDirective(a[s],"type_directive");break;case 7:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 8:r.parseDirective("}%%","close_directive","flowchart");break;case 10:case 36:case 37:case 38:case 39:case 40:this.$=[];break;case 11:a[s]!==[]&&a[s-1].push(a[s]),this.$=a[s-1];break;case 12:case 78:case 80:case 92:case 148:case 150:case 151:case 74:case 146:this.$=a[s];break;case 19:r.setDirection("TB"),this.$="TB";break;case 20:r.setDirection(a[s-1]),this.$=a[s-1];break;case 35:this.$=a[s-1].nodes;break;case 41:this.$=r.addSubGraph(a[s-6],a[s-1],a[s-4]);break;case 42:this.$=r.addSubGraph(a[s-3],a[s-1],a[s-3]);break;case 43:this.$=r.addSubGraph(void 0,a[s-1],void 0);break;case 48:r.addLink(a[s-2].stmt,a[s],a[s-1]),this.$={stmt:a[s],nodes:a[s].concat(a[s-2].nodes)};break;case 49:r.addLink(a[s-3].stmt,a[s-1],a[s-2]),this.$={stmt:a[s-1],nodes:a[s-1].concat(a[s-3].nodes)};break;case 50:this.$={stmt:a[s-1],nodes:a[s-1]};break;case 51:this.$={stmt:a[s],nodes:a[s]};break;case 52:case 119:case 121:this.$=[a[s]];break;case 53:this.$=a[s-4].concat(a[s]);break;case 54:this.$=[a[s-2]],r.setClass(a[s-2],a[s]);break;case 55:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"square");break;case 56:this.$=a[s-5],r.addVertex(a[s-5],a[s-2],"circle");break;case 57:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"ellipse");break;case 58:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"stadium");break;case 59:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"subroutine");break;case 60:this.$=a[s-7],r.addVertex(a[s-7],a[s-1],"rect",void 0,void 0,void 0,Object.fromEntries([[a[s-5],a[s-3]]]));break;case 61:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"cylinder");break;case 62:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"round");break;case 63:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"diamond");break;case 64:this.$=a[s-5],r.addVertex(a[s-5],a[s-2],"hexagon");break;case 65:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"odd");break;case 66:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"trapezoid");break;case 67:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"inv_trapezoid");break;case 68:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"lean_right");break;case 69:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"lean_left");break;case 70:this.$=a[s],r.addVertex(a[s]);break;case 71:a[s-1].text=a[s],this.$=a[s-1];break;case 72:case 73:a[s-2].text=a[s-1],this.$=a[s-2];break;case 75:var c=r.destructLink(a[s],a[s-2]);this.$={type:c.type,stroke:c.stroke,length:c.length,text:a[s-1]};break;case 76:c=r.destructLink(a[s]),this.$={type:c.type,stroke:c.stroke,length:c.length};break;case 77:this.$=a[s-1];break;case 79:case 93:case 149:case 147:this.$=a[s-1]+""+a[s];break;case 94:case 95:this.$=a[s-4],r.addClass(a[s-2],a[s]);break;case 96:this.$=a[s-4],r.setClass(a[s-2],a[s]);break;case 97:case 105:this.$=a[s-1],r.setClickEvent(a[s-1],a[s]);break;case 98:case 106:this.$=a[s-3],r.setClickEvent(a[s-3],a[s-2]),r.setTooltip(a[s-3],a[s]);break;case 99:this.$=a[s-2],r.setClickEvent(a[s-2],a[s-1],a[s]);break;case 100:this.$=a[s-4],r.setClickEvent(a[s-4],a[s-3],a[s-2]),r.setTooltip(a[s-4],a[s]);break;case 101:case 107:this.$=a[s-1],r.setLink(a[s-1],a[s]);break;case 102:case 108:this.$=a[s-3],r.setLink(a[s-3],a[s-2]),r.setTooltip(a[s-3],a[s]);break;case 103:case 109:this.$=a[s-3],r.setLink(a[s-3],a[s-2],a[s]);break;case 104:case 110:this.$=a[s-5],r.setLink(a[s-5],a[s-4],a[s]),r.setTooltip(a[s-5],a[s-2]);break;case 111:this.$=a[s-4],r.addVertex(a[s-2],void 0,void 0,a[s]);break;case 112:case 114:this.$=a[s-4],r.updateLink(a[s-2],a[s]);break;case 113:this.$=a[s-4],r.updateLink([a[s-2]],a[s]);break;case 115:this.$=a[s-8],r.updateLinkInterpolate([a[s-6]],a[s-2]),r.updateLink([a[s-6]],a[s]);break;case 116:this.$=a[s-8],r.updateLinkInterpolate(a[s-6],a[s-2]),r.updateLink(a[s-6],a[s]);break;case 117:this.$=a[s-6],r.updateLinkInterpolate([a[s-4]],a[s]);break;case 118:this.$=a[s-6],r.updateLinkInterpolate(a[s-4],a[s]);break;case 120:case 122:a[s-2].push(a[s]),this.$=a[s-2];break;case 124:this.$=a[s-1]+a[s];break;case 152:this.$="v";break;case 153:this.$="-";break;case 154:this.$={stmt:"dir",value:"TB"};break;case 155:this.$={stmt:"dir",value:"BT"};break;case 156:this.$={stmt:"dir",value:"RL"};break;case 157:this.$={stmt:"dir",value:"LR"}}},table:[{3:1,4:2,5:3,6:5,12:e,16:4,21:n,22:r,24:i},{1:[3]},{1:[2,1]},{3:10,4:2,5:3,6:5,12:e,16:4,21:n,22:r,24:i},t(a,o,{17:11}),{7:12,13:[1,13]},{16:14,21:n,22:r,24:i},{16:15,21:n,22:r,24:i},{25:[1,16],26:[1,17]},{13:[2,5]},{1:[2,2]},{1:[2,9],18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,43:31,45:32,46:42,47:f,49:43,59:d,60:p,79:y,80:g,81:m,82:v,83:b,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I,120:R},{8:61,10:[1,62],15:F},t([10,15],[2,6]),t(a,[2,17]),t(a,[2,18]),t(a,[2,19]),{20:[1,65],21:[1,66],22:P,27:64,30:67},t(j,[2,11]),t(j,[2,12]),t(j,[2,13]),t(j,[2,14]),t(j,[2,15]),t(j,[2,16]),{9:69,20:Y,21:z,23:U,44:70,71:74,74:[1,75],75:[1,76]},{9:77,20:Y,21:z,23:U},{9:78,20:Y,21:z,23:U},{9:79,20:Y,21:z,23:U},{9:80,20:Y,21:z,23:U},{9:81,20:Y,21:z,23:U},{9:83,20:Y,21:z,22:[1,82],23:U},t(j,[2,44]),t(q,[2,51],{30:84,22:P}),{22:[1,85]},{22:[1,86]},{22:[1,87]},{22:[1,88]},{26:H,47:$,59:W,60:V,77:[1,92],84:G,90:91,91:[1,89],93:[1,90],98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(j,[2,154]),t(j,[2,155]),t(j,[2,156]),t(j,[2,157]),t(ot,[2,52],{48:[1,111]}),t(st,[2,70],{109:123,40:[1,112],47:f,50:[1,113],52:[1,114],54:[1,115],56:[1,116],58:[1,117],59:d,60:p,62:[1,118],64:[1,119],66:[1,120],67:[1,121],69:[1,122],84:_,88:x,98:w,99:k,102:T,104:E,105:C,115:D,116:O,117:B,118:L,119:I,120:R}),t(ct,[2,146]),t(ct,[2,171]),t(ct,[2,172]),t(ct,[2,173]),t(ct,[2,174]),t(ct,[2,175]),t(ct,[2,176]),t(ct,[2,177]),t(ct,[2,178]),t(ct,[2,179]),t(ct,[2,180]),t(ct,[2,181]),t(ct,[2,182]),t(ct,[2,183]),t(ct,[2,184]),t(ct,[2,185]),t(ct,[2,186]),{9:124,20:Y,21:z,23:U},{11:125,14:[1,126]},t(ut,[2,8]),t(a,[2,20]),t(a,[2,26]),t(a,[2,27]),{21:[1,127]},t(lt,[2,34],{30:128,22:P}),t(j,[2,35]),{45:129,46:42,47:f,49:43,59:d,60:p,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,115:D,116:O,117:B,118:L,119:I,120:R},t(ht,[2,45]),t(ht,[2,46]),t(ht,[2,47]),t(ft,[2,74],{72:130,61:[1,132],73:[1,131]}),{22:dt,24:pt,26:yt,38:gt,39:133,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t([47,59,60,61,73,84,88,98,99,102,104,105,115,116,117,118,119,120],[2,76]),t(j,[2,36]),t(j,[2,37]),t(j,[2,38]),t(j,[2,39]),t(j,[2,40]),{22:dt,24:pt,26:yt,38:gt,39:157,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(Ot,o,{17:158}),t(q,[2,50],{47:Bt}),{26:H,47:$,59:W,60:V,84:G,90:160,95:[1,161],98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},{88:[1,162],96:163,98:[1,164]},{26:H,47:$,59:W,60:V,84:G,88:[1,165],90:166,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},{26:H,47:$,59:W,60:V,84:G,90:167,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ut,[2,97],{22:[1,168],92:[1,169]}),t(ut,[2,101],{22:[1,170]}),t(ut,[2,105],{108:95,110:172,22:[1,171],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,115:tt,116:et,117:nt,118:rt,119:it,120:at}),t(ut,[2,107],{22:[1,173]}),t(Lt,[2,148]),t(Lt,[2,150]),t(Lt,[2,151]),t(Lt,[2,152]),t(Lt,[2,153]),t(It,[2,158]),t(It,[2,159]),t(It,[2,160]),t(It,[2,161]),t(It,[2,162]),t(It,[2,163]),t(It,[2,164]),t(It,[2,165]),t(It,[2,166]),t(It,[2,167]),t(It,[2,168]),t(It,[2,169]),t(It,[2,170]),{47:f,49:174,59:d,60:p,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,115:D,116:O,117:B,118:L,119:I,120:R},{22:dt,24:pt,26:yt,38:gt,39:175,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:177,42:mt,47:$,50:[1,176],59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:178,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:179,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:180,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{59:[1,181]},{22:dt,24:pt,26:yt,38:gt,39:182,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:183,42:mt,47:$,59:W,60:V,64:[1,184],66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:185,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:186,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:187,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ct,[2,147]),t(Rt,[2,3]),{8:188,15:F},{15:[2,7]},t(a,[2,28]),t(lt,[2,33]),t(q,[2,48],{30:189,22:P}),t(ft,[2,71],{22:[1,190]}),{22:[1,191]},{22:dt,24:pt,26:yt,38:gt,39:192,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,66:vt,74:bt,75:[1,193],76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(It,[2,78]),t(It,[2,80]),t(It,[2,136]),t(It,[2,137]),t(It,[2,138]),t(It,[2,139]),t(It,[2,140]),t(It,[2,141]),t(It,[2,142]),t(It,[2,143]),t(It,[2,144]),t(It,[2,145]),t(It,[2,81]),t(It,[2,82]),t(It,[2,83]),t(It,[2,84]),t(It,[2,85]),t(It,[2,86]),t(It,[2,87]),t(It,[2,88]),t(It,[2,89]),t(It,[2,90]),t(It,[2,91]),{9:196,20:Y,21:z,22:dt,23:U,24:pt,26:yt,38:gt,40:[1,195],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,42:[1,197],43:31,45:32,46:42,47:f,49:43,59:d,60:p,79:y,80:g,81:m,82:v,83:b,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I,120:R},{22:P,30:198},{22:[1,199],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,108:95,110:172,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:[1,200]},{22:[1,201]},{22:[1,202],99:[1,203]},t(Ft,[2,119]),{22:[1,204]},{22:[1,205],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,108:95,110:172,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:[1,206],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,108:95,110:172,115:tt,116:et,117:nt,118:rt,119:it,120:at},{77:[1,207]},t(ut,[2,99],{22:[1,208]}),{77:[1,209],94:[1,210]},{77:[1,211]},t(Lt,[2,149]),{77:[1,212],94:[1,213]},t(ot,[2,54],{109:123,47:f,59:d,60:p,84:_,88:x,98:w,99:k,102:T,104:E,105:C,115:D,116:O,117:B,118:L,119:I,120:R}),{22:dt,24:pt,26:yt,38:gt,41:[1,214],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:215,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,51:[1,216],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,53:[1,217],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,55:[1,218],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,57:[1,219],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{60:[1,220]},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,63:[1,221],66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,65:[1,222],66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,39:223,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,41:[1,224],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,66:vt,68:[1,225],70:[1,226],74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,66:vt,68:[1,228],70:[1,227],74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{9:229,20:Y,21:z,23:U},t(q,[2,49],{47:Bt}),t(ft,[2,73]),t(ft,[2,72]),{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,61:[1,230],66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ft,[2,75]),t(It,[2,79]),{22:dt,24:pt,26:yt,38:gt,39:231,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(Ot,o,{17:232}),t(j,[2,43]),{46:233,47:f,49:43,59:d,60:p,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,115:D,116:O,117:B,118:L,119:I,120:R},{22:Pt,59:jt,60:Yt,79:zt,89:234,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:248,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:249,95:Ut,97:[1,250],98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:251,95:Ut,97:[1,252],98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{98:[1,253]},{22:Pt,59:jt,60:Yt,79:zt,89:254,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:255,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{26:H,47:$,59:W,60:V,84:G,90:256,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ut,[2,98]),{77:[1,257]},t(ut,[2,102],{22:[1,258]}),t(ut,[2,103]),t(ut,[2,106]),t(ut,[2,108],{22:[1,259]}),t(ut,[2,109]),t(st,[2,55]),{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,51:[1,260],59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(st,[2,62]),t(st,[2,57]),t(st,[2,58]),t(st,[2,59]),{59:[1,261]},t(st,[2,61]),t(st,[2,63]),{22:dt,24:pt,26:yt,38:gt,42:mt,47:$,59:W,60:V,65:[1,262],66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(st,[2,65]),t(st,[2,66]),t(st,[2,68]),t(st,[2,67]),t(st,[2,69]),t(Rt,[2,4]),t([22,47,59,60,84,88,98,99,102,104,105,115,116,117,118,119,120],[2,77]),{22:dt,24:pt,26:yt,38:gt,41:[1,263],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,42:[1,264],43:31,45:32,46:42,47:f,49:43,59:d,60:p,79:y,80:g,81:m,82:v,83:b,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I,120:R},t(ot,[2,53]),t(ut,[2,111],{99:Xt}),t(Zt,[2,121],{101:266,22:Pt,59:jt,60:Yt,79:zt,95:Ut,98:qt,102:Ht,103:$t,104:Wt,105:Vt,106:Gt}),t(Qt,[2,123]),t(Qt,[2,125]),t(Qt,[2,126]),t(Qt,[2,127]),t(Qt,[2,128]),t(Qt,[2,129]),t(Qt,[2,130]),t(Qt,[2,131]),t(Qt,[2,132]),t(Qt,[2,133]),t(Qt,[2,134]),t(Qt,[2,135]),t(ut,[2,112],{99:Xt}),t(ut,[2,113],{99:Xt}),{22:[1,267]},t(ut,[2,114],{99:Xt}),{22:[1,268]},t(Ft,[2,120]),t(ut,[2,94],{99:Xt}),t(ut,[2,95],{99:Xt}),t(ut,[2,96],{108:95,110:172,26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,115:tt,116:et,117:nt,118:rt,119:it,120:at}),t(ut,[2,100]),{94:[1,269]},{94:[1,270]},{51:[1,271]},{61:[1,272]},{65:[1,273]},{9:274,20:Y,21:z,23:U},t(j,[2,42]),{22:Pt,59:jt,60:Yt,79:zt,95:Ut,98:qt,100:275,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},t(Qt,[2,124]),{26:H,47:$,59:W,60:V,84:G,90:276,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},{26:H,47:$,59:W,60:V,84:G,90:277,98:X,99:Z,102:Q,104:K,105:J,108:95,110:93,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(ut,[2,104]),t(ut,[2,110]),t(st,[2,56]),{22:dt,24:pt,26:yt,38:gt,39:278,42:mt,47:$,59:W,60:V,66:vt,74:bt,76:134,77:_t,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},t(st,[2,64]),t(Ot,o,{17:279}),t(Zt,[2,122],{101:266,22:Pt,59:jt,60:Yt,79:zt,95:Ut,98:qt,102:Ht,103:$t,104:Wt,105:Vt,106:Gt}),t(ut,[2,117],{108:95,110:172,22:[1,280],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,115:tt,116:et,117:nt,118:rt,119:it,120:at}),t(ut,[2,118],{108:95,110:172,22:[1,281],26:H,47:$,59:W,60:V,84:G,98:X,99:Z,102:Q,104:K,105:J,115:tt,116:et,117:nt,118:rt,119:it,120:at}),{22:dt,24:pt,26:yt,38:gt,41:[1,282],42:mt,47:$,59:W,60:V,66:vt,74:bt,76:194,78:145,79:xt,80:wt,81:kt,82:Tt,83:Et,84:Ct,85:St,87:136,88:At,98:X,99:Z,102:Mt,104:K,105:J,106:Nt,107:Dt,108:142,115:tt,116:et,117:nt,118:rt,119:it,120:at},{18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,42:[1,283],43:31,45:32,46:42,47:f,49:43,59:d,60:p,79:y,80:g,81:m,82:v,83:b,84:_,88:x,98:w,99:k,102:T,104:E,105:C,109:44,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I,120:R},{22:Pt,59:jt,60:Yt,79:zt,89:284,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},{22:Pt,59:jt,60:Yt,79:zt,89:285,95:Ut,98:qt,100:235,101:236,102:Ht,103:$t,104:Wt,105:Vt,106:Gt},t(st,[2,60]),t(j,[2,41]),t(ut,[2,115],{99:Xt}),t(ut,[2,116],{99:Xt})],defaultActions:{2:[2,1],9:[2,5],10:[2,2],126:[2,7]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},Jt={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),12;case 1:return this.begin("type_directive"),13;case 2:return this.popState(),this.begin("arg_directive"),10;case 3:return this.popState(),this.popState(),15;case 4:return 14;case 5:case 6:break;case 7:this.begin("string");break;case 8:case 17:case 20:case 23:case 26:this.popState();break;case 9:return"STR";case 10:return 79;case 11:return 88;case 12:return 80;case 13:return 97;case 14:return 81;case 15:return 82;case 16:this.begin("href");break;case 18:return 93;case 19:this.begin("callbackname");break;case 21:this.popState(),this.begin("callbackargs");break;case 22:return 91;case 24:return 92;case 25:this.begin("click");break;case 27:return 83;case 28:case 29:return t.lex.firstGraph()&&this.begin("dir"),24;case 30:return 38;case 31:return 42;case 32:case 33:case 34:case 35:return 94;case 36:return this.popState(),25;case 37:case 38:case 39:case 40:case 41:case 42:case 43:case 44:case 45:case 46:return this.popState(),26;case 47:return 111;case 48:return 112;case 49:return 113;case 50:return 114;case 51:return 98;case 52:return 104;case 53:return 48;case 54:return 60;case 55:return 47;case 56:return 20;case 57:return 99;case 58:return 119;case 59:case 60:case 61:return 75;case 62:case 63:case 64:return 74;case 65:return 52;case 66:return 53;case 67:return 54;case 68:return 55;case 69:return 56;case 70:return 57;case 71:return 58;case 72:return 62;case 73:return 63;case 74:return 102;case 75:return 105;case 76:return 120;case 77:return 117;case 78:return 106;case 79:case 80:return 118;case 81:return 107;case 82:return 66;case 83:return 85;case 84:return"SEP";case 85:return 84;case 86:return 59;case 87:return 68;case 88:return 67;case 89:return 70;case 90:return 69;case 91:return 115;case 92:return 116;case 93:return 61;case 94:return 50;case 95:return 51;case 96:return 40;case 97:return 41;case 98:return 64;case 99:return 65;case 100:return 126;case 101:return 21;case 102:return 22;case 103:return 23}},rules:[/^(?:%%\{)/,/^(?:((?:(?!\}%%)[^:.])*))/,/^(?::)/,/^(?:\}%%)/,/^(?:((?:(?!\}%%).|\n)*))/,/^(?:%%(?!\{)[^\n]*)/,/^(?:[^\}]%%[^\n]*)/,/^(?:["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:style\b)/,/^(?:default\b)/,/^(?:linkStyle\b)/,/^(?:interpolate\b)/,/^(?:classDef\b)/,/^(?:class\b)/,/^(?:href[\s]+["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:click[\s]+)/,/^(?:[\s\n])/,/^(?:[^\s\n]*)/,/^(?:graph\b)/,/^(?:flowchart\b)/,/^(?:subgraph\b)/,/^(?:end\b\s*)/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:(\r?\n)*\s*\n)/,/^(?:\s*LR\b)/,/^(?:\s*RL\b)/,/^(?:\s*TB\b)/,/^(?:\s*BT\b)/,/^(?:\s*TD\b)/,/^(?:\s*BR\b)/,/^(?:\s*<)/,/^(?:\s*>)/,/^(?:\s*\^)/,/^(?:\s*v\b)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:[0-9]+)/,/^(?:#)/,/^(?::::)/,/^(?::)/,/^(?:&)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\s*[xo<]?--+[-xo>]\s*)/,/^(?:\s*[xo<]?==+[=xo>]\s*)/,/^(?:\s*[xo<]?-?\.+-[xo>]?\s*)/,/^(?:\s*[xo<]?--\s*)/,/^(?:\s*[xo<]?==\s*)/,/^(?:\s*[xo<]?-\.\s*)/,/^(?:\(-)/,/^(?:-\))/,/^(?:\(\[)/,/^(?:\]\))/,/^(?:\[\[)/,/^(?:\]\])/,/^(?:\[\|)/,/^(?:\[\()/,/^(?:\)\])/,/^(?:-)/,/^(?:\.)/,/^(?:[\_])/,/^(?:\+)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:<)/,/^(?:>)/,/^(?:\^)/,/^(?:\\\|)/,/^(?:v\b)/,/^(?:[A-Za-z]+)/,/^(?:\\\])/,/^(?:\[\/)/,/^(?:\/\])/,/^(?:\[\\)/,/^(?:[!"#$%&'*+,-.`?\\_/])/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\|)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:")/,/^(?:(\r?\n)+)/,/^(?:\s)/,/^(?:$)/],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},callbackargs:{rules:[23,24],inclusive:!1},callbackname:{rules:[20,21,22],inclusive:!1},href:{rules:[17,18],inclusive:!1},click:{rules:[26,27],inclusive:!1},vertex:{rules:[],inclusive:!1},dir:{rules:[36,37,38,39,40,41,42,43,44,45,46],inclusive:!1},string:{rules:[8,9],inclusive:!1},INITIAL:{rules:[0,5,6,7,10,11,12,13,14,15,16,19,25,28,29,30,31,32,33,34,35,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103],inclusive:!0}}};function te(){this.yy={}}return Kt.lexer=Jt,te.prototype=Kt,Kt.Parser=te,new te}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(5354).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},9959:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,3],n=[1,5],r=[7,9,11,12,13,14,15,16,17,18,19,20,22,29,34],i=[1,15],a=[1,16],o=[1,17],s=[1,18],c=[1,19],u=[1,20],l=[1,21],h=[1,22],f=[1,23],d=[1,25],p=[1,27],y=[1,30],g=[5,7,9,11,12,13,14,15,16,17,18,19,20,22,29,34],m={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,gantt:5,document:6,EOF:7,line:8,SPACE:9,statement:10,NL:11,dateFormat:12,inclusiveEndDates:13,topAxis:14,axisFormat:15,excludes:16,includes:17,todayMarker:18,title:19,section:20,clickStatement:21,taskTxt:22,taskData:23,openDirective:24,typeDirective:25,closeDirective:26,":":27,argDirective:28,click:29,callbackname:30,callbackargs:31,href:32,clickStatementDebug:33,open_directive:34,type_directive:35,arg_directive:36,close_directive:37,$accept:0,$end:1},terminals_:{2:"error",5:"gantt",7:"EOF",9:"SPACE",11:"NL",12:"dateFormat",13:"inclusiveEndDates",14:"topAxis",15:"axisFormat",16:"excludes",17:"includes",18:"todayMarker",19:"title",20:"section",22:"taskTxt",23:"taskData",27:":",29:"click",30:"callbackname",31:"callbackargs",32:"href",34:"open_directive",35:"type_directive",36:"arg_directive",37:"close_directive"},productions_:[0,[3,2],[3,3],[6,0],[6,2],[8,2],[8,1],[8,1],[8,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,2],[10,1],[4,4],[4,6],[21,2],[21,3],[21,3],[21,4],[21,3],[21,4],[21,2],[33,2],[33,3],[33,3],[33,4],[33,3],[33,4],[33,2],[24,1],[25,1],[28,1],[26,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 2:return a[s-1];case 3:case 7:case 8:this.$=[];break;case 4:a[s-1].push(a[s]),this.$=a[s-1];break;case 5:case 6:this.$=a[s];break;case 9:r.setDateFormat(a[s].substr(11)),this.$=a[s].substr(11);break;case 10:r.enableInclusiveEndDates(),this.$=a[s].substr(18);break;case 11:r.TopAxis(),this.$=a[s].substr(8);break;case 12:r.setAxisFormat(a[s].substr(11)),this.$=a[s].substr(11);break;case 13:r.setExcludes(a[s].substr(9)),this.$=a[s].substr(9);break;case 14:r.setIncludes(a[s].substr(9)),this.$=a[s].substr(9);break;case 15:r.setTodayMarker(a[s].substr(12)),this.$=a[s].substr(12);break;case 16:r.setTitle(a[s].substr(6)),this.$=a[s].substr(6);break;case 17:r.addSection(a[s].substr(8)),this.$=a[s].substr(8);break;case 19:r.addTask(a[s-1],a[s]),this.$="task";break;case 23:this.$=a[s-1],r.setClickEvent(a[s-1],a[s],null);break;case 24:this.$=a[s-2],r.setClickEvent(a[s-2],a[s-1],a[s]);break;case 25:this.$=a[s-2],r.setClickEvent(a[s-2],a[s-1],null),r.setLink(a[s-2],a[s]);break;case 26:this.$=a[s-3],r.setClickEvent(a[s-3],a[s-2],a[s-1]),r.setLink(a[s-3],a[s]);break;case 27:this.$=a[s-2],r.setClickEvent(a[s-2],a[s],null),r.setLink(a[s-2],a[s-1]);break;case 28:this.$=a[s-3],r.setClickEvent(a[s-3],a[s-1],a[s]),r.setLink(a[s-3],a[s-2]);break;case 29:this.$=a[s-1],r.setLink(a[s-1],a[s]);break;case 30:case 36:this.$=a[s-1]+" "+a[s];break;case 31:case 32:case 34:this.$=a[s-2]+" "+a[s-1]+" "+a[s];break;case 33:case 35:this.$=a[s-3]+" "+a[s-2]+" "+a[s-1]+" "+a[s];break;case 37:r.parseDirective("%%{","open_directive");break;case 38:r.parseDirective(a[s],"type_directive");break;case 39:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 40:r.parseDirective("}%%","close_directive","gantt")}},table:[{3:1,4:2,5:e,24:4,34:n},{1:[3]},{3:6,4:2,5:e,24:4,34:n},t(r,[2,3],{6:7}),{25:8,35:[1,9]},{35:[2,37]},{1:[2,1]},{4:26,7:[1,10],8:11,9:[1,12],10:13,11:[1,14],12:i,13:a,14:o,15:s,16:c,17:u,18:l,19:h,20:f,21:24,22:d,24:4,29:p,34:n},{26:28,27:[1,29],37:y},t([27,37],[2,38]),t(r,[2,8],{1:[2,2]}),t(r,[2,4]),{4:26,10:31,12:i,13:a,14:o,15:s,16:c,17:u,18:l,19:h,20:f,21:24,22:d,24:4,29:p,34:n},t(r,[2,6]),t(r,[2,7]),t(r,[2,9]),t(r,[2,10]),t(r,[2,11]),t(r,[2,12]),t(r,[2,13]),t(r,[2,14]),t(r,[2,15]),t(r,[2,16]),t(r,[2,17]),t(r,[2,18]),{23:[1,32]},t(r,[2,20]),{30:[1,33],32:[1,34]},{11:[1,35]},{28:36,36:[1,37]},{11:[2,40]},t(r,[2,5]),t(r,[2,19]),t(r,[2,23],{31:[1,38],32:[1,39]}),t(r,[2,29],{30:[1,40]}),t(g,[2,21]),{26:41,37:y},{37:[2,39]},t(r,[2,24],{32:[1,42]}),t(r,[2,25]),t(r,[2,27],{31:[1,43]}),{11:[1,44]},t(r,[2,26]),t(r,[2,28]),t(g,[2,22])],defaultActions:{5:[2,37],6:[2,1],30:[2,40],37:[2,39]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},v={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),34;case 1:return this.begin("type_directive"),35;case 2:return this.popState(),this.begin("arg_directive"),27;case 3:return this.popState(),this.popState(),37;case 4:return 36;case 5:case 6:case 7:case 9:case 10:case 11:break;case 8:return 11;case 12:this.begin("href");break;case 13:case 16:case 19:case 22:this.popState();break;case 14:return 32;case 15:this.begin("callbackname");break;case 17:this.popState(),this.begin("callbackargs");break;case 18:return 30;case 20:return 31;case 21:this.begin("click");break;case 23:return 29;case 24:return 5;case 25:return 12;case 26:return 13;case 27:return 14;case 28:return 15;case 29:return 17;case 30:return 16;case 31:return 18;case 32:return"date";case 33:return 19;case 34:return 20;case 35:return 22;case 36:return 23;case 37:return 27;case 38:return 7;case 39:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)*[^\n]*)/i,/^(?:[^\}]%%*[^\n]*)/i,/^(?:%%*[^\n]*[\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:href[\s]+["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:call[\s]+)/i,/^(?:\([\s]*\))/i,/^(?:\()/i,/^(?:[^(]*)/i,/^(?:\))/i,/^(?:[^)]*)/i,/^(?:click[\s]+)/i,/^(?:[\s\n])/i,/^(?:[^\s\n]*)/i,/^(?:gantt\b)/i,/^(?:dateFormat\s[^#\n;]+)/i,/^(?:inclusiveEndDates\b)/i,/^(?:topAxis\b)/i,/^(?:axisFormat\s[^#\n;]+)/i,/^(?:includes\s[^#\n;]+)/i,/^(?:excludes\s[^#\n;]+)/i,/^(?:todayMarker\s[^\n;]+)/i,/^(?:\d\d\d\d-\d\d-\d\d\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},callbackargs:{rules:[19,20],inclusive:!1},callbackname:{rules:[16,17,18],inclusive:!1},href:{rules:[13,14],inclusive:!1},click:{rules:[22,23],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,15,21,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],inclusive:!0}}};function b(){this.yy={}}return m.lexer=v,b.prototype=m,m.Parser=b,new b}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(6878).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},2553:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[2,3],n=[1,7],r=[7,12,15,17,19,20,21],i=[7,11,12,15,17,19,20,21],a=[2,20],o=[1,32],s={trace:function(){},yy:{},symbols_:{error:2,start:3,GG:4,":":5,document:6,EOF:7,DIR:8,options:9,body:10,OPT:11,NL:12,line:13,statement:14,COMMIT:15,commit_arg:16,BRANCH:17,ID:18,CHECKOUT:19,MERGE:20,RESET:21,reset_arg:22,STR:23,HEAD:24,reset_parents:25,CARET:26,$accept:0,$end:1},terminals_:{2:"error",4:"GG",5:":",7:"EOF",8:"DIR",11:"OPT",12:"NL",15:"COMMIT",17:"BRANCH",18:"ID",19:"CHECKOUT",20:"MERGE",21:"RESET",23:"STR",24:"HEAD",26:"CARET"},productions_:[0,[3,4],[3,5],[6,0],[6,2],[9,2],[9,1],[10,0],[10,2],[13,2],[13,1],[14,2],[14,2],[14,2],[14,2],[14,2],[16,0],[16,1],[22,2],[22,2],[25,0],[25,2]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 1:return a[s-1];case 2:return r.setDirection(a[s-3]),a[s-1];case 4:r.setOptions(a[s-1]),this.$=a[s];break;case 5:a[s-1]+=a[s],this.$=a[s-1];break;case 7:this.$=[];break;case 8:a[s-1].push(a[s]),this.$=a[s-1];break;case 9:this.$=a[s-1];break;case 11:r.commit(a[s]);break;case 12:r.branch(a[s]);break;case 13:r.checkout(a[s]);break;case 14:r.merge(a[s]);break;case 15:r.reset(a[s]);break;case 16:this.$="";break;case 17:this.$=a[s];break;case 18:this.$=a[s-1]+":"+a[s];break;case 19:this.$=a[s-1]+":"+r.count,r.count=0;break;case 20:r.count=0;break;case 21:r.count+=1}},table:[{3:1,4:[1,2]},{1:[3]},{5:[1,3],8:[1,4]},{6:5,7:e,9:6,12:n},{5:[1,8]},{7:[1,9]},t(r,[2,7],{10:10,11:[1,11]}),t(i,[2,6]),{6:12,7:e,9:6,12:n},{1:[2,1]},{7:[2,4],12:[1,15],13:13,14:14,15:[1,16],17:[1,17],19:[1,18],20:[1,19],21:[1,20]},t(i,[2,5]),{7:[1,21]},t(r,[2,8]),{12:[1,22]},t(r,[2,10]),{12:[2,16],16:23,23:[1,24]},{18:[1,25]},{18:[1,26]},{18:[1,27]},{18:[1,30],22:28,24:[1,29]},{1:[2,2]},t(r,[2,9]),{12:[2,11]},{12:[2,17]},{12:[2,12]},{12:[2,13]},{12:[2,14]},{12:[2,15]},{12:a,25:31,26:o},{12:a,25:33,26:o},{12:[2,18]},{12:a,25:34,26:o},{12:[2,19]},{12:[2,21]}],defaultActions:{9:[2,1],21:[2,2],23:[2,11],24:[2,17],25:[2,12],26:[2,13],27:[2,14],28:[2,15],31:[2,18],33:[2,19],34:[2,21]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},c={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return 12;case 1:case 2:case 3:break;case 4:return 4;case 5:return 15;case 6:return 17;case 7:return 20;case 8:return 21;case 9:return 19;case 10:case 11:return 8;case 12:return 5;case 13:return 26;case 14:this.begin("options");break;case 15:case 18:this.popState();break;case 16:return 11;case 17:this.begin("string");break;case 19:return 23;case 20:return 18;case 21:return 7}},rules:[/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:gitGraph\b)/i,/^(?:commit\b)/i,/^(?:branch\b)/i,/^(?:merge\b)/i,/^(?:reset\b)/i,/^(?:checkout\b)/i,/^(?:LR\b)/i,/^(?:BT\b)/i,/^(?::)/i,/^(?:\^)/i,/^(?:options\r?\n)/i,/^(?:end\r?\n)/i,/^(?:[^\n]+\r?\n)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[a-zA-Z][-_\.a-zA-Z0-9]*[-_a-zA-Z0-9])/i,/^(?:$)/i],conditions:{options:{rules:[15,16],inclusive:!1},string:{rules:[18,19],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17,20,21],inclusive:!0}}};function u(){this.yy={}}return s.lexer=c,u.prototype=s,s.Parser=u,new u}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8183).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},6765:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[6,9,10],n={trace:function(){},yy:{},symbols_:{error:2,start:3,info:4,document:5,EOF:6,line:7,statement:8,NL:9,showInfo:10,$accept:0,$end:1},terminals_:{2:"error",4:"info",6:"EOF",9:"NL",10:"showInfo"},productions_:[0,[3,3],[5,0],[5,2],[7,1],[7,1],[8,1]],performAction:function(t,e,n,r,i,a,o){switch(a.length,i){case 1:return r;case 4:break;case 6:r.setInfo(!0)}},table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:6,9:[1,7],10:[1,8]},{1:[2,1]},t(e,[2,3]),t(e,[2,4]),t(e,[2,5]),t(e,[2,6])],defaultActions:{4:[2,1]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},r={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return 4;case 1:return 9;case 2:return"space";case 3:return 10;case 4:return 6;case 5:return"TXT"}},rules:[/^(?:info\b)/i,/^(?:[\s\n\r]+)/i,/^(?:[\s]+)/i,/^(?:showInfo\b)/i,/^(?:$)/i,/^(?:.)/i],conditions:{INITIAL:{rules:[0,1,2,3,4,5],inclusive:!0}}};function i(){this.yy={}}return n.lexer=r,i.prototype=n,n.Parser=i,new i}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(1428).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},7062:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,4],n=[1,5],r=[1,6],i=[1,7],a=[1,9],o=[1,11,13,20,21,22,23],s=[2,5],c=[1,6,11,13,20,21,22,23],u=[20,21,22],l=[2,8],h=[1,18],f=[1,19],d=[1,24],p=[6,20,21,22,23],y={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,directive:5,PIE:6,document:7,showData:8,line:9,statement:10,txt:11,value:12,title:13,title_value:14,openDirective:15,typeDirective:16,closeDirective:17,":":18,argDirective:19,NEWLINE:20,";":21,EOF:22,open_directive:23,type_directive:24,arg_directive:25,close_directive:26,$accept:0,$end:1},terminals_:{2:"error",6:"PIE",8:"showData",11:"txt",12:"value",13:"title",14:"title_value",18:":",20:"NEWLINE",21:";",22:"EOF",23:"open_directive",24:"type_directive",25:"arg_directive",26:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,3],[7,0],[7,2],[9,2],[10,0],[10,2],[10,2],[10,1],[5,3],[5,5],[4,1],[4,1],[4,1],[15,1],[16,1],[19,1],[17,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:r.setShowData(!0);break;case 7:this.$=a[s-1];break;case 9:r.addSection(a[s-1],r.cleanupValue(a[s]));break;case 10:this.$=a[s].trim(),r.setTitle(this.$);break;case 17:r.parseDirective("%%{","open_directive");break;case 18:r.parseDirective(a[s],"type_directive");break;case 19:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 20:r.parseDirective("}%%","close_directive","pie")}},table:[{3:1,4:2,5:3,6:e,15:8,20:n,21:r,22:i,23:a},{1:[3]},{3:10,4:2,5:3,6:e,15:8,20:n,21:r,22:i,23:a},{3:11,4:2,5:3,6:e,15:8,20:n,21:r,22:i,23:a},t(o,s,{7:12,8:[1,13]}),t(c,[2,14]),t(c,[2,15]),t(c,[2,16]),{16:14,24:[1,15]},{24:[2,17]},{1:[2,1]},{1:[2,2]},t(u,l,{15:8,9:16,10:17,5:20,1:[2,3],11:h,13:f,23:a}),t(o,s,{7:21}),{17:22,18:[1,23],26:d},t([18,26],[2,18]),t(o,[2,6]),{4:25,20:n,21:r,22:i},{12:[1,26]},{14:[1,27]},t(u,[2,11]),t(u,l,{15:8,9:16,10:17,5:20,1:[2,4],11:h,13:f,23:a}),t(p,[2,12]),{19:28,25:[1,29]},t(p,[2,20]),t(o,[2,7]),t(u,[2,9]),t(u,[2,10]),{17:30,26:d},{26:[2,19]},t(p,[2,13])],defaultActions:{9:[2,17],10:[2,1],11:[2,2],29:[2,19]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},g={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),23;case 1:return this.begin("type_directive"),24;case 2:return this.popState(),this.begin("arg_directive"),18;case 3:return this.popState(),this.popState(),26;case 4:return 25;case 5:case 6:case 8:case 9:break;case 7:return 20;case 10:return this.begin("title"),13;case 11:return this.popState(),"title_value";case 12:this.begin("string");break;case 13:this.popState();break;case 14:return"txt";case 15:return 6;case 16:return 8;case 17:return"value";case 18:return 22}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:[\s]+)/i,/^(?:title\b)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:pie\b)/i,/^(?:showData\b)/i,/^(?::[\s]*[\d]+(?:\.[\d]+)?)/i,/^(?:$)/i],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},title:{rules:[11],inclusive:!1},string:{rules:[13,14],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,12,15,16,17,18],inclusive:!0}}};function m(){this.yy={}}return y.lexer=g,m.prototype=y,y.Parser=m,new m}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(4551).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},3176:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,3],n=[1,5],r=[1,17],i=[2,10],a=[1,21],o=[1,22],s=[1,23],c=[1,24],u=[1,25],l=[1,26],h=[1,19],f=[1,27],d=[1,28],p=[1,31],y=[66,67],g=[5,8,14,35,36,37,38,39,40,48,55,57,66,67],m=[5,6,8,14,35,36,37,38,39,40,48,66,67],v=[1,51],b=[1,52],_=[1,53],x=[1,54],w=[1,55],k=[1,56],T=[1,57],E=[57,58],C=[1,69],S=[1,65],A=[1,66],M=[1,67],N=[1,68],D=[1,70],O=[1,74],B=[1,75],L=[1,72],I=[1,73],R=[5,8,14,35,36,37,38,39,40,48,66,67],F={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,NEWLINE:5,RD:6,diagram:7,EOF:8,openDirective:9,typeDirective:10,closeDirective:11,":":12,argDirective:13,open_directive:14,type_directive:15,arg_directive:16,close_directive:17,requirementDef:18,elementDef:19,relationshipDef:20,requirementType:21,requirementName:22,STRUCT_START:23,requirementBody:24,ID:25,COLONSEP:26,id:27,TEXT:28,text:29,RISK:30,riskLevel:31,VERIFYMTHD:32,verifyType:33,STRUCT_STOP:34,REQUIREMENT:35,FUNCTIONAL_REQUIREMENT:36,INTERFACE_REQUIREMENT:37,PERFORMANCE_REQUIREMENT:38,PHYSICAL_REQUIREMENT:39,DESIGN_CONSTRAINT:40,LOW_RISK:41,MED_RISK:42,HIGH_RISK:43,VERIFY_ANALYSIS:44,VERIFY_DEMONSTRATION:45,VERIFY_INSPECTION:46,VERIFY_TEST:47,ELEMENT:48,elementName:49,elementBody:50,TYPE:51,type:52,DOCREF:53,ref:54,END_ARROW_L:55,relationship:56,LINE:57,END_ARROW_R:58,CONTAINS:59,COPIES:60,DERIVES:61,SATISFIES:62,VERIFIES:63,REFINES:64,TRACES:65,unqString:66,qString:67,$accept:0,$end:1},terminals_:{2:"error",5:"NEWLINE",6:"RD",8:"EOF",12:":",14:"open_directive",15:"type_directive",16:"arg_directive",17:"close_directive",23:"STRUCT_START",25:"ID",26:"COLONSEP",28:"TEXT",30:"RISK",32:"VERIFYMTHD",34:"STRUCT_STOP",35:"REQUIREMENT",36:"FUNCTIONAL_REQUIREMENT",37:"INTERFACE_REQUIREMENT",38:"PERFORMANCE_REQUIREMENT",39:"PHYSICAL_REQUIREMENT",40:"DESIGN_CONSTRAINT",41:"LOW_RISK",42:"MED_RISK",43:"HIGH_RISK",44:"VERIFY_ANALYSIS",45:"VERIFY_DEMONSTRATION",46:"VERIFY_INSPECTION",47:"VERIFY_TEST",48:"ELEMENT",51:"TYPE",53:"DOCREF",55:"END_ARROW_L",57:"LINE",58:"END_ARROW_R",59:"CONTAINS",60:"COPIES",61:"DERIVES",62:"SATISFIES",63:"VERIFIES",64:"REFINES",65:"TRACES",66:"unqString",67:"qString"},productions_:[0,[3,3],[3,2],[3,4],[4,3],[4,5],[9,1],[10,1],[13,1],[11,1],[7,0],[7,2],[7,2],[7,2],[7,2],[7,2],[18,5],[24,5],[24,5],[24,5],[24,5],[24,2],[24,1],[21,1],[21,1],[21,1],[21,1],[21,1],[21,1],[31,1],[31,1],[31,1],[33,1],[33,1],[33,1],[33,1],[19,5],[50,5],[50,5],[50,2],[50,1],[20,5],[20,5],[56,1],[56,1],[56,1],[56,1],[56,1],[56,1],[56,1],[22,1],[22,1],[27,1],[27,1],[29,1],[29,1],[49,1],[49,1],[52,1],[52,1],[54,1],[54,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 6:r.parseDirective("%%{","open_directive");break;case 7:r.parseDirective(a[s],"type_directive");break;case 8:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 9:r.parseDirective("}%%","close_directive","pie");break;case 10:this.$=[];break;case 16:r.addRequirement(a[s-3],a[s-4]);break;case 17:r.setNewReqId(a[s-2]);break;case 18:r.setNewReqText(a[s-2]);break;case 19:r.setNewReqRisk(a[s-2]);break;case 20:r.setNewReqVerifyMethod(a[s-2]);break;case 23:this.$=r.RequirementType.REQUIREMENT;break;case 24:this.$=r.RequirementType.FUNCTIONAL_REQUIREMENT;break;case 25:this.$=r.RequirementType.INTERFACE_REQUIREMENT;break;case 26:this.$=r.RequirementType.PERFORMANCE_REQUIREMENT;break;case 27:this.$=r.RequirementType.PHYSICAL_REQUIREMENT;break;case 28:this.$=r.RequirementType.DESIGN_CONSTRAINT;break;case 29:this.$=r.RiskLevel.LOW_RISK;break;case 30:this.$=r.RiskLevel.MED_RISK;break;case 31:this.$=r.RiskLevel.HIGH_RISK;break;case 32:this.$=r.VerifyType.VERIFY_ANALYSIS;break;case 33:this.$=r.VerifyType.VERIFY_DEMONSTRATION;break;case 34:this.$=r.VerifyType.VERIFY_INSPECTION;break;case 35:this.$=r.VerifyType.VERIFY_TEST;break;case 36:r.addElement(a[s-3]);break;case 37:r.setNewElementType(a[s-2]);break;case 38:r.setNewElementDocRef(a[s-2]);break;case 41:r.addRelationship(a[s-2],a[s],a[s-4]);break;case 42:r.addRelationship(a[s-2],a[s-4],a[s]);break;case 43:this.$=r.Relationships.CONTAINS;break;case 44:this.$=r.Relationships.COPIES;break;case 45:this.$=r.Relationships.DERIVES;break;case 46:this.$=r.Relationships.SATISFIES;break;case 47:this.$=r.Relationships.VERIFIES;break;case 48:this.$=r.Relationships.REFINES;break;case 49:this.$=r.Relationships.TRACES}},table:[{3:1,4:2,6:e,9:4,14:n},{1:[3]},{3:7,4:2,5:[1,6],6:e,9:4,14:n},{5:[1,8]},{10:9,15:[1,10]},{15:[2,6]},{3:11,4:2,6:e,9:4,14:n},{1:[2,2]},{4:16,5:r,7:12,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{11:29,12:[1,30],17:p},t([12,17],[2,7]),{1:[2,1]},{8:[1,32]},{4:16,5:r,7:33,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:34,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:35,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:36,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:37,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{22:38,66:[1,39],67:[1,40]},{49:41,66:[1,42],67:[1,43]},{55:[1,44],57:[1,45]},t(y,[2,23]),t(y,[2,24]),t(y,[2,25]),t(y,[2,26]),t(y,[2,27]),t(y,[2,28]),t(g,[2,52]),t(g,[2,53]),t(m,[2,4]),{13:46,16:[1,47]},t(m,[2,9]),{1:[2,3]},{8:[2,11]},{8:[2,12]},{8:[2,13]},{8:[2,14]},{8:[2,15]},{23:[1,48]},{23:[2,50]},{23:[2,51]},{23:[1,49]},{23:[2,56]},{23:[2,57]},{56:50,59:v,60:b,61:_,62:x,63:w,64:k,65:T},{56:58,59:v,60:b,61:_,62:x,63:w,64:k,65:T},{11:59,17:p},{17:[2,8]},{5:[1,60]},{5:[1,61]},{57:[1,62]},t(E,[2,43]),t(E,[2,44]),t(E,[2,45]),t(E,[2,46]),t(E,[2,47]),t(E,[2,48]),t(E,[2,49]),{58:[1,63]},t(m,[2,5]),{5:C,24:64,25:S,28:A,30:M,32:N,34:D},{5:O,34:B,50:71,51:L,53:I},{27:76,66:f,67:d},{27:77,66:f,67:d},t(R,[2,16]),{26:[1,78]},{26:[1,79]},{26:[1,80]},{26:[1,81]},{5:C,24:82,25:S,28:A,30:M,32:N,34:D},t(R,[2,22]),t(R,[2,36]),{26:[1,83]},{26:[1,84]},{5:O,34:B,50:85,51:L,53:I},t(R,[2,40]),t(R,[2,41]),t(R,[2,42]),{27:86,66:f,67:d},{29:87,66:[1,88],67:[1,89]},{31:90,41:[1,91],42:[1,92],43:[1,93]},{33:94,44:[1,95],45:[1,96],46:[1,97],47:[1,98]},t(R,[2,21]),{52:99,66:[1,100],67:[1,101]},{54:102,66:[1,103],67:[1,104]},t(R,[2,39]),{5:[1,105]},{5:[1,106]},{5:[2,54]},{5:[2,55]},{5:[1,107]},{5:[2,29]},{5:[2,30]},{5:[2,31]},{5:[1,108]},{5:[2,32]},{5:[2,33]},{5:[2,34]},{5:[2,35]},{5:[1,109]},{5:[2,58]},{5:[2,59]},{5:[1,110]},{5:[2,60]},{5:[2,61]},{5:C,24:111,25:S,28:A,30:M,32:N,34:D},{5:C,24:112,25:S,28:A,30:M,32:N,34:D},{5:C,24:113,25:S,28:A,30:M,32:N,34:D},{5:C,24:114,25:S,28:A,30:M,32:N,34:D},{5:O,34:B,50:115,51:L,53:I},{5:O,34:B,50:116,51:L,53:I},t(R,[2,17]),t(R,[2,18]),t(R,[2,19]),t(R,[2,20]),t(R,[2,37]),t(R,[2,38])],defaultActions:{5:[2,6],7:[2,2],11:[2,1],32:[2,3],33:[2,11],34:[2,12],35:[2,13],36:[2,14],37:[2,15],39:[2,50],40:[2,51],42:[2,56],43:[2,57],47:[2,8],88:[2,54],89:[2,55],91:[2,29],92:[2,30],93:[2,31],95:[2,32],96:[2,33],97:[2,34],98:[2,35],100:[2,58],101:[2,59],103:[2,60],104:[2,61]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},P={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),14;case 1:return this.begin("type_directive"),15;case 2:return this.popState(),this.begin("arg_directive"),12;case 3:return this.popState(),this.popState(),17;case 4:return 16;case 5:return 5;case 6:case 7:case 8:break;case 9:return 8;case 10:return 6;case 11:return 23;case 12:return 34;case 13:return 26;case 14:return 25;case 15:return 28;case 16:return 30;case 17:return 32;case 18:return 35;case 19:return 36;case 20:return 37;case 21:return 38;case 22:return 39;case 23:return 40;case 24:return 41;case 25:return 42;case 26:return 43;case 27:return 44;case 28:return 45;case 29:return 46;case 30:return 47;case 31:return 48;case 32:return 59;case 33:return 60;case 34:return 61;case 35:return 62;case 36:return 63;case 37:return 64;case 38:return 65;case 39:return 51;case 40:return 53;case 41:return 55;case 42:return 58;case 43:return 57;case 44:this.begin("string");break;case 45:this.popState();break;case 46:return"qString";case 47:return e.yytext=e.yytext.trim(),66}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:$)/i,/^(?:requirementDiagram\b)/i,/^(?:\{)/i,/^(?:\})/i,/^(?::)/i,/^(?:id\b)/i,/^(?:text\b)/i,/^(?:risk\b)/i,/^(?:verifyMethod\b)/i,/^(?:requirement\b)/i,/^(?:functionalRequirement\b)/i,/^(?:interfaceRequirement\b)/i,/^(?:performanceRequirement\b)/i,/^(?:physicalRequirement\b)/i,/^(?:designConstraint\b)/i,/^(?:low\b)/i,/^(?:medium\b)/i,/^(?:high\b)/i,/^(?:analysis\b)/i,/^(?:demonstration\b)/i,/^(?:inspection\b)/i,/^(?:test\b)/i,/^(?:element\b)/i,/^(?:contains\b)/i,/^(?:copies\b)/i,/^(?:derives\b)/i,/^(?:satisfies\b)/i,/^(?:verifies\b)/i,/^(?:refines\b)/i,/^(?:traces\b)/i,/^(?:type\b)/i,/^(?:docref\b)/i,/^(?:<-)/i,/^(?:->)/i,/^(?:-)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[\w][^\r\n\{\<\>\-\=]*)/i],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},unqString:{rules:[],inclusive:!1},token:{rules:[],inclusive:!1},string:{rules:[45,46],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,47],inclusive:!0}}};function j(){this.yy={}}return F.lexer=P,j.prototype=F,F.Parser=j,new j}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8800).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},6876:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,3],r=[1,5],i=[1,7],a=[2,5],o=[1,15],s=[1,17],c=[1,18],u=[1,19],l=[1,21],h=[1,22],f=[1,23],d=[1,29],p=[1,30],y=[1,31],g=[1,32],m=[1,33],v=[1,34],b=[1,37],_=[1,38],x=[1,39],w=[1,40],k=[1,41],T=[1,42],E=[1,45],C=[1,4,5,16,20,22,23,24,30,32,33,34,35,36,38,40,41,42,46,47,48,49,57,67],S=[1,58],A=[4,5,16,20,22,23,24,30,32,33,34,35,36,38,42,46,47,48,49,57,67],M=[4,5,16,20,22,23,24,30,32,33,34,35,36,38,41,42,46,47,48,49,57,67],N=[4,5,16,20,22,23,24,30,32,33,34,35,36,38,40,42,46,47,48,49,57,67],D=[55,56,57],O=[1,4,5,7,16,20,22,23,24,30,32,33,34,35,36,38,40,41,42,46,47,48,49,57,67],B={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NEWLINE:5,directive:6,SD:7,document:8,line:9,statement:10,openDirective:11,typeDirective:12,closeDirective:13,":":14,argDirective:15,participant:16,actor:17,AS:18,restOfLine:19,participant_actor:20,signal:21,autonumber:22,activate:23,deactivate:24,note_statement:25,links_statement:26,link_statement:27,properties_statement:28,details_statement:29,title:30,text2:31,loop:32,end:33,rect:34,opt:35,alt:36,else_sections:37,par:38,par_sections:39,and:40,else:41,note:42,placement:43,over:44,actor_pair:45,links:46,link:47,properties:48,details:49,spaceList:50,",":51,left_of:52,right_of:53,signaltype:54,"+":55,"-":56,ACTOR:57,SOLID_OPEN_ARROW:58,DOTTED_OPEN_ARROW:59,SOLID_ARROW:60,DOTTED_ARROW:61,SOLID_CROSS:62,DOTTED_CROSS:63,SOLID_POINT:64,DOTTED_POINT:65,TXT:66,open_directive:67,type_directive:68,arg_directive:69,close_directive:70,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NEWLINE",7:"SD",14:":",16:"participant",18:"AS",19:"restOfLine",20:"participant_actor",22:"autonumber",23:"activate",24:"deactivate",30:"title",32:"loop",33:"end",34:"rect",35:"opt",36:"alt",38:"par",40:"and",41:"else",42:"note",44:"over",46:"links",47:"link",48:"properties",49:"details",51:",",52:"left_of",53:"right_of",55:"+",56:"-",57:"ACTOR",58:"SOLID_OPEN_ARROW",59:"DOTTED_OPEN_ARROW",60:"SOLID_ARROW",61:"DOTTED_ARROW",62:"SOLID_CROSS",63:"DOTTED_CROSS",64:"SOLID_POINT",65:"DOTTED_POINT",66:"TXT",67:"open_directive",68:"type_directive",69:"arg_directive",70:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,2],[8,0],[8,2],[9,2],[9,1],[9,1],[6,4],[6,6],[10,5],[10,3],[10,5],[10,3],[10,2],[10,1],[10,3],[10,3],[10,2],[10,2],[10,2],[10,2],[10,2],[10,3],[10,4],[10,4],[10,4],[10,4],[10,4],[10,1],[39,1],[39,4],[37,1],[37,4],[25,4],[25,4],[26,3],[27,3],[28,3],[29,3],[50,2],[50,1],[45,3],[45,1],[43,1],[43,1],[21,5],[21,5],[21,4],[17,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[31,1],[11,1],[12,1],[15,1],[13,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:return r.apply(a[s]),a[s];case 5:case 9:this.$=[];break;case 6:a[s-1].push(a[s]),this.$=a[s-1];break;case 7:case 8:case 45:this.$=a[s];break;case 12:a[s-3].type="addParticipant",a[s-3].description=r.parseMessage(a[s-1]),this.$=a[s-3];break;case 13:a[s-1].type="addParticipant",this.$=a[s-1];break;case 14:a[s-3].type="addActor",a[s-3].description=r.parseMessage(a[s-1]),this.$=a[s-3];break;case 15:a[s-1].type="addActor",this.$=a[s-1];break;case 17:r.enableSequenceNumbers();break;case 18:this.$={type:"activeStart",signalType:r.LINETYPE.ACTIVE_START,actor:a[s-1]};break;case 19:this.$={type:"activeEnd",signalType:r.LINETYPE.ACTIVE_END,actor:a[s-1]};break;case 25:this.$=[{type:"setTitle",text:a[s-1]}];break;case 26:a[s-1].unshift({type:"loopStart",loopText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.LOOP_START}),a[s-1].push({type:"loopEnd",loopText:a[s-2],signalType:r.LINETYPE.LOOP_END}),this.$=a[s-1];break;case 27:a[s-1].unshift({type:"rectStart",color:r.parseMessage(a[s-2]),signalType:r.LINETYPE.RECT_START}),a[s-1].push({type:"rectEnd",color:r.parseMessage(a[s-2]),signalType:r.LINETYPE.RECT_END}),this.$=a[s-1];break;case 28:a[s-1].unshift({type:"optStart",optText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.OPT_START}),a[s-1].push({type:"optEnd",optText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.OPT_END}),this.$=a[s-1];break;case 29:a[s-1].unshift({type:"altStart",altText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.ALT_START}),a[s-1].push({type:"altEnd",signalType:r.LINETYPE.ALT_END}),this.$=a[s-1];break;case 30:a[s-1].unshift({type:"parStart",parText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.PAR_START}),a[s-1].push({type:"parEnd",signalType:r.LINETYPE.PAR_END}),this.$=a[s-1];break;case 33:this.$=a[s-3].concat([{type:"and",parText:r.parseMessage(a[s-1]),signalType:r.LINETYPE.PAR_AND},a[s]]);break;case 35:this.$=a[s-3].concat([{type:"else",altText:r.parseMessage(a[s-1]),signalType:r.LINETYPE.ALT_ELSE},a[s]]);break;case 36:this.$=[a[s-1],{type:"addNote",placement:a[s-2],actor:a[s-1].actor,text:a[s]}];break;case 37:a[s-2]=[].concat(a[s-1],a[s-1]).slice(0,2),a[s-2][0]=a[s-2][0].actor,a[s-2][1]=a[s-2][1].actor,this.$=[a[s-1],{type:"addNote",placement:r.PLACEMENT.OVER,actor:a[s-2].slice(0,2),text:a[s]}];break;case 38:this.$=[a[s-1],{type:"addLinks",actor:a[s-1].actor,text:a[s]}];break;case 39:this.$=[a[s-1],{type:"addALink",actor:a[s-1].actor,text:a[s]}];break;case 40:this.$=[a[s-1],{type:"addProperties",actor:a[s-1].actor,text:a[s]}];break;case 41:this.$=[a[s-1],{type:"addDetails",actor:a[s-1].actor,text:a[s]}];break;case 44:this.$=[a[s-2],a[s]];break;case 46:this.$=r.PLACEMENT.LEFTOF;break;case 47:this.$=r.PLACEMENT.RIGHTOF;break;case 48:this.$=[a[s-4],a[s-1],{type:"addMessage",from:a[s-4].actor,to:a[s-1].actor,signalType:a[s-3],msg:a[s]},{type:"activeStart",signalType:r.LINETYPE.ACTIVE_START,actor:a[s-1]}];break;case 49:this.$=[a[s-4],a[s-1],{type:"addMessage",from:a[s-4].actor,to:a[s-1].actor,signalType:a[s-3],msg:a[s]},{type:"activeEnd",signalType:r.LINETYPE.ACTIVE_END,actor:a[s-4]}];break;case 50:this.$=[a[s-3],a[s-1],{type:"addMessage",from:a[s-3].actor,to:a[s-1].actor,signalType:a[s-2],msg:a[s]}];break;case 51:this.$={type:"addParticipant",actor:a[s]};break;case 52:this.$=r.LINETYPE.SOLID_OPEN;break;case 53:this.$=r.LINETYPE.DOTTED_OPEN;break;case 54:this.$=r.LINETYPE.SOLID;break;case 55:this.$=r.LINETYPE.DOTTED;break;case 56:this.$=r.LINETYPE.SOLID_CROSS;break;case 57:this.$=r.LINETYPE.DOTTED_CROSS;break;case 58:this.$=r.LINETYPE.SOLID_POINT;break;case 59:this.$=r.LINETYPE.DOTTED_POINT;break;case 60:this.$=r.parseMessage(a[s].trim().substring(1));break;case 61:r.parseDirective("%%{","open_directive");break;case 62:r.parseDirective(a[s],"type_directive");break;case 63:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 64:r.parseDirective("}%%","close_directive","sequence")}},table:[{3:1,4:e,5:n,6:4,7:r,11:6,67:i},{1:[3]},{3:8,4:e,5:n,6:4,7:r,11:6,67:i},{3:9,4:e,5:n,6:4,7:r,11:6,67:i},{3:10,4:e,5:n,6:4,7:r,11:6,67:i},t([1,4,5,16,20,22,23,24,30,32,34,35,36,38,42,46,47,48,49,57,67],a,{8:11}),{12:12,68:[1,13]},{68:[2,61]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{1:[2,4],4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{13:43,14:[1,44],70:E},t([14,70],[2,62]),t(C,[2,6]),{6:35,10:46,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},t(C,[2,8]),t(C,[2,9]),{17:47,57:T},{17:48,57:T},{5:[1,49]},t(C,[2,17]),{17:50,57:T},{17:51,57:T},{5:[1,52]},{5:[1,53]},{5:[1,54]},{5:[1,55]},{5:[1,56]},{31:57,66:S},{19:[1,59]},{19:[1,60]},{19:[1,61]},{19:[1,62]},{19:[1,63]},t(C,[2,31]),{54:64,58:[1,65],59:[1,66],60:[1,67],61:[1,68],62:[1,69],63:[1,70],64:[1,71],65:[1,72]},{43:73,44:[1,74],52:[1,75],53:[1,76]},{17:77,57:T},{17:78,57:T},{17:79,57:T},{17:80,57:T},t([5,18,51,58,59,60,61,62,63,64,65,66],[2,51]),{5:[1,81]},{15:82,69:[1,83]},{5:[2,64]},t(C,[2,7]),{5:[1,85],18:[1,84]},{5:[1,87],18:[1,86]},t(C,[2,16]),{5:[1,88]},{5:[1,89]},t(C,[2,20]),t(C,[2,21]),t(C,[2,22]),t(C,[2,23]),t(C,[2,24]),{5:[1,90]},{5:[2,60]},t(A,a,{8:91}),t(A,a,{8:92}),t(A,a,{8:93}),t(M,a,{37:94,8:95}),t(N,a,{39:96,8:97}),{17:100,55:[1,98],56:[1,99],57:T},t(D,[2,52]),t(D,[2,53]),t(D,[2,54]),t(D,[2,55]),t(D,[2,56]),t(D,[2,57]),t(D,[2,58]),t(D,[2,59]),{17:101,57:T},{17:103,45:102,57:T},{57:[2,46]},{57:[2,47]},{31:104,66:S},{31:105,66:S},{31:106,66:S},{31:107,66:S},t(O,[2,10]),{13:108,70:E},{70:[2,63]},{19:[1,109]},t(C,[2,13]),{19:[1,110]},t(C,[2,15]),t(C,[2,18]),t(C,[2,19]),t(C,[2,25]),{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[1,111],34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[1,112],34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[1,113],34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{33:[1,114]},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[2,34],34:y,35:g,36:m,38:v,41:[1,115],42:b,46:_,47:x,48:w,49:k,57:T,67:i},{33:[1,116]},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[2,32],34:y,35:g,36:m,38:v,40:[1,117],42:b,46:_,47:x,48:w,49:k,57:T,67:i},{17:118,57:T},{17:119,57:T},{31:120,66:S},{31:121,66:S},{31:122,66:S},{51:[1,123],66:[2,45]},{5:[2,38]},{5:[2,39]},{5:[2,40]},{5:[2,41]},{5:[1,124]},{5:[1,125]},{5:[1,126]},t(C,[2,26]),t(C,[2,27]),t(C,[2,28]),t(C,[2,29]),{19:[1,127]},t(C,[2,30]),{19:[1,128]},{31:129,66:S},{31:130,66:S},{5:[2,50]},{5:[2,36]},{5:[2,37]},{17:131,57:T},t(O,[2,11]),t(C,[2,12]),t(C,[2,14]),t(M,a,{8:95,37:132}),t(N,a,{8:97,39:133}),{5:[2,48]},{5:[2,49]},{66:[2,44]},{33:[2,35]},{33:[2,33]}],defaultActions:{7:[2,61],8:[2,1],9:[2,2],10:[2,3],45:[2,64],58:[2,60],75:[2,46],76:[2,47],83:[2,63],104:[2,38],105:[2,39],106:[2,40],107:[2,41],120:[2,50],121:[2,36],122:[2,37],129:[2,48],130:[2,49],131:[2,44],132:[2,35],133:[2,33]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},L={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),67;case 1:return this.begin("type_directive"),68;case 2:return this.popState(),this.begin("arg_directive"),14;case 3:return this.popState(),this.popState(),70;case 4:return 69;case 5:case 39:case 52:return 5;case 6:case 7:case 8:case 9:case 10:break;case 11:return this.begin("ID"),16;case 12:return this.begin("ID"),20;case 13:return e.yytext=e.yytext.trim(),this.begin("ALIAS"),57;case 14:return this.popState(),this.popState(),this.begin("LINE"),18;case 15:return this.popState(),this.popState(),5;case 16:return this.begin("LINE"),32;case 17:return this.begin("LINE"),34;case 18:return this.begin("LINE"),35;case 19:return this.begin("LINE"),36;case 20:return this.begin("LINE"),41;case 21:return this.begin("LINE"),38;case 22:return this.begin("LINE"),40;case 23:return this.popState(),19;case 24:return 33;case 25:return 52;case 26:return 53;case 27:return 46;case 28:return 47;case 29:return 48;case 30:return 49;case 31:return 44;case 32:return 42;case 33:return this.begin("ID"),23;case 34:return this.begin("ID"),24;case 35:return 30;case 36:return 7;case 37:return 22;case 38:return 51;case 40:return e.yytext=e.yytext.trim(),57;case 41:return 60;case 42:return 61;case 43:return 58;case 44:return 59;case 45:return 62;case 46:return 63;case 47:return 64;case 48:return 65;case 49:return 66;case 50:return 55;case 51:return 56;case 53:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:participant\b)/i,/^(?:actor\b)/i,/^(?:[^\->:\n,;]+?(?=((?!\n)\s)+as(?!\n)\s|[#\n;]|$))/i,/^(?:as\b)/i,/^(?:(?:))/i,/^(?:loop\b)/i,/^(?:rect\b)/i,/^(?:opt\b)/i,/^(?:alt\b)/i,/^(?:else\b)/i,/^(?:par\b)/i,/^(?:and\b)/i,/^(?:(?:[:]?(?:no)?wrap)?[^#\n;]*)/i,/^(?:end\b)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:links\b)/i,/^(?:link\b)/i,/^(?:properties\b)/i,/^(?:details\b)/i,/^(?:over\b)/i,/^(?:note\b)/i,/^(?:activate\b)/i,/^(?:deactivate\b)/i,/^(?:title\b)/i,/^(?:sequenceDiagram\b)/i,/^(?:autonumber\b)/i,/^(?:,)/i,/^(?:;)/i,/^(?:[^\+\->:\n,;]+((?!(-x|--x|-\)|--\)))[\-]*[^\+\->:\n,;]+)*)/i,/^(?:->>)/i,/^(?:-->>)/i,/^(?:->)/i,/^(?:-->)/i,/^(?:-[x])/i,/^(?:--[x])/i,/^(?:-[\)])/i,/^(?:--[\)])/i,/^(?::(?:(?:no)?wrap)?[^#\n;]+)/i,/^(?:\+)/i,/^(?:-)/i,/^(?:$)/i,/^(?:.)/i],conditions:{open_directive:{rules:[1,8],inclusive:!1},type_directive:{rules:[2,3,8],inclusive:!1},arg_directive:{rules:[3,4,8],inclusive:!1},ID:{rules:[7,8,13],inclusive:!1},ALIAS:{rules:[7,8,14,15],inclusive:!1},LINE:{rules:[7,8,23],inclusive:!1},INITIAL:{rules:[0,5,6,8,9,10,11,12,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53],inclusive:!0}}};function I(){this.yy={}}return B.lexer=L,I.prototype=B,B.Parser=I,new I}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(1993).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},3584:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,3],r=[1,5],i=[1,7],a=[2,5],o=[1,15],s=[1,17],c=[1,19],u=[1,20],l=[1,21],h=[1,22],f=[1,30],d=[1,23],p=[1,24],y=[1,25],g=[1,26],m=[1,27],v=[1,32],b=[1,33],_=[1,34],x=[1,35],w=[1,31],k=[1,38],T=[1,4,5,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],E=[1,4,5,12,13,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],C=[1,4,5,7,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],S=[4,5,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],A={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NL:5,directive:6,SD:7,document:8,line:9,statement:10,idStatement:11,DESCR:12,"--\x3e":13,HIDE_EMPTY:14,scale:15,WIDTH:16,COMPOSIT_STATE:17,STRUCT_START:18,STRUCT_STOP:19,STATE_DESCR:20,AS:21,ID:22,FORK:23,JOIN:24,CHOICE:25,CONCURRENT:26,note:27,notePosition:28,NOTE_TEXT:29,direction:30,openDirective:31,typeDirective:32,closeDirective:33,":":34,argDirective:35,direction_tb:36,direction_bt:37,direction_rl:38,direction_lr:39,eol:40,";":41,EDGE_STATE:42,left_of:43,right_of:44,open_directive:45,type_directive:46,arg_directive:47,close_directive:48,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NL",7:"SD",12:"DESCR",13:"--\x3e",14:"HIDE_EMPTY",15:"scale",16:"WIDTH",17:"COMPOSIT_STATE",18:"STRUCT_START",19:"STRUCT_STOP",20:"STATE_DESCR",21:"AS",22:"ID",23:"FORK",24:"JOIN",25:"CHOICE",26:"CONCURRENT",27:"note",29:"NOTE_TEXT",34:":",36:"direction_tb",37:"direction_bt",38:"direction_rl",39:"direction_lr",41:";",42:"EDGE_STATE",43:"left_of",44:"right_of",45:"open_directive",46:"type_directive",47:"arg_directive",48:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,2],[8,0],[8,2],[9,2],[9,1],[9,1],[10,1],[10,2],[10,3],[10,4],[10,1],[10,2],[10,1],[10,4],[10,3],[10,6],[10,1],[10,1],[10,1],[10,1],[10,4],[10,4],[10,1],[10,1],[6,3],[6,5],[30,1],[30,1],[30,1],[30,1],[40,1],[40,1],[11,1],[11,1],[28,1],[28,1],[31,1],[32,1],[35,1],[33,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:return r.setRootDoc(a[s]),a[s];case 5:this.$=[];break;case 6:"nl"!=a[s]&&(a[s-1].push(a[s]),this.$=a[s-1]);break;case 7:case 8:case 36:case 37:this.$=a[s];break;case 9:this.$="nl";break;case 10:this.$={stmt:"state",id:a[s],type:"default",description:""};break;case 11:this.$={stmt:"state",id:a[s-1],type:"default",description:r.trimColon(a[s])};break;case 12:this.$={stmt:"relation",state1:{stmt:"state",id:a[s-2],type:"default",description:""},state2:{stmt:"state",id:a[s],type:"default",description:""}};break;case 13:this.$={stmt:"relation",state1:{stmt:"state",id:a[s-3],type:"default",description:""},state2:{stmt:"state",id:a[s-1],type:"default",description:""},description:a[s].substr(1).trim()};break;case 17:this.$={stmt:"state",id:a[s-3],type:"default",description:"",doc:a[s-1]};break;case 18:var c=a[s],u=a[s-2].trim();if(a[s].match(":")){var l=a[s].split(":");c=l[0],u=[u,l[1]]}this.$={stmt:"state",id:c,type:"default",description:u};break;case 19:this.$={stmt:"state",id:a[s-3],type:"default",description:a[s-5],doc:a[s-1]};break;case 20:this.$={stmt:"state",id:a[s],type:"fork"};break;case 21:this.$={stmt:"state",id:a[s],type:"join"};break;case 22:this.$={stmt:"state",id:a[s],type:"choice"};break;case 23:this.$={stmt:"state",id:r.getDividerId(),type:"divider"};break;case 24:this.$={stmt:"state",id:a[s-1].trim(),note:{position:a[s-2].trim(),text:a[s].trim()}};break;case 30:r.setDirection("TB"),this.$={stmt:"dir",value:"TB"};break;case 31:r.setDirection("BT"),this.$={stmt:"dir",value:"BT"};break;case 32:r.setDirection("RL"),this.$={stmt:"dir",value:"RL"};break;case 33:r.setDirection("LR"),this.$={stmt:"dir",value:"LR"};break;case 40:r.parseDirective("%%{","open_directive");break;case 41:r.parseDirective(a[s],"type_directive");break;case 42:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 43:r.parseDirective("}%%","close_directive","state")}},table:[{3:1,4:e,5:n,6:4,7:r,31:6,45:i},{1:[3]},{3:8,4:e,5:n,6:4,7:r,31:6,45:i},{3:9,4:e,5:n,6:4,7:r,31:6,45:i},{3:10,4:e,5:n,6:4,7:r,31:6,45:i},t([1,4,5,14,15,17,20,22,23,24,25,26,27,36,37,38,39,42,45],a,{8:11}),{32:12,46:[1,13]},{46:[2,40]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{1:[2,4],4:o,5:s,6:28,9:14,10:16,11:18,14:c,15:u,17:l,20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},{33:36,34:[1,37],48:k},t([34,48],[2,41]),t(T,[2,6]),{6:28,10:39,11:18,14:c,15:u,17:l,20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},t(T,[2,8]),t(T,[2,9]),t(T,[2,10],{12:[1,40],13:[1,41]}),t(T,[2,14]),{16:[1,42]},t(T,[2,16],{18:[1,43]}),{21:[1,44]},t(T,[2,20]),t(T,[2,21]),t(T,[2,22]),t(T,[2,23]),{28:45,29:[1,46],43:[1,47],44:[1,48]},t(T,[2,26]),t(T,[2,27]),t(E,[2,36]),t(E,[2,37]),t(T,[2,30]),t(T,[2,31]),t(T,[2,32]),t(T,[2,33]),t(C,[2,28]),{35:49,47:[1,50]},t(C,[2,43]),t(T,[2,7]),t(T,[2,11]),{11:51,22:f,42:w},t(T,[2,15]),t(S,a,{8:52}),{22:[1,53]},{22:[1,54]},{21:[1,55]},{22:[2,38]},{22:[2,39]},{33:56,48:k},{48:[2,42]},t(T,[2,12],{12:[1,57]}),{4:o,5:s,6:28,9:14,10:16,11:18,14:c,15:u,17:l,19:[1,58],20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},t(T,[2,18],{18:[1,59]}),{29:[1,60]},{22:[1,61]},t(C,[2,29]),t(T,[2,13]),t(T,[2,17]),t(S,a,{8:62}),t(T,[2,24]),t(T,[2,25]),{4:o,5:s,6:28,9:14,10:16,11:18,14:c,15:u,17:l,19:[1,63],20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},t(T,[2,19])],defaultActions:{7:[2,40],8:[2,1],9:[2,2],10:[2,3],47:[2,38],48:[2,39],50:[2,42]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},M={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:case 26:return 36;case 1:case 27:return 37;case 2:case 28:return 38;case 3:case 29:return 39;case 4:return this.begin("open_directive"),45;case 5:return this.begin("type_directive"),46;case 6:return this.popState(),this.begin("arg_directive"),34;case 7:return this.popState(),this.popState(),48;case 8:return 47;case 9:case 10:case 12:case 13:case 14:case 15:case 39:case 45:break;case 11:case 59:return 5;case 16:return this.pushState("SCALE"),15;case 17:return 16;case 18:case 33:case 36:this.popState();break;case 19:this.pushState("STATE");break;case 20:case 23:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),23;case 21:case 24:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),24;case 22:case 25:return this.popState(),e.yytext=e.yytext.slice(0,-10).trim(),25;case 30:this.begin("STATE_STRING");break;case 31:return this.popState(),this.pushState("STATE_ID"),"AS";case 32:case 47:return this.popState(),"ID";case 34:return"STATE_DESCR";case 35:return 17;case 37:return this.popState(),this.pushState("struct"),18;case 38:return this.popState(),19;case 40:return this.begin("NOTE"),27;case 41:return this.popState(),this.pushState("NOTE_ID"),43;case 42:return this.popState(),this.pushState("NOTE_ID"),44;case 43:this.popState(),this.pushState("FLOATING_NOTE");break;case 44:return this.popState(),this.pushState("FLOATING_NOTE_ID"),"AS";case 46:return"NOTE_TEXT";case 48:return this.popState(),this.pushState("NOTE_TEXT"),22;case 49:return this.popState(),e.yytext=e.yytext.substr(2).trim(),29;case 50:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),29;case 51:case 52:return 7;case 53:return 14;case 54:return 42;case 55:return 22;case 56:return e.yytext=e.yytext.trim(),12;case 57:return 13;case 58:return 26;case 60:return"INVALID"}},rules:[/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:[\s]+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:scale\s+)/i,/^(?:\d+)/i,/^(?:\s+width\b)/i,/^(?:state\s+)/i,/^(?:.*<<fork>>)/i,/^(?:.*<<join>>)/i,/^(?:.*<<choice>>)/i,/^(?:.*\[\[fork\]\])/i,/^(?:.*\[\[join\]\])/i,/^(?:.*\[\[choice\]\])/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:["])/i,/^(?:\s*as\s+)/i,/^(?:[^\n\{]*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n\s\{]+)/i,/^(?:\n)/i,/^(?:\{)/i,/^(?:\})/i,/^(?:[\n])/i,/^(?:note\s+)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:")/i,/^(?:\s*as\s*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n]*)/i,/^(?:\s*[^:\n\s\-]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:[\s\S]*?end note\b)/i,/^(?:stateDiagram\s+)/i,/^(?:stateDiagram-v2\s+)/i,/^(?:hide empty description\b)/i,/^(?:\[\*\])/i,/^(?:[^:\n\s\-\{]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:-->)/i,/^(?:--)/i,/^(?:$)/i,/^(?:.)/i],conditions:{LINE:{rules:[13,14],inclusive:!1},close_directive:{rules:[13,14],inclusive:!1},arg_directive:{rules:[7,8,13,14],inclusive:!1},type_directive:{rules:[6,7,13,14],inclusive:!1},open_directive:{rules:[5,13,14],inclusive:!1},struct:{rules:[13,14,19,26,27,28,29,38,39,40,54,55,56,57,58],inclusive:!1},FLOATING_NOTE_ID:{rules:[47],inclusive:!1},FLOATING_NOTE:{rules:[44,45,46],inclusive:!1},NOTE_TEXT:{rules:[49,50],inclusive:!1},NOTE_ID:{rules:[48],inclusive:!1},NOTE:{rules:[41,42,43],inclusive:!1},SCALE:{rules:[17,18],inclusive:!1},ALIAS:{rules:[],inclusive:!1},STATE_ID:{rules:[32],inclusive:!1},STATE_STRING:{rules:[33,34],inclusive:!1},FORK_STATE:{rules:[],inclusive:!1},STATE:{rules:[13,14,20,21,22,23,24,25,30,31,35,36,37],inclusive:!1},ID:{rules:[13,14],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,9,10,11,12,14,15,16,19,37,40,51,52,53,54,55,56,57,59,60],inclusive:!0}}};function N(){this.yy={}}return A.lexer=M,N.prototype=A,A.Parser=N,new N}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(3069).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},9763:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,5],r=[6,9,11,17,18,19,21],i=[1,15],a=[1,16],o=[1,17],s=[1,21],c=[4,6,9,11,17,18,19,21],u={trace:function(){},yy:{},symbols_:{error:2,start:3,journey:4,document:5,EOF:6,directive:7,line:8,SPACE:9,statement:10,NEWLINE:11,openDirective:12,typeDirective:13,closeDirective:14,":":15,argDirective:16,title:17,section:18,taskName:19,taskData:20,open_directive:21,type_directive:22,arg_directive:23,close_directive:24,$accept:0,$end:1},terminals_:{2:"error",4:"journey",6:"EOF",9:"SPACE",11:"NEWLINE",15:":",17:"title",18:"section",19:"taskName",20:"taskData",21:"open_directive",22:"type_directive",23:"arg_directive",24:"close_directive"},productions_:[0,[3,3],[3,2],[5,0],[5,2],[8,2],[8,1],[8,1],[8,1],[7,4],[7,6],[10,1],[10,1],[10,2],[10,1],[12,1],[13,1],[16,1],[14,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 1:return a[s-1];case 3:case 7:case 8:this.$=[];break;case 4:a[s-1].push(a[s]),this.$=a[s-1];break;case 5:case 6:this.$=a[s];break;case 11:r.setTitle(a[s].substr(6)),this.$=a[s].substr(6);break;case 12:r.addSection(a[s].substr(8)),this.$=a[s].substr(8);break;case 13:r.addTask(a[s-1],a[s]),this.$="task";break;case 15:r.parseDirective("%%{","open_directive");break;case 16:r.parseDirective(a[s],"type_directive");break;case 17:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 18:r.parseDirective("}%%","close_directive","journey")}},table:[{3:1,4:e,7:3,12:4,21:n},{1:[3]},t(r,[2,3],{5:6}),{3:7,4:e,7:3,12:4,21:n},{13:8,22:[1,9]},{22:[2,15]},{6:[1,10],7:18,8:11,9:[1,12],10:13,11:[1,14],12:4,17:i,18:a,19:o,21:n},{1:[2,2]},{14:19,15:[1,20],24:s},t([15,24],[2,16]),t(r,[2,8],{1:[2,1]}),t(r,[2,4]),{7:18,10:22,12:4,17:i,18:a,19:o,21:n},t(r,[2,6]),t(r,[2,7]),t(r,[2,11]),t(r,[2,12]),{20:[1,23]},t(r,[2,14]),{11:[1,24]},{16:25,23:[1,26]},{11:[2,18]},t(r,[2,5]),t(r,[2,13]),t(c,[2,9]),{14:27,24:s},{24:[2,17]},{11:[1,28]},t(c,[2,10])],defaultActions:{5:[2,15],7:[2,2],21:[2,18],26:[2,17]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},l={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;a<i.length;a++)if((n=this._input.match(this.rules[i[a]]))&&(!e||n[0].length>e[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),21;case 1:return this.begin("type_directive"),22;case 2:return this.popState(),this.begin("arg_directive"),15;case 3:return this.popState(),this.popState(),24;case 4:return 23;case 5:case 6:case 8:case 9:break;case 7:return 11;case 10:return 4;case 11:return 17;case 12:return 18;case 13:return 19;case 14:return 20;case 15:return 15;case 16:return 6;case 17:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:journey\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{open_directive:{rules:[1],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,13,14,15,16,17],inclusive:!0}}};function h(){this.yy={}}return u.lexer=l,h.prototype=u,u.Parser=h,new h}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(9143).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},9609:t=>{"use strict";var e=/^(%20|\s)*(javascript|data)/im,n=/[^\x20-\x7E]/gim,r=/^([^:]+):/gm,i=[".","/"];t.exports={sanitizeUrl:function(t){if(!t)return"about:blank";var a,o,s=t.replace(n,"").trim();return function(t){return i.indexOf(t[0])>-1}(s)?s:(o=s.match(r))?(a=o[0],e.test(a)?"about:blank":s):"about:blank"}}},3841:t=>{t.exports=function(t,e){return t.intersect(e)}},7458:(t,e,n)=>{"use strict";n.d(e,{default:()=>hC});var r=n(1941),i=n.n(r),a={debug:1,info:2,warn:3,error:4,fatal:5},o={debug:function(){},info:function(){},warn:function(){},error:function(){},fatal:function(){}},s=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"fatal";isNaN(t)&&(t=t.toLowerCase(),void 0!==a[t]&&(t=a[t])),o.trace=function(){},o.debug=function(){},o.info=function(){},o.warn=function(){},o.error=function(){},o.fatal=function(){},t<=a.fatal&&(o.fatal=console.error?console.error.bind(console,c("FATAL"),"color: orange"):console.log.bind(console,"",c("FATAL"))),t<=a.error&&(o.error=console.error?console.error.bind(console,c("ERROR"),"color: orange"):console.log.bind(console,"",c("ERROR"))),t<=a.warn&&(o.warn=console.warn?console.warn.bind(console,c("WARN"),"color: orange"):console.log.bind(console,"",c("WARN"))),t<=a.info&&(o.info=console.info?console.info.bind(console,c("INFO"),"color: lightblue"):console.log.bind(console,"",c("INFO"))),t<=a.debug&&(o.debug=console.debug?console.debug.bind(console,c("DEBUG"),"color: lightgreen"):console.log.bind(console,"",c("DEBUG")))},c=function(t){var e=i()().format("ss.SSS");return"%c".concat(e," : ").concat(t," : ")};function u(t,e){let n;if(void 0===e)for(const e of t)null!=e&&(n<e||void 0===n&&e>=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n<i||void 0===n&&i>=i)&&(n=i)}return n}function l(t,e){let n;if(void 0===e)for(const e of t)null!=e&&(n>e||void 0===n&&e>=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n>i||void 0===n&&i>=i)&&(n=i)}return n}function h(t){return t}var f=1e-6;function d(t){return"translate("+t+",0)"}function p(t){return"translate(0,"+t+")"}function y(t){return e=>+t(e)}function g(t,e){return e=Math.max(0,t.bandwidth()-2*e)/2,t.round()&&(e=Math.round(e)),n=>+t(n)+e}function m(){return!this.__axis}function v(t,e){var n=[],r=null,i=null,a=6,o=6,s=3,c="undefined"!=typeof window&&window.devicePixelRatio>1?0:.5,u=1===t||4===t?-1:1,l=4===t||2===t?"x":"y",v=1===t||3===t?d:p;function b(d){var p=null==r?e.ticks?e.ticks.apply(e,n):e.domain():r,b=null==i?e.tickFormat?e.tickFormat.apply(e,n):h:i,_=Math.max(a,0)+s,x=e.range(),w=+x[0]+c,k=+x[x.length-1]+c,T=(e.bandwidth?g:y)(e.copy(),c),E=d.selection?d.selection():d,C=E.selectAll(".domain").data([null]),S=E.selectAll(".tick").data(p,e).order(),A=S.exit(),M=S.enter().append("g").attr("class","tick"),N=S.select("line"),D=S.select("text");C=C.merge(C.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),S=S.merge(M),N=N.merge(M.append("line").attr("stroke","currentColor").attr(l+"2",u*a)),D=D.merge(M.append("text").attr("fill","currentColor").attr(l,u*_).attr("dy",1===t?"0em":3===t?"0.71em":"0.32em")),d!==E&&(C=C.transition(d),S=S.transition(d),N=N.transition(d),D=D.transition(d),A=A.transition(d).attr("opacity",f).attr("transform",(function(t){return isFinite(t=T(t))?v(t+c):this.getAttribute("transform")})),M.attr("opacity",f).attr("transform",(function(t){var e=this.parentNode.__axis;return v((e&&isFinite(e=e(t))?e:T(t))+c)}))),A.remove(),C.attr("d",4===t||2===t?o?"M"+u*o+","+w+"H"+c+"V"+k+"H"+u*o:"M"+c+","+w+"V"+k:o?"M"+w+","+u*o+"V"+c+"H"+k+"V"+u*o:"M"+w+","+c+"H"+k),S.attr("opacity",1).attr("transform",(function(t){return v(T(t)+c)})),N.attr(l+"2",u*a),D.attr(l,u*_).text(b),E.filter(m).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",2===t?"start":4===t?"end":"middle"),E.each((function(){this.__axis=T}))}return b.scale=function(t){return arguments.length?(e=t,b):e},b.ticks=function(){return n=Array.from(arguments),b},b.tickArguments=function(t){return arguments.length?(n=null==t?[]:Array.from(t),b):n.slice()},b.tickValues=function(t){return arguments.length?(r=null==t?null:Array.from(t),b):r&&r.slice()},b.tickFormat=function(t){return arguments.length?(i=t,b):i},b.tickSize=function(t){return arguments.length?(a=o=+t,b):a},b.tickSizeInner=function(t){return arguments.length?(a=+t,b):a},b.tickSizeOuter=function(t){return arguments.length?(o=+t,b):o},b.tickPadding=function(t){return arguments.length?(s=+t,b):s},b.offset=function(t){return arguments.length?(c=+t,b):c},b}function b(){}function _(t){return null==t?b:function(){return this.querySelector(t)}}function x(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}function w(){return[]}function k(t){return null==t?w:function(){return this.querySelectorAll(t)}}function T(t){return function(){return this.matches(t)}}function E(t){return function(e){return e.matches(t)}}var C=Array.prototype.find;function S(){return this.firstElementChild}var A=Array.prototype.filter;function M(){return Array.from(this.children)}function N(t){return new Array(t.length)}function D(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}function O(t){return function(){return t}}function B(t,e,n,r,i,a){for(var o,s=0,c=e.length,u=a.length;s<u;++s)(o=e[s])?(o.__data__=a[s],r[s]=o):n[s]=new D(t,a[s]);for(;s<c;++s)(o=e[s])&&(i[s]=o)}function L(t,e,n,r,i,a,o){var s,c,u,l=new Map,h=e.length,f=a.length,d=new Array(h);for(s=0;s<h;++s)(c=e[s])&&(d[s]=u=o.call(c,c.__data__,s,e)+"",l.has(u)?i[s]=c:l.set(u,c));for(s=0;s<f;++s)u=o.call(t,a[s],s,a)+"",(c=l.get(u))?(r[s]=c,c.__data__=a[s],l.delete(u)):n[s]=new D(t,a[s]);for(s=0;s<h;++s)(c=e[s])&&l.get(d[s])===c&&(i[s]=c)}function I(t){return t.__data__}function R(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function F(t,e){return t<e?-1:t>e?1:t>=e?0:NaN}D.prototype={constructor:D,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var P="http://www.w3.org/1999/xhtml";const j={svg:"http://www.w3.org/2000/svg",xhtml:P,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function Y(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),j.hasOwnProperty(e)?{space:j[e],local:t}:t}function z(t){return function(){this.removeAttribute(t)}}function U(t){return function(){this.removeAttributeNS(t.space,t.local)}}function q(t,e){return function(){this.setAttribute(t,e)}}function H(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function $(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function W(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function V(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function G(t){return function(){this.style.removeProperty(t)}}function X(t,e,n){return function(){this.style.setProperty(t,e,n)}}function Z(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function Q(t,e){return t.style.getPropertyValue(e)||V(t).getComputedStyle(t,null).getPropertyValue(e)}function K(t){return function(){delete this[t]}}function J(t,e){return function(){this[t]=e}}function tt(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function et(t){return t.trim().split(/^|\s+/)}function nt(t){return t.classList||new rt(t)}function rt(t){this._node=t,this._names=et(t.getAttribute("class")||"")}function it(t,e){for(var n=nt(t),r=-1,i=e.length;++r<i;)n.add(e[r])}function at(t,e){for(var n=nt(t),r=-1,i=e.length;++r<i;)n.remove(e[r])}function ot(t){return function(){it(this,t)}}function st(t){return function(){at(this,t)}}function ct(t,e){return function(){(e.apply(this,arguments)?it:at)(this,t)}}function ut(){this.textContent=""}function lt(t){return function(){this.textContent=t}}function ht(t){return function(){var e=t.apply(this,arguments);this.textContent=null==e?"":e}}function ft(){this.innerHTML=""}function dt(t){return function(){this.innerHTML=t}}function pt(t){return function(){var e=t.apply(this,arguments);this.innerHTML=null==e?"":e}}function yt(){this.nextSibling&&this.parentNode.appendChild(this)}function gt(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function mt(t){return function(){var e=this.ownerDocument,n=this.namespaceURI;return n===P&&e.documentElement.namespaceURI===P?e.createElement(t):e.createElementNS(n,t)}}function vt(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function bt(t){var e=Y(t);return(e.local?vt:mt)(e)}function _t(){return null}function xt(){var t=this.parentNode;t&&t.removeChild(this)}function wt(){var t=this.cloneNode(!1),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}function kt(){var t=this.cloneNode(!0),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}function Tt(t){return t.trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");return n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function Et(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r<a;++r)n=e[r],t.type&&n.type!==t.type||n.name!==t.name?e[++i]=n:this.removeEventListener(n.type,n.listener,n.options);++i?e.length=i:delete this.__on}}}function Ct(t,e,n){return function(){var r,i=this.__on,a=function(t){return function(e){t.call(this,e,this.__data__)}}(e);if(i)for(var o=0,s=i.length;o<s;++o)if((r=i[o]).type===t.type&&r.name===t.name)return this.removeEventListener(r.type,r.listener,r.options),this.addEventListener(r.type,r.listener=a,r.options=n),void(r.value=e);this.addEventListener(t.type,a,n),r={type:t.type,name:t.name,value:e,listener:a,options:n},i?i.push(r):this.__on=[r]}}function St(t,e,n){var r=V(t),i=r.CustomEvent;"function"==typeof i?i=new i(e,n):(i=r.document.createEvent("Event"),n?(i.initEvent(e,n.bubbles,n.cancelable),i.detail=n.detail):i.initEvent(e,!1,!1)),t.dispatchEvent(i)}function At(t,e){return function(){return St(this,t,e)}}function Mt(t,e){return function(){return St(this,t,e.apply(this,arguments))}}rt.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var Nt=[null];function Dt(t,e){this._groups=t,this._parents=e}function Ot(){return new Dt([[document.documentElement]],Nt)}Dt.prototype=Ot.prototype={constructor:Dt,select:function(t){"function"!=typeof t&&(t=_(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o,s=e[i],c=s.length,u=r[i]=new Array(c),l=0;l<c;++l)(a=s[l])&&(o=t.call(a,a.__data__,l,s))&&("__data__"in a&&(o.__data__=a.__data__),u[l]=o);return new Dt(r,this._parents)},selectAll:function(t){t="function"==typeof t?function(t){return function(){return x(t.apply(this,arguments))}}(t):k(t);for(var e=this._groups,n=e.length,r=[],i=[],a=0;a<n;++a)for(var o,s=e[a],c=s.length,u=0;u<c;++u)(o=s[u])&&(r.push(t.call(o,o.__data__,u,s)),i.push(o));return new Dt(r,i)},selectChild:function(t){return this.select(null==t?S:function(t){return function(){return C.call(this.children,t)}}("function"==typeof t?t:E(t)))},selectChildren:function(t){return this.selectAll(null==t?M:function(t){return function(){return A.call(this.children,t)}}("function"==typeof t?t:E(t)))},filter:function(t){"function"!=typeof t&&(t=T(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o=e[i],s=o.length,c=r[i]=[],u=0;u<s;++u)(a=o[u])&&t.call(a,a.__data__,u,o)&&c.push(a);return new Dt(r,this._parents)},data:function(t,e){if(!arguments.length)return Array.from(this,I);var n=e?L:B,r=this._parents,i=this._groups;"function"!=typeof t&&(t=O(t));for(var a=i.length,o=new Array(a),s=new Array(a),c=new Array(a),u=0;u<a;++u){var l=r[u],h=i[u],f=h.length,d=R(t.call(l,l&&l.__data__,u,r)),p=d.length,y=s[u]=new Array(p),g=o[u]=new Array(p),m=c[u]=new Array(f);n(l,h,y,g,m,d,e);for(var v,b,_=0,x=0;_<p;++_)if(v=y[_]){for(_>=x&&(x=_+1);!(b=g[x])&&++x<p;);v._next=b||null}}return(o=new Dt(o,r))._enter=s,o._exit=c,o},enter:function(){return new Dt(this._enter||this._groups.map(N),this._parents)},exit:function(){return new Dt(this._exit||this._groups.map(N),this._parents)},join:function(t,e,n){var r=this.enter(),i=this,a=this.exit();return"function"==typeof t?(r=t(r))&&(r=r.selection()):r=r.append(t+""),null!=e&&(i=e(i))&&(i=i.selection()),null==n?a.remove():n(a),r&&i?r.merge(i).order():i},merge:function(t){for(var e=t.selection?t.selection():t,n=this._groups,r=e._groups,i=n.length,a=r.length,o=Math.min(i,a),s=new Array(i),c=0;c<o;++c)for(var u,l=n[c],h=r[c],f=l.length,d=s[c]=new Array(f),p=0;p<f;++p)(u=l[p]||h[p])&&(d[p]=u);for(;c<i;++c)s[c]=n[c];return new Dt(s,this._parents)},selection:function(){return this},order:function(){for(var t=this._groups,e=-1,n=t.length;++e<n;)for(var r,i=t[e],a=i.length-1,o=i[a];--a>=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=F);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a<r;++a){for(var o,s=n[a],c=s.length,u=i[a]=new Array(c),l=0;l<c;++l)(o=s[l])&&(u[l]=o);u.sort(e)}return new Dt(i,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){return Array.from(this)},node:function(){for(var t=this._groups,e=0,n=t.length;e<n;++e)for(var r=t[e],i=0,a=r.length;i<a;++i){var o=r[i];if(o)return o}return null},size:function(){let t=0;for(const e of this)++t;return t},empty:function(){return!this.node()},each:function(t){for(var e=this._groups,n=0,r=e.length;n<r;++n)for(var i,a=e[n],o=0,s=a.length;o<s;++o)(i=a[o])&&t.call(i,i.__data__,o,a);return this},attr:function(t,e){var n=Y(t);if(arguments.length<2){var r=this.node();return n.local?r.getAttributeNS(n.space,n.local):r.getAttribute(n)}return this.each((null==e?n.local?U:z:"function"==typeof e?n.local?W:$:n.local?H:q)(n,e))},style:function(t,e,n){return arguments.length>1?this.each((null==e?G:"function"==typeof e?Z:X)(t,e,null==n?"":n)):Q(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?K:"function"==typeof e?tt:J)(t,e)):this.node()[t]},classed:function(t,e){var n=et(t+"");if(arguments.length<2){for(var r=nt(this.node()),i=-1,a=n.length;++i<a;)if(!r.contains(n[i]))return!1;return!0}return this.each(("function"==typeof e?ct:e?ot:st)(n,e))},text:function(t){return arguments.length?this.each(null==t?ut:("function"==typeof t?ht:lt)(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?ft:("function"==typeof t?pt:dt)(t)):this.node().innerHTML},raise:function(){return this.each(yt)},lower:function(){return this.each(gt)},append:function(t){var e="function"==typeof t?t:bt(t);return this.select((function(){return this.appendChild(e.apply(this,arguments))}))},insert:function(t,e){var n="function"==typeof t?t:bt(t),r=null==e?_t:"function"==typeof e?e:_(e);return this.select((function(){return this.insertBefore(n.apply(this,arguments),r.apply(this,arguments)||null)}))},remove:function(){return this.each(xt)},clone:function(t){return this.select(t?kt:wt)},datum:function(t){return arguments.length?this.property("__data__",t):this.node().__data__},on:function(t,e,n){var r,i,a=Tt(t+""),o=a.length;if(!(arguments.length<2)){for(s=e?Ct:Et,r=0;r<o;++r)this.each(s(a[r],e,n));return this}var s=this.node().__on;if(s)for(var c,u=0,l=s.length;u<l;++u)for(r=0,c=s[u];r<o;++r)if((i=a[r]).type===c.type&&i.name===c.name)return c.value},dispatch:function(t,e){return this.each(("function"==typeof e?Mt:At)(t,e))},[Symbol.iterator]:function*(){for(var t=this._groups,e=0,n=t.length;e<n;++e)for(var r,i=t[e],a=0,o=i.length;a<o;++a)(r=i[a])&&(yield r)}};const Bt=Ot;var Lt={value:()=>{}};function It(){for(var t,e=0,n=arguments.length,r={};e<n;++e){if(!(t=arguments[e]+"")||t in r||/[\s.]/.test(t))throw new Error("illegal type: "+t);r[t]=[]}return new Rt(r)}function Rt(t){this._=t}function Ft(t,e){return t.trim().split(/^|\s+/).map((function(t){var n="",r=t.indexOf(".");if(r>=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function Pt(t,e){for(var n,r=0,i=t.length;r<i;++r)if((n=t[r]).name===e)return n.value}function jt(t,e,n){for(var r=0,i=t.length;r<i;++r)if(t[r].name===e){t[r]=Lt,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=n&&t.push({name:e,value:n}),t}Rt.prototype=It.prototype={constructor:Rt,on:function(t,e){var n,r=this._,i=Ft(t+"",r),a=-1,o=i.length;if(!(arguments.length<2)){if(null!=e&&"function"!=typeof e)throw new Error("invalid callback: "+e);for(;++a<o;)if(n=(t=i[a]).type)r[n]=jt(r[n],t.name,e);else if(null==e)for(n in r)r[n]=jt(r[n],t.name,null);return this}for(;++a<o;)if((n=(t=i[a]).type)&&(n=Pt(r[n],t.name)))return n},copy:function(){var t={},e=this._;for(var n in e)t[n]=e[n].slice();return new Rt(t)},call:function(t,e){if((n=arguments.length-2)>0)for(var n,r,i=new Array(n),a=0;a<n;++a)i[a]=arguments[a+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(a=0,n=(r=this._[t]).length;a<n;++a)r[a].value.apply(e,i)},apply:function(t,e,n){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,a=r.length;i<a;++i)r[i].value.apply(e,n)}};const Yt=It;var zt,Ut,qt=0,Ht=0,$t=0,Wt=0,Vt=0,Gt=0,Xt="object"==typeof performance&&performance.now?performance:Date,Zt="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function Qt(){return Vt||(Zt(Kt),Vt=Xt.now()+Gt)}function Kt(){Vt=0}function Jt(){this._call=this._time=this._next=null}function te(t,e,n){var r=new Jt;return r.restart(t,e,n),r}function ee(){Vt=(Wt=Xt.now())+Gt,qt=Ht=0;try{!function(){Qt(),++qt;for(var t,e=zt;e;)(t=Vt-e._time)>=0&&e._call.call(void 0,t),e=e._next;--qt}()}finally{qt=0,function(){for(var t,e,n=zt,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:zt=e);Ut=t,re(r)}(),Vt=0}}function ne(){var t=Xt.now(),e=t-Wt;e>1e3&&(Gt-=e,Wt=t)}function re(t){qt||(Ht&&(Ht=clearTimeout(Ht)),t-Vt>24?(t<1/0&&(Ht=setTimeout(ee,t-Xt.now()-Gt)),$t&&($t=clearInterval($t))):($t||(Wt=Xt.now(),$t=setInterval(ne,1e3)),qt=1,Zt(ee)))}function ie(t,e,n){var r=new Jt;return e=null==e?0:+e,r.restart((n=>{r.stop(),t(n+e)}),e,n),r}Jt.prototype=te.prototype={constructor:Jt,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?Qt():+n)+(null==e?0:+e),this._next||Ut===this||(Ut?Ut._next=this:zt=this,Ut=this),this._call=t,this._time=n,re()},stop:function(){this._call&&(this._call=null,this._time=1/0,re())}};var ae=Yt("start","end","cancel","interrupt"),oe=[];function se(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return ie(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u<e&&(f.state=6,f.timer.stop(),f.on.call("cancel",t,t.__data__,f.index,f.group),delete i[u])}if(ie((function(){3===n.state&&(n.state=4,n.timer.restart(o,n.delay,n.time),o(c))})),n.state=2,n.on.call("start",t,t.__data__,n.index,n.group),2===n.state){for(n.state=3,r=new Array(h=n.tween.length),u=0,l=-1;u<h;++u)(f=n.tween[u].value.call(t,t.__data__,n.index,n.group))&&(r[++l]=f);r.length=l+1}}function o(e){for(var i=e<n.duration?n.ease.call(null,e/n.duration):(n.timer.restart(s),n.state=5,1),a=-1,o=r.length;++a<o;)r[a].call(t,i);5===n.state&&(n.on.call("end",t,t.__data__,n.index,n.group),s())}function s(){for(var r in n.state=6,n.timer.stop(),delete i[e],i)return;delete t.__transition}i[e]=n,n.timer=te((function(t){n.state=1,n.timer.restart(a,n.delay,n.time),n.delay<=t&&a(t-n.delay)}),0,n.time)}(t,n,{name:e,index:r,group:i,on:ae,tween:oe,time:a.time,delay:a.delay,duration:a.duration,ease:a.ease,timer:null,state:0})}function ce(t,e){var n=le(t,e);if(n.state>0)throw new Error("too late; already scheduled");return n}function ue(t,e){var n=le(t,e);if(n.state>3)throw new Error("too late; already running");return n}function le(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function he(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}var fe,de=180/Math.PI,pe={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function ye(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r<e*n&&(t=-t,e=-e,c=-c,o=-o),{translateX:i,translateY:a,rotate:Math.atan2(e,t)*de,skewX:Math.atan(c)*de,scaleX:o,scaleY:s}}function ge(t,e,n,r){function i(t){return t.length?t.pop()+" ":""}return function(a,o){var s=[],c=[];return a=t(a),o=t(o),function(t,r,i,a,o,s){if(t!==i||r!==a){var c=o.push("translate(",null,e,null,n);s.push({i:c-4,x:he(t,i)},{i:c-2,x:he(r,a)})}else(i||a)&&o.push("translate("+i+e+a+n)}(a.translateX,a.translateY,o.translateX,o.translateY,s,c),function(t,e,n,a){t!==e?(t-e>180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:he(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:he(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:he(t,n)},{i:s-2,x:he(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n<r;)s[(e=c[n]).i]=e.x(t);return s.join("")}}}var me=ge((function(t){const e=new("function"==typeof DOMMatrix?DOMMatrix:WebKitCSSMatrix)(t+"");return e.isIdentity?pe:ye(e.a,e.b,e.c,e.d,e.e,e.f)}),"px, ","px)","deg)"),ve=ge((function(t){return null==t?pe:(fe||(fe=document.createElementNS("http://www.w3.org/2000/svg","g")),fe.setAttribute("transform",t),(t=fe.transform.baseVal.consolidate())?ye((t=t.matrix).a,t.b,t.c,t.d,t.e,t.f):pe)}),", ",")",")");function be(t,e){var n,r;return function(){var i=ue(this,t),a=i.tween;if(a!==n)for(var o=0,s=(r=n=a).length;o<s;++o)if(r[o].name===e){(r=r.slice()).splice(o,1);break}i.tween=r}}function _e(t,e,n){var r,i;if("function"!=typeof n)throw new Error;return function(){var a=ue(this,t),o=a.tween;if(o!==r){i=(r=o).slice();for(var s={name:e,value:n},c=0,u=i.length;c<u;++c)if(i[c].name===e){i[c]=s;break}c===u&&i.push(s)}a.tween=i}}function xe(t,e,n){var r=t._id;return t.each((function(){var t=ue(this,r);(t.value||(t.value={}))[e]=n.apply(this,arguments)})),function(t){return le(t,r).value[e]}}function we(t,e,n){t.prototype=e.prototype=n,n.constructor=t}function ke(t,e){var n=Object.create(t.prototype);for(var r in e)n[r]=e[r];return n}function Te(){}var Ee=.7,Ce=1/Ee,Se="\\s*([+-]?\\d+)\\s*",Ae="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",Me="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",Ne=/^#([0-9a-f]{3,8})$/,De=new RegExp("^rgb\\("+[Se,Se,Se]+"\\)$"),Oe=new RegExp("^rgb\\("+[Me,Me,Me]+"\\)$"),Be=new RegExp("^rgba\\("+[Se,Se,Se,Ae]+"\\)$"),Le=new RegExp("^rgba\\("+[Me,Me,Me,Ae]+"\\)$"),Ie=new RegExp("^hsl\\("+[Ae,Me,Me]+"\\)$"),Re=new RegExp("^hsla\\("+[Ae,Me,Me,Ae]+"\\)$"),Fe={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function Pe(){return this.rgb().formatHex()}function je(){return this.rgb().formatRgb()}function Ye(t){var e,n;return t=(t+"").trim().toLowerCase(),(e=Ne.exec(t))?(n=e[1].length,e=parseInt(e[1],16),6===n?ze(e):3===n?new $e(e>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?Ue(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?Ue(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=De.exec(t))?new $e(e[1],e[2],e[3],1):(e=Oe.exec(t))?new $e(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Be.exec(t))?Ue(e[1],e[2],e[3],e[4]):(e=Le.exec(t))?Ue(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=Ie.exec(t))?Xe(e[1],e[2]/100,e[3]/100,1):(e=Re.exec(t))?Xe(e[1],e[2]/100,e[3]/100,e[4]):Fe.hasOwnProperty(t)?ze(Fe[t]):"transparent"===t?new $e(NaN,NaN,NaN,0):null}function ze(t){return new $e(t>>16&255,t>>8&255,255&t,1)}function Ue(t,e,n,r){return r<=0&&(t=e=n=NaN),new $e(t,e,n,r)}function qe(t){return t instanceof Te||(t=Ye(t)),t?new $e((t=t.rgb()).r,t.g,t.b,t.opacity):new $e}function He(t,e,n,r){return 1===arguments.length?qe(t):new $e(t,e,n,null==r?1:r)}function $e(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function We(){return"#"+Ge(this.r)+Ge(this.g)+Ge(this.b)}function Ve(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function Ge(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function Xe(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new Qe(t,e,n,r)}function Ze(t){if(t instanceof Qe)return new Qe(t.h,t.s,t.l,t.opacity);if(t instanceof Te||(t=Ye(t)),!t)return new Qe;if(t instanceof Qe)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n<r):n===a?(r-e)/s+2:(e-n)/s+4,s/=c<.5?a+i:2-a-i,o*=60):s=c>0&&c<1?0:o,new Qe(o,s,c,t.opacity)}function Qe(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function Ke(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function Je(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}we(Te,Ye,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:Pe,formatHex:Pe,formatHsl:function(){return Ze(this).formatHsl()},formatRgb:je,toString:je}),we($e,He,ke(Te,{brighter:function(t){return t=null==t?Ce:Math.pow(Ce,t),new $e(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?Ee:Math.pow(Ee,t),new $e(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:We,formatHex:We,formatRgb:Ve,toString:Ve})),we(Qe,(function(t,e,n,r){return 1===arguments.length?Ze(t):new Qe(t,e,n,null==r?1:r)}),ke(Te,{brighter:function(t){return t=null==t?Ce:Math.pow(Ce,t),new Qe(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Ee:Math.pow(Ee,t),new Qe(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new $e(Ke(t>=240?t-240:t+120,i,r),Ke(t,i,r),Ke(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const tn=t=>()=>t;function en(t,e){var n=e-t;return n?function(t,e){return function(n){return t+n*e}}(t,n):tn(isNaN(t)?e:t)}const nn=function t(e){var n=function(t){return 1==(t=+t)?en:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):tn(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=He(t)).r,(e=He(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=en(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function rn(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n<i;++n)r=He(e[n]),a[n]=r.r||0,o[n]=r.g||0,s[n]=r.b||0;return a=t(a),o=t(o),s=t(s),r.opacity=1,function(t){return r.r=a(t),r.g=o(t),r.b=s(t),r+""}}}rn((function(t){var e=t.length-1;return function(n){var r=n<=0?n=0:n>=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=r<e-1?t[r+2]:2*a-i;return Je((n-r/e)*e,o,i,a,s)}})),rn((function(t){var e=t.length;return function(n){var r=Math.floor(((n%=1)<0?++n:n)*e),i=t[(r+e-1)%e],a=t[r%e],o=t[(r+1)%e],s=t[(r+2)%e];return Je((n-r/e)*e,i,a,o,s)}}));var an=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,on=new RegExp(an.source,"g");function sn(t,e){var n,r,i,a=an.lastIndex=on.lastIndex=0,o=-1,s=[],c=[];for(t+="",e+="";(n=an.exec(t))&&(r=on.exec(e));)(i=r.index)>a&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:he(n,r)})),a=on.lastIndex;return a<e.length&&(i=e.slice(a),s[o]?s[o]+=i:s[++o]=i),s.length<2?c[0]?function(t){return function(e){return t(e)+""}}(c[0].x):function(t){return function(){return t}}(e):(e=c.length,function(t){for(var n,r=0;r<e;++r)s[(n=c[r]).i]=n.x(t);return s.join("")})}function cn(t,e){var n;return("number"==typeof e?he:e instanceof Ye?nn:(n=Ye(e))?(e=n,nn):sn)(t,e)}function un(t){return function(){this.removeAttribute(t)}}function ln(t){return function(){this.removeAttributeNS(t.space,t.local)}}function hn(t,e,n){var r,i,a=n+"";return function(){var o=this.getAttribute(t);return o===a?null:o===r?i:i=e(r=o,n)}}function fn(t,e,n){var r,i,a=n+"";return function(){var o=this.getAttributeNS(t.space,t.local);return o===a?null:o===r?i:i=e(r=o,n)}}function dn(t,e,n){var r,i,a;return function(){var o,s,c=n(this);if(null!=c)return(o=this.getAttribute(t))===(s=c+"")?null:o===r&&s===i?a:(i=s,a=e(r=o,c));this.removeAttribute(t)}}function pn(t,e,n){var r,i,a;return function(){var o,s,c=n(this);if(null!=c)return(o=this.getAttributeNS(t.space,t.local))===(s=c+"")?null:o===r&&s===i?a:(i=s,a=e(r=o,c));this.removeAttributeNS(t.space,t.local)}}function yn(t,e){return function(n){this.setAttribute(t,e.call(this,n))}}function gn(t,e){return function(n){this.setAttributeNS(t.space,t.local,e.call(this,n))}}function mn(t,e){var n,r;function i(){var i=e.apply(this,arguments);return i!==r&&(n=(r=i)&&gn(t,i)),n}return i._value=e,i}function vn(t,e){var n,r;function i(){var i=e.apply(this,arguments);return i!==r&&(n=(r=i)&&yn(t,i)),n}return i._value=e,i}function bn(t,e){return function(){ce(this,t).delay=+e.apply(this,arguments)}}function _n(t,e){return e=+e,function(){ce(this,t).delay=e}}function xn(t,e){return function(){ue(this,t).duration=+e.apply(this,arguments)}}function wn(t,e){return e=+e,function(){ue(this,t).duration=e}}function kn(t,e){if("function"!=typeof e)throw new Error;return function(){ue(this,t).ease=e}}function Tn(t,e,n){var r,i,a=function(t){return(t+"").trim().split(/^|\s+/).every((function(t){var e=t.indexOf(".");return e>=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?ce:ue;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var En=Bt.prototype.constructor;function Cn(t){return function(){this.style.removeProperty(t)}}function Sn(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function An(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&Sn(t,a,n)),r}return a._value=e,a}function Mn(t){return function(e){this.textContent=t.call(this,e)}}function Nn(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&Mn(r)),e}return r._value=t,r}var Dn=0;function On(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function Bn(){return++Dn}var Ln=Bt.prototype;On.prototype=function(t){return Bt().transition(t)}.prototype={constructor:On,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=_(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o<i;++o)for(var s,c,u=r[o],l=u.length,h=a[o]=new Array(l),f=0;f<l;++f)(s=u[f])&&(c=t.call(s,s.__data__,f,u))&&("__data__"in s&&(c.__data__=s.__data__),h[f]=c,se(h[f],e,n,f,h,le(s,n)));return new On(a,this._parents,e,n)},selectAll:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=k(t));for(var r=this._groups,i=r.length,a=[],o=[],s=0;s<i;++s)for(var c,u=r[s],l=u.length,h=0;h<l;++h)if(c=u[h]){for(var f,d=t.call(c,c.__data__,h,u),p=le(c,n),y=0,g=d.length;y<g;++y)(f=d[y])&&se(f,e,n,y,d,p);a.push(d),o.push(c)}return new On(a,o,e,n)},selectChild:Ln.selectChild,selectChildren:Ln.selectChildren,filter:function(t){"function"!=typeof t&&(t=T(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o=e[i],s=o.length,c=r[i]=[],u=0;u<s;++u)(a=o[u])&&t.call(a,a.__data__,u,o)&&c.push(a);return new On(r,this._parents,this._name,this._id)},merge:function(t){if(t._id!==this._id)throw new Error;for(var e=this._groups,n=t._groups,r=e.length,i=n.length,a=Math.min(r,i),o=new Array(r),s=0;s<a;++s)for(var c,u=e[s],l=n[s],h=u.length,f=o[s]=new Array(h),d=0;d<h;++d)(c=u[d]||l[d])&&(f[d]=c);for(;s<r;++s)o[s]=e[s];return new On(o,this._parents,this._name,this._id)},selection:function(){return new En(this._groups,this._parents)},transition:function(){for(var t=this._name,e=this._id,n=Bn(),r=this._groups,i=r.length,a=0;a<i;++a)for(var o,s=r[a],c=s.length,u=0;u<c;++u)if(o=s[u]){var l=le(o,e);se(o,t,n,u,s,{time:l.time+l.delay+l.duration,delay:0,duration:l.duration,ease:l.ease})}return new On(r,this._parents,t,n)},call:Ln.call,nodes:Ln.nodes,node:Ln.node,size:Ln.size,empty:Ln.empty,each:Ln.each,on:function(t,e){var n=this._id;return arguments.length<2?le(this.node(),n).on.on(t):this.each(Tn(n,t,e))},attr:function(t,e){var n=Y(t),r="transform"===n?ve:cn;return this.attrTween(t,"function"==typeof e?(n.local?pn:dn)(n,r,xe(this,"attr."+t,e)):null==e?(n.local?ln:un)(n):(n.local?fn:hn)(n,r,e))},attrTween:function(t,e){var n="attr."+t;if(arguments.length<2)return(n=this.tween(n))&&n._value;if(null==e)return this.tween(n,null);if("function"!=typeof e)throw new Error;var r=Y(t);return this.tween(n,(r.local?mn:vn)(r,e))},style:function(t,e,n){var r="transform"==(t+="")?me:cn;return null==e?this.styleTween(t,function(t,e){var n,r,i;return function(){var a=Q(this,t),o=(this.style.removeProperty(t),Q(this,t));return a===o?null:a===n&&o===r?i:i=e(n=a,r=o)}}(t,r)).on("end.style."+t,Cn(t)):"function"==typeof e?this.styleTween(t,function(t,e,n){var r,i,a;return function(){var o=Q(this,t),s=n(this),c=s+"";return null==s&&(this.style.removeProperty(t),c=s=Q(this,t)),o===c?null:o===r&&c===i?a:(i=c,a=e(r=o,s))}}(t,r,xe(this,"style."+t,e))).each(function(t,e){var n,r,i,a,o="style."+e,s="end."+o;return function(){var c=ue(this,t),u=c.on,l=null==c.value[o]?a||(a=Cn(e)):void 0;u===n&&i===l||(r=(n=u).copy()).on(s,i=l),c.on=r}}(this._id,t)):this.styleTween(t,function(t,e,n){var r,i,a=n+"";return function(){var o=Q(this,t);return o===a?null:o===r?i:i=e(r=o,n)}}(t,r,e),n).on("end.style."+t,null)},styleTween:function(t,e,n){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==e)return this.tween(r,null);if("function"!=typeof e)throw new Error;return this.tween(r,An(t,e,null==n?"":n))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var e=t(this);this.textContent=null==e?"":e}}(xe(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},textTween:function(t){var e="text";if(arguments.length<1)return(e=this.tween(e))&&e._value;if(null==t)return this.tween(e,null);if("function"!=typeof t)throw new Error;return this.tween(e,Nn(t))},remove:function(){return this.on("end.remove",function(t){return function(){var e=this.parentNode;for(var n in this.__transition)if(+n!==t)return;e&&e.removeChild(this)}}(this._id))},tween:function(t,e){var n=this._id;if(t+="",arguments.length<2){for(var r,i=le(this.node(),n).tween,a=0,o=i.length;a<o;++a)if((r=i[a]).name===t)return r.value;return null}return this.each((null==e?be:_e)(n,t,e))},delay:function(t){var e=this._id;return arguments.length?this.each(("function"==typeof t?bn:_n)(e,t)):le(this.node(),e).delay},duration:function(t){var e=this._id;return arguments.length?this.each(("function"==typeof t?xn:wn)(e,t)):le(this.node(),e).duration},ease:function(t){var e=this._id;return arguments.length?this.each(kn(e,t)):le(this.node(),e).ease},easeVarying:function(t){if("function"!=typeof t)throw new Error;return this.each(function(t,e){return function(){var n=e.apply(this,arguments);if("function"!=typeof n)throw new Error;ue(this,t).ease=n}}(this._id,t))},end:function(){var t,e,n=this,r=n._id,i=n.size();return new Promise((function(a,o){var s={value:o},c={value:function(){0==--i&&a()}};n.each((function(){var n=ue(this,r),i=n.on;i!==t&&((e=(t=i).copy())._.cancel.push(s),e._.interrupt.push(s),e._.end.push(c)),n.on=e})),0===i&&a()}))},[Symbol.iterator]:Ln[Symbol.iterator]};var In={time:null,delay:0,duration:250,ease:function(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}};function Rn(t,e){for(var n;!(n=t.__transition)||!(n=n[e]);)if(!(t=t.parentNode))throw new Error(`transition ${e} not found`);return n}Bt.prototype.interrupt=function(t){return this.each((function(){!function(t,e){var n,r,i,a=t.__transition,o=!0;if(a){for(i in e=null==e?null:e+"",a)(n=a[i]).name===e?(r=n.state>2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}(this,t)}))},Bt.prototype.transition=function(t){var e,n;t instanceof On?(e=t._id,t=t._name):(e=Bn(),(n=In).time=Qt(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;a<i;++a)for(var o,s=r[a],c=s.length,u=0;u<c;++u)(o=s[u])&&se(o,t,e,u,s,n||Rn(o,e));return new On(r,this._parents,t,e)};const{abs:Fn,max:Pn,min:jn}=Math;function Yn(t){return{type:t}}function zn(t,e,n){t.prototype=e.prototype=n,n.constructor=t}function Un(t,e){var n=Object.create(t.prototype);for(var r in e)n[r]=e[r];return n}function qn(){}["w","e"].map(Yn),["n","s"].map(Yn),["n","w","e","s","nw","ne","sw","se"].map(Yn);var Hn=.7,$n=1/Hn,Wn="\\s*([+-]?\\d+)\\s*",Vn="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",Gn="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",Xn=/^#([0-9a-f]{3,8})$/,Zn=new RegExp("^rgb\\("+[Wn,Wn,Wn]+"\\)$"),Qn=new RegExp("^rgb\\("+[Gn,Gn,Gn]+"\\)$"),Kn=new RegExp("^rgba\\("+[Wn,Wn,Wn,Vn]+"\\)$"),Jn=new RegExp("^rgba\\("+[Gn,Gn,Gn,Vn]+"\\)$"),tr=new RegExp("^hsl\\("+[Vn,Gn,Gn]+"\\)$"),er=new RegExp("^hsla\\("+[Vn,Gn,Gn,Vn]+"\\)$"),nr={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function rr(){return this.rgb().formatHex()}function ir(){return this.rgb().formatRgb()}function ar(t){var e,n;return t=(t+"").trim().toLowerCase(),(e=Xn.exec(t))?(n=e[1].length,e=parseInt(e[1],16),6===n?or(e):3===n?new lr(e>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?sr(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?sr(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Zn.exec(t))?new lr(e[1],e[2],e[3],1):(e=Qn.exec(t))?new lr(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Kn.exec(t))?sr(e[1],e[2],e[3],e[4]):(e=Jn.exec(t))?sr(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=tr.exec(t))?pr(e[1],e[2]/100,e[3]/100,1):(e=er.exec(t))?pr(e[1],e[2]/100,e[3]/100,e[4]):nr.hasOwnProperty(t)?or(nr[t]):"transparent"===t?new lr(NaN,NaN,NaN,0):null}function or(t){return new lr(t>>16&255,t>>8&255,255&t,1)}function sr(t,e,n,r){return r<=0&&(t=e=n=NaN),new lr(t,e,n,r)}function cr(t){return t instanceof qn||(t=ar(t)),t?new lr((t=t.rgb()).r,t.g,t.b,t.opacity):new lr}function ur(t,e,n,r){return 1===arguments.length?cr(t):new lr(t,e,n,null==r?1:r)}function lr(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function hr(){return"#"+dr(this.r)+dr(this.g)+dr(this.b)}function fr(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function dr(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function pr(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new gr(t,e,n,r)}function yr(t){if(t instanceof gr)return new gr(t.h,t.s,t.l,t.opacity);if(t instanceof qn||(t=ar(t)),!t)return new gr;if(t instanceof gr)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n<r):n===a?(r-e)/s+2:(e-n)/s+4,s/=c<.5?a+i:2-a-i,o*=60):s=c>0&&c<1?0:o,new gr(o,s,c,t.opacity)}function gr(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function mr(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}zn(qn,ar,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:rr,formatHex:rr,formatHsl:function(){return yr(this).formatHsl()},formatRgb:ir,toString:ir}),zn(lr,ur,Un(qn,{brighter:function(t){return t=null==t?$n:Math.pow($n,t),new lr(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?Hn:Math.pow(Hn,t),new lr(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:hr,formatHex:hr,formatRgb:fr,toString:fr})),zn(gr,(function(t,e,n,r){return 1===arguments.length?yr(t):new gr(t,e,n,null==r?1:r)}),Un(qn,{brighter:function(t){return t=null==t?$n:Math.pow($n,t),new gr(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Hn:Math.pow(Hn,t),new gr(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new lr(mr(t>=240?t-240:t+120,i,r),mr(t,i,r),mr(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const vr=Math.PI/180,br=180/Math.PI,_r=.96422,xr=.82521,wr=4/29,kr=6/29,Tr=3*kr*kr;function Er(t){if(t instanceof Cr)return new Cr(t.l,t.a,t.b,t.opacity);if(t instanceof Br)return Lr(t);t instanceof lr||(t=cr(t));var e,n,r=Nr(t.r),i=Nr(t.g),a=Nr(t.b),o=Sr((.2225045*r+.7168786*i+.0606169*a)/1);return r===i&&i===a?e=n=o:(e=Sr((.4360747*r+.3850649*i+.1430804*a)/_r),n=Sr((.0139322*r+.0971045*i+.7141733*a)/xr)),new Cr(116*o-16,500*(e-o),200*(o-n),t.opacity)}function Cr(t,e,n,r){this.l=+t,this.a=+e,this.b=+n,this.opacity=+r}function Sr(t){return t>.008856451679035631?Math.pow(t,1/3):t/Tr+wr}function Ar(t){return t>kr?t*t*t:Tr*(t-wr)}function Mr(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Nr(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Dr(t){if(t instanceof Br)return new Br(t.h,t.c,t.l,t.opacity);if(t instanceof Cr||(t=Er(t)),0===t.a&&0===t.b)return new Br(NaN,0<t.l&&t.l<100?0:NaN,t.l,t.opacity);var e=Math.atan2(t.b,t.a)*br;return new Br(e<0?e+360:e,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function Or(t,e,n,r){return 1===arguments.length?Dr(t):new Br(t,e,n,null==r?1:r)}function Br(t,e,n,r){this.h=+t,this.c=+e,this.l=+n,this.opacity=+r}function Lr(t){if(isNaN(t.h))return new Cr(t.l,0,0,t.opacity);var e=t.h*vr;return new Cr(t.l,Math.cos(e)*t.c,Math.sin(e)*t.c,t.opacity)}zn(Cr,(function(t,e,n,r){return 1===arguments.length?Er(t):new Cr(t,e,n,null==r?1:r)}),Un(qn,{brighter:function(t){return new Cr(this.l+18*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new Cr(this.l-18*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,e=isNaN(this.a)?t:t+this.a/500,n=isNaN(this.b)?t:t-this.b/200;return new lr(Mr(3.1338561*(e=_r*Ar(e))-1.6168667*(t=1*Ar(t))-.4906146*(n=xr*Ar(n))),Mr(-.9787684*e+1.9161415*t+.033454*n),Mr(.0719453*e-.2289914*t+1.4052427*n),this.opacity)}})),zn(Br,Or,Un(qn,{brighter:function(t){return new Br(this.h,this.c,this.l+18*(null==t?1:t),this.opacity)},darker:function(t){return new Br(this.h,this.c,this.l-18*(null==t?1:t),this.opacity)},rgb:function(){return Lr(this).rgb()}}));const Ir=t=>()=>t;function Rr(t,e){return function(n){return t+n*e}}function Fr(t,e){var n=e-t;return n?Rr(t,n):Ir(isNaN(t)?e:t)}function Pr(t){return function(e,n){var r=t((e=Or(e)).h,(n=Or(n)).h),i=Fr(e.c,n.c),a=Fr(e.l,n.l),o=Fr(e.opacity,n.opacity);return function(t){return e.h=r(t),e.c=i(t),e.l=a(t),e.opacity=o(t),e+""}}}const jr=Pr((function(t,e){var n=e-t;return n?Rr(t,n>180||n<-180?n-360*Math.round(n/360):n):Ir(isNaN(t)?e:t)}));Pr(Fr);var Yr=Math.sqrt(50),zr=Math.sqrt(10),Ur=Math.sqrt(2);function qr(t,e,n){var r=(e-t)/Math.max(0,n),i=Math.floor(Math.log(r)/Math.LN10),a=r/Math.pow(10,i);return i>=0?(a>=Yr?10:a>=zr?5:a>=Ur?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(a>=Yr?10:a>=zr?5:a>=Ur?2:1)}function Hr(t,e,n){var r=Math.abs(e-t)/Math.max(0,n),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),a=r/i;return a>=Yr?i*=10:a>=zr?i*=5:a>=Ur&&(i*=2),e<t?-i:i}function $r(t,e){return null==t||null==e?NaN:t<e?-1:t>e?1:t>=e?0:NaN}function Wr(t){let e=t,n=t,r=t;function i(t,e,i=0,a=t.length){if(i<a){if(0!==n(e,e))return a;do{const n=i+a>>>1;r(t[n],e)<0?i=n+1:a=n}while(i<a)}return i}return 2!==t.length&&(e=(e,n)=>t(e)-n,n=$r,r=(e,n)=>$r(t(e),n)),{left:i,center:function(t,n,r=0,a=t.length){const o=i(t,n,r,a-1);return o>r&&e(t[o-1],n)>-e(t[o],n)?o-1:o},right:function(t,e,i=0,a=t.length){if(i<a){if(0!==n(e,e))return a;do{const n=i+a>>>1;r(t[n],e)<=0?i=n+1:a=n}while(i<a)}return i}}}const Vr=Wr($r),Gr=Vr.right,Xr=(Vr.left,Wr((function(t){return null===t?NaN:+t})).center,Gr);function Zr(t,e,n){t.prototype=e.prototype=n,n.constructor=t}function Qr(t,e){var n=Object.create(t.prototype);for(var r in e)n[r]=e[r];return n}function Kr(){}var Jr=.7,ti=1.4285714285714286,ei="\\s*([+-]?\\d+)\\s*",ni="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",ri="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",ii=/^#([0-9a-f]{3,8})$/,ai=new RegExp("^rgb\\("+[ei,ei,ei]+"\\)$"),oi=new RegExp("^rgb\\("+[ri,ri,ri]+"\\)$"),si=new RegExp("^rgba\\("+[ei,ei,ei,ni]+"\\)$"),ci=new RegExp("^rgba\\("+[ri,ri,ri,ni]+"\\)$"),ui=new RegExp("^hsl\\("+[ni,ri,ri]+"\\)$"),li=new RegExp("^hsla\\("+[ni,ri,ri,ni]+"\\)$"),hi={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function fi(){return this.rgb().formatHex()}function di(){return this.rgb().formatRgb()}function pi(t){var e,n;return t=(t+"").trim().toLowerCase(),(e=ii.exec(t))?(n=e[1].length,e=parseInt(e[1],16),6===n?yi(e):3===n?new bi(e>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?gi(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?gi(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=ai.exec(t))?new bi(e[1],e[2],e[3],1):(e=oi.exec(t))?new bi(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=si.exec(t))?gi(e[1],e[2],e[3],e[4]):(e=ci.exec(t))?gi(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=ui.exec(t))?ki(e[1],e[2]/100,e[3]/100,1):(e=li.exec(t))?ki(e[1],e[2]/100,e[3]/100,e[4]):hi.hasOwnProperty(t)?yi(hi[t]):"transparent"===t?new bi(NaN,NaN,NaN,0):null}function yi(t){return new bi(t>>16&255,t>>8&255,255&t,1)}function gi(t,e,n,r){return r<=0&&(t=e=n=NaN),new bi(t,e,n,r)}function mi(t){return t instanceof Kr||(t=pi(t)),t?new bi((t=t.rgb()).r,t.g,t.b,t.opacity):new bi}function vi(t,e,n,r){return 1===arguments.length?mi(t):new bi(t,e,n,null==r?1:r)}function bi(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function _i(){return"#"+wi(this.r)+wi(this.g)+wi(this.b)}function xi(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function wi(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function ki(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new Ei(t,e,n,r)}function Ti(t){if(t instanceof Ei)return new Ei(t.h,t.s,t.l,t.opacity);if(t instanceof Kr||(t=pi(t)),!t)return new Ei;if(t instanceof Ei)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n<r):n===a?(r-e)/s+2:(e-n)/s+4,s/=c<.5?a+i:2-a-i,o*=60):s=c>0&&c<1?0:o,new Ei(o,s,c,t.opacity)}function Ei(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function Ci(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function Si(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}Zr(Kr,pi,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:fi,formatHex:fi,formatHsl:function(){return Ti(this).formatHsl()},formatRgb:di,toString:di}),Zr(bi,vi,Qr(Kr,{brighter:function(t){return t=null==t?ti:Math.pow(ti,t),new bi(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?Jr:Math.pow(Jr,t),new bi(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:_i,formatHex:_i,formatRgb:xi,toString:xi})),Zr(Ei,(function(t,e,n,r){return 1===arguments.length?Ti(t):new Ei(t,e,n,null==r?1:r)}),Qr(Kr,{brighter:function(t){return t=null==t?ti:Math.pow(ti,t),new Ei(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Jr:Math.pow(Jr,t),new Ei(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new bi(Ci(t>=240?t-240:t+120,i,r),Ci(t,i,r),Ci(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const Ai=t=>()=>t;function Mi(t,e){var n=e-t;return n?function(t,e){return function(n){return t+n*e}}(t,n):Ai(isNaN(t)?e:t)}const Ni=function t(e){var n=function(t){return 1==(t=+t)?Mi:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):Ai(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=vi(t)).r,(e=vi(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=Mi(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function Di(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n<i;++n)r=vi(e[n]),a[n]=r.r||0,o[n]=r.g||0,s[n]=r.b||0;return a=t(a),o=t(o),s=t(s),r.opacity=1,function(t){return r.r=a(t),r.g=o(t),r.b=s(t),r+""}}}function Oi(t,e){var n,r=e?e.length:0,i=t?Math.min(r,t.length):0,a=new Array(i),o=new Array(r);for(n=0;n<i;++n)a[n]=Yi(t[n],e[n]);for(;n<r;++n)o[n]=e[n];return function(t){for(n=0;n<i;++n)o[n]=a[n](t);return o}}function Bi(t,e){var n=new Date;return t=+t,e=+e,function(r){return n.setTime(t*(1-r)+e*r),n}}function Li(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}function Ii(t,e){var n,r={},i={};for(n in null!==t&&"object"==typeof t||(t={}),null!==e&&"object"==typeof e||(e={}),e)n in t?r[n]=Yi(t[n],e[n]):i[n]=e[n];return function(t){for(n in r)i[n]=r[n](t);return i}}Di((function(t){var e=t.length-1;return function(n){var r=n<=0?n=0:n>=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=r<e-1?t[r+2]:2*a-i;return Si((n-r/e)*e,o,i,a,s)}})),Di((function(t){var e=t.length;return function(n){var r=Math.floor(((n%=1)<0?++n:n)*e),i=t[(r+e-1)%e],a=t[r%e],o=t[(r+1)%e],s=t[(r+2)%e];return Si((n-r/e)*e,i,a,o,s)}}));var Ri=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Fi=new RegExp(Ri.source,"g");function Pi(t,e){var n,r,i,a=Ri.lastIndex=Fi.lastIndex=0,o=-1,s=[],c=[];for(t+="",e+="";(n=Ri.exec(t))&&(r=Fi.exec(e));)(i=r.index)>a&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:Li(n,r)})),a=Fi.lastIndex;return a<e.length&&(i=e.slice(a),s[o]?s[o]+=i:s[++o]=i),s.length<2?c[0]?function(t){return function(e){return t(e)+""}}(c[0].x):function(t){return function(){return t}}(e):(e=c.length,function(t){for(var n,r=0;r<e;++r)s[(n=c[r]).i]=n.x(t);return s.join("")})}function ji(t,e){e||(e=[]);var n,r=t?Math.min(e.length,t.length):0,i=e.slice();return function(a){for(n=0;n<r;++n)i[n]=t[n]*(1-a)+e[n]*a;return i}}function Yi(t,e){var n,r,i=typeof e;return null==e||"boolean"===i?Ai(e):("number"===i?Li:"string"===i?(n=pi(e))?(e=n,Ni):Pi:e instanceof pi?Ni:e instanceof Date?Bi:(r=e,!ArrayBuffer.isView(r)||r instanceof DataView?Array.isArray(e)?Oi:"function"!=typeof e.valueOf&&"function"!=typeof e.toString||isNaN(e)?Ii:Li:ji))(t,e)}function zi(t,e){return t=+t,e=+e,function(n){return Math.round(t*(1-n)+e*n)}}function Ui(t){return+t}var qi=[0,1];function Hi(t){return t}function $i(t,e){return(e-=t=+t)?function(n){return(n-t)/e}:(n=isNaN(e)?NaN:.5,function(){return n});var n}function Wi(t,e,n){var r=t[0],i=t[1],a=e[0],o=e[1];return i<r?(r=$i(i,r),a=n(o,a)):(r=$i(r,i),a=n(a,o)),function(t){return a(r(t))}}function Vi(t,e,n){var r=Math.min(t.length,e.length)-1,i=new Array(r),a=new Array(r),o=-1;for(t[r]<t[0]&&(t=t.slice().reverse(),e=e.slice().reverse());++o<r;)i[o]=$i(t[o],t[o+1]),a[o]=n(e[o],e[o+1]);return function(e){var n=Xr(t,e,1,r)-1;return a[n](i[n](e))}}function Gi(t,e){return e.domain(t.domain()).range(t.range()).interpolate(t.interpolate()).clamp(t.clamp()).unknown(t.unknown())}function Xi(){return function(){var t,e,n,r,i,a,o=qi,s=qi,c=Yi,u=Hi;function l(){var t,e,n,c=Math.min(o.length,s.length);return u!==Hi&&(t=o[0],e=o[c-1],t>e&&(n=t,t=e,e=n),u=function(n){return Math.max(t,Math.min(e,n))}),r=c>2?Vi:Wi,i=a=null,h}function h(e){return null==e||isNaN(e=+e)?n:(i||(i=r(o.map(t),s,c)))(t(u(e)))}return h.invert=function(n){return u(e((a||(a=r(s,o.map(t),Li)))(n)))},h.domain=function(t){return arguments.length?(o=Array.from(t,Ui),l()):o.slice()},h.range=function(t){return arguments.length?(s=Array.from(t),l()):s.slice()},h.rangeRound=function(t){return s=Array.from(t),c=zi,l()},h.clamp=function(t){return arguments.length?(u=!!t||Hi,l()):u!==Hi},h.interpolate=function(t){return arguments.length?(c=t,l()):c},h.unknown=function(t){return arguments.length?(n=t,h):n},function(n,r){return t=n,e=r,l()}}()(Hi,Hi)}function Zi(t,e){switch(arguments.length){case 0:break;case 1:this.range(t);break;default:this.range(e).domain(t)}return this}var Qi,Ki=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function Ji(t){if(!(e=Ki.exec(t)))throw new Error("invalid format: "+t);var e;return new ta({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function ta(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function ea(t,e){if((n=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var n,r=t.slice(0,n);return[r.length>1?r[0]+r.slice(2):r,+t.slice(n+1)]}function na(t){return(t=ea(Math.abs(t)))?t[1]:NaN}function ra(t,e){var n=ea(t,e);if(!n)return t+"";var r=n[0],i=n[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}Ji.prototype=ta.prototype,ta.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};const ia={"%":(t,e)=>(100*t).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>ra(100*t,e),r:ra,s:function(t,e){var n=ea(t,e);if(!n)return t+"";var r=n[0],i=n[1],a=i-(Qi=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,o=r.length;return a===o?r:a>o?r+new Array(a-o+1).join("0"):a>0?r.slice(0,a)+"."+r.slice(a):"0."+new Array(1-a).join("0")+ea(t,Math.max(0,e+a-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function aa(t){return t}var oa,sa,ca,ua=Array.prototype.map,la=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function ha(t){var e=t.domain;return t.ticks=function(t){var n=e();return function(t,e,n){var r,i,a,o,s=-1;if(n=+n,(t=+t)==(e=+e)&&n>0)return[t];if((r=e<t)&&(i=t,t=e,e=i),0===(o=qr(t,e,n))||!isFinite(o))return[];if(o>0){let n=Math.round(t/o),r=Math.round(e/o);for(n*o<t&&++n,r*o>e&&--r,a=new Array(i=r-n+1);++s<i;)a[s]=(n+s)*o}else{o=-o;let n=Math.round(t*o),r=Math.round(e*o);for(n/o<t&&++n,r/o>e&&--r,a=new Array(i=r-n+1);++s<i;)a[s]=(n+s)/o}return r&&a.reverse(),a}(n[0],n[n.length-1],null==t?10:t)},t.tickFormat=function(t,n){var r=e();return function(t,e,n,r){var i,a=Hr(t,e,n);switch((r=Ji(null==r?",f":r)).type){case"s":var o=Math.max(Math.abs(t),Math.abs(e));return null!=r.precision||isNaN(i=function(t,e){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(na(e)/3)))-na(Math.abs(t)))}(a,o))||(r.precision=i),ca(r,o);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(i=function(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,na(e)-na(t))+1}(a,Math.max(Math.abs(t),Math.abs(e))))||(r.precision=i-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(i=function(t){return Math.max(0,-na(Math.abs(t)))}(a))||(r.precision=i-2*("%"===r.type))}return sa(r)}(r[0],r[r.length-1],null==t?10:t,n)},t.nice=function(n){null==n&&(n=10);var r,i,a=e(),o=0,s=a.length-1,c=a[o],u=a[s],l=10;for(u<c&&(i=c,c=u,u=i,i=o,o=s,s=i);l-- >0;){if((i=qr(c,u,n))===r)return a[o]=c,a[s]=u,e(a);if(i>0)c=Math.floor(c/i)*i,u=Math.ceil(u/i)*i;else{if(!(i<0))break;c=Math.ceil(c*i)/i,u=Math.floor(u*i)/i}r=i}return t},t}function fa(){var t=Xi();return t.copy=function(){return Gi(t,fa())},Zi.apply(t,arguments),ha(t)}oa=function(t){var e,n,r=void 0===t.grouping||void 0===t.thousands?aa:(e=ua.call(t.grouping,Number),n=t.thousands+"",function(t,r){for(var i=t.length,a=[],o=0,s=e[0],c=0;i>0&&s>0&&(c+s+1>r&&(s=Math.max(1,r-c)),a.push(t.substring(i-=s,i+s)),!((c+=s+1)>r));)s=e[o=(o+1)%e.length];return a.reverse().join(n)}),i=void 0===t.currency?"":t.currency[0]+"",a=void 0===t.currency?"":t.currency[1]+"",o=void 0===t.decimal?".":t.decimal+"",s=void 0===t.numerals?aa:function(t){return function(e){return e.replace(/[0-9]/g,(function(e){return t[+e]}))}}(ua.call(t.numerals,String)),c=void 0===t.percent?"%":t.percent+"",u=void 0===t.minus?"−":t.minus+"",l=void 0===t.nan?"NaN":t.nan+"";function h(t){var e=(t=Ji(t)).fill,n=t.align,h=t.sign,f=t.symbol,d=t.zero,p=t.width,y=t.comma,g=t.precision,m=t.trim,v=t.type;"n"===v?(y=!0,v="g"):ia[v]||(void 0===g&&(g=12),m=!0,v="g"),(d||"0"===e&&"="===n)&&(d=!0,e="0",n="=");var b="$"===f?i:"#"===f&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",_="$"===f?a:/[%p]/.test(v)?c:"",x=ia[v],w=/[defgprs%]/.test(v);function k(t){var i,a,c,f=b,k=_;if("c"===v)k=x(t)+k,t="";else{var T=(t=+t)<0||1/t<0;if(t=isNaN(t)?l:x(Math.abs(t),g),m&&(t=function(t){t:for(var e,n=t.length,r=1,i=-1;r<n;++r)switch(t[r]){case".":i=e=r;break;case"0":0===i&&(i=r),e=r;break;default:if(!+t[r])break t;i>0&&(i=0)}return i>0?t.slice(0,i)+t.slice(e+1):t}(t)),T&&0==+t&&"+"!==h&&(T=!1),f=(T?"("===h?h:u:"-"===h||"("===h?"":h)+f,k=("s"===v?la[8+Qi/3]:"")+k+(T&&"("===h?")":""),w)for(i=-1,a=t.length;++i<a;)if(48>(c=t.charCodeAt(i))||c>57){k=(46===c?o+t.slice(i+1):t.slice(i))+k,t=t.slice(0,i);break}}y&&!d&&(t=r(t,1/0));var E=f.length+t.length+k.length,C=E<p?new Array(p-E+1).join(e):"";switch(y&&d&&(t=r(C+t,C.length?p-k.length:1/0),C=""),n){case"<":t=f+t+k+C;break;case"=":t=f+C+t+k;break;case"^":t=C.slice(0,E=C.length>>1)+f+t+k+C.slice(E);break;default:t=C+f+t+k}return s(t)}return g=void 0===g?6:/[gprs]/.test(v)?Math.max(1,Math.min(21,g)):Math.max(0,Math.min(20,g)),k.toString=function(){return t+""},k}return{format:h,formatPrefix:function(t,e){var n=h(((t=Ji(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(na(e)/3))),i=Math.pow(10,-r),a=la[8+r/3];return function(t){return n(i*t)+a}}}}({thousands:",",grouping:[3],currency:["$",""]}),sa=oa.format,ca=oa.formatPrefix;class da extends Map{constructor(t,e=ya){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:e}}),null!=t)for(const[e,n]of t)this.set(e,n)}get(t){return super.get(pa(this,t))}has(t){return super.has(pa(this,t))}set(t,e){return super.set(function({_intern:t,_key:e},n){const r=e(n);return t.has(r)?t.get(r):(t.set(r,n),n)}(this,t),e)}delete(t){return super.delete(function({_intern:t,_key:e},n){const r=e(n);return t.has(r)&&(n=t.get(r),t.delete(r)),n}(this,t))}}function pa({_intern:t,_key:e},n){const r=e(n);return t.has(r)?t.get(r):n}function ya(t){return null!==t&&"object"==typeof t?t.valueOf():t}Set;const ga=Symbol("implicit");function ma(){var t=new da,e=[],n=[],r=ga;function i(i){let a=t.get(i);if(void 0===a){if(r!==ga)return r;t.set(i,a=e.push(i)-1)}return n[a%n.length]}return i.domain=function(n){if(!arguments.length)return e.slice();e=[],t=new da;for(const r of n)t.has(r)||t.set(r,e.push(r)-1);return i},i.range=function(t){return arguments.length?(n=Array.from(t),i):n.slice()},i.unknown=function(t){return arguments.length?(r=t,i):r},i.copy=function(){return ma(e,n).unknown(r)},Zi.apply(i,arguments),i}const va=1e3,ba=6e4,_a=36e5,xa=864e5,wa=6048e5,ka=31536e6;var Ta=new Date,Ea=new Date;function Ca(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=function(e){return t(e=new Date(+e)),e},i.ceil=function(n){return t(n=new Date(n-1)),e(n,1),t(n),n},i.round=function(t){var e=i(t),n=i.ceil(t);return t-e<n-t?e:n},i.offset=function(t,n){return e(t=new Date(+t),null==n?1:Math.floor(n)),t},i.range=function(n,r,a){var o,s=[];if(n=i.ceil(n),a=null==a?1:Math.floor(a),!(n<r&&a>0))return s;do{s.push(o=new Date(+n)),e(n,a),t(n)}while(o<n&&n<r);return s},i.filter=function(n){return Ca((function(e){if(e>=e)for(;t(e),!n(e);)e.setTime(e-1)}),(function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););}))},n&&(i.count=function(e,r){return Ta.setTime(+e),Ea.setTime(+r),t(Ta),t(Ea),Math.floor(n(Ta,Ea))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(e){return r(e)%t==0}:function(e){return i.count(0,e)%t==0}):i:null}),i}var Sa=Ca((function(){}),(function(t,e){t.setTime(+t+e)}),(function(t,e){return e-t}));Sa.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?Ca((function(e){e.setTime(Math.floor(e/t)*t)}),(function(e,n){e.setTime(+e+n*t)}),(function(e,n){return(n-e)/t})):Sa:null};const Aa=Sa;Sa.range;var Ma=Ca((function(t){t.setTime(t-t.getMilliseconds())}),(function(t,e){t.setTime(+t+e*va)}),(function(t,e){return(e-t)/va}),(function(t){return t.getUTCSeconds()}));const Na=Ma;Ma.range;var Da=Ca((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*va)}),(function(t,e){t.setTime(+t+e*ba)}),(function(t,e){return(e-t)/ba}),(function(t){return t.getMinutes()}));const Oa=Da;Da.range;var Ba=Ca((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*va-t.getMinutes()*ba)}),(function(t,e){t.setTime(+t+e*_a)}),(function(t,e){return(e-t)/_a}),(function(t){return t.getHours()}));const La=Ba;Ba.range;var Ia=Ca((t=>t.setHours(0,0,0,0)),((t,e)=>t.setDate(t.getDate()+e)),((t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*ba)/xa),(t=>t.getDate()-1));const Ra=Ia;function Fa(t){return Ca((function(e){e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+7*e)}),(function(t,e){return(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*ba)/wa}))}Ia.range;var Pa=Fa(0),ja=Fa(1),Ya=Fa(2),za=Fa(3),Ua=Fa(4),qa=Fa(5),Ha=Fa(6),$a=(Pa.range,ja.range,Ya.range,za.range,Ua.range,qa.range,Ha.range,Ca((function(t){t.setDate(1),t.setHours(0,0,0,0)}),(function(t,e){t.setMonth(t.getMonth()+e)}),(function(t,e){return e.getMonth()-t.getMonth()+12*(e.getFullYear()-t.getFullYear())}),(function(t){return t.getMonth()})));const Wa=$a;$a.range;var Va=Ca((function(t){t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,e){t.setFullYear(t.getFullYear()+e)}),(function(t,e){return e.getFullYear()-t.getFullYear()}),(function(t){return t.getFullYear()}));Va.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Ca((function(e){e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,n){e.setFullYear(e.getFullYear()+n*t)})):null};const Ga=Va;Va.range;var Xa=Ca((function(t){t.setUTCSeconds(0,0)}),(function(t,e){t.setTime(+t+e*ba)}),(function(t,e){return(e-t)/ba}),(function(t){return t.getUTCMinutes()}));const Za=Xa;Xa.range;var Qa=Ca((function(t){t.setUTCMinutes(0,0,0)}),(function(t,e){t.setTime(+t+e*_a)}),(function(t,e){return(e-t)/_a}),(function(t){return t.getUTCHours()}));const Ka=Qa;Qa.range;var Ja=Ca((function(t){t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+e)}),(function(t,e){return(e-t)/xa}),(function(t){return t.getUTCDate()-1}));const to=Ja;function eo(t){return Ca((function(e){e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+7*e)}),(function(t,e){return(e-t)/wa}))}Ja.range;var no=eo(0),ro=eo(1),io=eo(2),ao=eo(3),oo=eo(4),so=eo(5),co=eo(6),uo=(no.range,ro.range,io.range,ao.range,oo.range,so.range,co.range,Ca((function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCMonth(t.getUTCMonth()+e)}),(function(t,e){return e.getUTCMonth()-t.getUTCMonth()+12*(e.getUTCFullYear()-t.getUTCFullYear())}),(function(t){return t.getUTCMonth()})));const lo=uo;uo.range;var ho=Ca((function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCFullYear(t.getUTCFullYear()+e)}),(function(t,e){return e.getUTCFullYear()-t.getUTCFullYear()}),(function(t){return t.getUTCFullYear()}));ho.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Ca((function(e){e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,n){e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null};const fo=ho;function po(t,e,n,r,i,a){const o=[[Na,1,va],[Na,5,5e3],[Na,15,15e3],[Na,30,3e4],[a,1,ba],[a,5,3e5],[a,15,9e5],[a,30,18e5],[i,1,_a],[i,3,108e5],[i,6,216e5],[i,12,432e5],[r,1,xa],[r,2,1728e5],[n,1,wa],[e,1,2592e6],[e,3,7776e6],[t,1,ka]];function s(e,n,r){const i=Math.abs(n-e)/r,a=Wr((([,,t])=>t)).right(o,i);if(a===o.length)return t.every(Hr(e/ka,n/ka,r));if(0===a)return Aa.every(Math.max(Hr(e,n,r),1));const[s,c]=o[i/o[a-1][2]<o[a][2]/i?a-1:a];return s.every(c)}return[function(t,e,n){const r=e<t;r&&([t,e]=[e,t]);const i=n&&"function"==typeof n.range?n:s(t,e,n),a=i?i.range(t,+e+1):[];return r?a.reverse():a},s]}ho.range;const[yo,go]=po(fo,lo,no,to,Ka,Za),[mo,vo]=po(Ga,Wa,Pa,Ra,La,Oa);function bo(t){if(0<=t.y&&t.y<100){var e=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return e.setFullYear(t.y),e}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function _o(t){if(0<=t.y&&t.y<100){var e=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return e.setUTCFullYear(t.y),e}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function xo(t,e,n){return{y:t,m:e,d:n,H:0,M:0,S:0,L:0}}var wo,ko,To={"-":"",_:" ",0:"0"},Eo=/^\s*\d+/,Co=/^%/,So=/[\\^$*+?|[\]().{}]/g;function Ao(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",a=i.length;return r+(a<n?new Array(n-a+1).join(e)+i:i)}function Mo(t){return t.replace(So,"\\$&")}function No(t){return new RegExp("^(?:"+t.map(Mo).join("|")+")","i")}function Do(t){return new Map(t.map(((t,e)=>[t.toLowerCase(),e])))}function Oo(t,e,n){var r=Eo.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function Bo(t,e,n){var r=Eo.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function Lo(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function Io(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function Ro(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function Fo(t,e,n){var r=Eo.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function Po(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function jo(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function Yo(t,e,n){var r=Eo.exec(e.slice(n,n+1));return r?(t.q=3*r[0]-3,n+r[0].length):-1}function zo(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function Uo(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function qo(t,e,n){var r=Eo.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function Ho(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function $o(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Wo(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function Vo(t,e,n){var r=Eo.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function Go(t,e,n){var r=Eo.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function Xo(t,e,n){var r=Co.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function Zo(t,e,n){var r=Eo.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function Qo(t,e,n){var r=Eo.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function Ko(t,e){return Ao(t.getDate(),e,2)}function Jo(t,e){return Ao(t.getHours(),e,2)}function ts(t,e){return Ao(t.getHours()%12||12,e,2)}function es(t,e){return Ao(1+Ra.count(Ga(t),t),e,3)}function ns(t,e){return Ao(t.getMilliseconds(),e,3)}function rs(t,e){return ns(t,e)+"000"}function is(t,e){return Ao(t.getMonth()+1,e,2)}function as(t,e){return Ao(t.getMinutes(),e,2)}function os(t,e){return Ao(t.getSeconds(),e,2)}function ss(t){var e=t.getDay();return 0===e?7:e}function cs(t,e){return Ao(Pa.count(Ga(t)-1,t),e,2)}function us(t){var e=t.getDay();return e>=4||0===e?Ua(t):Ua.ceil(t)}function ls(t,e){return t=us(t),Ao(Ua.count(Ga(t),t)+(4===Ga(t).getDay()),e,2)}function hs(t){return t.getDay()}function fs(t,e){return Ao(ja.count(Ga(t)-1,t),e,2)}function ds(t,e){return Ao(t.getFullYear()%100,e,2)}function ps(t,e){return Ao((t=us(t)).getFullYear()%100,e,2)}function ys(t,e){return Ao(t.getFullYear()%1e4,e,4)}function gs(t,e){var n=t.getDay();return Ao((t=n>=4||0===n?Ua(t):Ua.ceil(t)).getFullYear()%1e4,e,4)}function ms(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+Ao(e/60|0,"0",2)+Ao(e%60,"0",2)}function vs(t,e){return Ao(t.getUTCDate(),e,2)}function bs(t,e){return Ao(t.getUTCHours(),e,2)}function _s(t,e){return Ao(t.getUTCHours()%12||12,e,2)}function xs(t,e){return Ao(1+to.count(fo(t),t),e,3)}function ws(t,e){return Ao(t.getUTCMilliseconds(),e,3)}function ks(t,e){return ws(t,e)+"000"}function Ts(t,e){return Ao(t.getUTCMonth()+1,e,2)}function Es(t,e){return Ao(t.getUTCMinutes(),e,2)}function Cs(t,e){return Ao(t.getUTCSeconds(),e,2)}function Ss(t){var e=t.getUTCDay();return 0===e?7:e}function As(t,e){return Ao(no.count(fo(t)-1,t),e,2)}function Ms(t){var e=t.getUTCDay();return e>=4||0===e?oo(t):oo.ceil(t)}function Ns(t,e){return t=Ms(t),Ao(oo.count(fo(t),t)+(4===fo(t).getUTCDay()),e,2)}function Ds(t){return t.getUTCDay()}function Os(t,e){return Ao(ro.count(fo(t)-1,t),e,2)}function Bs(t,e){return Ao(t.getUTCFullYear()%100,e,2)}function Ls(t,e){return Ao((t=Ms(t)).getUTCFullYear()%100,e,2)}function Is(t,e){return Ao(t.getUTCFullYear()%1e4,e,4)}function Rs(t,e){var n=t.getUTCDay();return Ao((t=n>=4||0===n?oo(t):oo.ceil(t)).getUTCFullYear()%1e4,e,4)}function Fs(){return"+0000"}function Ps(){return"%"}function js(t){return+t}function Ys(t){return Math.floor(+t/1e3)}function zs(t){return new Date(t)}function Us(t){return t instanceof Date?+t:+new Date(+t)}function qs(t,e,n,r,i,a,o,s,c,u){var l=Xi(),h=l.invert,f=l.domain,d=u(".%L"),p=u(":%S"),y=u("%I:%M"),g=u("%I %p"),m=u("%a %d"),v=u("%b %d"),b=u("%B"),_=u("%Y");function x(t){return(c(t)<t?d:s(t)<t?p:o(t)<t?y:a(t)<t?g:r(t)<t?i(t)<t?m:v:n(t)<t?b:_)(t)}return l.invert=function(t){return new Date(h(t))},l.domain=function(t){return arguments.length?f(Array.from(t,Us)):f().map(zs)},l.ticks=function(e){var n=f();return t(n[0],n[n.length-1],null==e?10:e)},l.tickFormat=function(t,e){return null==e?x:u(e)},l.nice=function(t){var n=f();return t&&"function"==typeof t.range||(t=e(n[0],n[n.length-1],null==t?10:t)),t?f(function(t,e){var n,r=0,i=(t=t.slice()).length-1,a=t[r],o=t[i];return o<a&&(n=r,r=i,i=n,n=a,a=o,o=n),t[r]=e.floor(a),t[i]=e.ceil(o),t}(n,t)):l},l.copy=function(){return Gi(l,qs(t,e,n,r,i,a,o,s,c,u))},l}function Hs(){}function $s(t){return null==t?Hs:function(){return this.querySelector(t)}}function Ws(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}function Vs(){return[]}function Gs(t){return null==t?Vs:function(){return this.querySelectorAll(t)}}function Xs(t){return function(){return this.matches(t)}}function Zs(t){return function(e){return e.matches(t)}}wo=function(t){var e=t.dateTime,n=t.date,r=t.time,i=t.periods,a=t.days,o=t.shortDays,s=t.months,c=t.shortMonths,u=No(i),l=Do(i),h=No(a),f=Do(a),d=No(o),p=Do(o),y=No(s),g=Do(s),m=No(c),v=Do(c),b={a:function(t){return o[t.getDay()]},A:function(t){return a[t.getDay()]},b:function(t){return c[t.getMonth()]},B:function(t){return s[t.getMonth()]},c:null,d:Ko,e:Ko,f:rs,g:ps,G:gs,H:Jo,I:ts,j:es,L:ns,m:is,M:as,p:function(t){return i[+(t.getHours()>=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:js,s:Ys,S:os,u:ss,U:cs,V:ls,w:hs,W:fs,x:null,X:null,y:ds,Y:ys,Z:ms,"%":Ps},_={a:function(t){return o[t.getUTCDay()]},A:function(t){return a[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:vs,e:vs,f:ks,g:Ls,G:Rs,H:bs,I:_s,j:xs,L:ws,m:Ts,M:Es,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:js,s:Ys,S:Cs,u:Ss,U:As,V:Ns,w:Ds,W:Os,x:null,X:null,y:Bs,Y:Is,Z:Fs,"%":Ps},x={a:function(t,e,n){var r=d.exec(e.slice(n));return r?(t.w=p.get(r[0].toLowerCase()),n+r[0].length):-1},A:function(t,e,n){var r=h.exec(e.slice(n));return r?(t.w=f.get(r[0].toLowerCase()),n+r[0].length):-1},b:function(t,e,n){var r=m.exec(e.slice(n));return r?(t.m=v.get(r[0].toLowerCase()),n+r[0].length):-1},B:function(t,e,n){var r=y.exec(e.slice(n));return r?(t.m=g.get(r[0].toLowerCase()),n+r[0].length):-1},c:function(t,n,r){return T(t,e,n,r)},d:Uo,e:Uo,f:Go,g:Po,G:Fo,H:Ho,I:Ho,j:qo,L:Vo,m:zo,M:$o,p:function(t,e,n){var r=u.exec(e.slice(n));return r?(t.p=l.get(r[0].toLowerCase()),n+r[0].length):-1},q:Yo,Q:Zo,s:Qo,S:Wo,u:Bo,U:Lo,V:Io,w:Oo,W:Ro,x:function(t,e,r){return T(t,n,e,r)},X:function(t,e,n){return T(t,r,e,n)},y:Po,Y:Fo,Z:jo,"%":Xo};function w(t,e){return function(n){var r,i,a,o=[],s=-1,c=0,u=t.length;for(n instanceof Date||(n=new Date(+n));++s<u;)37===t.charCodeAt(s)&&(o.push(t.slice(c,s)),null!=(i=To[r=t.charAt(++s)])?r=t.charAt(++s):i="e"===r?" ":"0",(a=e[r])&&(r=a(n,i)),o.push(r),c=s+1);return o.push(t.slice(c,s)),o.join("")}}function k(t,e){return function(n){var r,i,a=xo(1900,void 0,1);if(T(a,t,n+="",0)!=n.length)return null;if("Q"in a)return new Date(a.Q);if("s"in a)return new Date(1e3*a.s+("L"in a?a.L:0));if(e&&!("Z"in a)&&(a.Z=0),"p"in a&&(a.H=a.H%12+12*a.p),void 0===a.m&&(a.m="q"in a?a.q:0),"V"in a){if(a.V<1||a.V>53)return null;"w"in a||(a.w=1),"Z"in a?(i=(r=_o(xo(a.y,0,1))).getUTCDay(),r=i>4||0===i?ro.ceil(r):ro(r),r=to.offset(r,7*(a.V-1)),a.y=r.getUTCFullYear(),a.m=r.getUTCMonth(),a.d=r.getUTCDate()+(a.w+6)%7):(i=(r=bo(xo(a.y,0,1))).getDay(),r=i>4||0===i?ja.ceil(r):ja(r),r=Ra.offset(r,7*(a.V-1)),a.y=r.getFullYear(),a.m=r.getMonth(),a.d=r.getDate()+(a.w+6)%7)}else("W"in a||"U"in a)&&("w"in a||(a.w="u"in a?a.u%7:"W"in a?1:0),i="Z"in a?_o(xo(a.y,0,1)).getUTCDay():bo(xo(a.y,0,1)).getDay(),a.m=0,a.d="W"in a?(a.w+6)%7+7*a.W-(i+5)%7:a.w+7*a.U-(i+6)%7);return"Z"in a?(a.H+=a.Z/100|0,a.M+=a.Z%100,_o(a)):bo(a)}}function T(t,e,n,r){for(var i,a,o=0,s=e.length,c=n.length;o<s;){if(r>=c)return-1;if(37===(i=e.charCodeAt(o++))){if(i=e.charAt(o++),!(a=x[i in To?e.charAt(o++):i])||(r=a(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return b.x=w(n,b),b.X=w(r,b),b.c=w(e,b),_.x=w(n,_),_.X=w(r,_),_.c=w(e,_),{format:function(t){var e=w(t+="",b);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),ko=wo.format,wo.parse,wo.utcFormat,wo.utcParse;var Qs=Array.prototype.find;function Ks(){return this.firstElementChild}var Js=Array.prototype.filter;function tc(){return Array.from(this.children)}function ec(t){return new Array(t.length)}function nc(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}function rc(t){return function(){return t}}function ic(t,e,n,r,i,a){for(var o,s=0,c=e.length,u=a.length;s<u;++s)(o=e[s])?(o.__data__=a[s],r[s]=o):n[s]=new nc(t,a[s]);for(;s<c;++s)(o=e[s])&&(i[s]=o)}function ac(t,e,n,r,i,a,o){var s,c,u,l=new Map,h=e.length,f=a.length,d=new Array(h);for(s=0;s<h;++s)(c=e[s])&&(d[s]=u=o.call(c,c.__data__,s,e)+"",l.has(u)?i[s]=c:l.set(u,c));for(s=0;s<f;++s)u=o.call(t,a[s],s,a)+"",(c=l.get(u))?(r[s]=c,c.__data__=a[s],l.delete(u)):n[s]=new nc(t,a[s]);for(s=0;s<h;++s)(c=e[s])&&l.get(d[s])===c&&(i[s]=c)}function oc(t){return t.__data__}function sc(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function cc(t,e){return t<e?-1:t>e?1:t>=e?0:NaN}nc.prototype={constructor:nc,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var uc="http://www.w3.org/1999/xhtml";const lc={svg:"http://www.w3.org/2000/svg",xhtml:uc,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function hc(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),lc.hasOwnProperty(e)?{space:lc[e],local:t}:t}function fc(t){return function(){this.removeAttribute(t)}}function dc(t){return function(){this.removeAttributeNS(t.space,t.local)}}function pc(t,e){return function(){this.setAttribute(t,e)}}function yc(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function gc(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function mc(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function vc(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function bc(t){return function(){this.style.removeProperty(t)}}function _c(t,e,n){return function(){this.style.setProperty(t,e,n)}}function xc(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function wc(t,e){return t.style.getPropertyValue(e)||vc(t).getComputedStyle(t,null).getPropertyValue(e)}function kc(t){return function(){delete this[t]}}function Tc(t,e){return function(){this[t]=e}}function Ec(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function Cc(t){return t.trim().split(/^|\s+/)}function Sc(t){return t.classList||new Ac(t)}function Ac(t){this._node=t,this._names=Cc(t.getAttribute("class")||"")}function Mc(t,e){for(var n=Sc(t),r=-1,i=e.length;++r<i;)n.add(e[r])}function Nc(t,e){for(var n=Sc(t),r=-1,i=e.length;++r<i;)n.remove(e[r])}function Dc(t){return function(){Mc(this,t)}}function Oc(t){return function(){Nc(this,t)}}function Bc(t,e){return function(){(e.apply(this,arguments)?Mc:Nc)(this,t)}}function Lc(){this.textContent=""}function Ic(t){return function(){this.textContent=t}}function Rc(t){return function(){var e=t.apply(this,arguments);this.textContent=null==e?"":e}}function Fc(){this.innerHTML=""}function Pc(t){return function(){this.innerHTML=t}}function jc(t){return function(){var e=t.apply(this,arguments);this.innerHTML=null==e?"":e}}function Yc(){this.nextSibling&&this.parentNode.appendChild(this)}function zc(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function Uc(t){return function(){var e=this.ownerDocument,n=this.namespaceURI;return n===uc&&e.documentElement.namespaceURI===uc?e.createElement(t):e.createElementNS(n,t)}}function qc(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Hc(t){var e=hc(t);return(e.local?qc:Uc)(e)}function $c(){return null}function Wc(){var t=this.parentNode;t&&t.removeChild(this)}function Vc(){var t=this.cloneNode(!1),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}function Gc(){var t=this.cloneNode(!0),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}function Xc(t){return t.trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");return n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function Zc(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r<a;++r)n=e[r],t.type&&n.type!==t.type||n.name!==t.name?e[++i]=n:this.removeEventListener(n.type,n.listener,n.options);++i?e.length=i:delete this.__on}}}function Qc(t,e,n){return function(){var r,i=this.__on,a=function(t){return function(e){t.call(this,e,this.__data__)}}(e);if(i)for(var o=0,s=i.length;o<s;++o)if((r=i[o]).type===t.type&&r.name===t.name)return this.removeEventListener(r.type,r.listener,r.options),this.addEventListener(r.type,r.listener=a,r.options=n),void(r.value=e);this.addEventListener(t.type,a,n),r={type:t.type,name:t.name,value:e,listener:a,options:n},i?i.push(r):this.__on=[r]}}function Kc(t,e,n){var r=vc(t),i=r.CustomEvent;"function"==typeof i?i=new i(e,n):(i=r.document.createEvent("Event"),n?(i.initEvent(e,n.bubbles,n.cancelable),i.detail=n.detail):i.initEvent(e,!1,!1)),t.dispatchEvent(i)}function Jc(t,e){return function(){return Kc(this,t,e)}}function tu(t,e){return function(){return Kc(this,t,e.apply(this,arguments))}}Ac.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var eu=[null];function nu(t,e){this._groups=t,this._parents=e}function ru(){return new nu([[document.documentElement]],eu)}nu.prototype=ru.prototype={constructor:nu,select:function(t){"function"!=typeof t&&(t=$s(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o,s=e[i],c=s.length,u=r[i]=new Array(c),l=0;l<c;++l)(a=s[l])&&(o=t.call(a,a.__data__,l,s))&&("__data__"in a&&(o.__data__=a.__data__),u[l]=o);return new nu(r,this._parents)},selectAll:function(t){t="function"==typeof t?function(t){return function(){return Ws(t.apply(this,arguments))}}(t):Gs(t);for(var e=this._groups,n=e.length,r=[],i=[],a=0;a<n;++a)for(var o,s=e[a],c=s.length,u=0;u<c;++u)(o=s[u])&&(r.push(t.call(o,o.__data__,u,s)),i.push(o));return new nu(r,i)},selectChild:function(t){return this.select(null==t?Ks:function(t){return function(){return Qs.call(this.children,t)}}("function"==typeof t?t:Zs(t)))},selectChildren:function(t){return this.selectAll(null==t?tc:function(t){return function(){return Js.call(this.children,t)}}("function"==typeof t?t:Zs(t)))},filter:function(t){"function"!=typeof t&&(t=Xs(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o=e[i],s=o.length,c=r[i]=[],u=0;u<s;++u)(a=o[u])&&t.call(a,a.__data__,u,o)&&c.push(a);return new nu(r,this._parents)},data:function(t,e){if(!arguments.length)return Array.from(this,oc);var n=e?ac:ic,r=this._parents,i=this._groups;"function"!=typeof t&&(t=rc(t));for(var a=i.length,o=new Array(a),s=new Array(a),c=new Array(a),u=0;u<a;++u){var l=r[u],h=i[u],f=h.length,d=sc(t.call(l,l&&l.__data__,u,r)),p=d.length,y=s[u]=new Array(p),g=o[u]=new Array(p),m=c[u]=new Array(f);n(l,h,y,g,m,d,e);for(var v,b,_=0,x=0;_<p;++_)if(v=y[_]){for(_>=x&&(x=_+1);!(b=g[x])&&++x<p;);v._next=b||null}}return(o=new nu(o,r))._enter=s,o._exit=c,o},enter:function(){return new nu(this._enter||this._groups.map(ec),this._parents)},exit:function(){return new nu(this._exit||this._groups.map(ec),this._parents)},join:function(t,e,n){var r=this.enter(),i=this,a=this.exit();return"function"==typeof t?(r=t(r))&&(r=r.selection()):r=r.append(t+""),null!=e&&(i=e(i))&&(i=i.selection()),null==n?a.remove():n(a),r&&i?r.merge(i).order():i},merge:function(t){for(var e=t.selection?t.selection():t,n=this._groups,r=e._groups,i=n.length,a=r.length,o=Math.min(i,a),s=new Array(i),c=0;c<o;++c)for(var u,l=n[c],h=r[c],f=l.length,d=s[c]=new Array(f),p=0;p<f;++p)(u=l[p]||h[p])&&(d[p]=u);for(;c<i;++c)s[c]=n[c];return new nu(s,this._parents)},selection:function(){return this},order:function(){for(var t=this._groups,e=-1,n=t.length;++e<n;)for(var r,i=t[e],a=i.length-1,o=i[a];--a>=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=cc);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a<r;++a){for(var o,s=n[a],c=s.length,u=i[a]=new Array(c),l=0;l<c;++l)(o=s[l])&&(u[l]=o);u.sort(e)}return new nu(i,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){return Array.from(this)},node:function(){for(var t=this._groups,e=0,n=t.length;e<n;++e)for(var r=t[e],i=0,a=r.length;i<a;++i){var o=r[i];if(o)return o}return null},size:function(){let t=0;for(const e of this)++t;return t},empty:function(){return!this.node()},each:function(t){for(var e=this._groups,n=0,r=e.length;n<r;++n)for(var i,a=e[n],o=0,s=a.length;o<s;++o)(i=a[o])&&t.call(i,i.__data__,o,a);return this},attr:function(t,e){var n=hc(t);if(arguments.length<2){var r=this.node();return n.local?r.getAttributeNS(n.space,n.local):r.getAttribute(n)}return this.each((null==e?n.local?dc:fc:"function"==typeof e?n.local?mc:gc:n.local?yc:pc)(n,e))},style:function(t,e,n){return arguments.length>1?this.each((null==e?bc:"function"==typeof e?xc:_c)(t,e,null==n?"":n)):wc(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?kc:"function"==typeof e?Ec:Tc)(t,e)):this.node()[t]},classed:function(t,e){var n=Cc(t+"");if(arguments.length<2){for(var r=Sc(this.node()),i=-1,a=n.length;++i<a;)if(!r.contains(n[i]))return!1;return!0}return this.each(("function"==typeof e?Bc:e?Dc:Oc)(n,e))},text:function(t){return arguments.length?this.each(null==t?Lc:("function"==typeof t?Rc:Ic)(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?Fc:("function"==typeof t?jc:Pc)(t)):this.node().innerHTML},raise:function(){return this.each(Yc)},lower:function(){return this.each(zc)},append:function(t){var e="function"==typeof t?t:Hc(t);return this.select((function(){return this.appendChild(e.apply(this,arguments))}))},insert:function(t,e){var n="function"==typeof t?t:Hc(t),r=null==e?$c:"function"==typeof e?e:$s(e);return this.select((function(){return this.insertBefore(n.apply(this,arguments),r.apply(this,arguments)||null)}))},remove:function(){return this.each(Wc)},clone:function(t){return this.select(t?Gc:Vc)},datum:function(t){return arguments.length?this.property("__data__",t):this.node().__data__},on:function(t,e,n){var r,i,a=Xc(t+""),o=a.length;if(!(arguments.length<2)){for(s=e?Qc:Zc,r=0;r<o;++r)this.each(s(a[r],e,n));return this}var s=this.node().__on;if(s)for(var c,u=0,l=s.length;u<l;++u)for(r=0,c=s[u];r<o;++r)if((i=a[r]).type===c.type&&i.name===c.name)return c.value},dispatch:function(t,e){return this.each(("function"==typeof e?tu:Jc)(t,e))},[Symbol.iterator]:function*(){for(var t=this._groups,e=0,n=t.length;e<n;++e)for(var r,i=t[e],a=0,o=i.length;a<o;++a)(r=i[a])&&(yield r)}};const iu=ru;function au(t){return"string"==typeof t?new nu([[document.querySelector(t)]],[document.documentElement]):new nu([[t]],eu)}function ou(t){return"string"==typeof t?new nu([document.querySelectorAll(t)],[document.documentElement]):new nu([Ws(t)],eu)}const su=Math.PI,cu=2*su,uu=1e-6,lu=cu-uu;function hu(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function fu(){return new hu}hu.prototype=fu.prototype={constructor:hu,moveTo:function(t,e){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)},closePath:function(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,e){this._+="L"+(this._x1=+t)+","+(this._y1=+e)},quadraticCurveTo:function(t,e,n,r){this._+="Q"+ +t+","+ +e+","+(this._x1=+n)+","+(this._y1=+r)},bezierCurveTo:function(t,e,n,r,i,a){this._+="C"+ +t+","+ +e+","+ +n+","+ +r+","+(this._x1=+i)+","+(this._y1=+a)},arcTo:function(t,e,n,r,i){t=+t,e=+e,n=+n,r=+r,i=+i;var a=this._x1,o=this._y1,s=n-t,c=r-e,u=a-t,l=o-e,h=u*u+l*l;if(i<0)throw new Error("negative radius: "+i);if(null===this._x1)this._+="M"+(this._x1=t)+","+(this._y1=e);else if(h>uu)if(Math.abs(l*s-c*u)>uu&&i){var f=n-a,d=r-o,p=s*s+c*c,y=f*f+d*d,g=Math.sqrt(p),m=Math.sqrt(h),v=i*Math.tan((su-Math.acos((p+h-y)/(2*g*m)))/2),b=v/m,_=v/g;Math.abs(b-1)>uu&&(this._+="L"+(t+b*u)+","+(e+b*l)),this._+="A"+i+","+i+",0,0,"+ +(l*f>u*d)+","+(this._x1=t+_*s)+","+(this._y1=e+_*c)}else this._+="L"+(this._x1=t)+","+(this._y1=e)},arc:function(t,e,n,r,i,a){t=+t,e=+e,a=!!a;var o=(n=+n)*Math.cos(r),s=n*Math.sin(r),c=t+o,u=e+s,l=1^a,h=a?r-i:i-r;if(n<0)throw new Error("negative radius: "+n);null===this._x1?this._+="M"+c+","+u:(Math.abs(this._x1-c)>uu||Math.abs(this._y1-u)>uu)&&(this._+="L"+c+","+u),n&&(h<0&&(h=h%cu+cu),h>lu?this._+="A"+n+","+n+",0,1,"+l+","+(t-o)+","+(e-s)+"A"+n+","+n+",0,1,"+l+","+(this._x1=c)+","+(this._y1=u):h>uu&&(this._+="A"+n+","+n+",0,"+ +(h>=su)+","+l+","+(this._x1=t+n*Math.cos(i))+","+(this._y1=e+n*Math.sin(i))))},rect:function(t,e,n,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +n+"v"+ +r+"h"+-n+"Z"},toString:function(){return this._}};const du=fu;function pu(t){return function(){return t}}var yu=Math.abs,gu=Math.atan2,mu=Math.cos,vu=Math.max,bu=Math.min,_u=Math.sin,xu=Math.sqrt,wu=1e-12,ku=Math.PI,Tu=ku/2,Eu=2*ku;function Cu(t){return t>1?0:t<-1?ku:Math.acos(t)}function Su(t){return t>=1?Tu:t<=-1?-Tu:Math.asin(t)}function Au(t){return t.innerRadius}function Mu(t){return t.outerRadius}function Nu(t){return t.startAngle}function Du(t){return t.endAngle}function Ou(t){return t&&t.padAngle}function Bu(t,e,n,r,i,a,o,s){var c=n-t,u=r-e,l=o-i,h=s-a,f=h*c-l*u;if(!(f*f<wu))return[t+(f=(l*(e-a)-h*(t-i))/f)*c,e+f*u]}function Lu(t,e,n,r,i,a,o){var s=t-n,c=e-r,u=(o?a:-a)/xu(s*s+c*c),l=u*c,h=-u*s,f=t+l,d=e+h,p=n+l,y=r+h,g=(f+p)/2,m=(d+y)/2,v=p-f,b=y-d,_=v*v+b*b,x=i-a,w=f*y-p*d,k=(b<0?-1:1)*xu(vu(0,x*x*_-w*w)),T=(w*b-v*k)/_,E=(-w*v-b*k)/_,C=(w*b+v*k)/_,S=(-w*v+b*k)/_,A=T-g,M=E-m,N=C-g,D=S-m;return A*A+M*M>N*N+D*D&&(T=C,E=S),{cx:T,cy:E,x01:-l,y01:-h,x11:T*(i/x-1),y11:E*(i/x-1)}}function Iu(){var t=Au,e=Mu,n=pu(0),r=null,i=Nu,a=Du,o=Ou,s=null;function c(){var c,u,l=+t.apply(this,arguments),h=+e.apply(this,arguments),f=i.apply(this,arguments)-Tu,d=a.apply(this,arguments)-Tu,p=yu(d-f),y=d>f;if(s||(s=c=du()),h<l&&(u=h,h=l,l=u),h>wu)if(p>Eu-wu)s.moveTo(h*mu(f),h*_u(f)),s.arc(0,0,h,f,d,!y),l>wu&&(s.moveTo(l*mu(d),l*_u(d)),s.arc(0,0,l,d,f,y));else{var g,m,v=f,b=d,_=f,x=d,w=p,k=p,T=o.apply(this,arguments)/2,E=T>wu&&(r?+r.apply(this,arguments):xu(l*l+h*h)),C=bu(yu(h-l)/2,+n.apply(this,arguments)),S=C,A=C;if(E>wu){var M=Su(E/l*_u(T)),N=Su(E/h*_u(T));(w-=2*M)>wu?(_+=M*=y?1:-1,x-=M):(w=0,_=x=(f+d)/2),(k-=2*N)>wu?(v+=N*=y?1:-1,b-=N):(k=0,v=b=(f+d)/2)}var D=h*mu(v),O=h*_u(v),B=l*mu(x),L=l*_u(x);if(C>wu){var I,R=h*mu(b),F=h*_u(b),P=l*mu(_),j=l*_u(_);if(p<ku&&(I=Bu(D,O,P,j,R,F,B,L))){var Y=D-I[0],z=O-I[1],U=R-I[0],q=F-I[1],H=1/_u(Cu((Y*U+z*q)/(xu(Y*Y+z*z)*xu(U*U+q*q)))/2),$=xu(I[0]*I[0]+I[1]*I[1]);S=bu(C,(l-$)/(H-1)),A=bu(C,(h-$)/(H+1))}}k>wu?A>wu?(g=Lu(P,j,D,O,h,A,y),m=Lu(R,F,B,L,h,A,y),s.moveTo(g.cx+g.x01,g.cy+g.y01),A<C?s.arc(g.cx,g.cy,A,gu(g.y01,g.x01),gu(m.y01,m.x01),!y):(s.arc(g.cx,g.cy,A,gu(g.y01,g.x01),gu(g.y11,g.x11),!y),s.arc(0,0,h,gu(g.cy+g.y11,g.cx+g.x11),gu(m.cy+m.y11,m.cx+m.x11),!y),s.arc(m.cx,m.cy,A,gu(m.y11,m.x11),gu(m.y01,m.x01),!y))):(s.moveTo(D,O),s.arc(0,0,h,v,b,!y)):s.moveTo(D,O),l>wu&&w>wu?S>wu?(g=Lu(B,L,R,F,l,-S,y),m=Lu(D,O,P,j,l,-S,y),s.lineTo(g.cx+g.x01,g.cy+g.y01),S<C?s.arc(g.cx,g.cy,S,gu(g.y01,g.x01),gu(m.y01,m.x01),!y):(s.arc(g.cx,g.cy,S,gu(g.y01,g.x01),gu(g.y11,g.x11),!y),s.arc(0,0,l,gu(g.cy+g.y11,g.cx+g.x11),gu(m.cy+m.y11,m.cx+m.x11),y),s.arc(m.cx,m.cy,S,gu(m.y11,m.x11),gu(m.y01,m.x01),!y))):s.arc(0,0,l,x,_,y):s.lineTo(B,L)}else s.moveTo(0,0);if(s.closePath(),c)return s=null,c+""||null}return c.centroid=function(){var n=(+t.apply(this,arguments)+ +e.apply(this,arguments))/2,r=(+i.apply(this,arguments)+ +a.apply(this,arguments))/2-ku/2;return[mu(r)*n,_u(r)*n]},c.innerRadius=function(e){return arguments.length?(t="function"==typeof e?e:pu(+e),c):t},c.outerRadius=function(t){return arguments.length?(e="function"==typeof t?t:pu(+t),c):e},c.cornerRadius=function(t){return arguments.length?(n="function"==typeof t?t:pu(+t),c):n},c.padRadius=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:pu(+t),c):r},c.startAngle=function(t){return arguments.length?(i="function"==typeof t?t:pu(+t),c):i},c.endAngle=function(t){return arguments.length?(a="function"==typeof t?t:pu(+t),c):a},c.padAngle=function(t){return arguments.length?(o="function"==typeof t?t:pu(+t),c):o},c.context=function(t){return arguments.length?(s=null==t?null:t,c):s},c}function Ru(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function Fu(t){this._context=t}function Pu(t){return new Fu(t)}function ju(t){return t[0]}function Yu(t){return t[1]}function zu(t,e){var n=pu(!0),r=null,i=Pu,a=null;function o(o){var s,c,u,l=(o=Ru(o)).length,h=!1;for(null==r&&(a=i(u=du())),s=0;s<=l;++s)!(s<l&&n(c=o[s],s,o))===h&&((h=!h)?a.lineStart():a.lineEnd()),h&&a.point(+t(c,s,o),+e(c,s,o));if(u)return a=null,u+""||null}return t="function"==typeof t?t:void 0===t?ju:pu(t),e="function"==typeof e?e:void 0===e?Yu:pu(e),o.x=function(e){return arguments.length?(t="function"==typeof e?e:pu(+e),o):t},o.y=function(t){return arguments.length?(e="function"==typeof t?t:pu(+t),o):e},o.defined=function(t){return arguments.length?(n="function"==typeof t?t:pu(!!t),o):n},o.curve=function(t){return arguments.length?(i=t,null!=r&&(a=i(r)),o):i},o.context=function(t){return arguments.length?(null==t?r=a=null:a=i(r=t),o):r},o}function Uu(t,e){return e<t?-1:e>t?1:e>=t?0:NaN}function qu(t){return t}function Hu(){}function $u(t,e,n){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+e)/6,(t._y0+4*t._y1+n)/6)}function Wu(t){this._context=t}function Vu(t){return new Wu(t)}function Gu(t){this._context=t}function Xu(t){this._context=t}function Zu(t){this._context=t}function Qu(t){return t<0?-1:1}function Ku(t,e,n){var r=t._x1-t._x0,i=e-t._x1,a=(t._y1-t._y0)/(r||i<0&&-0),o=(n-t._y1)/(i||r<0&&-0),s=(a*i+o*r)/(r+i);return(Qu(a)+Qu(o))*Math.min(Math.abs(a),Math.abs(o),.5*Math.abs(s))||0}function Ju(t,e){var n=t._x1-t._x0;return n?(3*(t._y1-t._y0)/n-e)/2:e}function tl(t,e,n){var r=t._x0,i=t._y0,a=t._x1,o=t._y1,s=(a-r)/3;t._context.bezierCurveTo(r+s,i+s*e,a-s,o-s*n,a,o)}function el(t){this._context=t}function nl(t){this._context=new rl(t)}function rl(t){this._context=t}function il(t){this._context=t}function al(t){var e,n,r=t.length-1,i=new Array(r),a=new Array(r),o=new Array(r);for(i[0]=0,a[0]=2,o[0]=t[0]+2*t[1],e=1;e<r-1;++e)i[e]=1,a[e]=4,o[e]=4*t[e]+2*t[e+1];for(i[r-1]=2,a[r-1]=7,o[r-1]=8*t[r-1]+t[r],e=1;e<r;++e)n=i[e]/a[e-1],a[e]-=n,o[e]-=n*o[e-1];for(i[r-1]=o[r-1]/a[r-1],e=r-2;e>=0;--e)i[e]=(o[e]-i[e+1])/a[e];for(a[r-1]=(t[r]+i[r-1])/2,e=0;e<r-1;++e)a[e]=2*t[e+1]-i[e+1];return[i,a]}function ol(t,e){this._context=t,this._t=e}Array.prototype.slice,Fu.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:this._context.lineTo(t,e)}}},Wu.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:$u(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:$u(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},Gu.prototype={areaStart:Hu,areaEnd:Hu,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x2=t,this._y2=e;break;case 1:this._point=2,this._x3=t,this._y3=e;break;case 2:this._point=3,this._x4=t,this._y4=e,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+e)/6);break;default:$u(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},Xu.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var n=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+e)/6;this._line?this._context.lineTo(n,r):this._context.moveTo(n,r);break;case 3:this._point=4;default:$u(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},Zu.prototype={areaStart:Hu,areaEnd:Hu,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(t,e){t=+t,e=+e,this._point?this._context.lineTo(t,e):(this._point=1,this._context.moveTo(t,e))}},el.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:tl(this,this._t0,Ju(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){var n=NaN;if(e=+e,(t=+t)!==this._x1||e!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,tl(this,Ju(this,n=Ku(this,t,e)),n);break;default:tl(this,this._t0,n=Ku(this,t,e))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e,this._t0=n}}},(nl.prototype=Object.create(el.prototype)).point=function(t,e){el.prototype.point.call(this,e,t)},rl.prototype={moveTo:function(t,e){this._context.moveTo(e,t)},closePath:function(){this._context.closePath()},lineTo:function(t,e){this._context.lineTo(e,t)},bezierCurveTo:function(t,e,n,r,i,a){this._context.bezierCurveTo(e,t,r,n,a,i)}},il.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var t=this._x,e=this._y,n=t.length;if(n)if(this._line?this._context.lineTo(t[0],e[0]):this._context.moveTo(t[0],e[0]),2===n)this._context.lineTo(t[1],e[1]);else for(var r=al(t),i=al(e),a=0,o=1;o<n;++a,++o)this._context.bezierCurveTo(r[0][a],i[0][a],r[1][a],i[1][a],t[o],e[o]);(this._line||0!==this._line&&1===n)&&this._context.closePath(),this._line=1-this._line,this._x=this._y=null},point:function(t,e){this._x.push(+t),this._y.push(+e)}},ol.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=this._y=NaN,this._point=0},lineEnd:function(){0<this._t&&this._t<1&&2===this._point&&this._context.lineTo(this._x,this._y),(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line>=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,e),this._context.lineTo(t,e);else{var n=this._x*(1-this._t)+t*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,e)}}this._x=t,this._y=e}};var sl=new Date,cl=new Date;function ul(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=function(e){return t(e=new Date(+e)),e},i.ceil=function(n){return t(n=new Date(n-1)),e(n,1),t(n),n},i.round=function(t){var e=i(t),n=i.ceil(t);return t-e<n-t?e:n},i.offset=function(t,n){return e(t=new Date(+t),null==n?1:Math.floor(n)),t},i.range=function(n,r,a){var o,s=[];if(n=i.ceil(n),a=null==a?1:Math.floor(a),!(n<r&&a>0))return s;do{s.push(o=new Date(+n)),e(n,a),t(n)}while(o<n&&n<r);return s},i.filter=function(n){return ul((function(e){if(e>=e)for(;t(e),!n(e);)e.setTime(e-1)}),(function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););}))},n&&(i.count=function(e,r){return sl.setTime(+e),cl.setTime(+r),t(sl),t(cl),Math.floor(n(sl,cl))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(e){return r(e)%t==0}:function(e){return i.count(0,e)%t==0}):i:null}),i}const ll=864e5,hl=6048e5;function fl(t){return ul((function(e){e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+7*e)}),(function(t,e){return(e-t)/hl}))}var dl=fl(0),pl=fl(1),yl=fl(2),gl=fl(3),ml=fl(4),vl=fl(5),bl=fl(6),_l=(dl.range,pl.range,yl.range,gl.range,ml.range,vl.range,bl.range,ul((function(t){t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+e)}),(function(t,e){return(e-t)/ll}),(function(t){return t.getUTCDate()-1})));const xl=_l;function wl(t){return ul((function(e){e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+7*e)}),(function(t,e){return(e-t-6e4*(e.getTimezoneOffset()-t.getTimezoneOffset()))/hl}))}_l.range;var kl=wl(0),Tl=wl(1),El=wl(2),Cl=wl(3),Sl=wl(4),Al=wl(5),Ml=wl(6),Nl=(kl.range,Tl.range,El.range,Cl.range,Sl.range,Al.range,Ml.range,ul((t=>t.setHours(0,0,0,0)),((t,e)=>t.setDate(t.getDate()+e)),((t,e)=>(e-t-6e4*(e.getTimezoneOffset()-t.getTimezoneOffset()))/ll),(t=>t.getDate()-1)));const Dl=Nl;Nl.range;var Ol=ul((function(t){t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,e){t.setFullYear(t.getFullYear()+e)}),(function(t,e){return e.getFullYear()-t.getFullYear()}),(function(t){return t.getFullYear()}));Ol.every=function(t){return isFinite(t=Math.floor(t))&&t>0?ul((function(e){e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,n){e.setFullYear(e.getFullYear()+n*t)})):null};const Bl=Ol;Ol.range;var Ll=ul((function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCFullYear(t.getUTCFullYear()+e)}),(function(t,e){return e.getUTCFullYear()-t.getUTCFullYear()}),(function(t){return t.getUTCFullYear()}));Ll.every=function(t){return isFinite(t=Math.floor(t))&&t>0?ul((function(e){e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,n){e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null};const Il=Ll;function Rl(t){if(0<=t.y&&t.y<100){var e=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return e.setFullYear(t.y),e}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function Fl(t){if(0<=t.y&&t.y<100){var e=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return e.setUTCFullYear(t.y),e}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function Pl(t,e,n){return{y:t,m:e,d:n,H:0,M:0,S:0,L:0}}Ll.range;var jl,Yl,zl={"-":"",_:" ",0:"0"},Ul=/^\s*\d+/,ql=/^%/,Hl=/[\\^$*+?|[\]().{}]/g;function $l(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",a=i.length;return r+(a<n?new Array(n-a+1).join(e)+i:i)}function Wl(t){return t.replace(Hl,"\\$&")}function Vl(t){return new RegExp("^(?:"+t.map(Wl).join("|")+")","i")}function Gl(t){return new Map(t.map(((t,e)=>[t.toLowerCase(),e])))}function Xl(t,e,n){var r=Ul.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function Zl(t,e,n){var r=Ul.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function Ql(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function Kl(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function Jl(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function th(t,e,n){var r=Ul.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function eh(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function nh(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function rh(t,e,n){var r=Ul.exec(e.slice(n,n+1));return r?(t.q=3*r[0]-3,n+r[0].length):-1}function ih(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function ah(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function oh(t,e,n){var r=Ul.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function sh(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function ch(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function uh(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function lh(t,e,n){var r=Ul.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function hh(t,e,n){var r=Ul.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function fh(t,e,n){var r=ql.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function dh(t,e,n){var r=Ul.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function ph(t,e,n){var r=Ul.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function yh(t,e){return $l(t.getDate(),e,2)}function gh(t,e){return $l(t.getHours(),e,2)}function mh(t,e){return $l(t.getHours()%12||12,e,2)}function vh(t,e){return $l(1+Dl.count(Bl(t),t),e,3)}function bh(t,e){return $l(t.getMilliseconds(),e,3)}function _h(t,e){return bh(t,e)+"000"}function xh(t,e){return $l(t.getMonth()+1,e,2)}function wh(t,e){return $l(t.getMinutes(),e,2)}function kh(t,e){return $l(t.getSeconds(),e,2)}function Th(t){var e=t.getDay();return 0===e?7:e}function Eh(t,e){return $l(kl.count(Bl(t)-1,t),e,2)}function Ch(t){var e=t.getDay();return e>=4||0===e?Sl(t):Sl.ceil(t)}function Sh(t,e){return t=Ch(t),$l(Sl.count(Bl(t),t)+(4===Bl(t).getDay()),e,2)}function Ah(t){return t.getDay()}function Mh(t,e){return $l(Tl.count(Bl(t)-1,t),e,2)}function Nh(t,e){return $l(t.getFullYear()%100,e,2)}function Dh(t,e){return $l((t=Ch(t)).getFullYear()%100,e,2)}function Oh(t,e){return $l(t.getFullYear()%1e4,e,4)}function Bh(t,e){var n=t.getDay();return $l((t=n>=4||0===n?Sl(t):Sl.ceil(t)).getFullYear()%1e4,e,4)}function Lh(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+$l(e/60|0,"0",2)+$l(e%60,"0",2)}function Ih(t,e){return $l(t.getUTCDate(),e,2)}function Rh(t,e){return $l(t.getUTCHours(),e,2)}function Fh(t,e){return $l(t.getUTCHours()%12||12,e,2)}function Ph(t,e){return $l(1+xl.count(Il(t),t),e,3)}function jh(t,e){return $l(t.getUTCMilliseconds(),e,3)}function Yh(t,e){return jh(t,e)+"000"}function zh(t,e){return $l(t.getUTCMonth()+1,e,2)}function Uh(t,e){return $l(t.getUTCMinutes(),e,2)}function qh(t,e){return $l(t.getUTCSeconds(),e,2)}function Hh(t){var e=t.getUTCDay();return 0===e?7:e}function $h(t,e){return $l(dl.count(Il(t)-1,t),e,2)}function Wh(t){var e=t.getUTCDay();return e>=4||0===e?ml(t):ml.ceil(t)}function Vh(t,e){return t=Wh(t),$l(ml.count(Il(t),t)+(4===Il(t).getUTCDay()),e,2)}function Gh(t){return t.getUTCDay()}function Xh(t,e){return $l(pl.count(Il(t)-1,t),e,2)}function Zh(t,e){return $l(t.getUTCFullYear()%100,e,2)}function Qh(t,e){return $l((t=Wh(t)).getUTCFullYear()%100,e,2)}function Kh(t,e){return $l(t.getUTCFullYear()%1e4,e,4)}function Jh(t,e){var n=t.getUTCDay();return $l((t=n>=4||0===n?ml(t):ml.ceil(t)).getUTCFullYear()%1e4,e,4)}function tf(){return"+0000"}function ef(){return"%"}function nf(t){return+t}function rf(t){return Math.floor(+t/1e3)}jl=function(t){var e=t.dateTime,n=t.date,r=t.time,i=t.periods,a=t.days,o=t.shortDays,s=t.months,c=t.shortMonths,u=Vl(i),l=Gl(i),h=Vl(a),f=Gl(a),d=Vl(o),p=Gl(o),y=Vl(s),g=Gl(s),m=Vl(c),v=Gl(c),b={a:function(t){return o[t.getDay()]},A:function(t){return a[t.getDay()]},b:function(t){return c[t.getMonth()]},B:function(t){return s[t.getMonth()]},c:null,d:yh,e:yh,f:_h,g:Dh,G:Bh,H:gh,I:mh,j:vh,L:bh,m:xh,M:wh,p:function(t){return i[+(t.getHours()>=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:nf,s:rf,S:kh,u:Th,U:Eh,V:Sh,w:Ah,W:Mh,x:null,X:null,y:Nh,Y:Oh,Z:Lh,"%":ef},_={a:function(t){return o[t.getUTCDay()]},A:function(t){return a[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:Ih,e:Ih,f:Yh,g:Qh,G:Jh,H:Rh,I:Fh,j:Ph,L:jh,m:zh,M:Uh,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:nf,s:rf,S:qh,u:Hh,U:$h,V:Vh,w:Gh,W:Xh,x:null,X:null,y:Zh,Y:Kh,Z:tf,"%":ef},x={a:function(t,e,n){var r=d.exec(e.slice(n));return r?(t.w=p.get(r[0].toLowerCase()),n+r[0].length):-1},A:function(t,e,n){var r=h.exec(e.slice(n));return r?(t.w=f.get(r[0].toLowerCase()),n+r[0].length):-1},b:function(t,e,n){var r=m.exec(e.slice(n));return r?(t.m=v.get(r[0].toLowerCase()),n+r[0].length):-1},B:function(t,e,n){var r=y.exec(e.slice(n));return r?(t.m=g.get(r[0].toLowerCase()),n+r[0].length):-1},c:function(t,n,r){return T(t,e,n,r)},d:ah,e:ah,f:hh,g:eh,G:th,H:sh,I:sh,j:oh,L:lh,m:ih,M:ch,p:function(t,e,n){var r=u.exec(e.slice(n));return r?(t.p=l.get(r[0].toLowerCase()),n+r[0].length):-1},q:rh,Q:dh,s:ph,S:uh,u:Zl,U:Ql,V:Kl,w:Xl,W:Jl,x:function(t,e,r){return T(t,n,e,r)},X:function(t,e,n){return T(t,r,e,n)},y:eh,Y:th,Z:nh,"%":fh};function w(t,e){return function(n){var r,i,a,o=[],s=-1,c=0,u=t.length;for(n instanceof Date||(n=new Date(+n));++s<u;)37===t.charCodeAt(s)&&(o.push(t.slice(c,s)),null!=(i=zl[r=t.charAt(++s)])?r=t.charAt(++s):i="e"===r?" ":"0",(a=e[r])&&(r=a(n,i)),o.push(r),c=s+1);return o.push(t.slice(c,s)),o.join("")}}function k(t,e){return function(n){var r,i,a=Pl(1900,void 0,1);if(T(a,t,n+="",0)!=n.length)return null;if("Q"in a)return new Date(a.Q);if("s"in a)return new Date(1e3*a.s+("L"in a?a.L:0));if(e&&!("Z"in a)&&(a.Z=0),"p"in a&&(a.H=a.H%12+12*a.p),void 0===a.m&&(a.m="q"in a?a.q:0),"V"in a){if(a.V<1||a.V>53)return null;"w"in a||(a.w=1),"Z"in a?(i=(r=Fl(Pl(a.y,0,1))).getUTCDay(),r=i>4||0===i?pl.ceil(r):pl(r),r=xl.offset(r,7*(a.V-1)),a.y=r.getUTCFullYear(),a.m=r.getUTCMonth(),a.d=r.getUTCDate()+(a.w+6)%7):(i=(r=Rl(Pl(a.y,0,1))).getDay(),r=i>4||0===i?Tl.ceil(r):Tl(r),r=Dl.offset(r,7*(a.V-1)),a.y=r.getFullYear(),a.m=r.getMonth(),a.d=r.getDate()+(a.w+6)%7)}else("W"in a||"U"in a)&&("w"in a||(a.w="u"in a?a.u%7:"W"in a?1:0),i="Z"in a?Fl(Pl(a.y,0,1)).getUTCDay():Rl(Pl(a.y,0,1)).getDay(),a.m=0,a.d="W"in a?(a.w+6)%7+7*a.W-(i+5)%7:a.w+7*a.U-(i+6)%7);return"Z"in a?(a.H+=a.Z/100|0,a.M+=a.Z%100,Fl(a)):Rl(a)}}function T(t,e,n,r){for(var i,a,o=0,s=e.length,c=n.length;o<s;){if(r>=c)return-1;if(37===(i=e.charCodeAt(o++))){if(i=e.charAt(o++),!(a=x[i in zl?e.charAt(o++):i])||(r=a(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return b.x=w(n,b),b.X=w(r,b),b.c=w(e,b),_.x=w(n,_),_.X=w(r,_),_.c=w(e,_),{format:function(t){var e=w(t+="",b);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),Yl=jl.format,jl.parse,jl.utcFormat,jl.utcParse;var af={value:()=>{}};function of(){for(var t,e=0,n=arguments.length,r={};e<n;++e){if(!(t=arguments[e]+"")||t in r||/[\s.]/.test(t))throw new Error("illegal type: "+t);r[t]=[]}return new sf(r)}function sf(t){this._=t}function cf(t,e){return t.trim().split(/^|\s+/).map((function(t){var n="",r=t.indexOf(".");if(r>=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function uf(t,e){for(var n,r=0,i=t.length;r<i;++r)if((n=t[r]).name===e)return n.value}function lf(t,e,n){for(var r=0,i=t.length;r<i;++r)if(t[r].name===e){t[r]=af,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=n&&t.push({name:e,value:n}),t}sf.prototype=of.prototype={constructor:sf,on:function(t,e){var n,r=this._,i=cf(t+"",r),a=-1,o=i.length;if(!(arguments.length<2)){if(null!=e&&"function"!=typeof e)throw new Error("invalid callback: "+e);for(;++a<o;)if(n=(t=i[a]).type)r[n]=lf(r[n],t.name,e);else if(null==e)for(n in r)r[n]=lf(r[n],t.name,null);return this}for(;++a<o;)if((n=(t=i[a]).type)&&(n=uf(r[n],t.name)))return n},copy:function(){var t={},e=this._;for(var n in e)t[n]=e[n].slice();return new sf(t)},call:function(t,e){if((n=arguments.length-2)>0)for(var n,r,i=new Array(n),a=0;a<n;++a)i[a]=arguments[a+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(a=0,n=(r=this._[t]).length;a<n;++a)r[a].value.apply(e,i)},apply:function(t,e,n){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,a=r.length;i<a;++i)r[i].value.apply(e,n)}};const hf=of;var ff,df,pf=0,yf=0,gf=0,mf=0,vf=0,bf=0,_f="object"==typeof performance&&performance.now?performance:Date,xf="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function wf(){return vf||(xf(kf),vf=_f.now()+bf)}function kf(){vf=0}function Tf(){this._call=this._time=this._next=null}function Ef(t,e,n){var r=new Tf;return r.restart(t,e,n),r}function Cf(){vf=(mf=_f.now())+bf,pf=yf=0;try{!function(){wf(),++pf;for(var t,e=ff;e;)(t=vf-e._time)>=0&&e._call.call(void 0,t),e=e._next;--pf}()}finally{pf=0,function(){for(var t,e,n=ff,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:ff=e);df=t,Af(r)}(),vf=0}}function Sf(){var t=_f.now(),e=t-mf;e>1e3&&(bf-=e,mf=t)}function Af(t){pf||(yf&&(yf=clearTimeout(yf)),t-vf>24?(t<1/0&&(yf=setTimeout(Cf,t-_f.now()-bf)),gf&&(gf=clearInterval(gf))):(gf||(mf=_f.now(),gf=setInterval(Sf,1e3)),pf=1,xf(Cf)))}function Mf(t,e,n){var r=new Tf;return e=null==e?0:+e,r.restart((n=>{r.stop(),t(n+e)}),e,n),r}Tf.prototype=Ef.prototype={constructor:Tf,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?wf():+n)+(null==e?0:+e),this._next||df===this||(df?df._next=this:ff=this,df=this),this._call=t,this._time=n,Af()},stop:function(){this._call&&(this._call=null,this._time=1/0,Af())}};var Nf=hf("start","end","cancel","interrupt"),Df=[];function Of(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return Mf(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u<e&&(f.state=6,f.timer.stop(),f.on.call("cancel",t,t.__data__,f.index,f.group),delete i[u])}if(Mf((function(){3===n.state&&(n.state=4,n.timer.restart(o,n.delay,n.time),o(c))})),n.state=2,n.on.call("start",t,t.__data__,n.index,n.group),2===n.state){for(n.state=3,r=new Array(h=n.tween.length),u=0,l=-1;u<h;++u)(f=n.tween[u].value.call(t,t.__data__,n.index,n.group))&&(r[++l]=f);r.length=l+1}}function o(e){for(var i=e<n.duration?n.ease.call(null,e/n.duration):(n.timer.restart(s),n.state=5,1),a=-1,o=r.length;++a<o;)r[a].call(t,i);5===n.state&&(n.on.call("end",t,t.__data__,n.index,n.group),s())}function s(){for(var r in n.state=6,n.timer.stop(),delete i[e],i)return;delete t.__transition}i[e]=n,n.timer=Ef((function(t){n.state=1,n.timer.restart(a,n.delay,n.time),n.delay<=t&&a(t-n.delay)}),0,n.time)}(t,n,{name:e,index:r,group:i,on:Nf,tween:Df,time:a.time,delay:a.delay,duration:a.duration,ease:a.ease,timer:null,state:0})}function Bf(t,e){var n=If(t,e);if(n.state>0)throw new Error("too late; already scheduled");return n}function Lf(t,e){var n=If(t,e);if(n.state>3)throw new Error("too late; already running");return n}function If(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function Rf(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}var Ff,Pf=180/Math.PI,jf={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function Yf(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r<e*n&&(t=-t,e=-e,c=-c,o=-o),{translateX:i,translateY:a,rotate:Math.atan2(e,t)*Pf,skewX:Math.atan(c)*Pf,scaleX:o,scaleY:s}}function zf(t,e,n,r){function i(t){return t.length?t.pop()+" ":""}return function(a,o){var s=[],c=[];return a=t(a),o=t(o),function(t,r,i,a,o,s){if(t!==i||r!==a){var c=o.push("translate(",null,e,null,n);s.push({i:c-4,x:Rf(t,i)},{i:c-2,x:Rf(r,a)})}else(i||a)&&o.push("translate("+i+e+a+n)}(a.translateX,a.translateY,o.translateX,o.translateY,s,c),function(t,e,n,a){t!==e?(t-e>180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:Rf(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:Rf(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:Rf(t,n)},{i:s-2,x:Rf(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n<r;)s[(e=c[n]).i]=e.x(t);return s.join("")}}}var Uf=zf((function(t){const e=new("function"==typeof DOMMatrix?DOMMatrix:WebKitCSSMatrix)(t+"");return e.isIdentity?jf:Yf(e.a,e.b,e.c,e.d,e.e,e.f)}),"px, ","px)","deg)"),qf=zf((function(t){return null==t?jf:(Ff||(Ff=document.createElementNS("http://www.w3.org/2000/svg","g")),Ff.setAttribute("transform",t),(t=Ff.transform.baseVal.consolidate())?Yf((t=t.matrix).a,t.b,t.c,t.d,t.e,t.f):jf)}),", ",")",")");function Hf(t,e){var n,r;return function(){var i=Lf(this,t),a=i.tween;if(a!==n)for(var o=0,s=(r=n=a).length;o<s;++o)if(r[o].name===e){(r=r.slice()).splice(o,1);break}i.tween=r}}function $f(t,e,n){var r,i;if("function"!=typeof n)throw new Error;return function(){var a=Lf(this,t),o=a.tween;if(o!==r){i=(r=o).slice();for(var s={name:e,value:n},c=0,u=i.length;c<u;++c)if(i[c].name===e){i[c]=s;break}c===u&&i.push(s)}a.tween=i}}function Wf(t,e,n){var r=t._id;return t.each((function(){var t=Lf(this,r);(t.value||(t.value={}))[e]=n.apply(this,arguments)})),function(t){return If(t,r).value[e]}}function Vf(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}const Gf=function t(e){var n=function(t){return 1==(t=+t)?Fr:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):Ir(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=ur(t)).r,(e=ur(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=Fr(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function Xf(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n<i;++n)r=ur(e[n]),a[n]=r.r||0,o[n]=r.g||0,s[n]=r.b||0;return a=t(a),o=t(o),s=t(s),r.opacity=1,function(t){return r.r=a(t),r.g=o(t),r.b=s(t),r+""}}}Xf((function(t){var e=t.length-1;return function(n){var r=n<=0?n=0:n>=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=r<e-1?t[r+2]:2*a-i;return Vf((n-r/e)*e,o,i,a,s)}})),Xf((function(t){var e=t.length;return function(n){var r=Math.floor(((n%=1)<0?++n:n)*e),i=t[(r+e-1)%e],a=t[r%e],o=t[(r+1)%e],s=t[(r+2)%e];return Vf((n-r/e)*e,i,a,o,s)}}));var Zf=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Qf=new RegExp(Zf.source,"g");function Kf(t,e){var n,r,i,a=Zf.lastIndex=Qf.lastIndex=0,o=-1,s=[],c=[];for(t+="",e+="";(n=Zf.exec(t))&&(r=Qf.exec(e));)(i=r.index)>a&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:Rf(n,r)})),a=Qf.lastIndex;return a<e.length&&(i=e.slice(a),s[o]?s[o]+=i:s[++o]=i),s.length<2?c[0]?function(t){return function(e){return t(e)+""}}(c[0].x):function(t){return function(){return t}}(e):(e=c.length,function(t){for(var n,r=0;r<e;++r)s[(n=c[r]).i]=n.x(t);return s.join("")})}function Jf(t,e){var n;return("number"==typeof e?Rf:e instanceof ar?Gf:(n=ar(e))?(e=n,Gf):Kf)(t,e)}function td(t){return function(){this.removeAttribute(t)}}function ed(t){return function(){this.removeAttributeNS(t.space,t.local)}}function nd(t,e,n){var r,i,a=n+"";return function(){var o=this.getAttribute(t);return o===a?null:o===r?i:i=e(r=o,n)}}function rd(t,e,n){var r,i,a=n+"";return function(){var o=this.getAttributeNS(t.space,t.local);return o===a?null:o===r?i:i=e(r=o,n)}}function id(t,e,n){var r,i,a;return function(){var o,s,c=n(this);if(null!=c)return(o=this.getAttribute(t))===(s=c+"")?null:o===r&&s===i?a:(i=s,a=e(r=o,c));this.removeAttribute(t)}}function ad(t,e,n){var r,i,a;return function(){var o,s,c=n(this);if(null!=c)return(o=this.getAttributeNS(t.space,t.local))===(s=c+"")?null:o===r&&s===i?a:(i=s,a=e(r=o,c));this.removeAttributeNS(t.space,t.local)}}function od(t,e){return function(n){this.setAttribute(t,e.call(this,n))}}function sd(t,e){return function(n){this.setAttributeNS(t.space,t.local,e.call(this,n))}}function cd(t,e){var n,r;function i(){var i=e.apply(this,arguments);return i!==r&&(n=(r=i)&&sd(t,i)),n}return i._value=e,i}function ud(t,e){var n,r;function i(){var i=e.apply(this,arguments);return i!==r&&(n=(r=i)&&od(t,i)),n}return i._value=e,i}function ld(t,e){return function(){Bf(this,t).delay=+e.apply(this,arguments)}}function hd(t,e){return e=+e,function(){Bf(this,t).delay=e}}function fd(t,e){return function(){Lf(this,t).duration=+e.apply(this,arguments)}}function dd(t,e){return e=+e,function(){Lf(this,t).duration=e}}function pd(t,e){if("function"!=typeof e)throw new Error;return function(){Lf(this,t).ease=e}}function yd(t,e,n){var r,i,a=function(t){return(t+"").trim().split(/^|\s+/).every((function(t){var e=t.indexOf(".");return e>=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?Bf:Lf;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var gd=iu.prototype.constructor;function md(t){return function(){this.style.removeProperty(t)}}function vd(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function bd(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&vd(t,a,n)),r}return a._value=e,a}function _d(t){return function(e){this.textContent=t.call(this,e)}}function xd(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&_d(r)),e}return r._value=t,r}var wd=0;function kd(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function Td(){return++wd}var Ed=iu.prototype;kd.prototype=function(t){return iu().transition(t)}.prototype={constructor:kd,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=$s(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o<i;++o)for(var s,c,u=r[o],l=u.length,h=a[o]=new Array(l),f=0;f<l;++f)(s=u[f])&&(c=t.call(s,s.__data__,f,u))&&("__data__"in s&&(c.__data__=s.__data__),h[f]=c,Of(h[f],e,n,f,h,If(s,n)));return new kd(a,this._parents,e,n)},selectAll:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=Gs(t));for(var r=this._groups,i=r.length,a=[],o=[],s=0;s<i;++s)for(var c,u=r[s],l=u.length,h=0;h<l;++h)if(c=u[h]){for(var f,d=t.call(c,c.__data__,h,u),p=If(c,n),y=0,g=d.length;y<g;++y)(f=d[y])&&Of(f,e,n,y,d,p);a.push(d),o.push(c)}return new kd(a,o,e,n)},selectChild:Ed.selectChild,selectChildren:Ed.selectChildren,filter:function(t){"function"!=typeof t&&(t=Xs(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o=e[i],s=o.length,c=r[i]=[],u=0;u<s;++u)(a=o[u])&&t.call(a,a.__data__,u,o)&&c.push(a);return new kd(r,this._parents,this._name,this._id)},merge:function(t){if(t._id!==this._id)throw new Error;for(var e=this._groups,n=t._groups,r=e.length,i=n.length,a=Math.min(r,i),o=new Array(r),s=0;s<a;++s)for(var c,u=e[s],l=n[s],h=u.length,f=o[s]=new Array(h),d=0;d<h;++d)(c=u[d]||l[d])&&(f[d]=c);for(;s<r;++s)o[s]=e[s];return new kd(o,this._parents,this._name,this._id)},selection:function(){return new gd(this._groups,this._parents)},transition:function(){for(var t=this._name,e=this._id,n=Td(),r=this._groups,i=r.length,a=0;a<i;++a)for(var o,s=r[a],c=s.length,u=0;u<c;++u)if(o=s[u]){var l=If(o,e);Of(o,t,n,u,s,{time:l.time+l.delay+l.duration,delay:0,duration:l.duration,ease:l.ease})}return new kd(r,this._parents,t,n)},call:Ed.call,nodes:Ed.nodes,node:Ed.node,size:Ed.size,empty:Ed.empty,each:Ed.each,on:function(t,e){var n=this._id;return arguments.length<2?If(this.node(),n).on.on(t):this.each(yd(n,t,e))},attr:function(t,e){var n=hc(t),r="transform"===n?qf:Jf;return this.attrTween(t,"function"==typeof e?(n.local?ad:id)(n,r,Wf(this,"attr."+t,e)):null==e?(n.local?ed:td)(n):(n.local?rd:nd)(n,r,e))},attrTween:function(t,e){var n="attr."+t;if(arguments.length<2)return(n=this.tween(n))&&n._value;if(null==e)return this.tween(n,null);if("function"!=typeof e)throw new Error;var r=hc(t);return this.tween(n,(r.local?cd:ud)(r,e))},style:function(t,e,n){var r="transform"==(t+="")?Uf:Jf;return null==e?this.styleTween(t,function(t,e){var n,r,i;return function(){var a=wc(this,t),o=(this.style.removeProperty(t),wc(this,t));return a===o?null:a===n&&o===r?i:i=e(n=a,r=o)}}(t,r)).on("end.style."+t,md(t)):"function"==typeof e?this.styleTween(t,function(t,e,n){var r,i,a;return function(){var o=wc(this,t),s=n(this),c=s+"";return null==s&&(this.style.removeProperty(t),c=s=wc(this,t)),o===c?null:o===r&&c===i?a:(i=c,a=e(r=o,s))}}(t,r,Wf(this,"style."+t,e))).each(function(t,e){var n,r,i,a,o="style."+e,s="end."+o;return function(){var c=Lf(this,t),u=c.on,l=null==c.value[o]?a||(a=md(e)):void 0;u===n&&i===l||(r=(n=u).copy()).on(s,i=l),c.on=r}}(this._id,t)):this.styleTween(t,function(t,e,n){var r,i,a=n+"";return function(){var o=wc(this,t);return o===a?null:o===r?i:i=e(r=o,n)}}(t,r,e),n).on("end.style."+t,null)},styleTween:function(t,e,n){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==e)return this.tween(r,null);if("function"!=typeof e)throw new Error;return this.tween(r,bd(t,e,null==n?"":n))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var e=t(this);this.textContent=null==e?"":e}}(Wf(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},textTween:function(t){var e="text";if(arguments.length<1)return(e=this.tween(e))&&e._value;if(null==t)return this.tween(e,null);if("function"!=typeof t)throw new Error;return this.tween(e,xd(t))},remove:function(){return this.on("end.remove",function(t){return function(){var e=this.parentNode;for(var n in this.__transition)if(+n!==t)return;e&&e.removeChild(this)}}(this._id))},tween:function(t,e){var n=this._id;if(t+="",arguments.length<2){for(var r,i=If(this.node(),n).tween,a=0,o=i.length;a<o;++a)if((r=i[a]).name===t)return r.value;return null}return this.each((null==e?Hf:$f)(n,t,e))},delay:function(t){var e=this._id;return arguments.length?this.each(("function"==typeof t?ld:hd)(e,t)):If(this.node(),e).delay},duration:function(t){var e=this._id;return arguments.length?this.each(("function"==typeof t?fd:dd)(e,t)):If(this.node(),e).duration},ease:function(t){var e=this._id;return arguments.length?this.each(pd(e,t)):If(this.node(),e).ease},easeVarying:function(t){if("function"!=typeof t)throw new Error;return this.each(function(t,e){return function(){var n=e.apply(this,arguments);if("function"!=typeof n)throw new Error;Lf(this,t).ease=n}}(this._id,t))},end:function(){var t,e,n=this,r=n._id,i=n.size();return new Promise((function(a,o){var s={value:o},c={value:function(){0==--i&&a()}};n.each((function(){var n=Lf(this,r),i=n.on;i!==t&&((e=(t=i).copy())._.cancel.push(s),e._.interrupt.push(s),e._.end.push(c)),n.on=e})),0===i&&a()}))},[Symbol.iterator]:Ed[Symbol.iterator]};var Cd={time:null,delay:0,duration:250,ease:function(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}};function Sd(t,e){for(var n;!(n=t.__transition)||!(n=n[e]);)if(!(t=t.parentNode))throw new Error(`transition ${e} not found`);return n}function Ad(){}function Md(t){return null==t?Ad:function(){return this.querySelector(t)}}function Nd(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}function Dd(){return[]}function Od(t){return null==t?Dd:function(){return this.querySelectorAll(t)}}function Bd(t){return function(){return this.matches(t)}}function Ld(t){return function(e){return e.matches(t)}}iu.prototype.interrupt=function(t){return this.each((function(){!function(t,e){var n,r,i,a=t.__transition,o=!0;if(a){for(i in e=null==e?null:e+"",a)(n=a[i]).name===e?(r=n.state>2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}(this,t)}))},iu.prototype.transition=function(t){var e,n;t instanceof kd?(e=t._id,t=t._name):(e=Td(),(n=Cd).time=wf(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;a<i;++a)for(var o,s=r[a],c=s.length,u=0;u<c;++u)(o=s[u])&&Of(o,t,e,u,s,n||Sd(o,e));return new kd(r,this._parents,t,e)};var Id=Array.prototype.find;function Rd(){return this.firstElementChild}var Fd=Array.prototype.filter;function Pd(){return Array.from(this.children)}function jd(t){return new Array(t.length)}function Yd(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}function zd(t){return function(){return t}}function Ud(t,e,n,r,i,a){for(var o,s=0,c=e.length,u=a.length;s<u;++s)(o=e[s])?(o.__data__=a[s],r[s]=o):n[s]=new Yd(t,a[s]);for(;s<c;++s)(o=e[s])&&(i[s]=o)}function qd(t,e,n,r,i,a,o){var s,c,u,l=new Map,h=e.length,f=a.length,d=new Array(h);for(s=0;s<h;++s)(c=e[s])&&(d[s]=u=o.call(c,c.__data__,s,e)+"",l.has(u)?i[s]=c:l.set(u,c));for(s=0;s<f;++s)u=o.call(t,a[s],s,a)+"",(c=l.get(u))?(r[s]=c,c.__data__=a[s],l.delete(u)):n[s]=new Yd(t,a[s]);for(s=0;s<h;++s)(c=e[s])&&l.get(d[s])===c&&(i[s]=c)}function Hd(t){return t.__data__}function $d(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function Wd(t,e){return t<e?-1:t>e?1:t>=e?0:NaN}Yd.prototype={constructor:Yd,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var Vd="http://www.w3.org/1999/xhtml";const Gd={svg:"http://www.w3.org/2000/svg",xhtml:Vd,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function Xd(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),Gd.hasOwnProperty(e)?{space:Gd[e],local:t}:t}function Zd(t){return function(){this.removeAttribute(t)}}function Qd(t){return function(){this.removeAttributeNS(t.space,t.local)}}function Kd(t,e){return function(){this.setAttribute(t,e)}}function Jd(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function tp(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function ep(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function np(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function rp(t){return function(){this.style.removeProperty(t)}}function ip(t,e,n){return function(){this.style.setProperty(t,e,n)}}function ap(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function op(t,e){return t.style.getPropertyValue(e)||np(t).getComputedStyle(t,null).getPropertyValue(e)}function sp(t){return function(){delete this[t]}}function cp(t,e){return function(){this[t]=e}}function up(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function lp(t){return t.trim().split(/^|\s+/)}function hp(t){return t.classList||new fp(t)}function fp(t){this._node=t,this._names=lp(t.getAttribute("class")||"")}function dp(t,e){for(var n=hp(t),r=-1,i=e.length;++r<i;)n.add(e[r])}function pp(t,e){for(var n=hp(t),r=-1,i=e.length;++r<i;)n.remove(e[r])}function yp(t){return function(){dp(this,t)}}function gp(t){return function(){pp(this,t)}}function mp(t,e){return function(){(e.apply(this,arguments)?dp:pp)(this,t)}}function vp(){this.textContent=""}function bp(t){return function(){this.textContent=t}}function _p(t){return function(){var e=t.apply(this,arguments);this.textContent=null==e?"":e}}function xp(){this.innerHTML=""}function wp(t){return function(){this.innerHTML=t}}function kp(t){return function(){var e=t.apply(this,arguments);this.innerHTML=null==e?"":e}}function Tp(){this.nextSibling&&this.parentNode.appendChild(this)}function Ep(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function Cp(t){return function(){var e=this.ownerDocument,n=this.namespaceURI;return n===Vd&&e.documentElement.namespaceURI===Vd?e.createElement(t):e.createElementNS(n,t)}}function Sp(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Ap(t){var e=Xd(t);return(e.local?Sp:Cp)(e)}function Mp(){return null}function Np(){var t=this.parentNode;t&&t.removeChild(this)}function Dp(){var t=this.cloneNode(!1),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}function Op(){var t=this.cloneNode(!0),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}function Bp(t){return t.trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");return n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function Lp(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r<a;++r)n=e[r],t.type&&n.type!==t.type||n.name!==t.name?e[++i]=n:this.removeEventListener(n.type,n.listener,n.options);++i?e.length=i:delete this.__on}}}function Ip(t,e,n){return function(){var r,i=this.__on,a=function(t){return function(e){t.call(this,e,this.__data__)}}(e);if(i)for(var o=0,s=i.length;o<s;++o)if((r=i[o]).type===t.type&&r.name===t.name)return this.removeEventListener(r.type,r.listener,r.options),this.addEventListener(r.type,r.listener=a,r.options=n),void(r.value=e);this.addEventListener(t.type,a,n),r={type:t.type,name:t.name,value:e,listener:a,options:n},i?i.push(r):this.__on=[r]}}function Rp(t,e,n){var r=np(t),i=r.CustomEvent;"function"==typeof i?i=new i(e,n):(i=r.document.createEvent("Event"),n?(i.initEvent(e,n.bubbles,n.cancelable),i.detail=n.detail):i.initEvent(e,!1,!1)),t.dispatchEvent(i)}function Fp(t,e){return function(){return Rp(this,t,e)}}function Pp(t,e){return function(){return Rp(this,t,e.apply(this,arguments))}}fp.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var jp=[null];function Yp(t,e){this._groups=t,this._parents=e}function zp(){return new Yp([[document.documentElement]],jp)}Yp.prototype=zp.prototype={constructor:Yp,select:function(t){"function"!=typeof t&&(t=Md(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o,s=e[i],c=s.length,u=r[i]=new Array(c),l=0;l<c;++l)(a=s[l])&&(o=t.call(a,a.__data__,l,s))&&("__data__"in a&&(o.__data__=a.__data__),u[l]=o);return new Yp(r,this._parents)},selectAll:function(t){t="function"==typeof t?function(t){return function(){return Nd(t.apply(this,arguments))}}(t):Od(t);for(var e=this._groups,n=e.length,r=[],i=[],a=0;a<n;++a)for(var o,s=e[a],c=s.length,u=0;u<c;++u)(o=s[u])&&(r.push(t.call(o,o.__data__,u,s)),i.push(o));return new Yp(r,i)},selectChild:function(t){return this.select(null==t?Rd:function(t){return function(){return Id.call(this.children,t)}}("function"==typeof t?t:Ld(t)))},selectChildren:function(t){return this.selectAll(null==t?Pd:function(t){return function(){return Fd.call(this.children,t)}}("function"==typeof t?t:Ld(t)))},filter:function(t){"function"!=typeof t&&(t=Bd(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o=e[i],s=o.length,c=r[i]=[],u=0;u<s;++u)(a=o[u])&&t.call(a,a.__data__,u,o)&&c.push(a);return new Yp(r,this._parents)},data:function(t,e){if(!arguments.length)return Array.from(this,Hd);var n=e?qd:Ud,r=this._parents,i=this._groups;"function"!=typeof t&&(t=zd(t));for(var a=i.length,o=new Array(a),s=new Array(a),c=new Array(a),u=0;u<a;++u){var l=r[u],h=i[u],f=h.length,d=$d(t.call(l,l&&l.__data__,u,r)),p=d.length,y=s[u]=new Array(p),g=o[u]=new Array(p),m=c[u]=new Array(f);n(l,h,y,g,m,d,e);for(var v,b,_=0,x=0;_<p;++_)if(v=y[_]){for(_>=x&&(x=_+1);!(b=g[x])&&++x<p;);v._next=b||null}}return(o=new Yp(o,r))._enter=s,o._exit=c,o},enter:function(){return new Yp(this._enter||this._groups.map(jd),this._parents)},exit:function(){return new Yp(this._exit||this._groups.map(jd),this._parents)},join:function(t,e,n){var r=this.enter(),i=this,a=this.exit();return"function"==typeof t?(r=t(r))&&(r=r.selection()):r=r.append(t+""),null!=e&&(i=e(i))&&(i=i.selection()),null==n?a.remove():n(a),r&&i?r.merge(i).order():i},merge:function(t){for(var e=t.selection?t.selection():t,n=this._groups,r=e._groups,i=n.length,a=r.length,o=Math.min(i,a),s=new Array(i),c=0;c<o;++c)for(var u,l=n[c],h=r[c],f=l.length,d=s[c]=new Array(f),p=0;p<f;++p)(u=l[p]||h[p])&&(d[p]=u);for(;c<i;++c)s[c]=n[c];return new Yp(s,this._parents)},selection:function(){return this},order:function(){for(var t=this._groups,e=-1,n=t.length;++e<n;)for(var r,i=t[e],a=i.length-1,o=i[a];--a>=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=Wd);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a<r;++a){for(var o,s=n[a],c=s.length,u=i[a]=new Array(c),l=0;l<c;++l)(o=s[l])&&(u[l]=o);u.sort(e)}return new Yp(i,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){return Array.from(this)},node:function(){for(var t=this._groups,e=0,n=t.length;e<n;++e)for(var r=t[e],i=0,a=r.length;i<a;++i){var o=r[i];if(o)return o}return null},size:function(){let t=0;for(const e of this)++t;return t},empty:function(){return!this.node()},each:function(t){for(var e=this._groups,n=0,r=e.length;n<r;++n)for(var i,a=e[n],o=0,s=a.length;o<s;++o)(i=a[o])&&t.call(i,i.__data__,o,a);return this},attr:function(t,e){var n=Xd(t);if(arguments.length<2){var r=this.node();return n.local?r.getAttributeNS(n.space,n.local):r.getAttribute(n)}return this.each((null==e?n.local?Qd:Zd:"function"==typeof e?n.local?ep:tp:n.local?Jd:Kd)(n,e))},style:function(t,e,n){return arguments.length>1?this.each((null==e?rp:"function"==typeof e?ap:ip)(t,e,null==n?"":n)):op(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?sp:"function"==typeof e?up:cp)(t,e)):this.node()[t]},classed:function(t,e){var n=lp(t+"");if(arguments.length<2){for(var r=hp(this.node()),i=-1,a=n.length;++i<a;)if(!r.contains(n[i]))return!1;return!0}return this.each(("function"==typeof e?mp:e?yp:gp)(n,e))},text:function(t){return arguments.length?this.each(null==t?vp:("function"==typeof t?_p:bp)(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?xp:("function"==typeof t?kp:wp)(t)):this.node().innerHTML},raise:function(){return this.each(Tp)},lower:function(){return this.each(Ep)},append:function(t){var e="function"==typeof t?t:Ap(t);return this.select((function(){return this.appendChild(e.apply(this,arguments))}))},insert:function(t,e){var n="function"==typeof t?t:Ap(t),r=null==e?Mp:"function"==typeof e?e:Md(e);return this.select((function(){return this.insertBefore(n.apply(this,arguments),r.apply(this,arguments)||null)}))},remove:function(){return this.each(Np)},clone:function(t){return this.select(t?Op:Dp)},datum:function(t){return arguments.length?this.property("__data__",t):this.node().__data__},on:function(t,e,n){var r,i,a=Bp(t+""),o=a.length;if(!(arguments.length<2)){for(s=e?Ip:Lp,r=0;r<o;++r)this.each(s(a[r],e,n));return this}var s=this.node().__on;if(s)for(var c,u=0,l=s.length;u<l;++u)for(r=0,c=s[u];r<o;++r)if((i=a[r]).type===c.type&&i.name===c.name)return c.value},dispatch:function(t,e){return this.each(("function"==typeof e?Pp:Fp)(t,e))},[Symbol.iterator]:function*(){for(var t=this._groups,e=0,n=t.length;e<n;++e)for(var r,i=t[e],a=0,o=i.length;a<o;++a)(r=i[a])&&(yield r)}};const Up=zp;var qp={value:()=>{}};function Hp(){for(var t,e=0,n=arguments.length,r={};e<n;++e){if(!(t=arguments[e]+"")||t in r||/[\s.]/.test(t))throw new Error("illegal type: "+t);r[t]=[]}return new $p(r)}function $p(t){this._=t}function Wp(t,e){return t.trim().split(/^|\s+/).map((function(t){var n="",r=t.indexOf(".");if(r>=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function Vp(t,e){for(var n,r=0,i=t.length;r<i;++r)if((n=t[r]).name===e)return n.value}function Gp(t,e,n){for(var r=0,i=t.length;r<i;++r)if(t[r].name===e){t[r]=qp,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=n&&t.push({name:e,value:n}),t}$p.prototype=Hp.prototype={constructor:$p,on:function(t,e){var n,r=this._,i=Wp(t+"",r),a=-1,o=i.length;if(!(arguments.length<2)){if(null!=e&&"function"!=typeof e)throw new Error("invalid callback: "+e);for(;++a<o;)if(n=(t=i[a]).type)r[n]=Gp(r[n],t.name,e);else if(null==e)for(n in r)r[n]=Gp(r[n],t.name,null);return this}for(;++a<o;)if((n=(t=i[a]).type)&&(n=Vp(r[n],t.name)))return n},copy:function(){var t={},e=this._;for(var n in e)t[n]=e[n].slice();return new $p(t)},call:function(t,e){if((n=arguments.length-2)>0)for(var n,r,i=new Array(n),a=0;a<n;++a)i[a]=arguments[a+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(a=0,n=(r=this._[t]).length;a<n;++a)r[a].value.apply(e,i)},apply:function(t,e,n){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,a=r.length;i<a;++i)r[i].value.apply(e,n)}};const Xp=Hp;var Zp,Qp,Kp=0,Jp=0,ty=0,ey=0,ny=0,ry=0,iy="object"==typeof performance&&performance.now?performance:Date,ay="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function oy(){return ny||(ay(sy),ny=iy.now()+ry)}function sy(){ny=0}function cy(){this._call=this._time=this._next=null}function uy(t,e,n){var r=new cy;return r.restart(t,e,n),r}function ly(){ny=(ey=iy.now())+ry,Kp=Jp=0;try{!function(){oy(),++Kp;for(var t,e=Zp;e;)(t=ny-e._time)>=0&&e._call.call(void 0,t),e=e._next;--Kp}()}finally{Kp=0,function(){for(var t,e,n=Zp,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:Zp=e);Qp=t,fy(r)}(),ny=0}}function hy(){var t=iy.now(),e=t-ey;e>1e3&&(ry-=e,ey=t)}function fy(t){Kp||(Jp&&(Jp=clearTimeout(Jp)),t-ny>24?(t<1/0&&(Jp=setTimeout(ly,t-iy.now()-ry)),ty&&(ty=clearInterval(ty))):(ty||(ey=iy.now(),ty=setInterval(hy,1e3)),Kp=1,ay(ly)))}function dy(t,e,n){var r=new cy;return e=null==e?0:+e,r.restart((n=>{r.stop(),t(n+e)}),e,n),r}cy.prototype=uy.prototype={constructor:cy,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?oy():+n)+(null==e?0:+e),this._next||Qp===this||(Qp?Qp._next=this:Zp=this,Qp=this),this._call=t,this._time=n,fy()},stop:function(){this._call&&(this._call=null,this._time=1/0,fy())}};var py=Xp("start","end","cancel","interrupt"),yy=[];function gy(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return dy(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u<e&&(f.state=6,f.timer.stop(),f.on.call("cancel",t,t.__data__,f.index,f.group),delete i[u])}if(dy((function(){3===n.state&&(n.state=4,n.timer.restart(o,n.delay,n.time),o(c))})),n.state=2,n.on.call("start",t,t.__data__,n.index,n.group),2===n.state){for(n.state=3,r=new Array(h=n.tween.length),u=0,l=-1;u<h;++u)(f=n.tween[u].value.call(t,t.__data__,n.index,n.group))&&(r[++l]=f);r.length=l+1}}function o(e){for(var i=e<n.duration?n.ease.call(null,e/n.duration):(n.timer.restart(s),n.state=5,1),a=-1,o=r.length;++a<o;)r[a].call(t,i);5===n.state&&(n.on.call("end",t,t.__data__,n.index,n.group),s())}function s(){for(var r in n.state=6,n.timer.stop(),delete i[e],i)return;delete t.__transition}i[e]=n,n.timer=uy((function(t){n.state=1,n.timer.restart(a,n.delay,n.time),n.delay<=t&&a(t-n.delay)}),0,n.time)}(t,n,{name:e,index:r,group:i,on:py,tween:yy,time:a.time,delay:a.delay,duration:a.duration,ease:a.ease,timer:null,state:0})}function my(t,e){var n=by(t,e);if(n.state>0)throw new Error("too late; already scheduled");return n}function vy(t,e){var n=by(t,e);if(n.state>3)throw new Error("too late; already running");return n}function by(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function _y(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}var xy,wy=180/Math.PI,ky={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function Ty(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r<e*n&&(t=-t,e=-e,c=-c,o=-o),{translateX:i,translateY:a,rotate:Math.atan2(e,t)*wy,skewX:Math.atan(c)*wy,scaleX:o,scaleY:s}}function Ey(t,e,n,r){function i(t){return t.length?t.pop()+" ":""}return function(a,o){var s=[],c=[];return a=t(a),o=t(o),function(t,r,i,a,o,s){if(t!==i||r!==a){var c=o.push("translate(",null,e,null,n);s.push({i:c-4,x:_y(t,i)},{i:c-2,x:_y(r,a)})}else(i||a)&&o.push("translate("+i+e+a+n)}(a.translateX,a.translateY,o.translateX,o.translateY,s,c),function(t,e,n,a){t!==e?(t-e>180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:_y(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:_y(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:_y(t,n)},{i:s-2,x:_y(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n<r;)s[(e=c[n]).i]=e.x(t);return s.join("")}}}var Cy=Ey((function(t){const e=new("function"==typeof DOMMatrix?DOMMatrix:WebKitCSSMatrix)(t+"");return e.isIdentity?ky:Ty(e.a,e.b,e.c,e.d,e.e,e.f)}),"px, ","px)","deg)"),Sy=Ey((function(t){return null==t?ky:(xy||(xy=document.createElementNS("http://www.w3.org/2000/svg","g")),xy.setAttribute("transform",t),(t=xy.transform.baseVal.consolidate())?Ty((t=t.matrix).a,t.b,t.c,t.d,t.e,t.f):ky)}),", ",")",")");function Ay(t,e){var n,r;return function(){var i=vy(this,t),a=i.tween;if(a!==n)for(var o=0,s=(r=n=a).length;o<s;++o)if(r[o].name===e){(r=r.slice()).splice(o,1);break}i.tween=r}}function My(t,e,n){var r,i;if("function"!=typeof n)throw new Error;return function(){var a=vy(this,t),o=a.tween;if(o!==r){i=(r=o).slice();for(var s={name:e,value:n},c=0,u=i.length;c<u;++c)if(i[c].name===e){i[c]=s;break}c===u&&i.push(s)}a.tween=i}}function Ny(t,e,n){var r=t._id;return t.each((function(){var t=vy(this,r);(t.value||(t.value={}))[e]=n.apply(this,arguments)})),function(t){return by(t,r).value[e]}}function Dy(t,e,n){t.prototype=e.prototype=n,n.constructor=t}function Oy(t,e){var n=Object.create(t.prototype);for(var r in e)n[r]=e[r];return n}function By(){}var Ly=.7,Iy=1.4285714285714286,Ry="\\s*([+-]?\\d+)\\s*",Fy="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",Py="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",jy=/^#([0-9a-f]{3,8})$/,Yy=new RegExp("^rgb\\("+[Ry,Ry,Ry]+"\\)$"),zy=new RegExp("^rgb\\("+[Py,Py,Py]+"\\)$"),Uy=new RegExp("^rgba\\("+[Ry,Ry,Ry,Fy]+"\\)$"),qy=new RegExp("^rgba\\("+[Py,Py,Py,Fy]+"\\)$"),Hy=new RegExp("^hsl\\("+[Fy,Py,Py]+"\\)$"),$y=new RegExp("^hsla\\("+[Fy,Py,Py,Fy]+"\\)$"),Wy={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function Vy(){return this.rgb().formatHex()}function Gy(){return this.rgb().formatRgb()}function Xy(t){var e,n;return t=(t+"").trim().toLowerCase(),(e=jy.exec(t))?(n=e[1].length,e=parseInt(e[1],16),6===n?Zy(e):3===n?new tg(e>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?Qy(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?Qy(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Yy.exec(t))?new tg(e[1],e[2],e[3],1):(e=zy.exec(t))?new tg(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Uy.exec(t))?Qy(e[1],e[2],e[3],e[4]):(e=qy.exec(t))?Qy(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=Hy.exec(t))?ig(e[1],e[2]/100,e[3]/100,1):(e=$y.exec(t))?ig(e[1],e[2]/100,e[3]/100,e[4]):Wy.hasOwnProperty(t)?Zy(Wy[t]):"transparent"===t?new tg(NaN,NaN,NaN,0):null}function Zy(t){return new tg(t>>16&255,t>>8&255,255&t,1)}function Qy(t,e,n,r){return r<=0&&(t=e=n=NaN),new tg(t,e,n,r)}function Ky(t){return t instanceof By||(t=Xy(t)),t?new tg((t=t.rgb()).r,t.g,t.b,t.opacity):new tg}function Jy(t,e,n,r){return 1===arguments.length?Ky(t):new tg(t,e,n,null==r?1:r)}function tg(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function eg(){return"#"+rg(this.r)+rg(this.g)+rg(this.b)}function ng(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function rg(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function ig(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new og(t,e,n,r)}function ag(t){if(t instanceof og)return new og(t.h,t.s,t.l,t.opacity);if(t instanceof By||(t=Xy(t)),!t)return new og;if(t instanceof og)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n<r):n===a?(r-e)/s+2:(e-n)/s+4,s/=c<.5?a+i:2-a-i,o*=60):s=c>0&&c<1?0:o,new og(o,s,c,t.opacity)}function og(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function sg(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function cg(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}Dy(By,Xy,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:Vy,formatHex:Vy,formatHsl:function(){return ag(this).formatHsl()},formatRgb:Gy,toString:Gy}),Dy(tg,Jy,Oy(By,{brighter:function(t){return t=null==t?Iy:Math.pow(Iy,t),new tg(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?Ly:Math.pow(Ly,t),new tg(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:eg,formatHex:eg,formatRgb:ng,toString:ng})),Dy(og,(function(t,e,n,r){return 1===arguments.length?ag(t):new og(t,e,n,null==r?1:r)}),Oy(By,{brighter:function(t){return t=null==t?Iy:Math.pow(Iy,t),new og(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Ly:Math.pow(Ly,t),new og(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new tg(sg(t>=240?t-240:t+120,i,r),sg(t,i,r),sg(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const ug=t=>()=>t;function lg(t,e){var n=e-t;return n?function(t,e){return function(n){return t+n*e}}(t,n):ug(isNaN(t)?e:t)}const hg=function t(e){var n=function(t){return 1==(t=+t)?lg:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):ug(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=Jy(t)).r,(e=Jy(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=lg(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function fg(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n<i;++n)r=Jy(e[n]),a[n]=r.r||0,o[n]=r.g||0,s[n]=r.b||0;return a=t(a),o=t(o),s=t(s),r.opacity=1,function(t){return r.r=a(t),r.g=o(t),r.b=s(t),r+""}}}fg((function(t){var e=t.length-1;return function(n){var r=n<=0?n=0:n>=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=r<e-1?t[r+2]:2*a-i;return cg((n-r/e)*e,o,i,a,s)}})),fg((function(t){var e=t.length;return function(n){var r=Math.floor(((n%=1)<0?++n:n)*e),i=t[(r+e-1)%e],a=t[r%e],o=t[(r+1)%e],s=t[(r+2)%e];return cg((n-r/e)*e,i,a,o,s)}}));var dg=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,pg=new RegExp(dg.source,"g");function yg(t,e){var n,r,i,a=dg.lastIndex=pg.lastIndex=0,o=-1,s=[],c=[];for(t+="",e+="";(n=dg.exec(t))&&(r=pg.exec(e));)(i=r.index)>a&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:_y(n,r)})),a=pg.lastIndex;return a<e.length&&(i=e.slice(a),s[o]?s[o]+=i:s[++o]=i),s.length<2?c[0]?function(t){return function(e){return t(e)+""}}(c[0].x):function(t){return function(){return t}}(e):(e=c.length,function(t){for(var n,r=0;r<e;++r)s[(n=c[r]).i]=n.x(t);return s.join("")})}function gg(t,e){var n;return("number"==typeof e?_y:e instanceof Xy?hg:(n=Xy(e))?(e=n,hg):yg)(t,e)}function mg(t){return function(){this.removeAttribute(t)}}function vg(t){return function(){this.removeAttributeNS(t.space,t.local)}}function bg(t,e,n){var r,i,a=n+"";return function(){var o=this.getAttribute(t);return o===a?null:o===r?i:i=e(r=o,n)}}function _g(t,e,n){var r,i,a=n+"";return function(){var o=this.getAttributeNS(t.space,t.local);return o===a?null:o===r?i:i=e(r=o,n)}}function xg(t,e,n){var r,i,a;return function(){var o,s,c=n(this);if(null!=c)return(o=this.getAttribute(t))===(s=c+"")?null:o===r&&s===i?a:(i=s,a=e(r=o,c));this.removeAttribute(t)}}function wg(t,e,n){var r,i,a;return function(){var o,s,c=n(this);if(null!=c)return(o=this.getAttributeNS(t.space,t.local))===(s=c+"")?null:o===r&&s===i?a:(i=s,a=e(r=o,c));this.removeAttributeNS(t.space,t.local)}}function kg(t,e){return function(n){this.setAttribute(t,e.call(this,n))}}function Tg(t,e){return function(n){this.setAttributeNS(t.space,t.local,e.call(this,n))}}function Eg(t,e){var n,r;function i(){var i=e.apply(this,arguments);return i!==r&&(n=(r=i)&&Tg(t,i)),n}return i._value=e,i}function Cg(t,e){var n,r;function i(){var i=e.apply(this,arguments);return i!==r&&(n=(r=i)&&kg(t,i)),n}return i._value=e,i}function Sg(t,e){return function(){my(this,t).delay=+e.apply(this,arguments)}}function Ag(t,e){return e=+e,function(){my(this,t).delay=e}}function Mg(t,e){return function(){vy(this,t).duration=+e.apply(this,arguments)}}function Ng(t,e){return e=+e,function(){vy(this,t).duration=e}}function Dg(t,e){if("function"!=typeof e)throw new Error;return function(){vy(this,t).ease=e}}function Og(t,e,n){var r,i,a=function(t){return(t+"").trim().split(/^|\s+/).every((function(t){var e=t.indexOf(".");return e>=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?my:vy;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var Bg=Up.prototype.constructor;function Lg(t){return function(){this.style.removeProperty(t)}}function Ig(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function Rg(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&Ig(t,a,n)),r}return a._value=e,a}function Fg(t){return function(e){this.textContent=t.call(this,e)}}function Pg(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&Fg(r)),e}return r._value=t,r}var jg=0;function Yg(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function zg(){return++jg}var Ug=Up.prototype;Yg.prototype=function(t){return Up().transition(t)}.prototype={constructor:Yg,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=Md(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o<i;++o)for(var s,c,u=r[o],l=u.length,h=a[o]=new Array(l),f=0;f<l;++f)(s=u[f])&&(c=t.call(s,s.__data__,f,u))&&("__data__"in s&&(c.__data__=s.__data__),h[f]=c,gy(h[f],e,n,f,h,by(s,n)));return new Yg(a,this._parents,e,n)},selectAll:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=Od(t));for(var r=this._groups,i=r.length,a=[],o=[],s=0;s<i;++s)for(var c,u=r[s],l=u.length,h=0;h<l;++h)if(c=u[h]){for(var f,d=t.call(c,c.__data__,h,u),p=by(c,n),y=0,g=d.length;y<g;++y)(f=d[y])&&gy(f,e,n,y,d,p);a.push(d),o.push(c)}return new Yg(a,o,e,n)},selectChild:Ug.selectChild,selectChildren:Ug.selectChildren,filter:function(t){"function"!=typeof t&&(t=Bd(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o=e[i],s=o.length,c=r[i]=[],u=0;u<s;++u)(a=o[u])&&t.call(a,a.__data__,u,o)&&c.push(a);return new Yg(r,this._parents,this._name,this._id)},merge:function(t){if(t._id!==this._id)throw new Error;for(var e=this._groups,n=t._groups,r=e.length,i=n.length,a=Math.min(r,i),o=new Array(r),s=0;s<a;++s)for(var c,u=e[s],l=n[s],h=u.length,f=o[s]=new Array(h),d=0;d<h;++d)(c=u[d]||l[d])&&(f[d]=c);for(;s<r;++s)o[s]=e[s];return new Yg(o,this._parents,this._name,this._id)},selection:function(){return new Bg(this._groups,this._parents)},transition:function(){for(var t=this._name,e=this._id,n=zg(),r=this._groups,i=r.length,a=0;a<i;++a)for(var o,s=r[a],c=s.length,u=0;u<c;++u)if(o=s[u]){var l=by(o,e);gy(o,t,n,u,s,{time:l.time+l.delay+l.duration,delay:0,duration:l.duration,ease:l.ease})}return new Yg(r,this._parents,t,n)},call:Ug.call,nodes:Ug.nodes,node:Ug.node,size:Ug.size,empty:Ug.empty,each:Ug.each,on:function(t,e){var n=this._id;return arguments.length<2?by(this.node(),n).on.on(t):this.each(Og(n,t,e))},attr:function(t,e){var n=Xd(t),r="transform"===n?Sy:gg;return this.attrTween(t,"function"==typeof e?(n.local?wg:xg)(n,r,Ny(this,"attr."+t,e)):null==e?(n.local?vg:mg)(n):(n.local?_g:bg)(n,r,e))},attrTween:function(t,e){var n="attr."+t;if(arguments.length<2)return(n=this.tween(n))&&n._value;if(null==e)return this.tween(n,null);if("function"!=typeof e)throw new Error;var r=Xd(t);return this.tween(n,(r.local?Eg:Cg)(r,e))},style:function(t,e,n){var r="transform"==(t+="")?Cy:gg;return null==e?this.styleTween(t,function(t,e){var n,r,i;return function(){var a=op(this,t),o=(this.style.removeProperty(t),op(this,t));return a===o?null:a===n&&o===r?i:i=e(n=a,r=o)}}(t,r)).on("end.style."+t,Lg(t)):"function"==typeof e?this.styleTween(t,function(t,e,n){var r,i,a;return function(){var o=op(this,t),s=n(this),c=s+"";return null==s&&(this.style.removeProperty(t),c=s=op(this,t)),o===c?null:o===r&&c===i?a:(i=c,a=e(r=o,s))}}(t,r,Ny(this,"style."+t,e))).each(function(t,e){var n,r,i,a,o="style."+e,s="end."+o;return function(){var c=vy(this,t),u=c.on,l=null==c.value[o]?a||(a=Lg(e)):void 0;u===n&&i===l||(r=(n=u).copy()).on(s,i=l),c.on=r}}(this._id,t)):this.styleTween(t,function(t,e,n){var r,i,a=n+"";return function(){var o=op(this,t);return o===a?null:o===r?i:i=e(r=o,n)}}(t,r,e),n).on("end.style."+t,null)},styleTween:function(t,e,n){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==e)return this.tween(r,null);if("function"!=typeof e)throw new Error;return this.tween(r,Rg(t,e,null==n?"":n))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var e=t(this);this.textContent=null==e?"":e}}(Ny(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},textTween:function(t){var e="text";if(arguments.length<1)return(e=this.tween(e))&&e._value;if(null==t)return this.tween(e,null);if("function"!=typeof t)throw new Error;return this.tween(e,Pg(t))},remove:function(){return this.on("end.remove",function(t){return function(){var e=this.parentNode;for(var n in this.__transition)if(+n!==t)return;e&&e.removeChild(this)}}(this._id))},tween:function(t,e){var n=this._id;if(t+="",arguments.length<2){for(var r,i=by(this.node(),n).tween,a=0,o=i.length;a<o;++a)if((r=i[a]).name===t)return r.value;return null}return this.each((null==e?Ay:My)(n,t,e))},delay:function(t){var e=this._id;return arguments.length?this.each(("function"==typeof t?Sg:Ag)(e,t)):by(this.node(),e).delay},duration:function(t){var e=this._id;return arguments.length?this.each(("function"==typeof t?Mg:Ng)(e,t)):by(this.node(),e).duration},ease:function(t){var e=this._id;return arguments.length?this.each(Dg(e,t)):by(this.node(),e).ease},easeVarying:function(t){if("function"!=typeof t)throw new Error;return this.each(function(t,e){return function(){var n=e.apply(this,arguments);if("function"!=typeof n)throw new Error;vy(this,t).ease=n}}(this._id,t))},end:function(){var t,e,n=this,r=n._id,i=n.size();return new Promise((function(a,o){var s={value:o},c={value:function(){0==--i&&a()}};n.each((function(){var n=vy(this,r),i=n.on;i!==t&&((e=(t=i).copy())._.cancel.push(s),e._.interrupt.push(s),e._.end.push(c)),n.on=e})),0===i&&a()}))},[Symbol.iterator]:Ug[Symbol.iterator]};var qg={time:null,delay:0,duration:250,ease:function(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}};function Hg(t,e){for(var n;!(n=t.__transition)||!(n=n[e]);)if(!(t=t.parentNode))throw new Error(`transition ${e} not found`);return n}function $g(t,e,n){this.k=t,this.x=e,this.y=n}Up.prototype.interrupt=function(t){return this.each((function(){!function(t,e){var n,r,i,a=t.__transition,o=!0;if(a){for(i in e=null==e?null:e+"",a)(n=a[i]).name===e?(r=n.state>2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}(this,t)}))},Up.prototype.transition=function(t){var e,n;t instanceof Yg?(e=t._id,t=t._name):(e=zg(),(n=qg).time=oy(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;a<i;++a)for(var o,s=r[a],c=s.length,u=0;u<c;++u)(o=s[u])&&gy(o,t,e,u,s,n||Hg(o,e));return new Yg(r,this._parents,t,e)},$g.prototype={constructor:$g,scale:function(t){return 1===t?this:new $g(this.k*t,this.x,this.y)},translate:function(t,e){return 0===t&0===e?this:new $g(this.k,this.x+this.k*t,this.y+this.k*e)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}},new $g(1,0,0),$g.prototype;var Wg="comm",Vg="rule",Gg="decl",Xg=Math.abs,Zg=String.fromCharCode;function Qg(t){return t.trim()}function Kg(t,e,n){return t.replace(e,n)}function Jg(t,e){return t.indexOf(e)}function tm(t,e){return 0|t.charCodeAt(e)}function em(t,e,n){return t.slice(e,n)}function nm(t){return t.length}function rm(t){return t.length}function im(t,e){return e.push(t),t}function am(t,e){for(var n="",r=rm(t),i=0;i<r;i++)n+=e(t[i],i,t,e)||"";return n}function om(t,e,n,r){switch(t.type){case"@import":case Gg:return t.return=t.return||t.value;case Wg:return"";case"@keyframes":return t.return=t.value+"{"+am(t.children,r)+"}";case Vg:t.value=t.props.join(",")}return nm(n=am(t.children,r))?t.return=t.value+"{"+n+"}":""}Object.assign;var sm=1,cm=1,um=0,lm=0,hm=0,fm="";function dm(t,e,n,r,i,a,o){return{value:t,root:e,parent:n,type:r,props:i,children:a,line:sm,column:cm,length:o,return:""}}function pm(){return hm=lm>0?tm(fm,--lm):0,cm--,10===hm&&(cm=1,sm--),hm}function ym(){return hm=lm<um?tm(fm,lm++):0,cm++,10===hm&&(cm=1,sm++),hm}function gm(){return tm(fm,lm)}function mm(){return lm}function vm(t,e){return em(fm,t,e)}function bm(t){switch(t){case 0:case 9:case 10:case 13:case 32:return 5;case 33:case 43:case 44:case 47:case 62:case 64:case 126:case 59:case 123:case 125:return 4;case 58:return 3;case 34:case 39:case 40:case 91:return 2;case 41:case 93:return 1}return 0}function _m(t){return Qg(vm(lm-1,km(91===t?t+2:40===t?t+1:t)))}function xm(t){for(;(hm=gm())&&hm<33;)ym();return bm(t)>2||bm(hm)>3?"":" "}function wm(t,e){for(;--e&&ym()&&!(hm<48||hm>102||hm>57&&hm<65||hm>70&&hm<97););return vm(t,mm()+(e<6&&32==gm()&&32==ym()))}function km(t){for(;ym();)switch(hm){case t:return lm;case 34:case 39:34!==t&&39!==t&&km(hm);break;case 40:41===t&&km(t);break;case 92:ym()}return lm}function Tm(t,e){for(;ym()&&t+hm!==57&&(t+hm!==84||47!==gm()););return"/*"+vm(e,lm-1)+"*"+Zg(47===t?t:ym())}function Em(t){for(;!bm(gm());)ym();return vm(t,lm)}function Cm(t){return function(t){return fm="",t}(Sm("",null,null,null,[""],t=function(t){return sm=cm=1,um=nm(fm=t),lm=0,[]}(t),0,[0],t))}function Sm(t,e,n,r,i,a,o,s,c){for(var u=0,l=0,h=o,f=0,d=0,p=0,y=1,g=1,m=1,v=0,b="",_=i,x=a,w=r,k=b;g;)switch(p=v,v=ym()){case 40:if(108!=p&&58==k.charCodeAt(h-1)){-1!=Jg(k+=Kg(_m(v),"&","&\f"),"&\f")&&(m=-1);break}case 34:case 39:case 91:k+=_m(v);break;case 9:case 10:case 13:case 32:k+=xm(p);break;case 92:k+=wm(mm()-1,7);continue;case 47:switch(gm()){case 42:case 47:im(Mm(Tm(ym(),mm()),e,n),c);break;default:k+="/"}break;case 123*y:s[u++]=nm(k)*m;case 125*y:case 59:case 0:switch(v){case 0:case 125:g=0;case 59+l:d>0&&nm(k)-h&&im(d>32?Nm(k+";",r,n,h-1):Nm(Kg(k," ","")+";",r,n,h-2),c);break;case 59:k+=";";default:if(im(w=Am(k,e,n,u,l,i,s,b,_=[],x=[],h),a),123===v)if(0===l)Sm(k,e,w,w,_,a,h,s,x);else switch(f){case 100:case 109:case 115:Sm(t,w,w,r&&im(Am(t,w,w,0,0,i,s,b,i,_=[],h),x),i,x,h,s,r?_:x);break;default:Sm(k,w,w,w,[""],x,0,s,x)}}u=l=d=0,y=m=1,b=k="",h=o;break;case 58:h=1+nm(k),d=p;default:if(y<1)if(123==v)--y;else if(125==v&&0==y++&&125==pm())continue;switch(k+=Zg(v),v*y){case 38:m=l>0?1:(k+="\f",-1);break;case 44:s[u++]=(nm(k)-1)*m,m=1;break;case 64:45===gm()&&(k+=_m(ym())),f=gm(),l=h=nm(b=k+=Em(mm())),v++;break;case 45:45===p&&2==nm(k)&&(y=0)}}return a}function Am(t,e,n,r,i,a,o,s,c,u,l){for(var h=i-1,f=0===i?a:[""],d=rm(f),p=0,y=0,g=0;p<r;++p)for(var m=0,v=em(t,h+1,h=Xg(y=o[p])),b=t;m<d;++m)(b=Qg(y>0?f[m]+" "+v:Kg(v,/&\f/g,f[m])))&&(c[g++]=b);return dm(t,e,n,0===i?Vg:s,c,u,l)}function Mm(t,e,n){return dm(t,e,n,Wg,Zg(hm),em(t,2,-2),0)}function Nm(t,e,n,r){return dm(t,e,n,Gg,em(t,0,r),em(t,r+1,-1),r)}const Dm="8.13.10";var Om=n(9609),Bm=n(7856),Lm=n.n(Bm),Im=function(t){var e=t.replace(/\\u[\dA-F]{4}/gi,(function(t){return String.fromCharCode(parseInt(t.replace(/\\u/g,""),16))}));return e=(e=(e=e.replace(/\\x([0-9a-f]{2})/gi,(function(t,e){return String.fromCharCode(parseInt(e,16))}))).replace(/\\[\d\d\d]{3}/gi,(function(t){return String.fromCharCode(parseInt(t.replace(/\\/g,""),8))}))).replace(/\\[\d\d\d]{2}/gi,(function(t){return String.fromCharCode(parseInt(t.replace(/\\/g,""),8))}))},Rm=function(t){for(var e="",n=0;n>=0;){if(!((n=t.indexOf("<script"))>=0)){e+=t,n=-1;break}e+=t.substr(0,n),(n=(t=t.substr(n+1)).indexOf("<\/script>"))>=0&&(n+=9,t=t.substr(n))}var r=Im(e);return(r=(r=(r=r.replace(/script>/gi,"#")).replace(/javascript:/gi,"#")).replace(/onerror=/gi,"onerror:")).replace(/<iframe/gi,"")},Fm=function(t,e){if(!t)return t;var n=Lm().sanitize(function(t,e){var n=t,r=!0;if(!e.flowchart||!1!==e.flowchart.htmlLabels&&"false"!==e.flowchart.htmlLabels||(r=!1),r){var i=e.securityLevel;"antiscript"===i||"strict"===i?n=Rm(n):"loose"!==i&&(n=(n=(n=Ym(n)).replace(/</g,"&lt;").replace(/>/g,"&gt;")).replace(/=/g,"&equals;"),n=jm(n))}return n}(t,e));return n},Pm=/<br\s*\/?>/gi,jm=function(t){return t.replace(/#br#/g,"<br/>")},Ym=function(t){return t.replace(Pm,"#br#")},zm=function(t){return"false"!==t&&!1!==t};const Um={getRows:function(t){if(!t)return 1;var e=Ym(t);return(e=e.replace(/\\n/g,"#br#")).split("#br#")},sanitizeText:Fm,sanitizeTextOrArray:function(t,e){return"string"==typeof t?Fm(t,e):t.flat().map((function(t){return Fm(t,e)}))},hasBreaks:function(t){return Pm.test(t)},splitBreaks:function(t){return t.split(Pm)},lineBreakRegex:Pm,removeScript:Rm,getUrl:function(t){var e="";return t&&(e=(e=(e=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search).replace(/\(/g,"\\(")).replace(/\)/g,"\\)")),e},evaluate:zm,removeEscapes:Im};var qm=n(8613),Hm=function(t,e){return e?(0,qm.adjust)(t,{s:-40,l:10}):(0,qm.adjust)(t,{s:-40,l:-10})};function $m(t){return $m="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},$m(t)}function Wm(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}var Vm=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.background="#f4f4f4",this.darkMode=!1,this.primaryColor="#fff4dd",this.noteBkgColor="#fff5ad",this.noteTextColor="#333",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px"}var e,n;return e=t,n=[{key:"updateColors",value:function(){this.primaryTextColor=this.primaryTextColor||(this.darkMode?"#ddd":"#333"),this.secondaryColor=this.secondaryColor||(0,qm.adjust)(this.primaryColor,{h:-120}),this.tertiaryColor=this.tertiaryColor||(0,qm.adjust)(this.primaryColor,{h:180,l:5}),this.primaryBorderColor=this.primaryBorderColor||Hm(this.primaryColor,this.darkMode),this.secondaryBorderColor=this.secondaryBorderColor||Hm(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=this.tertiaryBorderColor||Hm(this.tertiaryColor,this.darkMode),this.noteBorderColor=this.noteBorderColor||Hm(this.noteBkgColor,this.darkMode),this.noteBkgColor=this.noteBkgColor||"#fff5ad",this.noteTextColor=this.noteTextColor||"#333",this.secondaryTextColor=this.secondaryTextColor||(0,qm.invert)(this.secondaryColor),this.tertiaryTextColor=this.tertiaryTextColor||(0,qm.invert)(this.tertiaryColor),this.lineColor=this.lineColor||(0,qm.invert)(this.background),this.textColor=this.textColor||this.primaryTextColor,this.nodeBkg=this.nodeBkg||this.primaryColor,this.mainBkg=this.mainBkg||this.primaryColor,this.nodeBorder=this.nodeBorder||this.primaryBorderColor,this.clusterBkg=this.clusterBkg||this.tertiaryColor,this.clusterBorder=this.clusterBorder||this.tertiaryBorderColor,this.defaultLinkColor=this.defaultLinkColor||this.lineColor,this.titleColor=this.titleColor||this.tertiaryTextColor,this.edgeLabelBackground=this.edgeLabelBackground||(this.darkMode?(0,qm.darken)(this.secondaryColor,30):this.secondaryColor),this.nodeTextColor=this.nodeTextColor||this.primaryTextColor,this.actorBorder=this.actorBorder||this.primaryBorderColor,this.actorBkg=this.actorBkg||this.mainBkg,this.actorTextColor=this.actorTextColor||this.primaryTextColor,this.actorLineColor=this.actorLineColor||"grey",this.labelBoxBkgColor=this.labelBoxBkgColor||this.actorBkg,this.signalColor=this.signalColor||this.textColor,this.signalTextColor=this.signalTextColor||this.textColor,this.labelBoxBorderColor=this.labelBoxBorderColor||this.actorBorder,this.labelTextColor=this.labelTextColor||this.actorTextColor,this.loopTextColor=this.loopTextColor||this.actorTextColor,this.activationBorderColor=this.activationBorderColor||(0,qm.darken)(this.secondaryColor,10),this.activationBkgColor=this.activationBkgColor||this.secondaryColor,this.sequenceNumberColor=this.sequenceNumberColor||(0,qm.invert)(this.lineColor),this.sectionBkgColor=this.sectionBkgColor||this.tertiaryColor,this.altSectionBkgColor=this.altSectionBkgColor||"white",this.sectionBkgColor=this.sectionBkgColor||this.secondaryColor,this.sectionBkgColor2=this.sectionBkgColor2||this.primaryColor,this.excludeBkgColor=this.excludeBkgColor||"#eeeeee",this.taskBorderColor=this.taskBorderColor||this.primaryBorderColor,this.taskBkgColor=this.taskBkgColor||this.primaryColor,this.activeTaskBorderColor=this.activeTaskBorderColor||this.primaryColor,this.activeTaskBkgColor=this.activeTaskBkgColor||(0,qm.lighten)(this.primaryColor,23),this.gridColor=this.gridColor||"lightgrey",this.doneTaskBkgColor=this.doneTaskBkgColor||"lightgrey",this.doneTaskBorderColor=this.doneTaskBorderColor||"grey",this.critBorderColor=this.critBorderColor||"#ff8888",this.critBkgColor=this.critBkgColor||"red",this.todayLineColor=this.todayLineColor||"red",this.taskTextColor=this.taskTextColor||this.textColor,this.taskTextOutsideColor=this.taskTextOutsideColor||this.textColor,this.taskTextLightColor=this.taskTextLightColor||this.textColor,this.taskTextColor=this.taskTextColor||this.primaryTextColor,this.taskTextDarkColor=this.taskTextDarkColor||this.textColor,this.taskTextClickableColor=this.taskTextClickableColor||"#003163",this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||this.tertiaryColor,this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.nodeBorder,this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.specialStateColor=this.lineColor,this.classText=this.classText||this.textColor,this.fillType0=this.fillType0||this.primaryColor,this.fillType1=this.fillType1||this.secondaryColor,this.fillType2=this.fillType2||(0,qm.adjust)(this.primaryColor,{h:64}),this.fillType3=this.fillType3||(0,qm.adjust)(this.secondaryColor,{h:64}),this.fillType4=this.fillType4||(0,qm.adjust)(this.primaryColor,{h:-64}),this.fillType5=this.fillType5||(0,qm.adjust)(this.secondaryColor,{h:-64}),this.fillType6=this.fillType6||(0,qm.adjust)(this.primaryColor,{h:128}),this.fillType7=this.fillType7||(0,qm.adjust)(this.secondaryColor,{h:128}),this.pie1=this.pie1||this.primaryColor,this.pie2=this.pie2||this.secondaryColor,this.pie3=this.pie3||this.tertiaryColor,this.pie4=this.pie4||(0,qm.adjust)(this.primaryColor,{l:-10}),this.pie5=this.pie5||(0,qm.adjust)(this.secondaryColor,{l:-10}),this.pie6=this.pie6||(0,qm.adjust)(this.tertiaryColor,{l:-10}),this.pie7=this.pie7||(0,qm.adjust)(this.primaryColor,{h:60,l:-10}),this.pie8=this.pie8||(0,qm.adjust)(this.primaryColor,{h:-60,l:-10}),this.pie9=this.pie9||(0,qm.adjust)(this.primaryColor,{h:120,l:0}),this.pie10=this.pie10||(0,qm.adjust)(this.primaryColor,{h:60,l:-20}),this.pie11=this.pie11||(0,qm.adjust)(this.primaryColor,{h:-60,l:-20}),this.pie12=this.pie12||(0,qm.adjust)(this.primaryColor,{h:120,l:-10}),this.pieTitleTextSize=this.pieTitleTextSize||"25px",this.pieTitleTextColor=this.pieTitleTextColor||this.taskTextDarkColor,this.pieSectionTextSize=this.pieSectionTextSize||"17px",this.pieSectionTextColor=this.pieSectionTextColor||this.textColor,this.pieLegendTextSize=this.pieLegendTextSize||"17px",this.pieLegendTextColor=this.pieLegendTextColor||this.taskTextDarkColor,this.pieStrokeColor=this.pieStrokeColor||"black",this.pieStrokeWidth=this.pieStrokeWidth||"2px",this.pieOpacity=this.pieOpacity||"0.7",this.requirementBackground=this.requirementBackground||this.primaryColor,this.requirementBorderColor=this.requirementBorderColor||this.primaryBorderColor,this.requirementBorderSize=this.requirementBorderSize||this.primaryBorderColor,this.requirementTextColor=this.requirementTextColor||this.primaryTextColor,this.relationColor=this.relationColor||this.lineColor,this.relationLabelBackground=this.relationLabelBackground||(this.darkMode?(0,qm.darken)(this.secondaryColor,30):this.secondaryColor),this.relationLabelColor=this.relationLabelColor||this.actorTextColor}},{key:"calculate",value:function(t){var e=this;if("object"===$m(t)){var n=Object.keys(t);n.forEach((function(n){e[n]=t[n]})),this.updateColors(),n.forEach((function(n){e[n]=t[n]}))}else this.updateColors()}}],n&&Wm(e.prototype,n),Object.defineProperty(e,"prototype",{writable:!1}),t}();function Gm(t){return Gm="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},Gm(t)}function Xm(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}var Zm=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.background="#333",this.primaryColor="#1f2020",this.secondaryColor=(0,qm.lighten)(this.primaryColor,16),this.tertiaryColor=(0,qm.adjust)(this.primaryColor,{h:-160}),this.primaryBorderColor=Hm(this.primaryColor,this.darkMode),this.secondaryBorderColor=Hm(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=Hm(this.tertiaryColor,this.darkMode),this.primaryTextColor=(0,qm.invert)(this.primaryColor),this.secondaryTextColor=(0,qm.invert)(this.secondaryColor),this.tertiaryTextColor=(0,qm.invert)(this.tertiaryColor),this.lineColor=(0,qm.invert)(this.background),this.textColor=(0,qm.invert)(this.background),this.mainBkg="#1f2020",this.secondBkg="calculated",this.mainContrastColor="lightgrey",this.darkTextColor=(0,qm.lighten)((0,qm.invert)("#323D47"),10),this.lineColor="calculated",this.border1="#81B1DB",this.border2=(0,qm.rgba)(255,255,255,.25),this.arrowheadColor="calculated",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.labelBackground="#181818",this.textColor="#ccc",this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="#F9FFFE",this.edgeLabelBackground="calculated",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="calculated",this.actorLineColor="calculated",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="calculated",this.activationBkgColor="calculated",this.sequenceNumberColor="black",this.sectionBkgColor=(0,qm.darken)("#EAE8D9",30),this.altSectionBkgColor="calculated",this.sectionBkgColor2="#EAE8D9",this.taskBorderColor=(0,qm.rgba)(255,255,255,70),this.taskBkgColor="calculated",this.taskTextColor="calculated",this.taskTextLightColor="calculated",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor=(0,qm.rgba)(255,255,255,50),this.activeTaskBkgColor="#81B1DB",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="grey",this.critBorderColor="#E83737",this.critBkgColor="#E83737",this.taskTextDarkColor="calculated",this.todayLineColor="#DB5757",this.labelColor="calculated",this.errorBkgColor="#a44141",this.errorTextColor="#ddd"}var e,n;return e=t,n=[{key:"updateColors",value:function(){this.secondBkg=(0,qm.lighten)(this.mainBkg,16),this.lineColor=this.mainContrastColor,this.arrowheadColor=this.mainContrastColor,this.nodeBkg=this.mainBkg,this.nodeBorder=this.border1,this.clusterBkg=this.secondBkg,this.clusterBorder=this.border2,this.defaultLinkColor=this.lineColor,this.edgeLabelBackground=(0,qm.lighten)(this.labelBackground,25),this.actorBorder=this.border1,this.actorBkg=this.mainBkg,this.actorTextColor=this.mainContrastColor,this.actorLineColor=this.mainContrastColor,this.signalColor=this.mainContrastColor,this.signalTextColor=this.mainContrastColor,this.labelBoxBkgColor=this.actorBkg,this.labelBoxBorderColor=this.actorBorder,this.labelTextColor=this.mainContrastColor,this.loopTextColor=this.mainContrastColor,this.noteBorderColor=this.secondaryBorderColor,this.noteBkgColor=this.secondBkg,this.noteTextColor=this.secondaryTextColor,this.activationBorderColor=this.border1,this.activationBkgColor=this.secondBkg,this.altSectionBkgColor=this.background,this.taskBkgColor=(0,qm.lighten)(this.mainBkg,23),this.taskTextColor=this.darkTextColor,this.taskTextLightColor=this.mainContrastColor,this.taskTextOutsideColor=this.taskTextLightColor,this.gridColor=this.mainContrastColor,this.doneTaskBkgColor=this.mainContrastColor,this.taskTextDarkColor=this.darkTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||"#555",this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.primaryBorderColor,this.specialStateColor="#f4f4f4",this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.fillType0=this.primaryColor,this.fillType1=this.secondaryColor,this.fillType2=(0,qm.adjust)(this.primaryColor,{h:64}),this.fillType3=(0,qm.adjust)(this.secondaryColor,{h:64}),this.fillType4=(0,qm.adjust)(this.primaryColor,{h:-64}),this.fillType5=(0,qm.adjust)(this.secondaryColor,{h:-64}),this.fillType6=(0,qm.adjust)(this.primaryColor,{h:128}),this.fillType7=(0,qm.adjust)(this.secondaryColor,{h:128}),this.pie1=this.pie1||"#0b0000",this.pie2=this.pie2||"#4d1037",this.pie3=this.pie3||"#3f5258",this.pie4=this.pie4||"#4f2f1b",this.pie5=this.pie5||"#6e0a0a",this.pie6=this.pie6||"#3b0048",this.pie7=this.pie7||"#995a01",this.pie8=this.pie8||"#154706",this.pie9=this.pie9||"#161722",this.pie10=this.pie10||"#00296f",this.pie11=this.pie11||"#01629c",this.pie12=this.pie12||"#010029",this.pieTitleTextSize=this.pieTitleTextSize||"25px",this.pieTitleTextColor=this.pieTitleTextColor||this.taskTextDarkColor,this.pieSectionTextSize=this.pieSectionTextSize||"17px",this.pieSectionTextColor=this.pieSectionTextColor||this.textColor,this.pieLegendTextSize=this.pieLegendTextSize||"17px",this.pieLegendTextColor=this.pieLegendTextColor||this.taskTextDarkColor,this.pieStrokeColor=this.pieStrokeColor||"black",this.pieStrokeWidth=this.pieStrokeWidth||"2px",this.pieOpacity=this.pieOpacity||"0.7",this.classText=this.primaryTextColor,this.requirementBackground=this.requirementBackground||this.primaryColor,this.requirementBorderColor=this.requirementBorderColor||this.primaryBorderColor,this.requirementBorderSize=this.requirementBorderSize||this.primaryBorderColor,this.requirementTextColor=this.requirementTextColor||this.primaryTextColor,this.relationColor=this.relationColor||this.lineColor,this.relationLabelBackground=this.relationLabelBackground||(this.darkMode?(0,qm.darken)(this.secondaryColor,30):this.secondaryColor),this.relationLabelColor=this.relationLabelColor||this.actorTextColor}},{key:"calculate",value:function(t){var e=this;if("object"===Gm(t)){var n=Object.keys(t);n.forEach((function(n){e[n]=t[n]})),this.updateColors(),n.forEach((function(n){e[n]=t[n]}))}else this.updateColors()}}],n&&Xm(e.prototype,n),Object.defineProperty(e,"prototype",{writable:!1}),t}();function Qm(t){return Qm="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},Qm(t)}function Km(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}var Jm=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.background="#f4f4f4",this.primaryColor="#ECECFF",this.secondaryColor=(0,qm.adjust)(this.primaryColor,{h:120}),this.secondaryColor="#ffffde",this.tertiaryColor=(0,qm.adjust)(this.primaryColor,{h:-160}),this.primaryBorderColor=Hm(this.primaryColor,this.darkMode),this.secondaryBorderColor=Hm(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=Hm(this.tertiaryColor,this.darkMode),this.primaryTextColor=(0,qm.invert)(this.primaryColor),this.secondaryTextColor=(0,qm.invert)(this.secondaryColor),this.tertiaryTextColor=(0,qm.invert)(this.tertiaryColor),this.lineColor=(0,qm.invert)(this.background),this.textColor=(0,qm.invert)(this.background),this.background="white",this.mainBkg="#ECECFF",this.secondBkg="#ffffde",this.lineColor="#333333",this.border1="#9370DB",this.border2="#aaaa33",this.arrowheadColor="#333333",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.labelBackground="#e8e8e8",this.textColor="#333",this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="calculated",this.edgeLabelBackground="calculated",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="black",this.actorLineColor="grey",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="calculated",this.altSectionBkgColor="calculated",this.sectionBkgColor2="calculated",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="calculated",this.taskTextLightColor="calculated",this.taskTextColor=this.taskTextLightColor,this.taskTextDarkColor="calculated",this.taskTextOutsideColor=this.taskTextDarkColor,this.taskTextClickableColor="calculated",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="calculated",this.critBorderColor="calculated",this.critBkgColor="calculated",this.todayLineColor="calculated",this.sectionBkgColor=(0,qm.rgba)(102,102,255,.49),this.altSectionBkgColor="white",this.sectionBkgColor2="#fff400",this.taskBorderColor="#534fbc",this.taskBkgColor="#8a90dd",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="black",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="#534fbc",this.activeTaskBkgColor="#bfc7ff",this.gridColor="lightgrey",this.doneTaskBkgColor="lightgrey",this.doneTaskBorderColor="grey",this.critBorderColor="#ff8888",this.critBkgColor="red",this.todayLineColor="red",this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222",this.updateColors()}var e,n;return e=t,n=[{key:"updateColors",value:function(){this.nodeBkg=this.mainBkg,this.nodeBorder=this.border1,this.clusterBkg=this.secondBkg,this.clusterBorder=this.border2,this.defaultLinkColor=this.lineColor,this.titleColor=this.textColor,this.edgeLabelBackground=this.labelBackground,this.actorBorder=(0,qm.lighten)(this.border1,23),this.actorBkg=this.mainBkg,this.labelBoxBkgColor=this.actorBkg,this.signalColor=this.textColor,this.signalTextColor=this.textColor,this.labelBoxBorderColor=this.actorBorder,this.labelTextColor=this.actorTextColor,this.loopTextColor=this.actorTextColor,this.noteBorderColor=this.border2,this.noteTextColor=this.actorTextColor,this.taskTextColor=this.taskTextLightColor,this.taskTextOutsideColor=this.taskTextDarkColor,this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||"#f0f0f0",this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.nodeBorder,this.specialStateColor=this.lineColor,this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.classText=this.primaryTextColor,this.fillType0=this.primaryColor,this.fillType1=this.secondaryColor,this.fillType2=(0,qm.adjust)(this.primaryColor,{h:64}),this.fillType3=(0,qm.adjust)(this.secondaryColor,{h:64}),this.fillType4=(0,qm.adjust)(this.primaryColor,{h:-64}),this.fillType5=(0,qm.adjust)(this.secondaryColor,{h:-64}),this.fillType6=(0,qm.adjust)(this.primaryColor,{h:128}),this.fillType7=(0,qm.adjust)(this.secondaryColor,{h:128}),this.pie1=this.pie1||this.primaryColor,this.pie2=this.pie2||this.secondaryColor,this.pie3=this.pie3||(0,qm.adjust)(this.tertiaryColor,{l:-40}),this.pie4=this.pie4||(0,qm.adjust)(this.primaryColor,{l:-10}),this.pie5=this.pie5||(0,qm.adjust)(this.secondaryColor,{l:-30}),this.pie6=this.pie6||(0,qm.adjust)(this.tertiaryColor,{l:-20}),this.pie7=this.pie7||(0,qm.adjust)(this.primaryColor,{h:60,l:-20}),this.pie8=this.pie8||(0,qm.adjust)(this.primaryColor,{h:-60,l:-40}),this.pie9=this.pie9||(0,qm.adjust)(this.primaryColor,{h:120,l:-40}),this.pie10=this.pie10||(0,qm.adjust)(this.primaryColor,{h:60,l:-40}),this.pie11=this.pie11||(0,qm.adjust)(this.primaryColor,{h:-90,l:-40}),this.pie12=this.pie12||(0,qm.adjust)(this.primaryColor,{h:120,l:-30}),this.pieTitleTextSize=this.pieTitleTextSize||"25px",this.pieTitleTextColor=this.pieTitleTextColor||this.taskTextDarkColor,this.pieSectionTextSize=this.pieSectionTextSize||"17px",this.pieSectionTextColor=this.pieSectionTextColor||this.textColor,this.pieLegendTextSize=this.pieLegendTextSize||"17px",this.pieLegendTextColor=this.pieLegendTextColor||this.taskTextDarkColor,this.pieStrokeColor=this.pieStrokeColor||"black",this.pieStrokeWidth=this.pieStrokeWidth||"2px",this.pieOpacity=this.pieOpacity||"0.7",this.requirementBackground=this.requirementBackground||this.primaryColor,this.requirementBorderColor=this.requirementBorderColor||this.primaryBorderColor,this.requirementBorderSize=this.requirementBorderSize||this.primaryBorderColor,this.requirementTextColor=this.requirementTextColor||this.primaryTextColor,this.relationColor=this.relationColor||this.lineColor,this.relationLabelBackground=this.relationLabelBackground||this.labelBackground,this.relationLabelColor=this.relationLabelColor||this.actorTextColor}},{key:"calculate",value:function(t){var e=this;if("object"===Qm(t)){var n=Object.keys(t);n.forEach((function(n){e[n]=t[n]})),this.updateColors(),n.forEach((function(n){e[n]=t[n]}))}else this.updateColors()}}],n&&Km(e.prototype,n),Object.defineProperty(e,"prototype",{writable:!1}),t}();function tv(t){return tv="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},tv(t)}function ev(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}var nv=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.background="#f4f4f4",this.primaryColor="#cde498",this.secondaryColor="#cdffb2",this.background="white",this.mainBkg="#cde498",this.secondBkg="#cdffb2",this.lineColor="green",this.border1="#13540c",this.border2="#6eaa49",this.arrowheadColor="green",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.tertiaryColor=(0,qm.lighten)("#cde498",10),this.primaryBorderColor=Hm(this.primaryColor,this.darkMode),this.secondaryBorderColor=Hm(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=Hm(this.tertiaryColor,this.darkMode),this.primaryTextColor=(0,qm.invert)(this.primaryColor),this.secondaryTextColor=(0,qm.invert)(this.secondaryColor),this.tertiaryTextColor=(0,qm.invert)(this.primaryColor),this.lineColor=(0,qm.invert)(this.background),this.textColor=(0,qm.invert)(this.background),this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="#333",this.edgeLabelBackground="#e8e8e8",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="black",this.actorLineColor="grey",this.signalColor="#333",this.signalTextColor="#333",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="#326932",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="#6eaa49",this.altSectionBkgColor="white",this.sectionBkgColor2="#6eaa49",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="#487e3a",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="black",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="lightgrey",this.doneTaskBkgColor="lightgrey",this.doneTaskBorderColor="grey",this.critBorderColor="#ff8888",this.critBkgColor="red",this.todayLineColor="red",this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222"}var e,n;return e=t,n=[{key:"updateColors",value:function(){this.nodeBkg=this.mainBkg,this.nodeBorder=this.border1,this.clusterBkg=this.secondBkg,this.clusterBorder=this.border2,this.defaultLinkColor=this.lineColor,this.actorBorder=(0,qm.darken)(this.mainBkg,20),this.actorBkg=this.mainBkg,this.labelBoxBkgColor=this.actorBkg,this.labelTextColor=this.actorTextColor,this.loopTextColor=this.actorTextColor,this.noteBorderColor=this.border2,this.noteTextColor=this.actorTextColor,this.taskBorderColor=this.border1,this.taskTextColor=this.taskTextLightColor,this.taskTextOutsideColor=this.taskTextDarkColor,this.activeTaskBorderColor=this.taskBorderColor,this.activeTaskBkgColor=this.mainBkg,this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||"#f0f0f0",this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.primaryBorderColor,this.specialStateColor=this.lineColor,this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.classText=this.primaryTextColor,this.fillType0=this.primaryColor,this.fillType1=this.secondaryColor,this.fillType2=(0,qm.adjust)(this.primaryColor,{h:64}),this.fillType3=(0,qm.adjust)(this.secondaryColor,{h:64}),this.fillType4=(0,qm.adjust)(this.primaryColor,{h:-64}),this.fillType5=(0,qm.adjust)(this.secondaryColor,{h:-64}),this.fillType6=(0,qm.adjust)(this.primaryColor,{h:128}),this.fillType7=(0,qm.adjust)(this.secondaryColor,{h:128}),this.pie1=this.pie1||this.primaryColor,this.pie2=this.pie2||this.secondaryColor,this.pie3=this.pie3||this.tertiaryColor,this.pie4=this.pie4||(0,qm.adjust)(this.primaryColor,{l:-30}),this.pie5=this.pie5||(0,qm.adjust)(this.secondaryColor,{l:-30}),this.pie6=this.pie6||(0,qm.adjust)(this.tertiaryColor,{h:40,l:-40}),this.pie7=this.pie7||(0,qm.adjust)(this.primaryColor,{h:60,l:-10}),this.pie8=this.pie8||(0,qm.adjust)(this.primaryColor,{h:-60,l:-10}),this.pie9=this.pie9||(0,qm.adjust)(this.primaryColor,{h:120,l:0}),this.pie10=this.pie10||(0,qm.adjust)(this.primaryColor,{h:60,l:-50}),this.pie11=this.pie11||(0,qm.adjust)(this.primaryColor,{h:-60,l:-50}),this.pie12=this.pie12||(0,qm.adjust)(this.primaryColor,{h:120,l:-50}),this.pieTitleTextSize=this.pieTitleTextSize||"25px",this.pieTitleTextColor=this.pieTitleTextColor||this.taskTextDarkColor,this.pieSectionTextSize=this.pieSectionTextSize||"17px",this.pieSectionTextColor=this.pieSectionTextColor||this.textColor,this.pieLegendTextSize=this.pieLegendTextSize||"17px",this.pieLegendTextColor=this.pieLegendTextColor||this.taskTextDarkColor,this.pieStrokeColor=this.pieStrokeColor||"black",this.pieStrokeWidth=this.pieStrokeWidth||"2px",this.pieOpacity=this.pieOpacity||"0.7",this.requirementBackground=this.requirementBackground||this.primaryColor,this.requirementBorderColor=this.requirementBorderColor||this.primaryBorderColor,this.requirementBorderSize=this.requirementBorderSize||this.primaryBorderColor,this.requirementTextColor=this.requirementTextColor||this.primaryTextColor,this.relationColor=this.relationColor||this.lineColor,this.relationLabelBackground=this.relationLabelBackground||this.edgeLabelBackground,this.relationLabelColor=this.relationLabelColor||this.actorTextColor}},{key:"calculate",value:function(t){var e=this;if("object"===tv(t)){var n=Object.keys(t);n.forEach((function(n){e[n]=t[n]})),this.updateColors(),n.forEach((function(n){e[n]=t[n]}))}else this.updateColors()}}],n&&ev(e.prototype,n),Object.defineProperty(e,"prototype",{writable:!1}),t}();function rv(t){return rv="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},rv(t)}function iv(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}var av=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.primaryColor="#eee",this.contrast="#707070",this.secondaryColor=(0,qm.lighten)(this.contrast,55),this.background="#ffffff",this.tertiaryColor=(0,qm.adjust)(this.primaryColor,{h:-160}),this.primaryBorderColor=Hm(this.primaryColor,this.darkMode),this.secondaryBorderColor=Hm(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=Hm(this.tertiaryColor,this.darkMode),this.primaryTextColor=(0,qm.invert)(this.primaryColor),this.secondaryTextColor=(0,qm.invert)(this.secondaryColor),this.tertiaryTextColor=(0,qm.invert)(this.tertiaryColor),this.lineColor=(0,qm.invert)(this.background),this.textColor=(0,qm.invert)(this.background),this.mainBkg="#eee",this.secondBkg="calculated",this.lineColor="#666",this.border1="#999",this.border2="calculated",this.note="#ffa",this.text="#333",this.critical="#d42",this.done="#bbb",this.arrowheadColor="#333333",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="calculated",this.edgeLabelBackground="white",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="calculated",this.actorLineColor="calculated",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="calculated",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="calculated",this.altSectionBkgColor="white",this.sectionBkgColor2="calculated",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="calculated",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="calculated",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="calculated",this.critBkgColor="calculated",this.critBorderColor="calculated",this.todayLineColor="calculated",this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222"}var e,n;return e=t,n=[{key:"updateColors",value:function(){this.secondBkg=(0,qm.lighten)(this.contrast,55),this.border2=this.contrast,this.nodeBkg=this.mainBkg,this.nodeBorder=this.border1,this.clusterBkg=this.secondBkg,this.clusterBorder=this.border2,this.defaultLinkColor=this.lineColor,this.titleColor=this.text,this.actorBorder=(0,qm.lighten)(this.border1,23),this.actorBkg=this.mainBkg,this.actorTextColor=this.text,this.actorLineColor=this.lineColor,this.signalColor=this.text,this.signalTextColor=this.text,this.labelBoxBkgColor=this.actorBkg,this.labelBoxBorderColor=this.actorBorder,this.labelTextColor=this.text,this.loopTextColor=this.text,this.noteBorderColor="#999",this.noteBkgColor="#666",this.noteTextColor="#fff",this.sectionBkgColor=(0,qm.lighten)(this.contrast,30),this.sectionBkgColor2=(0,qm.lighten)(this.contrast,30),this.taskBorderColor=(0,qm.darken)(this.contrast,10),this.taskBkgColor=this.contrast,this.taskTextColor=this.taskTextLightColor,this.taskTextDarkColor=this.text,this.taskTextOutsideColor=this.taskTextDarkColor,this.activeTaskBorderColor=this.taskBorderColor,this.activeTaskBkgColor=this.mainBkg,this.gridColor=(0,qm.lighten)(this.border1,30),this.doneTaskBkgColor=this.done,this.doneTaskBorderColor=this.lineColor,this.critBkgColor=this.critical,this.critBorderColor=(0,qm.darken)(this.critBkgColor,10),this.todayLineColor=this.critBkgColor,this.transitionColor=this.transitionColor||"#000",this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||"#f4f4f4",this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.stateBorder=this.stateBorder||"#000",this.innerEndBackground=this.primaryBorderColor,this.specialStateColor="#222",this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.classText=this.primaryTextColor,this.fillType0=this.primaryColor,this.fillType1=this.secondaryColor,this.fillType2=(0,qm.adjust)(this.primaryColor,{h:64}),this.fillType3=(0,qm.adjust)(this.secondaryColor,{h:64}),this.fillType4=(0,qm.adjust)(this.primaryColor,{h:-64}),this.fillType5=(0,qm.adjust)(this.secondaryColor,{h:-64}),this.fillType6=(0,qm.adjust)(this.primaryColor,{h:128}),this.fillType7=(0,qm.adjust)(this.secondaryColor,{h:128}),this.pie1=this.pie1||"#F4F4F4",this.pie2=this.pie2||"#555",this.pie3=this.pie3||"#BBB",this.pie4=this.pie4||"#777",this.pie5=this.pie5||"#999",this.pie6=this.pie6||"#DDD",this.pie7=this.pie7||"#FFF",this.pie8=this.pie8||"#DDD",this.pie9=this.pie9||"#BBB",this.pie10=this.pie10||"#999",this.pie11=this.pie11||"#777",this.pie12=this.pie12||"#555",this.pieTitleTextSize=this.pieTitleTextSize||"25px",this.pieTitleTextColor=this.pieTitleTextColor||this.taskTextDarkColor,this.pieSectionTextSize=this.pieSectionTextSize||"17px",this.pieSectionTextColor=this.pieSectionTextColor||this.textColor,this.pieLegendTextSize=this.pieLegendTextSize||"17px",this.pieLegendTextColor=this.pieLegendTextColor||this.taskTextDarkColor,this.pieStrokeColor=this.pieStrokeColor||"black",this.pieStrokeWidth=this.pieStrokeWidth||"2px",this.pieOpacity=this.pieOpacity||"0.7",this.requirementBackground=this.requirementBackground||this.primaryColor,this.requirementBorderColor=this.requirementBorderColor||this.primaryBorderColor,this.requirementBorderSize=this.requirementBorderSize||this.primaryBorderColor,this.requirementTextColor=this.requirementTextColor||this.primaryTextColor,this.relationColor=this.relationColor||this.lineColor,this.relationLabelBackground=this.relationLabelBackground||this.edgeLabelBackground,this.relationLabelColor=this.relationLabelColor||this.actorTextColor}},{key:"calculate",value:function(t){var e=this;if("object"===rv(t)){var n=Object.keys(t);n.forEach((function(n){e[n]=t[n]})),this.updateColors(),n.forEach((function(n){e[n]=t[n]}))}else this.updateColors()}}],n&&iv(e.prototype,n),Object.defineProperty(e,"prototype",{writable:!1}),t}();const ov={base:{getThemeVariables:function(t){var e=new Vm;return e.calculate(t),e}},dark:{getThemeVariables:function(t){var e=new Zm;return e.calculate(t),e}},default:{getThemeVariables:function(t){var e=new Jm;return e.calculate(t),e}},forest:{getThemeVariables:function(t){var e=new nv;return e.calculate(t),e}},neutral:{getThemeVariables:function(t){var e=new av;return e.calculate(t),e}}};function sv(t){return function(t){if(Array.isArray(t))return cv(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return cv(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?cv(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function cv(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}function uv(t){return uv="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},uv(t)}var lv={theme:"default",themeVariables:ov.default.getThemeVariables(),themeCSS:void 0,maxTextSize:5e4,darkMode:!1,fontFamily:'"trebuchet ms", verdana, arial, sans-serif;',logLevel:5,securityLevel:"strict",startOnLoad:!0,arrowMarkerAbsolute:!1,secure:["secure","securityLevel","startOnLoad","maxTextSize"],deterministicIds:!1,deterministicIDSeed:void 0,flowchart:{diagramPadding:8,htmlLabels:!0,nodeSpacing:50,rankSpacing:50,curve:"basis",padding:15,useMaxWidth:!0,defaultRenderer:"dagre-d3"},sequence:{activationWidth:10,diagramMarginX:50,diagramMarginY:10,actorMargin:50,width:150,height:65,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",mirrorActors:!0,forceMenus:!1,bottomMarginAdj:1,useMaxWidth:!0,rightAngles:!1,showSequenceNumbers:!1,actorFontSize:14,actorFontFamily:'"Open-Sans", "sans-serif"',actorFontWeight:400,noteFontSize:14,noteFontFamily:'"trebuchet ms", verdana, arial, sans-serif',noteFontWeight:400,noteAlign:"center",messageFontSize:16,messageFontFamily:'"trebuchet ms", verdana, arial, sans-serif',messageFontWeight:400,wrap:!1,wrapPadding:10,labelBoxWidth:50,labelBoxHeight:20,messageFont:function(){return{fontFamily:this.messageFontFamily,fontSize:this.messageFontSize,fontWeight:this.messageFontWeight}},noteFont:function(){return{fontFamily:this.noteFontFamily,fontSize:this.noteFontSize,fontWeight:this.noteFontWeight}},actorFont:function(){return{fontFamily:this.actorFontFamily,fontSize:this.actorFontSize,fontWeight:this.actorFontWeight}}},gantt:{titleTopMargin:25,barHeight:20,barGap:4,topPadding:50,rightPadding:75,leftPadding:75,gridLineStartPadding:35,fontSize:11,sectionFontSize:11,numberSectionStyles:4,axisFormat:"%Y-%m-%d",useMaxWidth:!0,topAxis:!1,useWidth:void 0},journey:{diagramMarginX:50,diagramMarginY:10,leftMargin:150,width:150,height:50,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",bottomMarginAdj:1,useMaxWidth:!0,rightAngles:!1,taskFontSize:14,taskFontFamily:'"Open-Sans", "sans-serif"',taskMargin:50,activationWidth:10,textPlacement:"fo",actorColours:["#8FBC8F","#7CFC00","#00FFFF","#20B2AA","#B0E0E6","#FFFFE0"],sectionFills:["#191970","#8B008B","#4B0082","#2F4F4F","#800000","#8B4513","#00008B"],sectionColours:["#fff"]},class:{arrowMarkerAbsolute:!1,useMaxWidth:!0,defaultRenderer:"dagre-wrapper"},git:{arrowMarkerAbsolute:!1,useWidth:void 0,useMaxWidth:!0},state:{dividerMargin:10,sizeUnit:5,padding:8,textHeight:10,titleShift:-15,noteMargin:10,forkWidth:70,forkHeight:7,miniPadding:2,fontSizeFactor:5.02,fontSize:24,labelHeight:16,edgeLengthFactor:"20",compositTitleSize:35,radius:5,useMaxWidth:!0,defaultRenderer:"dagre-wrapper"},er:{diagramPadding:20,layoutDirection:"TB",minEntityWidth:100,minEntityHeight:75,entityPadding:15,stroke:"gray",fill:"honeydew",fontSize:12,useMaxWidth:!0},pie:{useWidth:void 0,useMaxWidth:!0},requirement:{useWidth:void 0,useMaxWidth:!0,rect_fill:"#f9f9f9",text_color:"#333",rect_border_size:"0.5px",rect_border_color:"#bbb",rect_min_width:200,rect_min_height:200,fontSize:14,rect_padding:10,line_height:20}};lv.class.arrowMarkerAbsolute=lv.arrowMarkerAbsolute,lv.git.arrowMarkerAbsolute=lv.arrowMarkerAbsolute;var hv=function t(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return Object.keys(e).reduce((function(r,i){return Array.isArray(e[i])?r:"object"===uv(e[i])&&null!==e[i]?[].concat(sv(r),[n+i],sv(t(e[i],""))):[].concat(sv(r),[n+i])}),[])}(lv,"");const fv=lv;var dv=void 0;function pv(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}function yv(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=vv(t))||e&&t&&"number"==typeof t.length){n&&(t=n);var r=0,i=function(){};return{s:i,n:function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,o=!0,s=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return o=t.done,t},e:function(t){s=!0,a=t},f:function(){try{o||null==n.return||n.return()}finally{if(s)throw a}}}}function gv(t){return gv="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},gv(t)}function mv(t){return function(t){if(Array.isArray(t))return bv(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||vv(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function vv(t,e){if(t){if("string"==typeof t)return bv(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?bv(t,e):void 0}}function bv(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}var _v,xv={curveBasis:Vu,curveBasisClosed:function(t){return new Gu(t)},curveBasisOpen:function(t){return new Xu(t)},curveLinear:Pu,curveLinearClosed:function(t){return new Zu(t)},curveMonotoneX:function(t){return new el(t)},curveMonotoneY:function(t){return new nl(t)},curveNatural:function(t){return new il(t)},curveStep:function(t){return new ol(t,.5)},curveStepAfter:function(t){return new ol(t,1)},curveStepBefore:function(t){return new ol(t,0)}},wv=/[%]{2}[{]\s*(?:(?:(\w+)\s*:|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi,kv=/\s*(?:(?:(\w+)(?=:):|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi,Tv=/\s*%%.*\n/gm,Ev=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;try{var n=new RegExp("[%]{2}(?![{]".concat(kv.source,")(?=[}][%]{2}).*\n"),"ig");t=t.trim().replace(n,"").replace(/'/gm,'"'),o.debug("Detecting diagram directive".concat(null!==e?" type:"+e:""," based on the text:").concat(t));for(var r,i=[];null!==(r=wv.exec(t));)if(r.index===wv.lastIndex&&wv.lastIndex++,r&&!e||e&&r[1]&&r[1].match(e)||e&&r[2]&&r[2].match(e)){var a=r[1]?r[1]:r[2],s=r[3]?r[3].trim():r[4]?JSON.parse(r[4].trim()):null;i.push({type:a,args:s})}return 0===i.length&&i.push({type:t,args:null}),1===i.length?i[0]:i}catch(n){return o.error("ERROR: ".concat(n.message," - Unable to parse directive\n      ").concat(null!==e?" type:"+e:""," based on the text:").concat(t)),{type:null,args:null}}},Cv=function(t,e){return(t=t.replace(wv,"").replace(Tv,"\n")).match(/^\s*sequenceDiagram/)?"sequence":t.match(/^\s*gantt/)?"gantt":t.match(/^\s*classDiagram-v2/)?"classDiagram":t.match(/^\s*classDiagram/)?e&&e.class&&"dagre-wrapper"===e.class.defaultRenderer?"classDiagram":"class":t.match(/^\s*stateDiagram-v2/)?"stateDiagram":t.match(/^\s*stateDiagram/)?e&&e.class&&"dagre-wrapper"===e.state.defaultRenderer?"stateDiagram":"state":t.match(/^\s*gitGraph/)?"git":t.match(/^\s*flowchart/)?"flowchart-v2":t.match(/^\s*info/)?"info":t.match(/^\s*pie/)?"pie":t.match(/^\s*erDiagram/)?"er":t.match(/^\s*journey/)?"journey":t.match(/^\s*requirement/)||t.match(/^\s*requirementDiagram/)?"requirement":e&&e.flowchart&&"dagre-wrapper"===e.flowchart.defaultRenderer?"flowchart-v2":"flowchart"},Sv=function(t,e){var n={};return function(){for(var r=arguments.length,i=new Array(r),a=0;a<r;a++)i[a]=arguments[a];var o=e?e.apply(dv,i):i[0];if(o in n)return n[o];var s=t.apply(void 0,i);return n[o]=s,s}},Av=function(t,e){if(!t)return e;var n="curve".concat(t.charAt(0).toUpperCase()+t.slice(1));return xv[n]||e},Mv=function(t,e){return t&&e?Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2)):0},Nv=function(t){for(var e="",n="",r=0;r<t.length;r++)void 0!==t[r]&&(t[r].startsWith("color:")||t[r].startsWith("text-align:")?n=n+t[r]+";":e=e+t[r]+";");return{style:e,labelStyle:n}},Dv=0,Ov=function(){return Dv++,"id-"+Math.random().toString(36).substr(2,12)+"-"+Dv},Bv=function(t){return function(t){for(var e="",n="0123456789abcdef",r=n.length,i=0;i<t;i++)e+=n.charAt(Math.floor(Math.random()*r));return e}(t.length)},Lv=function t(e,n,r){var i=Object.assign({depth:2,clobber:!1},r),a=i.depth,o=i.clobber;return Array.isArray(n)&&!Array.isArray(e)?(n.forEach((function(n){return t(e,n,r)})),e):Array.isArray(n)&&Array.isArray(e)?(n.forEach((function(t){-1===e.indexOf(t)&&e.push(t)})),e):void 0===e||a<=0?null!=e&&"object"===gv(e)&&"object"===gv(n)?Object.assign(e,n):n:(void 0!==n&&"object"===gv(e)&&"object"===gv(n)&&Object.keys(n).forEach((function(r){"object"!==gv(n[r])||void 0!==e[r]&&"object"!==gv(e[r])?(o||"object"!==gv(e[r])&&"object"!==gv(n[r]))&&(e[r]=n[r]):(void 0===e[r]&&(e[r]=Array.isArray(n[r])?[]:{}),e[r]=t(e[r],n[r],{depth:a-1,clobber:o}))})),e)},Iv=function(t,e){var n=e.text.replace(Um.lineBreakRegex," "),r=t.append("text");r.attr("x",e.x),r.attr("y",e.y),r.style("text-anchor",e.anchor),r.style("font-family",e.fontFamily),r.style("font-size",e.fontSize),r.style("font-weight",e.fontWeight),r.attr("fill",e.fill),void 0!==e.class&&r.attr("class",e.class);var i=r.append("tspan");return i.attr("x",e.x+2*e.textMargin),i.attr("fill",e.fill),i.text(n),r},Rv=Sv((function(t,e,n){if(!t)return t;if(n=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",joinWith:"<br/>"},n),Um.lineBreakRegex.test(t))return t;var r=t.split(" "),i=[],a="";return r.forEach((function(t,o){var s=Pv("".concat(t," "),n),c=Pv(a,n);if(s>e){var u=Fv(t,e,"-",n),l=u.hyphenatedStrings,h=u.remainingWord;i.push.apply(i,[a].concat(mv(l))),a=h}else c+s>=e?(i.push(a),a=t):a=[a,t].filter(Boolean).join(" ");o+1===r.length&&i.push(a)})),i.filter((function(t){return""!==t})).join(n.joinWith)}),(function(t,e,n){return"".concat(t,"-").concat(e,"-").concat(n.fontSize,"-").concat(n.fontWeight,"-").concat(n.fontFamily,"-").concat(n.joinWith)})),Fv=Sv((function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"-",r=arguments.length>3?arguments[3]:void 0;r=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",margin:0},r);var i=t.split(""),a=[],o="";return i.forEach((function(t,s){var c="".concat(o).concat(t);if(Pv(c,r)>=e){var u=s+1,l=i.length===u,h="".concat(c).concat(n);a.push(l?c:h),o=""}else o=c})),{hyphenatedStrings:a,remainingWord:o}}),(function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"-",r=arguments.length>3?arguments[3]:void 0;return"".concat(t,"-").concat(e,"-").concat(n,"-").concat(r.fontSize,"-").concat(r.fontWeight,"-").concat(r.fontFamily)})),Pv=function(t,e){return e=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial"},e),jv(t,e).width},jv=Sv((function(t,e){var n=e=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial"},e),r=n.fontSize,i=n.fontFamily,a=n.fontWeight;if(!t)return{width:0,height:0};var o=["sans-serif",i],s=t.split(Um.lineBreakRegex),c=[],u=au("body");if(!u.remove)return{width:0,height:0,lineHeight:0};for(var l=u.append("svg"),h=0,f=o;h<f.length;h++){var d,p=f[h],y=0,g={width:0,height:0,lineHeight:0},m=yv(s);try{for(m.s();!(d=m.n()).done;){var v=d.value,b={x:0,y:0,fill:void 0,anchor:"start",style:"#666",width:100,height:100,textMargin:0,rx:0,ry:0,valign:void 0};b.text=v;var _=Iv(l,b).style("font-size",r).style("font-weight",a).style("font-family",p),x=(_._groups||_)[0][0].getBBox();g.width=Math.round(Math.max(g.width,x.width)),y=Math.round(x.height),g.height+=y,g.lineHeight=Math.round(Math.max(g.lineHeight,y))}}catch(t){m.e(t)}finally{m.f()}c.push(g)}return l.remove(),c[isNaN(c[1].height)||isNaN(c[1].width)||isNaN(c[1].lineHeight)||c[0].height>c[1].height&&c[0].width>c[1].width&&c[0].lineHeight>c[1].lineHeight?0:1]}),(function(t,e){return"".concat(t,"-").concat(e.fontSize,"-").concat(e.fontWeight,"-").concat(e.fontFamily)})),Yv=function(t,e,n){var r=new Map;return r.set("height",t),n?(r.set("width","100%"),r.set("style","max-width: ".concat(e,"px;"))):r.set("width",e),r},zv=function(t,e,n,r){!function(t,e){var n,r=yv(e);try{for(r.s();!(n=r.n()).done;){var i=n.value;t.attr(i[0],i[1])}}catch(t){r.e(t)}finally{r.f()}}(t,Yv(e,n,r))},Uv=function t(e){o.debug("directiveSanitizer called with",e),"object"===gv(e)&&(e.length?e.forEach((function(e){return t(e)})):Object.keys(e).forEach((function(n){o.debug("Checking key",n),0===n.indexOf("__")&&(o.debug("sanitize deleting __ option",n),delete e[n]),n.indexOf("proto")>=0&&(o.debug("sanitize deleting proto option",n),delete e[n]),n.indexOf("constr")>=0&&(o.debug("sanitize deleting constr option",n),delete e[n]),n.indexOf("themeCSS")>=0&&(o.debug("sanitizing themeCss option"),e[n]=qv(e[n])),hv.indexOf(n)<0?(o.debug("sanitize deleting option",n),delete e[n]):"object"===gv(e[n])&&(o.debug("sanitize deleting object",n),t(e[n]))})))},qv=function(t){return(t.match(/\{/g)||[]).length!==(t.match(/\}/g)||[]).length?"{ /* ERROR: Unbalanced CSS */ }":t};const Hv={assignWithDepth:Lv,wrapLabel:Rv,calculateTextHeight:function(t,e){return e=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",margin:15},e),jv(t,e).height},calculateTextWidth:Pv,calculateTextDimensions:jv,calculateSvgSizeAttrs:Yv,configureSvgSize:zv,detectInit:function(t,e){var n=Ev(t,/(?:init\b)|(?:initialize\b)/),r={};if(Array.isArray(n)){var i=n.map((function(t){return t.args}));Uv(i),r=Lv(r,mv(i))}else r=n.args;if(r){var a=Cv(t,e);["config"].forEach((function(t){void 0!==r[t]&&("flowchart-v2"===a&&(a="flowchart"),r[a]=r[t],delete r[t])}))}return r},detectDirective:Ev,detectType:Cv,isSubstringInArray:function(t,e){for(var n=0;n<e.length;n++)if(e[n].match(t))return n;return-1},interpolateToCurve:Av,calcLabelPosition:function(t){return function(t){var e,n=0;t.forEach((function(t){n+=Mv(t,e),e=t}));var r=n/2,i=void 0;return e=void 0,t.forEach((function(t){if(e&&!i){var n=Mv(t,e);if(n<r)r-=n;else{var a=r/n;a<=0&&(i=e),a>=1&&(i={x:t.x,y:t.y}),a>0&&a<1&&(i={x:(1-a)*e.x+a*t.x,y:(1-a)*e.y+a*t.y})}}e=t})),i}(t)},calcCardinalityPosition:function(t,e,n){var r;o.info("our points",e),e[0]!==n&&(e=e.reverse()),e.forEach((function(t){Mv(t,r),r=t}));var i,a=25;r=void 0,e.forEach((function(t){if(r&&!i){var e=Mv(t,r);if(e<a)a-=e;else{var n=a/e;n<=0&&(i=r),n>=1&&(i={x:t.x,y:t.y}),n>0&&n<1&&(i={x:(1-n)*r.x+n*t.x,y:(1-n)*r.y+n*t.y})}}r=t}));var s=t?10:5,c=Math.atan2(e[0].y-i.y,e[0].x-i.x),u={x:0,y:0};return u.x=Math.sin(c)*s+(e[0].x+i.x)/2,u.y=-Math.cos(c)*s+(e[0].y+i.y)/2,u},calcTerminalLabelPosition:function(t,e,n){var r,i=JSON.parse(JSON.stringify(n));o.info("our points",i),"start_left"!==e&&"start_right"!==e&&(i=i.reverse()),i.forEach((function(t){Mv(t,r),r=t}));var a,s=25+t;r=void 0,i.forEach((function(t){if(r&&!a){var e=Mv(t,r);if(e<s)s-=e;else{var n=s/e;n<=0&&(a=r),n>=1&&(a={x:t.x,y:t.y}),n>0&&n<1&&(a={x:(1-n)*r.x+n*t.x,y:(1-n)*r.y+n*t.y})}}r=t}));var c=10+.5*t,u=Math.atan2(i[0].y-a.y,i[0].x-a.x),l={x:0,y:0};return l.x=Math.sin(u)*c+(i[0].x+a.x)/2,l.y=-Math.cos(u)*c+(i[0].y+a.y)/2,"start_left"===e&&(l.x=Math.sin(u+Math.PI)*c+(i[0].x+a.x)/2,l.y=-Math.cos(u+Math.PI)*c+(i[0].y+a.y)/2),"end_right"===e&&(l.x=Math.sin(u-Math.PI)*c+(i[0].x+a.x)/2-5,l.y=-Math.cos(u-Math.PI)*c+(i[0].y+a.y)/2-5),"end_left"===e&&(l.x=Math.sin(u)*c+(i[0].x+a.x)/2-5,l.y=-Math.cos(u)*c+(i[0].y+a.y)/2-5),l},formatUrl:function(t,e){var n=t.trim();if(n)return"loose"!==e.securityLevel?(0,Om.sanitizeUrl)(n):n},getStylesFromArray:Nv,generateId:Ov,random:Bv,memoize:Sv,runFunc:function(t){for(var e,n=t.split("."),r=n.length-1,i=n[r],a=window,o=0;o<r;o++)if(!(a=a[n[o]]))return;for(var s=arguments.length,c=new Array(s>1?s-1:0),u=1;u<s;u++)c[u-1]=arguments[u];(e=a)[i].apply(e,c)},entityDecode:function(t){return _v=_v||document.createElement("div"),t=escape(t).replace(/%26/g,"&").replace(/%23/g,"#").replace(/%3B/g,";"),_v.innerHTML=t,unescape(_v.textContent)},initIdGeneratior:function(){function t(e,n){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.deterministic=e,this.seed=n,this.count=n?n.length:0}var e,n;return e=t,(n=[{key:"next",value:function(){return this.deterministic?this.count++:Date.now()}}])&&pv(e.prototype,n),Object.defineProperty(e,"prototype",{writable:!1}),t}(),directiveSanitizer:Uv,sanitizeCss:qv};function $v(t){return $v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},$v(t)}var Wv,Vv=Object.freeze(fv),Gv=Lv({},Vv),Xv=[],Zv=Lv({},Vv),Qv=function(t,e){for(var n=Lv({},t),r={},i=0;i<e.length;i++){var a=e[i];tb(a),r=Lv(r,a)}if(n=Lv(n,r),r.theme){var o=Lv({},Wv),s=Lv(o.themeVariables||{},r.themeVariables);n.themeVariables=ov[n.theme].getThemeVariables(s)}return Zv=n,n},Kv=function(){return Lv({},Gv)},Jv=function(){return Lv({},Zv)},tb=function t(e){Object.keys(Gv.secure).forEach((function(t){void 0!==e[Gv.secure[t]]&&(o.debug("Denied attempt to modify a secure key ".concat(Gv.secure[t]),e[Gv.secure[t]]),delete e[Gv.secure[t]])})),Object.keys(e).forEach((function(t){0===t.indexOf("__")&&delete e[t]})),Object.keys(e).forEach((function(n){"string"==typeof e[n]&&(e[n].indexOf("<")>-1||e[n].indexOf(">")>-1||e[n].indexOf("url(data:")>-1)&&delete e[n],"object"===$v(e[n])&&t(e[n])}))},eb=function(t){t.fontFamily&&(t.themeVariables&&t.themeVariables.fontFamily||(t.themeVariables={fontFamily:t.fontFamily})),Xv.push(t),Qv(Gv,Xv)},nb=function(){Qv(Gv,Xv=[])};function rb(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}var ib="classid-",ab=[],ob={},sb=0,cb=[],ub=function(t){return Um.sanitizeText(t,Jv())},lb=function(t){var e="",n=t;if(t.indexOf("~")>0){var r=t.split("~");n=r[0],e=Um.sanitizeText(r[1],Jv())}return{className:n,type:e}},hb=function(t){var e=lb(t);void 0===ob[e.className]&&(ob[e.className]={id:e.className,type:e.type,cssClasses:[],methods:[],members:[],annotations:[],domId:ib+e.className+"-"+sb},sb++)},fb=function(t){for(var e=Object.keys(ob),n=0;n<e.length;n++)if(ob[e[n]].id===t)return ob[e[n]].domId},db=function(t,e){var n=lb(t).className,r=ob[n];if("string"==typeof e){var i=e.trim();i.startsWith("<<")&&i.endsWith(">>")?r.annotations.push(ub(i.substring(2,i.length-2))):i.indexOf(")")>0?r.methods.push(ub(i)):i&&r.members.push(ub(i))}},pb=function(t,e){t.split(",").forEach((function(t){var n=t;t[0].match(/\d/)&&(n=ib+n),void 0!==ob[n]&&ob[n].cssClasses.push(e)}))},yb=function(t,e,n){var r=Jv(),i=t,a=fb(i);if("loose"===r.securityLevel&&void 0!==e&&void 0!==ob[i]){var o=[];if("string"==typeof n){o=n.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(var s=0;s<o.length;s++){var c=o[s].trim();'"'===c.charAt(0)&&'"'===c.charAt(c.length-1)&&(c=c.substr(1,c.length-2)),o[s]=c}}0===o.length&&o.push(a),cb.push((function(){var t=document.querySelector('[id="'.concat(a,'"]'));null!==t&&t.addEventListener("click",(function(){var t;Hv.runFunc.apply(Hv,[e].concat(function(t){if(Array.isArray(t))return rb(t)}(t=o)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return rb(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?rb(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()))}),!1)}))}},gb={AGGREGATION:0,EXTENSION:1,COMPOSITION:2,DEPENDENCY:3},mb=function(t){var e=au(".mermaidTooltip");null===(e._groups||e)[0][0]&&(e=au("body").append("div").attr("class","mermaidTooltip").style("opacity",0)),au(t).select("svg").selectAll("g.node").on("mouseover",(function(){var t=au(this);if(null!==t.attr("title")){var n=this.getBoundingClientRect();e.transition().duration(200).style("opacity",".9"),e.html(t.attr("title")).style("left",window.scrollX+n.left+(n.right-n.left)/2+"px").style("top",window.scrollY+n.top-14+document.body.scrollTop+"px"),t.classed("hover",!0)}})).on("mouseout",(function(){e.transition().duration(500).style("opacity",0),au(this).classed("hover",!1)}))};cb.push(mb);var vb="TB";const bb={parseDirective:function(t,e,n){cC.parseDirective(this,t,e,n)},getConfig:function(){return Jv().class},addClass:hb,bindFunctions:function(t){cb.forEach((function(e){e(t)}))},clear:function(){ab=[],ob={},(cb=[]).push(mb)},getClass:function(t){return ob[t]},getClasses:function(){return ob},addAnnotation:function(t,e){var n=lb(t).className;ob[n].annotations.push(e)},getRelations:function(){return ab},addRelation:function(t){o.debug("Adding relation: "+JSON.stringify(t)),hb(t.id1),hb(t.id2),t.id1=lb(t.id1).className,t.id2=lb(t.id2).className,t.relationTitle1=Um.sanitizeText(t.relationTitle1.trim(),Jv()),t.relationTitle2=Um.sanitizeText(t.relationTitle2.trim(),Jv()),ab.push(t)},getDirection:function(){return vb},setDirection:function(t){vb=t},addMember:db,addMembers:function(t,e){Array.isArray(e)&&(e.reverse(),e.forEach((function(e){return db(t,e)})))},cleanupLabel:function(t){return":"===t.substring(0,1)?Um.sanitizeText(t.substr(1).trim(),Jv()):ub(t.trim())},lineType:{LINE:0,DOTTED_LINE:1},relationType:gb,setClickEvent:function(t,e,n){t.split(",").forEach((function(t){yb(t,e,n),ob[t].haveCallback=!0})),pb(t,"clickable")},setCssClass:pb,setLink:function(t,e,n){var r=Jv();t.split(",").forEach((function(t){var i=t;t[0].match(/\d/)&&(i=ib+i),void 0!==ob[i]&&(ob[i].link=Hv.formatUrl(e,r),ob[i].linkTarget="string"==typeof n?n:"_blank")})),pb(t,"clickable")},setTooltip:function(t,e){var n=Jv();t.split(",").forEach((function(t){void 0!==e&&(ob[t].tooltip=Um.sanitizeText(e,n))}))},lookUpDomId:fb};var _b=n(681),xb=n.n(_b),wb=n(8282),kb=n.n(wb),Tb=n(1362),Eb=n.n(Tb),Cb=0,Sb=function(t){var e=t.match(/^(\+|-|~|#)?(\w+)(~\w+~|\[\])?\s+(\w+) *(\*|\$)?$/),n=t.match(/^([+|\-|~|#])?(\w+) *\( *(.*)\) *(\*|\$)? *(\w*[~|[\]]*\s*\w*~?)$/);return e&&!n?Ab(e):n?Mb(n):Nb(t)},Ab=function(t){var e="",n="";try{var r=t[1]?t[1].trim():"",i=t[2]?t[2].trim():"",a=t[3]?Ob(t[3].trim()):"",o=t[4]?t[4].trim():"",s=t[5]?t[5].trim():"";n=r+i+a+" "+o,e=Bb(s)}catch(e){n=t}return{displayText:n,cssStyle:e}},Mb=function(t){var e="",n="";try{var r=t[1]?t[1].trim():"",i=t[2]?t[2].trim():"",a=t[3]?Ob(t[3].trim()):"",o=t[4]?t[4].trim():"";n=r+i+"("+a+")"+(t[5]?" : "+Ob(t[5]).trim():""),e=Bb(o)}catch(e){n=t}return{displayText:n,cssStyle:e}},Nb=function(t){var e="",n="",r="",i=t.indexOf("("),a=t.indexOf(")");if(i>1&&a>i&&a<=t.length){var o="",s="",c=t.substring(0,1);c.match(/\w/)?s=t.substring(0,i).trim():(c.match(/\+|-|~|#/)&&(o=c),s=t.substring(1,i).trim());var u=t.substring(i+1,a),l=t.substring(a+1,1);n=Bb(l),e=o+s+"("+Ob(u.trim())+")",a<"".length&&""!==(r=t.substring(a+2).trim())&&(r=" : "+Ob(r))}else e=Ob(t);return{displayText:e,cssStyle:n}},Db=function(t,e,n,r){var i=Sb(e),a=t.append("tspan").attr("x",r.padding).text(i.displayText);""!==i.cssStyle&&a.attr("style",i.cssStyle),n||a.attr("dy",r.textHeight)},Ob=function t(e){var n=e;return-1!=e.indexOf("~")?t(n=(n=n.replace("~","<")).replace("~",">")):n},Bb=function(t){switch(t){case"*":return"font-style:italic;";case"$":return"text-decoration:underline;";default:return""}};const Lb=function(t,e,n){o.info("Rendering class "+e);var r,i=e.id,a={id:i,label:e.id,width:0,height:0},s=t.append("g").attr("id",fb(i)).attr("class","classGroup");r=e.link?s.append("svg:a").attr("xlink:href",e.link).attr("target",e.linkTarget).append("text").attr("y",n.textHeight+n.padding).attr("x",0):s.append("text").attr("y",n.textHeight+n.padding).attr("x",0);var c=!0;e.annotations.forEach((function(t){var e=r.append("tspan").text("«"+t+"»");c||e.attr("dy",n.textHeight),c=!1}));var u=e.id;void 0!==e.type&&""!==e.type&&(u+="<"+e.type+">");var l=r.append("tspan").text(u).attr("class","title");c||l.attr("dy",n.textHeight);var h=r.node().getBBox().height,f=s.append("line").attr("x1",0).attr("y1",n.padding+h+n.dividerMargin/2).attr("y2",n.padding+h+n.dividerMargin/2),d=s.append("text").attr("x",n.padding).attr("y",h+n.dividerMargin+n.textHeight).attr("fill","white").attr("class","classText");c=!0,e.members.forEach((function(t){Db(d,t,c,n),c=!1}));var p=d.node().getBBox(),y=s.append("line").attr("x1",0).attr("y1",n.padding+h+n.dividerMargin+p.height).attr("y2",n.padding+h+n.dividerMargin+p.height),g=s.append("text").attr("x",n.padding).attr("y",h+2*n.dividerMargin+p.height+n.textHeight).attr("fill","white").attr("class","classText");c=!0,e.methods.forEach((function(t){Db(g,t,c,n),c=!1}));var m=s.node().getBBox(),v=" ";e.cssClasses.length>0&&(v+=e.cssClasses.join(" "));var b=s.insert("rect",":first-child").attr("x",0).attr("y",0).attr("width",m.width+2*n.padding).attr("height",m.height+n.padding+.5*n.dividerMargin).attr("class",v).node().getBBox().width;return r.node().childNodes.forEach((function(t){t.setAttribute("x",(b-t.getBBox().width)/2)})),e.tooltip&&r.insert("title").text(e.tooltip),f.attr("x2",b),y.attr("x2",b),a.width=b,a.height=m.height+n.padding+.5*n.dividerMargin,a};Tb.parser.yy=bb;var Ib={},Rb={dividerMargin:10,padding:5,textHeight:10},Fb=function(t){var e=Object.entries(Ib).find((function(e){return e[1].label===t}));if(e)return e[0]};const Pb=function(t){Object.keys(t).forEach((function(e){Rb[e]=t[e]}))},jb=function(t,e){Ib={},Tb.parser.yy.clear(),Tb.parser.parse(t),o.info("Rendering diagram "+t);var n,r=au("[id='".concat(e,"']"));r.attr("xmlns:xlink","http://www.w3.org/1999/xlink"),(n=r).append("defs").append("marker").attr("id","extensionStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 1,7 L18,13 V 1 Z"),n.append("defs").append("marker").attr("id","extensionEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 1,1 V 13 L18,7 Z"),n.append("defs").append("marker").attr("id","compositionStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),n.append("defs").append("marker").attr("id","compositionEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),n.append("defs").append("marker").attr("id","aggregationStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),n.append("defs").append("marker").attr("id","aggregationEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),n.append("defs").append("marker").attr("id","dependencyStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 5,7 L9,13 L1,7 L9,1 Z"),n.append("defs").append("marker").attr("id","dependencyEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z");var i=new(kb().Graph)({multigraph:!0});i.setGraph({isMultiGraph:!0}),i.setDefaultEdgeLabel((function(){return{}}));for(var a=bb.getClasses(),s=Object.keys(a),c=0;c<s.length;c++){var u=a[s[c]],l=Lb(r,u,Rb);Ib[l.id]=l,i.setNode(l.id,l),o.info("Org height: "+l.height)}bb.getRelations().forEach((function(t){o.info("tjoho"+Fb(t.id1)+Fb(t.id2)+JSON.stringify(t)),i.setEdge(Fb(t.id1),Fb(t.id2),{relation:t},t.title||"DEFAULT")})),xb().layout(i),i.nodes().forEach((function(t){void 0!==t&&void 0!==i.node(t)&&(o.debug("Node "+t+": "+JSON.stringify(i.node(t))),au("#"+fb(t)).attr("transform","translate("+(i.node(t).x-i.node(t).width/2)+","+(i.node(t).y-i.node(t).height/2)+" )"))})),i.edges().forEach((function(t){void 0!==t&&void 0!==i.edge(t)&&(o.debug("Edge "+t.v+" -> "+t.w+": "+JSON.stringify(i.edge(t))),function(t,e,n,r){var i=function(t){switch(t){case gb.AGGREGATION:return"aggregation";case gb.EXTENSION:return"extension";case gb.COMPOSITION:return"composition";case gb.DEPENDENCY:return"dependency"}};e.points=e.points.filter((function(t){return!Number.isNaN(t.y)}));var a,s,c=e.points,u=zu().x((function(t){return t.x})).y((function(t){return t.y})).curve(Vu),l=t.append("path").attr("d",u(c)).attr("id","edge"+Cb).attr("class","relation"),h="";r.arrowMarkerAbsolute&&(h=(h=(h=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search).replace(/\(/g,"\\(")).replace(/\)/g,"\\)")),1==n.relation.lineType&&l.attr("class","relation dashed-line"),"none"!==n.relation.type1&&l.attr("marker-start","url("+h+"#"+i(n.relation.type1)+"Start)"),"none"!==n.relation.type2&&l.attr("marker-end","url("+h+"#"+i(n.relation.type2)+"End)");var f,d,p,y,g=e.points.length,m=Hv.calcLabelPosition(e.points);if(a=m.x,s=m.y,g%2!=0&&g>1){var v=Hv.calcCardinalityPosition("none"!==n.relation.type1,e.points,e.points[0]),b=Hv.calcCardinalityPosition("none"!==n.relation.type2,e.points,e.points[g-1]);o.debug("cardinality_1_point "+JSON.stringify(v)),o.debug("cardinality_2_point "+JSON.stringify(b)),f=v.x,d=v.y,p=b.x,y=b.y}if(void 0!==n.title){var _=t.append("g").attr("class","classLabel"),x=_.append("text").attr("class","label").attr("x",a).attr("y",s).attr("fill","red").attr("text-anchor","middle").text(n.title);window.label=x;var w=x.node().getBBox();_.insert("rect",":first-child").attr("class","box").attr("x",w.x-r.padding/2).attr("y",w.y-r.padding/2).attr("width",w.width+r.padding).attr("height",w.height+r.padding)}o.info("Rendering relation "+JSON.stringify(n)),void 0!==n.relationTitle1&&"none"!==n.relationTitle1&&t.append("g").attr("class","cardinality").append("text").attr("class","type1").attr("x",f).attr("y",d).attr("fill","black").attr("font-size","6").text(n.relationTitle1),void 0!==n.relationTitle2&&"none"!==n.relationTitle2&&t.append("g").attr("class","cardinality").append("text").attr("class","type2").attr("x",p).attr("y",y).attr("fill","black").attr("font-size","6").text(n.relationTitle2),Cb++}(r,i.edge(t),i.edge(t).relation,Rb))}));var h=r.node().getBBox(),f=h.width+40,d=h.height+40;zv(r,d,f,Rb.useMaxWidth);var p="".concat(h.x-20," ").concat(h.y-20," ").concat(f," ").concat(d);o.debug("viewBox ".concat(p)),r.attr("viewBox",p)};var Yb={extension:function(t,e,n){o.trace("Making markers for ",n),t.append("defs").append("marker").attr("id",e+"-extensionStart").attr("class","marker extension "+e).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 1,7 L18,13 V 1 Z"),t.append("defs").append("marker").attr("id",e+"-extensionEnd").attr("class","marker extension "+e).attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 1,1 V 13 L18,7 Z")},composition:function(t,e){t.append("defs").append("marker").attr("id",e+"-compositionStart").attr("class","marker composition "+e).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),t.append("defs").append("marker").attr("id",e+"-compositionEnd").attr("class","marker composition "+e).attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},aggregation:function(t,e){t.append("defs").append("marker").attr("id",e+"-aggregationStart").attr("class","marker aggregation "+e).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),t.append("defs").append("marker").attr("id",e+"-aggregationEnd").attr("class","marker aggregation "+e).attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},dependency:function(t,e){t.append("defs").append("marker").attr("id",e+"-dependencyStart").attr("class","marker dependency "+e).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 5,7 L9,13 L1,7 L9,1 Z"),t.append("defs").append("marker").attr("id",e+"-dependencyEnd").attr("class","marker dependency "+e).attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},point:function(t,e){t.append("marker").attr("id",e+"-pointEnd").attr("class","marker "+e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),t.append("marker").attr("id",e+"-pointStart").attr("class","marker "+e).attr("viewBox","0 0 10 10").attr("refX",0).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 5 L 10 10 L 10 0 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},circle:function(t,e){t.append("marker").attr("id",e+"-circleEnd").attr("class","marker "+e).attr("viewBox","0 0 10 10").attr("refX",11).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),t.append("marker").attr("id",e+"-circleStart").attr("class","marker "+e).attr("viewBox","0 0 10 10").attr("refX",-1).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},cross:function(t,e){t.append("marker").attr("id",e+"-crossEnd").attr("class","marker cross "+e).attr("viewBox","0 0 11 11").attr("refX",12).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0"),t.append("marker").attr("id",e+"-crossStart").attr("class","marker cross "+e).attr("viewBox","0 0 11 11").attr("refX",-1).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0")},barb:function(t,e){t.append("defs").append("marker").attr("id",e+"-barbEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",14).attr("markerUnits","strokeWidth").attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z")}};const zb=function(t,e,n,r){e.forEach((function(e){Yb[e](t,n,r)}))};function Ub(t){return Ub="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},Ub(t)}const qb=function(t,e,n,r){var i,a,s,c,u,l,h=t||"";if("object"===Ub(h)&&(h=h[0]),zm(Jv().flowchart.htmlLabels))return h=h.replace(/\\n|\n/g,"<br />"),o.info("vertexText"+h),i={isNode:r,label:h.replace(/fa[lrsb]?:fa-[\w-]+/g,(function(t){return"<i class='".concat(t.replace(":"," "),"'></i>")})),labelStyle:e.replace("fill:","color:")},s=au(document.createElementNS("http://www.w3.org/2000/svg","foreignObject")),c=s.append("xhtml:div"),u=i.label,l=i.isNode?"nodeLabel":"edgeLabel",c.html('<span class="'+l+'" '+(i.labelStyle?'style="'+i.labelStyle+'"':"")+">"+u+"</span>"),(a=i.labelStyle)&&c.attr("style",a),c.style("display","inline-block"),c.style("white-space","nowrap"),c.attr("xmlns","http://www.w3.org/1999/xhtml"),s.node();var f=document.createElementNS("http://www.w3.org/2000/svg","text");f.setAttribute("style",e.replace("color:","fill:"));var d=[];d="string"==typeof h?h.split(/\\n|\n|<br\s*\/?>/gi):Array.isArray(h)?h:[];for(var p=0;p<d.length;p++){var y=document.createElementNS("http://www.w3.org/2000/svg","tspan");y.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),y.setAttribute("dy","1em"),y.setAttribute("x","0"),n?y.setAttribute("class","title-row"):y.setAttribute("class","row"),y.textContent=d[p].trim(),f.appendChild(y)}return f};var Hb=function(t,e,n,r){var i;i=n||"node default";var a=t.insert("g").attr("class",i).attr("id",e.domId||e.id),o=a.insert("g").attr("class","label").attr("style",e.labelStyle),s="string"==typeof e.labelText?e.labelText:e.labelText[0],c=o.node().appendChild(qb(Fm(iC(s),Jv()),e.labelStyle,!1,r)),u=c.getBBox();if(zm(Jv().flowchart.htmlLabels)){var l=c.children[0],h=au(c);u=l.getBoundingClientRect(),h.attr("width",u.width),h.attr("height",u.height)}var f=e.padding/2;return o.attr("transform","translate("+-u.width/2+", "+-u.height/2+")"),{shapeSvg:a,bbox:u,halfPadding:f,label:o}},$b=function(t,e){var n=e.node().getBBox();t.width=n.width,t.height=n.height};function Wb(t,e,n,r){return t.insert("polygon",":first-child").attr("points",r.map((function(t){return t.x+","+t.y})).join(" ")).attr("class","label-container").attr("transform","translate("+-e/2+","+n/2+")")}var Vb={},Gb={},Xb={},Zb=function(t,e){return o.trace("In isDecendant",e," ",t," = ",Gb[e].indexOf(t)>=0),Gb[e].indexOf(t)>=0},Qb=function t(e,n,r,i){o.warn("Copying children of ",e,"root",i,"data",n.node(e),i);var a=n.children(e)||[];e!==i&&a.push(e),o.warn("Copying (nodes) clusterId",e,"nodes",a),a.forEach((function(a){if(n.children(a).length>0)t(a,n,r,i);else{var s=n.node(a);o.info("cp ",a," to ",i," with parent ",e),r.setNode(a,s),i!==n.parent(a)&&(o.warn("Setting parent",a,n.parent(a)),r.setParent(a,n.parent(a))),e!==i&&a!==e?(o.debug("Setting parent",a,e),r.setParent(a,e)):(o.info("In copy ",e,"root",i,"data",n.node(e),i),o.debug("Not Setting parent for node=",a,"cluster!==rootId",e!==i,"node!==clusterId",a!==e));var c=n.edges(a);o.debug("Copying Edges",c),c.forEach((function(t){o.info("Edge",t);var a=n.edge(t.v,t.w,t.name);o.info("Edge data",a,i);try{!function(t,e){return o.info("Decendants of ",e," is ",Gb[e]),o.info("Edge is ",t),t.v!==e&&t.w!==e&&(Gb[e]?(o.info("Here "),Gb[e].indexOf(t.v)>=0||!!Zb(t.v,e)||!!Zb(t.w,e)||Gb[e].indexOf(t.w)>=0):(o.debug("Tilt, ",e,",not in decendants"),!1))}(t,i)?o.info("Skipping copy of edge ",t.v,"--\x3e",t.w," rootId: ",i," clusterId:",e):(o.info("Copying as ",t.v,t.w,a,t.name),r.setEdge(t.v,t.w,a,t.name),o.info("newGraph edges ",r.edges(),r.edge(r.edges()[0])))}catch(t){o.error(t)}}))}o.debug("Removing node",a),n.removeNode(a)}))},Kb=function t(e,n){for(var r=n.children(e),i=[].concat(r),a=0;a<r.length;a++)Xb[r[a]]=e,i=i.concat(t(r[a],n));return i},Jb=function t(e,n){o.trace("Searching",e);var r=n.children(e);if(o.trace("Searching children of id ",e,r),r.length<1)return o.trace("This is a valid node",e),e;for(var i=0;i<r.length;i++){var a=t(r[i],n);if(a)return o.trace("Found replacement for",e," => ",a),a}},t_=function(t){return Vb[t]&&Vb[t].externalConnections&&Vb[t]?Vb[t].id:t},e_=function(t,e){!t||e>10?o.debug("Opting out, no graph "):(o.debug("Opting in, graph "),t.nodes().forEach((function(e){t.children(e).length>0&&(o.warn("Cluster identified",e," Replacement id in edges: ",Jb(e,t)),Gb[e]=Kb(e,t),Vb[e]={id:Jb(e,t),clusterData:t.node(e)})})),t.nodes().forEach((function(e){var n=t.children(e),r=t.edges();n.length>0?(o.debug("Cluster identified",e,Gb),r.forEach((function(t){t.v!==e&&t.w!==e&&Zb(t.v,e)^Zb(t.w,e)&&(o.warn("Edge: ",t," leaves cluster ",e),o.warn("Decendants of XXX ",e,": ",Gb[e]),Vb[e].externalConnections=!0)}))):o.debug("Not a cluster ",e,Gb)})),t.edges().forEach((function(e){var n=t.edge(e);o.warn("Edge "+e.v+" -> "+e.w+": "+JSON.stringify(e)),o.warn("Edge "+e.v+" -> "+e.w+": "+JSON.stringify(t.edge(e)));var r=e.v,i=e.w;o.warn("Fix XXX",Vb,"ids:",e.v,e.w,"Translateing: ",Vb[e.v]," --- ",Vb[e.w]),(Vb[e.v]||Vb[e.w])&&(o.warn("Fixing and trixing - removing XXX",e.v,e.w,e.name),r=t_(e.v),i=t_(e.w),t.removeEdge(e.v,e.w,e.name),r!==e.v&&(n.fromCluster=e.v),i!==e.w&&(n.toCluster=e.w),o.warn("Fix Replacing with XXX",r,i,e.name),t.setEdge(r,i,n,e.name))})),o.warn("Adjusted Graph",kb().json.write(t)),n_(t,0),o.trace(Vb))},n_=function t(e,n){if(o.warn("extractor - ",n,kb().json.write(e),e.children("D")),n>10)o.error("Bailing out");else{for(var r=e.nodes(),i=!1,a=0;a<r.length;a++){var s=r[a],c=e.children(s);i=i||c.length>0}if(i){o.debug("Nodes = ",r,n);for(var u=0;u<r.length;u++){var l=r[u];if(o.debug("Extracting node",l,Vb,Vb[l]&&!Vb[l].externalConnections,!e.parent(l),e.node(l),e.children("D")," Depth ",n),Vb[l])if(!Vb[l].externalConnections&&e.children(l)&&e.children(l).length>0){o.warn("Cluster without external connections, without a parent and with children",l,n);var h="TB"===e.graph().rankdir?"LR":"TB";Vb[l]&&Vb[l].clusterData&&Vb[l].clusterData.dir&&(h=Vb[l].clusterData.dir,o.warn("Fixing dir",Vb[l].clusterData.dir,h));var f=new(kb().Graph)({multigraph:!0,compound:!0}).setGraph({rankdir:h,nodesep:50,ranksep:50,marginx:8,marginy:8}).setDefaultEdgeLabel((function(){return{}}));o.warn("Old graph before copy",kb().json.write(e)),Qb(l,e,f,l),e.setNode(l,{clusterNode:!0,id:l,clusterData:Vb[l].clusterData,labelText:Vb[l].labelText,graph:f}),o.warn("New graph after copy node: (",l,")",kb().json.write(f)),o.debug("Old graph after copy",kb().json.write(e))}else o.warn("Cluster ** ",l," **not meeting the criteria !externalConnections:",!Vb[l].externalConnections," no parent: ",!e.parent(l)," children ",e.children(l)&&e.children(l).length>0,e.children("D"),n),o.debug(Vb);else o.debug("Not a cluster",l,n)}r=e.nodes(),o.warn("New list of nodes",r);for(var d=0;d<r.length;d++){var p=r[d],y=e.node(p);o.warn(" Now next level",p,y),y.clusterNode&&t(y.graph,n+1)}}else o.debug("Done, no node has children",e.nodes())}},r_=function t(e,n){if(0===n.length)return[];var r=Object.assign(n);return n.forEach((function(n){var i=e.children(n),a=t(e,i);r=r.concat(a)})),r},i_=function(t){return r_(t,t.children())},a_=n(3841);const o_=function(t,e,n,r){var i=t.x,a=t.y,o=i-r.x,s=a-r.y,c=Math.sqrt(e*e*s*s+n*n*o*o),u=Math.abs(e*n*o/c);r.x<i&&(u=-u);var l=Math.abs(e*n*s/c);return r.y<a&&(l=-l),{x:i+u,y:a+l}};function s_(t,e){return t*e>0}const c_=function(t,e,n,r){var i,a,o,s,c,u,l,h,f,d,p,y,g;if(i=e.y-t.y,o=t.x-e.x,c=e.x*t.y-t.x*e.y,f=i*n.x+o*n.y+c,d=i*r.x+o*r.y+c,!(0!==f&&0!==d&&s_(f,d)||(a=r.y-n.y,s=n.x-r.x,u=r.x*n.y-n.x*r.y,l=a*t.x+s*t.y+u,h=a*e.x+s*e.y+u,0!==l&&0!==h&&s_(l,h)||0==(p=i*s-a*o))))return y=Math.abs(p/2),{x:(g=o*u-s*c)<0?(g-y)/p:(g+y)/p,y:(g=a*c-i*u)<0?(g-y)/p:(g+y)/p}},u_=function(t,e){var n,r,i=t.x,a=t.y,o=e.x-i,s=e.y-a,c=t.width/2,u=t.height/2;return Math.abs(s)*c>Math.abs(o)*u?(s<0&&(u=-u),n=0===s?0:u*o/s,r=u):(o<0&&(c=-c),n=c,r=0===o?0:c*s/o),{x:i+n,y:a+r}},l_=(n.n(a_)(),function(t,e,n){return o_(t,e,e,n)}),h_=function(t,e,n){var r=t.x,i=t.y,a=[],o=Number.POSITIVE_INFINITY,s=Number.POSITIVE_INFINITY;"function"==typeof e.forEach?e.forEach((function(t){o=Math.min(o,t.x),s=Math.min(s,t.y)})):(o=Math.min(o,e.x),s=Math.min(s,e.y));for(var c=r-t.width/2-o,u=i-t.height/2-s,l=0;l<e.length;l++){var h=e[l],f=e[l<e.length-1?l+1:0],d=c_(t,n,{x:c+h.x,y:u+h.y},{x:c+f.x,y:u+f.y});d&&a.push(d)}return a.length?(a.length>1&&a.sort((function(t,e){var r=t.x-n.x,i=t.y-n.y,a=Math.sqrt(r*r+i*i),o=e.x-n.x,s=e.y-n.y,c=Math.sqrt(o*o+s*s);return a<c?-1:a===c?0:1})),a[0]):t},f_=u_;function d_(t){return d_="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},d_(t)}var p_=function(t,e,n){var r=t.insert("g").attr("class","node default").attr("id",e.domId||e.id),i=70,a=10;"LR"===n&&(i=10,a=70);var o=r.append("rect").attr("x",-1*i/2).attr("y",-1*a/2).attr("width",i).attr("height",a).attr("class","fork-join");return $b(e,o),e.height=e.height+e.padding/2,e.width=e.width+e.padding/2,e.intersect=function(t){return f_(e,t)},r},y_={question:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.width+e.padding+(i.height+e.padding),s=[{x:a/2,y:0},{x:a,y:-a/2},{x:a/2,y:-a},{x:0,y:-a/2}];o.info("Question main (Circle)");var c=Wb(r,a,a,s);return c.attr("style",e.style),$b(e,c),e.intersect=function(t){return o.warn("Intersect called"),h_(e,s,t)},r},rect:function(t,e){var n=Hb(t,e,"node "+e.classes,!0),r=n.shapeSvg,i=n.bbox,a=n.halfPadding;o.trace("Classes = ",e.classes);var s=r.insert("rect",":first-child"),c=i.width+e.padding,u=i.height+e.padding;if(s.attr("class","basic label-container").attr("style",e.style).attr("rx",e.rx).attr("ry",e.ry).attr("x",-i.width/2-a).attr("y",-i.height/2-a).attr("width",c).attr("height",u),e.props){var l=new Set(Object.keys(e.props));e.props.borders&&(function(t,e,n,r){var i=[],a=function(t){i.push(t),i.push(0)},s=function(t){i.push(0),i.push(t)};e.includes("t")?(o.debug("add top border"),a(n)):s(n),e.includes("r")?(o.debug("add right border"),a(r)):s(r),e.includes("b")?(o.debug("add bottom border"),a(n)):s(n),e.includes("l")?(o.debug("add left border"),a(r)):s(r),t.attr("stroke-dasharray",i.join(" "))}(s,e.props.borders,c,u),l.delete("borders")),l.forEach((function(t){o.warn("Unknown node property ".concat(t))}))}return $b(e,s),e.intersect=function(t){return f_(e,t)},r},rectWithTitle:function(t,e){var n;n=e.classes?"node "+e.classes:"node default";var r,i=t.insert("g").attr("class",n).attr("id",e.domId||e.id),a=i.insert("rect",":first-child"),s=i.insert("line"),c=i.insert("g").attr("class","label"),u=e.labelText.flat?e.labelText.flat():e.labelText;r="object"===d_(u)?u[0]:u,o.info("Label text abc79",r,u,"object"===d_(u));var l=c.node().appendChild(qb(r,e.labelStyle,!0,!0)),h={width:0,height:0};if(zm(Jv().flowchart.htmlLabels)){var f=l.children[0],d=au(l);h=f.getBoundingClientRect(),d.attr("width",h.width),d.attr("height",h.height)}o.info("Text 2",u);var p=u.slice(1,u.length),y=l.getBBox(),g=c.node().appendChild(qb(p.join?p.join("<br/>"):p,e.labelStyle,!0,!0));if(zm(Jv().flowchart.htmlLabels)){var m=g.children[0],v=au(g);h=m.getBoundingClientRect(),v.attr("width",h.width),v.attr("height",h.height)}var b=e.padding/2;return au(g).attr("transform","translate( "+(h.width>y.width?0:(y.width-h.width)/2)+", "+(y.height+b+5)+")"),au(l).attr("transform","translate( "+(h.width<y.width?0:-(y.width-h.width)/2)+", 0)"),h=c.node().getBBox(),c.attr("transform","translate("+-h.width/2+", "+(-h.height/2-b+3)+")"),a.attr("class","outer title-state").attr("x",-h.width/2-b).attr("y",-h.height/2-b).attr("width",h.width+e.padding).attr("height",h.height+e.padding),s.attr("class","divider").attr("x1",-h.width/2-b).attr("x2",h.width/2+b).attr("y1",-h.height/2-b+y.height+b).attr("y2",-h.height/2-b+y.height+b),$b(e,a),e.intersect=function(t){return f_(e,t)},i},choice:function(t,e){var n=t.insert("g").attr("class","node default").attr("id",e.domId||e.id);return n.insert("polygon",":first-child").attr("points",[{x:0,y:14},{x:14,y:0},{x:0,y:-14},{x:-14,y:0}].map((function(t){return t.x+","+t.y})).join(" ")).attr("class","state-start").attr("r",7).attr("width",28).attr("height",28),e.width=28,e.height=28,e.intersect=function(t){return l_(e,14,t)},n},circle:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=n.halfPadding,s=r.insert("circle",":first-child");return s.attr("style",e.style).attr("rx",e.rx).attr("ry",e.ry).attr("r",i.width/2+a).attr("width",i.width+e.padding).attr("height",i.height+e.padding),o.info("Circle main"),$b(e,s),e.intersect=function(t){return o.info("Circle intersect",e,i.width/2+a,t),l_(e,i.width/2+a,t)},r},stadium:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.height+e.padding,o=i.width+a/4+e.padding,s=r.insert("rect",":first-child").attr("style",e.style).attr("rx",a/2).attr("ry",a/2).attr("x",-o/2).attr("y",-a/2).attr("width",o).attr("height",a);return $b(e,s),e.intersect=function(t){return f_(e,t)},r},hexagon:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.height+e.padding,o=a/4,s=i.width+2*o+e.padding,c=[{x:o,y:0},{x:s-o,y:0},{x:s,y:-a/2},{x:s-o,y:-a},{x:o,y:-a},{x:0,y:-a/2}],u=Wb(r,s,a,c);return u.attr("style",e.style),$b(e,u),e.intersect=function(t){return h_(e,c,t)},r},rect_left_inv_arrow:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.width+e.padding,o=i.height+e.padding,s=[{x:-o/2,y:0},{x:a,y:0},{x:a,y:-o},{x:-o/2,y:-o},{x:0,y:-o/2}];return Wb(r,a,o,s).attr("style",e.style),e.width=a+o,e.height=o,e.intersect=function(t){return h_(e,s,t)},r},lean_right:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.width+e.padding,o=i.height+e.padding,s=[{x:-2*o/6,y:0},{x:a-o/6,y:0},{x:a+2*o/6,y:-o},{x:o/6,y:-o}],c=Wb(r,a,o,s);return c.attr("style",e.style),$b(e,c),e.intersect=function(t){return h_(e,s,t)},r},lean_left:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.width+e.padding,o=i.height+e.padding,s=[{x:2*o/6,y:0},{x:a+o/6,y:0},{x:a-2*o/6,y:-o},{x:-o/6,y:-o}],c=Wb(r,a,o,s);return c.attr("style",e.style),$b(e,c),e.intersect=function(t){return h_(e,s,t)},r},trapezoid:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.width+e.padding,o=i.height+e.padding,s=[{x:-2*o/6,y:0},{x:a+2*o/6,y:0},{x:a-o/6,y:-o},{x:o/6,y:-o}],c=Wb(r,a,o,s);return c.attr("style",e.style),$b(e,c),e.intersect=function(t){return h_(e,s,t)},r},inv_trapezoid:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.width+e.padding,o=i.height+e.padding,s=[{x:o/6,y:0},{x:a-o/6,y:0},{x:a+2*o/6,y:-o},{x:-2*o/6,y:-o}],c=Wb(r,a,o,s);return c.attr("style",e.style),$b(e,c),e.intersect=function(t){return h_(e,s,t)},r},rect_right_inv_arrow:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.width+e.padding,o=i.height+e.padding,s=[{x:0,y:0},{x:a+o/2,y:0},{x:a,y:-o/2},{x:a+o/2,y:-o},{x:0,y:-o}],c=Wb(r,a,o,s);return c.attr("style",e.style),$b(e,c),e.intersect=function(t){return h_(e,s,t)},r},cylinder:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.width+e.padding,o=a/2,s=o/(2.5+a/50),c=i.height+s+e.padding,u="M 0,"+s+" a "+o+","+s+" 0,0,0 "+a+" 0 a "+o+","+s+" 0,0,0 "+-a+" 0 l 0,"+c+" a "+o+","+s+" 0,0,0 "+a+" 0 l 0,"+-c,l=r.attr("label-offset-y",s).insert("path",":first-child").attr("style",e.style).attr("d",u).attr("transform","translate("+-a/2+","+-(c/2+s)+")");return $b(e,l),e.intersect=function(t){var n=f_(e,t),r=n.x-e.x;if(0!=o&&(Math.abs(r)<e.width/2||Math.abs(r)==e.width/2&&Math.abs(n.y-e.y)>e.height/2-s)){var i=s*s*(1-r*r/(o*o));0!=i&&(i=Math.sqrt(i)),i=s-i,t.y-e.y>0&&(i=-i),n.y+=i}return n},r},start:function(t,e){var n=t.insert("g").attr("class","node default").attr("id",e.domId||e.id),r=n.insert("circle",":first-child");return r.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),$b(e,r),e.intersect=function(t){return l_(e,7,t)},n},end:function(t,e){var n=t.insert("g").attr("class","node default").attr("id",e.domId||e.id),r=n.insert("circle",":first-child"),i=n.insert("circle",":first-child");return i.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),r.attr("class","state-end").attr("r",5).attr("width",10).attr("height",10),$b(e,i),e.intersect=function(t){return l_(e,7,t)},n},note:function(t,e){var n=Hb(t,e,"node "+e.classes,!0),r=n.shapeSvg,i=n.bbox,a=n.halfPadding;o.info("Classes = ",e.classes);var s=r.insert("rect",":first-child");return s.attr("rx",e.rx).attr("ry",e.ry).attr("x",-i.width/2-a).attr("y",-i.height/2-a).attr("width",i.width+e.padding).attr("height",i.height+e.padding),$b(e,s),e.intersect=function(t){return f_(e,t)},r},subroutine:function(t,e){var n=Hb(t,e,void 0,!0),r=n.shapeSvg,i=n.bbox,a=i.width+e.padding,o=i.height+e.padding,s=[{x:0,y:0},{x:a,y:0},{x:a,y:-o},{x:0,y:-o},{x:0,y:0},{x:-8,y:0},{x:a+8,y:0},{x:a+8,y:-o},{x:-8,y:-o},{x:-8,y:0}],c=Wb(r,a,o,s);return c.attr("style",e.style),$b(e,c),e.intersect=function(t){return h_(e,s,t)},r},fork:p_,join:p_,class_box:function(t,e){var n,r=e.padding/2;n=e.classes?"node "+e.classes:"node default";var i=t.insert("g").attr("class",n).attr("id",e.domId||e.id),a=i.insert("rect",":first-child"),o=i.insert("line"),s=i.insert("line"),c=0,u=4,l=i.insert("g").attr("class","label"),h=0,f=e.classData.annotations&&e.classData.annotations[0],d=e.classData.annotations[0]?"«"+e.classData.annotations[0]+"»":"",p=l.node().appendChild(qb(d,e.labelStyle,!0,!0)),y=p.getBBox();if(zm(Jv().flowchart.htmlLabels)){var g=p.children[0],m=au(p);y=g.getBoundingClientRect(),m.attr("width",y.width),m.attr("height",y.height)}e.classData.annotations[0]&&(u+=y.height+4,c+=y.width);var v=e.classData.id;void 0!==e.classData.type&&""!==e.classData.type&&(Jv().flowchart.htmlLabels?v+="&lt;"+e.classData.type+"&gt;":v+="<"+e.classData.type+">");var b=l.node().appendChild(qb(v,e.labelStyle,!0,!0));au(b).attr("class","classTitle");var _=b.getBBox();if(zm(Jv().flowchart.htmlLabels)){var x=b.children[0],w=au(b);_=x.getBoundingClientRect(),w.attr("width",_.width),w.attr("height",_.height)}u+=_.height+4,_.width>c&&(c=_.width);var k=[];e.classData.members.forEach((function(t){var n=Sb(t),r=n.displayText;Jv().flowchart.htmlLabels&&(r=r.replace(/</g,"&lt;").replace(/>/g,"&gt;"));var i=l.node().appendChild(qb(r,n.cssStyle?n.cssStyle:e.labelStyle,!0,!0)),a=i.getBBox();if(zm(Jv().flowchart.htmlLabels)){var o=i.children[0],s=au(i);a=o.getBoundingClientRect(),s.attr("width",a.width),s.attr("height",a.height)}a.width>c&&(c=a.width),u+=a.height+4,k.push(i)})),u+=8;var T=[];if(e.classData.methods.forEach((function(t){var n=Sb(t),r=n.displayText;Jv().flowchart.htmlLabels&&(r=r.replace(/</g,"&lt;").replace(/>/g,"&gt;"));var i=l.node().appendChild(qb(r,n.cssStyle?n.cssStyle:e.labelStyle,!0,!0)),a=i.getBBox();if(zm(Jv().flowchart.htmlLabels)){var o=i.children[0],s=au(i);a=o.getBoundingClientRect(),s.attr("width",a.width),s.attr("height",a.height)}a.width>c&&(c=a.width),u+=a.height+4,T.push(i)})),u+=8,f){var E=(c-y.width)/2;au(p).attr("transform","translate( "+(-1*c/2+E)+", "+-1*u/2+")"),h=y.height+4}var C=(c-_.width)/2;return au(b).attr("transform","translate( "+(-1*c/2+C)+", "+(-1*u/2+h)+")"),h+=_.height+4,o.attr("class","divider").attr("x1",-c/2-r).attr("x2",c/2+r).attr("y1",-u/2-r+8+h).attr("y2",-u/2-r+8+h),h+=8,k.forEach((function(t){au(t).attr("transform","translate( "+-c/2+", "+(-1*u/2+h+4)+")"),h+=_.height+4})),h+=8,s.attr("class","divider").attr("x1",-c/2-r).attr("x2",c/2+r).attr("y1",-u/2-r+8+h).attr("y2",-u/2-r+8+h),h+=8,T.forEach((function(t){au(t).attr("transform","translate( "+-c/2+", "+(-1*u/2+h)+")"),h+=_.height+4})),a.attr("class","outer title-state").attr("x",-c/2-r).attr("y",-u/2-r).attr("width",c+e.padding).attr("height",u+e.padding),$b(e,a),e.intersect=function(t){return f_(e,t)},i}},g_={},m_=function(t){var e=g_[t.id];o.trace("Transforming node",t.diff,t,"translate("+(t.x-t.width/2-5)+", "+t.width/2+")");var n=t.diff||0;return t.clusterNode?e.attr("transform","translate("+(t.x+n-t.width/2)+", "+(t.y-t.height/2-8)+")"):e.attr("transform","translate("+t.x+", "+t.y+")"),n},v_={rect:function(t,e){o.trace("Creating subgraph rect for ",e.id,e);var n=t.insert("g").attr("class","cluster"+(e.class?" "+e.class:"")).attr("id",e.id),r=n.insert("rect",":first-child"),i=n.insert("g").attr("class","cluster-label"),a=i.node().appendChild(qb(e.labelText,e.labelStyle,void 0,!0)),s=a.getBBox();if(zm(Jv().flowchart.htmlLabels)){var c=a.children[0],u=au(a);s=c.getBoundingClientRect(),u.attr("width",s.width),u.attr("height",s.height)}var l=0*e.padding,h=l/2,f=e.width<=s.width+l?s.width+l:e.width;e.width<=s.width+l?e.diff=(s.width-e.width)/2:e.diff=-e.padding/2,o.trace("Data ",e,JSON.stringify(e)),r.attr("style",e.style).attr("rx",e.rx).attr("ry",e.ry).attr("x",e.x-f/2).attr("y",e.y-e.height/2-h).attr("width",f).attr("height",e.height+l),i.attr("transform","translate("+(e.x-s.width/2)+", "+(e.y-e.height/2+e.padding/3)+")");var d=r.node().getBBox();return e.width=d.width,e.height=d.height,e.intersect=function(t){return u_(e,t)},n},roundedWithTitle:function(t,e){var n=t.insert("g").attr("class",e.classes).attr("id",e.id),r=n.insert("rect",":first-child"),i=n.insert("g").attr("class","cluster-label"),a=n.append("rect"),o=i.node().appendChild(qb(e.labelText,e.labelStyle,void 0,!0)),s=o.getBBox();if(zm(Jv().flowchart.htmlLabels)){var c=o.children[0],u=au(o);s=c.getBoundingClientRect(),u.attr("width",s.width),u.attr("height",s.height)}s=o.getBBox();var l=0*e.padding,h=l/2,f=e.width<=s.width+e.padding?s.width+e.padding:e.width;e.width<=s.width+e.padding?e.diff=(s.width+0*e.padding-e.width)/2:e.diff=-e.padding/2,r.attr("class","outer").attr("x",e.x-f/2-h).attr("y",e.y-e.height/2-h).attr("width",f+l).attr("height",e.height+l),a.attr("class","inner").attr("x",e.x-f/2-h).attr("y",e.y-e.height/2-h+s.height-1).attr("width",f+l).attr("height",e.height+l-s.height-3),i.attr("transform","translate("+(e.x-s.width/2)+", "+(e.y-e.height/2-e.padding/3+(zm(Jv().flowchart.htmlLabels)?5:3))+")");var d=r.node().getBBox();return e.height=d.height,e.intersect=function(t){return u_(e,t)},n},noteGroup:function(t,e){var n=t.insert("g").attr("class","note-cluster").attr("id",e.id),r=n.insert("rect",":first-child"),i=0*e.padding,a=i/2;r.attr("rx",e.rx).attr("ry",e.ry).attr("x",e.x-e.width/2-a).attr("y",e.y-e.height/2-a).attr("width",e.width+i).attr("height",e.height+i).attr("fill","none");var o=r.node().getBBox();return e.width=o.width,e.height=o.height,e.intersect=function(t){return u_(e,t)},n},divider:function(t,e){var n=t.insert("g").attr("class",e.classes).attr("id",e.id),r=n.insert("rect",":first-child"),i=0*e.padding,a=i/2;r.attr("class","divider").attr("x",e.x-e.width/2-a).attr("y",e.y-e.height/2).attr("width",e.width+i).attr("height",e.height+i);var o=r.node().getBBox();return e.width=o.width,e.height=o.height,e.diff=-e.padding/2,e.intersect=function(t){return u_(e,t)},n}},b_={},__={},x_={},w_=function(t,e){var n=qb(e.label,e.labelStyle),r=t.insert("g").attr("class","edgeLabel"),i=r.insert("g").attr("class","label");i.node().appendChild(n);var a,o=n.getBBox();if(zm(Jv().flowchart.htmlLabels)){var s=n.children[0],c=au(n);o=s.getBoundingClientRect(),c.attr("width",o.width),c.attr("height",o.height)}if(i.attr("transform","translate("+-o.width/2+", "+-o.height/2+")"),__[e.id]=r,e.width=o.width,e.height=o.height,e.startLabelLeft){var u=qb(e.startLabelLeft,e.labelStyle),l=t.insert("g").attr("class","edgeTerminals"),h=l.insert("g").attr("class","inner");a=h.node().appendChild(u);var f=u.getBBox();h.attr("transform","translate("+-f.width/2+", "+-f.height/2+")"),x_[e.id]||(x_[e.id]={}),x_[e.id].startLeft=l,k_(a,e.startLabelLeft)}if(e.startLabelRight){var d=qb(e.startLabelRight,e.labelStyle),p=t.insert("g").attr("class","edgeTerminals"),y=p.insert("g").attr("class","inner");a=p.node().appendChild(d),y.node().appendChild(d);var g=d.getBBox();y.attr("transform","translate("+-g.width/2+", "+-g.height/2+")"),x_[e.id]||(x_[e.id]={}),x_[e.id].startRight=p,k_(a,e.startLabelRight)}if(e.endLabelLeft){var m=qb(e.endLabelLeft,e.labelStyle),v=t.insert("g").attr("class","edgeTerminals"),b=v.insert("g").attr("class","inner");a=b.node().appendChild(m);var _=m.getBBox();b.attr("transform","translate("+-_.width/2+", "+-_.height/2+")"),v.node().appendChild(m),x_[e.id]||(x_[e.id]={}),x_[e.id].endLeft=v,k_(a,e.endLabelLeft)}if(e.endLabelRight){var x=qb(e.endLabelRight,e.labelStyle),w=t.insert("g").attr("class","edgeTerminals"),k=w.insert("g").attr("class","inner");a=k.node().appendChild(x);var T=x.getBBox();k.attr("transform","translate("+-T.width/2+", "+-T.height/2+")"),w.node().appendChild(x),x_[e.id]||(x_[e.id]={}),x_[e.id].endRight=w,k_(a,e.endLabelRight)}};function k_(t,e){Jv().flowchart.htmlLabels&&t&&(t.style.width=9*e.length+"px",t.style.height="12px")}var T_=function(t,e){o.info("Moving label abc78 ",t.id,t.label,__[t.id]);var n=e.updatedPath?e.updatedPath:e.originalPath;if(t.label){var r=__[t.id],i=t.x,a=t.y;if(n){var s=Hv.calcLabelPosition(n);o.info("Moving label from (",i,",",a,") to (",s.x,",",s.y,") abc78")}r.attr("transform","translate("+i+", "+a+")")}if(t.startLabelLeft){var c=x_[t.id].startLeft,u=t.x,l=t.y;if(n){var h=Hv.calcTerminalLabelPosition(t.arrowTypeStart?10:0,"start_left",n);u=h.x,l=h.y}c.attr("transform","translate("+u+", "+l+")")}if(t.startLabelRight){var f=x_[t.id].startRight,d=t.x,p=t.y;if(n){var y=Hv.calcTerminalLabelPosition(t.arrowTypeStart?10:0,"start_right",n);d=y.x,p=y.y}f.attr("transform","translate("+d+", "+p+")")}if(t.endLabelLeft){var g=x_[t.id].endLeft,m=t.x,v=t.y;if(n){var b=Hv.calcTerminalLabelPosition(t.arrowTypeEnd?10:0,"end_left",n);m=b.x,v=b.y}g.attr("transform","translate("+m+", "+v+")")}if(t.endLabelRight){var _=x_[t.id].endRight,x=t.x,w=t.y;if(n){var k=Hv.calcTerminalLabelPosition(t.arrowTypeEnd?10:0,"end_right",n);x=k.x,w=k.y}_.attr("transform","translate("+x+", "+w+")")}},E_=function(t,e){o.warn("abc88 cutPathAtIntersect",t,e);var n=[],r=t[0],i=!1;return t.forEach((function(t){if(o.info("abc88 checking point",t,e),function(t,e){var n=t.x,r=t.y,i=Math.abs(e.x-n),a=Math.abs(e.y-r),o=t.width/2,s=t.height/2;return i>=o||a>=s}(e,t)||i)o.warn("abc88 outside",t,r),r=t,i||n.push(t);else{var a=function(t,e,n){o.warn("intersection calc abc89:\n  outsidePoint: ".concat(JSON.stringify(e),"\n  insidePoint : ").concat(JSON.stringify(n),"\n  node        : x:").concat(t.x," y:").concat(t.y," w:").concat(t.width," h:").concat(t.height));var r=t.x,i=t.y,a=Math.abs(r-n.x),s=t.width/2,c=n.x<e.x?s-a:s+a,u=t.height/2,l=Math.abs(e.y-n.y),h=Math.abs(e.x-n.x);if(Math.abs(i-e.y)*s>Math.abs(r-e.x)*u){var f=n.y<e.y?e.y-u-i:i-u-e.y;c=h*f/l;var d={x:n.x<e.x?n.x+c:n.x-h+c,y:n.y<e.y?n.y+l-f:n.y-l+f};return 0===c&&(d.x=e.x,d.y=e.y),0===h&&(d.x=e.x),0===l&&(d.y=e.y),o.warn("abc89 topp/bott calc, Q ".concat(l,", q ").concat(f,", R ").concat(h,", r ").concat(c),d),d}var p=l*(c=n.x<e.x?e.x-s-r:r-s-e.x)/h,y=n.x<e.x?n.x+h-c:n.x-h+c,g=n.y<e.y?n.y+p:n.y-p;return o.warn("sides calc abc89, Q ".concat(l,", q ").concat(p,", R ").concat(h,", r ").concat(c),{_x:y,_y:g}),0===c&&(y=e.x,g=e.y),0===h&&(y=e.x),0===l&&(g=e.y),{x:y,y:g}}(e,r,t);o.warn("abc88 inside",t,r,a),o.warn("abc88 intersection",a);var s=!1;n.forEach((function(t){s=s||t.x===a.x&&t.y===a.y})),n.find((function(t){return t.x===a.x&&t.y===a.y}))?o.warn("abc88 no intersect",a,n):n.push(a),i=!0}})),o.warn("abc88 returning points",n),n},C_=function t(e,n,r,i){o.info("Graph in recursive render: XXX",kb().json.write(n),i);var a=n.graph().rankdir;o.trace("Dir in recursive render - dir:",a);var s=e.insert("g").attr("class","root");n.nodes()?o.info("Recursive render XXX",n.nodes()):o.info("No nodes found for",n),n.edges().length>0&&o.trace("Recursive edges",n.edge(n.edges()[0]));var c=s.insert("g").attr("class","clusters"),u=s.insert("g").attr("class","edgePaths"),l=s.insert("g").attr("class","edgeLabels"),h=s.insert("g").attr("class","nodes");n.nodes().forEach((function(e){var s=n.node(e);if(void 0!==i){var c=JSON.parse(JSON.stringify(i.clusterData));o.info("Setting data for cluster XXX (",e,") ",c,i),n.setNode(i.id,c),n.parent(e)||(o.trace("Setting parent",e,i.id),n.setParent(e,i.id,c))}if(o.info("(Insert) Node XXX"+e+": "+JSON.stringify(n.node(e))),s&&s.clusterNode){o.info("Cluster identified",e,s.width,n.node(e));var u=t(h,s.graph,r,n.node(e)),l=u.elem;$b(s,l),s.diff=u.diff||0,o.info("Node bounds (abc123)",e,s,s.width,s.x,s.y),function(t,e){g_[e.id]=t}(l,s),o.warn("Recursive render complete ",l,s)}else n.children(e).length>0?(o.info("Cluster - the non recursive path XXX",e,s.id,s,n),o.info(Jb(s.id,n)),Vb[s.id]={id:Jb(s.id,n),node:s}):(o.info("Node - the non recursive path",e,s.id,s),function(t,e,n){var r,i;e.link?(r=t.insert("svg:a").attr("xlink:href",e.link).attr("target",e.linkTarget||"_blank"),i=y_[e.shape](r,e,n)):r=i=y_[e.shape](t,e,n),e.tooltip&&i.attr("title",e.tooltip),e.class&&i.attr("class","node default "+e.class),g_[e.id]=r,e.haveCallback&&g_[e.id].attr("class",g_[e.id].attr("class")+" clickable")}(h,n.node(e),a))})),n.edges().forEach((function(t){var e=n.edge(t.v,t.w,t.name);o.info("Edge "+t.v+" -> "+t.w+": "+JSON.stringify(t)),o.info("Edge "+t.v+" -> "+t.w+": ",t," ",JSON.stringify(n.edge(t))),o.info("Fix",Vb,"ids:",t.v,t.w,"Translateing: ",Vb[t.v],Vb[t.w]),w_(l,e)})),n.edges().forEach((function(t){o.info("Edge "+t.v+" -> "+t.w+": "+JSON.stringify(t))})),o.info("#############################################"),o.info("###                Layout                 ###"),o.info("#############################################"),o.info(n),xb().layout(n),o.info("Graph after layout:",kb().json.write(n));var f=0;return i_(n).forEach((function(t){var e=n.node(t);o.info("Position "+t+": "+JSON.stringify(n.node(t))),o.info("Position "+t+": ("+e.x,","+e.y,") width: ",e.width," height: ",e.height),e&&e.clusterNode?m_(e):n.children(t).length>0?(function(t,e){o.trace("Inserting cluster");var n=e.shape||"rect";b_[e.id]=v_[n](t,e)}(c,e),Vb[e.id].node=e):m_(e)})),n.edges().forEach((function(t){var e=n.edge(t);o.info("Edge "+t.v+" -> "+t.w+": "+JSON.stringify(e),e);var i=function(t,e,n,r,i,a){var s=n.points,c=!1,u=a.node(e.v),l=a.node(e.w);o.info("abc88 InsertEdge: ",n),l.intersect&&u.intersect&&((s=s.slice(1,n.points.length-1)).unshift(u.intersect(s[0])),o.info("Last point",s[s.length-1],l,l.intersect(s[s.length-1])),s.push(l.intersect(s[s.length-1]))),n.toCluster&&(o.info("to cluster abc88",r[n.toCluster]),s=E_(n.points,r[n.toCluster].node),c=!0),n.fromCluster&&(o.info("from cluster abc88",r[n.fromCluster]),s=E_(s.reverse(),r[n.fromCluster].node).reverse(),c=!0);var h,f=s.filter((function(t){return!Number.isNaN(t.y)}));h=("graph"===i||"flowchart"===i)&&n.curve||Vu;var d,p=zu().x((function(t){return t.x})).y((function(t){return t.y})).curve(h);switch(n.thickness){case"normal":d="edge-thickness-normal";break;case"thick":d="edge-thickness-thick";break;default:d=""}switch(n.pattern){case"solid":d+=" edge-pattern-solid";break;case"dotted":d+=" edge-pattern-dotted";break;case"dashed":d+=" edge-pattern-dashed"}var y=t.append("path").attr("d",p(f)).attr("id",n.id).attr("class"," "+d+(n.classes?" "+n.classes:"")).attr("style",n.style),g="";switch(Jv().state.arrowMarkerAbsolute&&(g=(g=(g=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search).replace(/\(/g,"\\(")).replace(/\)/g,"\\)")),o.info("arrowTypeStart",n.arrowTypeStart),o.info("arrowTypeEnd",n.arrowTypeEnd),n.arrowTypeStart){case"arrow_cross":y.attr("marker-start","url("+g+"#"+i+"-crossStart)");break;case"arrow_point":y.attr("marker-start","url("+g+"#"+i+"-pointStart)");break;case"arrow_barb":y.attr("marker-start","url("+g+"#"+i+"-barbStart)");break;case"arrow_circle":y.attr("marker-start","url("+g+"#"+i+"-circleStart)");break;case"aggregation":y.attr("marker-start","url("+g+"#"+i+"-aggregationStart)");break;case"extension":y.attr("marker-start","url("+g+"#"+i+"-extensionStart)");break;case"composition":y.attr("marker-start","url("+g+"#"+i+"-compositionStart)");break;case"dependency":y.attr("marker-start","url("+g+"#"+i+"-dependencyStart)")}switch(n.arrowTypeEnd){case"arrow_cross":y.attr("marker-end","url("+g+"#"+i+"-crossEnd)");break;case"arrow_point":y.attr("marker-end","url("+g+"#"+i+"-pointEnd)");break;case"arrow_barb":y.attr("marker-end","url("+g+"#"+i+"-barbEnd)");break;case"arrow_circle":y.attr("marker-end","url("+g+"#"+i+"-circleEnd)");break;case"aggregation":y.attr("marker-end","url("+g+"#"+i+"-aggregationEnd)");break;case"extension":y.attr("marker-end","url("+g+"#"+i+"-extensionEnd)");break;case"composition":y.attr("marker-end","url("+g+"#"+i+"-compositionEnd)");break;case"dependency":y.attr("marker-end","url("+g+"#"+i+"-dependencyEnd)")}var m={};return c&&(m.updatedPath=s),m.originalPath=n.points,m}(u,t,e,Vb,r,n);T_(e,i)})),n.nodes().forEach((function(t){var e=n.node(t);o.info(t,e.type,e.diff),"group"===e.type&&(f=e.diff)})),{elem:s,diff:f}},S_=function(t,e,n,r,i){zb(t,n,r,i),g_={},__={},x_={},b_={},Gb={},Xb={},Vb={},o.warn("Graph at first:",kb().json.write(e)),e_(e),o.warn("Graph after:",kb().json.write(e)),C_(t,e,r)};Tb.parser.yy=bb;var A_={dividerMargin:10,padding:5,textHeight:10};function M_(t){var e;switch(t){case 0:e="aggregation";break;case 1:e="extension";break;case 2:e="composition";break;case 3:e="dependency";break;default:e="none"}return e}var N_={},D_=[],O_="",B_=function(t){return void 0===N_[t]&&(N_[t]={attributes:[]},o.info("Added new entity :",t)),N_[t]};const L_={Cardinality:{ZERO_OR_ONE:"ZERO_OR_ONE",ZERO_OR_MORE:"ZERO_OR_MORE",ONE_OR_MORE:"ONE_OR_MORE",ONLY_ONE:"ONLY_ONE"},Identification:{NON_IDENTIFYING:"NON_IDENTIFYING",IDENTIFYING:"IDENTIFYING"},parseDirective:function(t,e,n){cC.parseDirective(this,t,e,n)},getConfig:function(){return Jv().er},addEntity:B_,addAttributes:function(t,e){var n,r=B_(t);for(n=e.length-1;n>=0;n--)r.attributes.push(e[n]),o.debug("Added attribute ",e[n].attributeName)},getEntities:function(){return N_},addRelationship:function(t,e,n,r){var i={entityA:t,roleA:e,entityB:n,relSpec:r};D_.push(i),o.debug("Added new relationship :",i)},getRelationships:function(){return D_},clear:function(){N_={},D_=[],O_=""},setTitle:function(t){O_=t},getTitle:function(){return O_}};var I_=n(5890),R_=n.n(I_),F_={ONLY_ONE_START:"ONLY_ONE_START",ONLY_ONE_END:"ONLY_ONE_END",ZERO_OR_ONE_START:"ZERO_OR_ONE_START",ZERO_OR_ONE_END:"ZERO_OR_ONE_END",ONE_OR_MORE_START:"ONE_OR_MORE_START",ONE_OR_MORE_END:"ONE_OR_MORE_END",ZERO_OR_MORE_START:"ZERO_OR_MORE_START",ZERO_OR_MORE_END:"ZERO_OR_MORE_END"};const P_=F_;var j_={},Y_=function(t){return(t.entityA+t.roleA+t.entityB).replace(/\s/g,"")},z_=0;const U_=function(t){for(var e=Object.keys(t),n=0;n<e.length;n++)j_[e[n]]=t[e[n]]},q_=function(t,e){o.info("Drawing ER diagram"),L_.clear();var n=R_().parser;n.yy=L_;try{n.parse(t)}catch(t){o.debug("Parsing failed")}var r,i=au("[id='".concat(e,"']"));(function(t,e){var n;t.append("defs").append("marker").attr("id",F_.ONLY_ONE_START).attr("refX",0).attr("refY",9).attr("markerWidth",18).attr("markerHeight",18).attr("orient","auto").append("path").attr("stroke",e.stroke).attr("fill","none").attr("d","M9,0 L9,18 M15,0 L15,18"),t.append("defs").append("marker").attr("id",F_.ONLY_ONE_END).attr("refX",18).attr("refY",9).attr("markerWidth",18).attr("markerHeight",18).attr("orient","auto").append("path").attr("stroke",e.stroke).attr("fill","none").attr("d","M3,0 L3,18 M9,0 L9,18"),(n=t.append("defs").append("marker").attr("id",F_.ZERO_OR_ONE_START).attr("refX",0).attr("refY",9).attr("markerWidth",30).attr("markerHeight",18).attr("orient","auto")).append("circle").attr("stroke",e.stroke).attr("fill","white").attr("cx",21).attr("cy",9).attr("r",6),n.append("path").attr("stroke",e.stroke).attr("fill","none").attr("d","M9,0 L9,18"),(n=t.append("defs").append("marker").attr("id",F_.ZERO_OR_ONE_END).attr("refX",30).attr("refY",9).attr("markerWidth",30).attr("markerHeight",18).attr("orient","auto")).append("circle").attr("stroke",e.stroke).attr("fill","white").attr("cx",9).attr("cy",9).attr("r",6),n.append("path").attr("stroke",e.stroke).attr("fill","none").attr("d","M21,0 L21,18"),t.append("defs").append("marker").attr("id",F_.ONE_OR_MORE_START).attr("refX",18).attr("refY",18).attr("markerWidth",45).attr("markerHeight",36).attr("orient","auto").append("path").attr("stroke",e.stroke).attr("fill","none").attr("d","M0,18 Q 18,0 36,18 Q 18,36 0,18 M42,9 L42,27"),t.append("defs").append("marker").attr("id",F_.ONE_OR_MORE_END).attr("refX",27).attr("refY",18).attr("markerWidth",45).attr("markerHeight",36).attr("orient","auto").append("path").attr("stroke",e.stroke).attr("fill","none").attr("d","M3,9 L3,27 M9,18 Q27,0 45,18 Q27,36 9,18"),(n=t.append("defs").append("marker").attr("id",F_.ZERO_OR_MORE_START).attr("refX",18).attr("refY",18).attr("markerWidth",57).attr("markerHeight",36).attr("orient","auto")).append("circle").attr("stroke",e.stroke).attr("fill","white").attr("cx",48).attr("cy",18).attr("r",6),n.append("path").attr("stroke",e.stroke).attr("fill","none").attr("d","M0,18 Q18,0 36,18 Q18,36 0,18"),(n=t.append("defs").append("marker").attr("id",F_.ZERO_OR_MORE_END).attr("refX",39).attr("refY",18).attr("markerWidth",57).attr("markerHeight",36).attr("orient","auto")).append("circle").attr("stroke",e.stroke).attr("fill","white").attr("cx",9).attr("cy",18).attr("r",6),n.append("path").attr("stroke",e.stroke).attr("fill","none").attr("d","M21,18 Q39,0 57,18 Q39,36 21,18")})(i,j_),r=new(kb().Graph)({multigraph:!0,directed:!0,compound:!1}).setGraph({rankdir:j_.layoutDirection,marginx:20,marginy:20,nodesep:100,edgesep:100,ranksep:100}).setDefaultEdgeLabel((function(){return{}}));var a=function(t,e,n){var r;return Object.keys(e).forEach((function(i){var a=t.append("g").attr("id",i);r=void 0===r?i:r;var o="entity-"+i,s=a.append("text").attr("class","er entityLabel").attr("id",o).attr("x",0).attr("y",0).attr("dominant-baseline","middle").attr("text-anchor","middle").attr("style","font-family: "+Jv().fontFamily+"; font-size: "+j_.fontSize+"px").text(i),c=function(t,e,n){var r=j_.entityPadding/3,i=j_.entityPadding/3,a=.85*j_.fontSize,o=e.node().getBBox(),s=[],c=!1,u=!1,l=0,h=0,f=0,d=0,p=o.height+2*r,y=1;n.forEach((function(t){void 0!==t.attributeKeyType&&(c=!0),void 0!==t.attributeComment&&(u=!0)})),n.forEach((function(n){var i="".concat(e.node().id,"-attr-").concat(y),o=0,g=t.append("text").attr("class","er entityLabel").attr("id","".concat(i,"-type")).attr("x",0).attr("y",0).attr("dominant-baseline","middle").attr("text-anchor","left").attr("style","font-family: "+Jv().fontFamily+"; font-size: "+a+"px").text(n.attributeType),m=t.append("text").attr("class","er entityLabel").attr("id","".concat(i,"-name")).attr("x",0).attr("y",0).attr("dominant-baseline","middle").attr("text-anchor","left").attr("style","font-family: "+Jv().fontFamily+"; font-size: "+a+"px").text(n.attributeName),v={};v.tn=g,v.nn=m;var b=g.node().getBBox(),_=m.node().getBBox();if(l=Math.max(l,b.width),h=Math.max(h,_.width),o=Math.max(b.height,_.height),c){var x=t.append("text").attr("class","er entityLabel").attr("id","".concat(i,"-key")).attr("x",0).attr("y",0).attr("dominant-baseline","middle").attr("text-anchor","left").attr("style","font-family: "+Jv().fontFamily+"; font-size: "+a+"px").text(n.attributeKeyType||"");v.kn=x;var w=x.node().getBBox();f=Math.max(f,w.width),o=Math.max(o,w.height)}if(u){var k=t.append("text").attr("class","er entityLabel").attr("id","".concat(i,"-comment")).attr("x",0).attr("y",0).attr("dominant-baseline","middle").attr("text-anchor","left").attr("style","font-family: "+Jv().fontFamily+"; font-size: "+a+"px").text(n.attributeComment||"");v.cn=k;var T=k.node().getBBox();d=Math.max(d,T.width),o=Math.max(o,T.height)}v.height=o,s.push(v),p+=o+2*r,y+=1}));var g=4;c&&(g+=2),u&&(g+=2);var m=l+h+f+d,v={width:Math.max(j_.minEntityWidth,Math.max(o.width+2*j_.entityPadding,m+i*g)),height:n.length>0?p:Math.max(j_.minEntityHeight,o.height+2*j_.entityPadding)};if(n.length>0){var b=Math.max(0,(v.width-m-i*g)/(g/2));e.attr("transform","translate("+v.width/2+","+(r+o.height/2)+")");var _=o.height+2*r,x="attributeBoxOdd";s.forEach((function(e){var n=_+r+e.height/2;e.tn.attr("transform","translate("+i+","+n+")");var a=t.insert("rect","#"+e.tn.node().id).attr("class","er ".concat(x)).attr("fill",j_.fill).attr("fill-opacity","100%").attr("stroke",j_.stroke).attr("x",0).attr("y",_).attr("width",l+2*i+b).attr("height",e.height+2*r),o=parseFloat(a.attr("x"))+parseFloat(a.attr("width"));e.nn.attr("transform","translate("+(o+i)+","+n+")");var s=t.insert("rect","#"+e.nn.node().id).attr("class","er ".concat(x)).attr("fill",j_.fill).attr("fill-opacity","100%").attr("stroke",j_.stroke).attr("x",o).attr("y",_).attr("width",h+2*i+b).attr("height",e.height+2*r),p=parseFloat(s.attr("x"))+parseFloat(s.attr("width"));if(c){e.kn.attr("transform","translate("+(p+i)+","+n+")");var y=t.insert("rect","#"+e.kn.node().id).attr("class","er ".concat(x)).attr("fill",j_.fill).attr("fill-opacity","100%").attr("stroke",j_.stroke).attr("x",p).attr("y",_).attr("width",f+2*i+b).attr("height",e.height+2*r);p=parseFloat(y.attr("x"))+parseFloat(y.attr("width"))}u&&(e.cn.attr("transform","translate("+(p+i)+","+n+")"),t.insert("rect","#"+e.cn.node().id).attr("class","er ".concat(x)).attr("fill",j_.fill).attr("fill-opacity","100%").attr("stroke",j_.stroke).attr("x",p).attr("y",_).attr("width",d+2*i+b).attr("height",e.height+2*r)),_+=e.height+2*r,x="attributeBoxOdd"==x?"attributeBoxEven":"attributeBoxOdd"}))}else v.height=Math.max(j_.minEntityHeight,p),e.attr("transform","translate("+v.width/2+","+v.height/2+")");return v}(a,s,e[i].attributes),u=c.width,l=c.height,h=a.insert("rect","#"+o).attr("class","er entityBox").attr("fill",j_.fill).attr("fill-opacity","100%").attr("stroke",j_.stroke).attr("x",0).attr("y",0).attr("width",u).attr("height",l).node().getBBox();n.setNode(i,{width:h.width,height:h.height,shape:"rect",id:i})})),r}(i,L_.getEntities(),r),s=function(t,e){return t.forEach((function(t){e.setEdge(t.entityA,t.entityB,{relationship:t},Y_(t))})),t}(L_.getRelationships(),r);xb().layout(r),function(t,e){e.nodes().forEach((function(n){void 0!==n&&void 0!==e.node(n)&&t.select("#"+n).attr("transform","translate("+(e.node(n).x-e.node(n).width/2)+","+(e.node(n).y-e.node(n).height/2)+" )")}))}(i,r),s.forEach((function(t){!function(t,e,n,r){z_++;var i=n.edge(e.entityA,e.entityB,Y_(e)),a=zu().x((function(t){return t.x})).y((function(t){return t.y})).curve(Vu),o=t.insert("path","#"+r).attr("class","er relationshipLine").attr("d",a(i.points)).attr("stroke",j_.stroke).attr("fill","none");e.relSpec.relType===L_.Identification.NON_IDENTIFYING&&o.attr("stroke-dasharray","8,8");var s="";switch(j_.arrowMarkerAbsolute&&(s=(s=(s=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search).replace(/\(/g,"\\(")).replace(/\)/g,"\\)")),e.relSpec.cardA){case L_.Cardinality.ZERO_OR_ONE:o.attr("marker-end","url("+s+"#"+P_.ZERO_OR_ONE_END+")");break;case L_.Cardinality.ZERO_OR_MORE:o.attr("marker-end","url("+s+"#"+P_.ZERO_OR_MORE_END+")");break;case L_.Cardinality.ONE_OR_MORE:o.attr("marker-end","url("+s+"#"+P_.ONE_OR_MORE_END+")");break;case L_.Cardinality.ONLY_ONE:o.attr("marker-end","url("+s+"#"+P_.ONLY_ONE_END+")")}switch(e.relSpec.cardB){case L_.Cardinality.ZERO_OR_ONE:o.attr("marker-start","url("+s+"#"+P_.ZERO_OR_ONE_START+")");break;case L_.Cardinality.ZERO_OR_MORE:o.attr("marker-start","url("+s+"#"+P_.ZERO_OR_MORE_START+")");break;case L_.Cardinality.ONE_OR_MORE:o.attr("marker-start","url("+s+"#"+P_.ONE_OR_MORE_START+")");break;case L_.Cardinality.ONLY_ONE:o.attr("marker-start","url("+s+"#"+P_.ONLY_ONE_START+")")}var c=o.node().getTotalLength(),u=o.node().getPointAtLength(.5*c),l="rel"+z_,h=t.append("text").attr("class","er relationshipLabel").attr("id",l).attr("x",u.x).attr("y",u.y).attr("text-anchor","middle").attr("dominant-baseline","middle").attr("style","font-family: "+Jv().fontFamily+"; font-size: "+j_.fontSize+"px").text(e.roleA).node().getBBox();t.insert("rect","#"+l).attr("class","er relationshipLabelBox").attr("x",u.x-h.width/2).attr("y",u.y-h.height/2).attr("width",h.width).attr("height",h.height).attr("fill","white").attr("fill-opacity","85%")}(i,t,r,a)}));var c=j_.diagramPadding,u=i.node().getBBox(),l=u.width+2*c,h=u.height+2*c;zv(i,h,l,j_.useMaxWidth),i.attr("viewBox","".concat(u.x-c," ").concat(u.y-c," ").concat(l," ").concat(h))};function H_(t){return H_="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},H_(t)}function $_(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}var W_,V_,G_="flowchart-",X_=0,Z_=Jv(),Q_={},K_=[],J_=[],tx=[],ex={},nx={},rx=0,ix=!0,ax=[],ox=function(t){for(var e=Object.keys(Q_),n=0;n<e.length;n++)if(Q_[e[n]].id===t)return Q_[e[n]].domId;return t},sx=function(t,e,n,r){var i={start:t,end:e,type:void 0,text:""};void 0!==(r=n.text)&&(i.text=Um.sanitizeText(r.trim(),Z_),'"'===i.text[0]&&'"'===i.text[i.text.length-1]&&(i.text=i.text.substring(1,i.text.length-1))),void 0!==n&&(i.type=n.type,i.stroke=n.stroke,i.length=n.length),K_.push(i)},cx=function(t,e){t.split(",").forEach((function(t){var n=t;void 0!==Q_[n]&&Q_[n].classes.push(e),void 0!==ex[n]&&ex[n].classes.push(e)}))},ux=function(t){var e=au(".mermaidTooltip");null===(e._groups||e)[0][0]&&(e=au("body").append("div").attr("class","mermaidTooltip").style("opacity",0)),au(t).select("svg").selectAll("g.node").on("mouseover",(function(){var t=au(this);if(null!==t.attr("title")){var n=this.getBoundingClientRect();e.transition().duration(200).style("opacity",".9"),e.html(t.attr("title")).style("left",window.scrollX+n.left+(n.right-n.left)/2+"px").style("top",window.scrollY+n.top-14+document.body.scrollTop+"px"),t.classed("hover",!0)}})).on("mouseout",(function(){e.transition().duration(500).style("opacity",0),au(this).classed("hover",!1)}))};ax.push(ux);var lx=function(t){for(var e=0;e<tx.length;e++)if(tx[e].id===t)return e;return-1},hx=-1,fx=[],dx=function t(e,n){var r=tx[n].nodes;if(!((hx+=1)>2e3)){if(fx[hx]=n,tx[n].id===e)return{result:!0,count:0};for(var i=0,a=1;i<r.length;){var o=lx(r[i]);if(o>=0){var s=t(e,o);if(s.result)return{result:!0,count:a+s.count};a+=s.count}i+=1}return{result:!1,count:a}}},px=function(t,e){var n=!1;return t.forEach((function(t){t.nodes.indexOf(e)>=0&&(n=!0)})),n},yx=function(t,e){var n=[];return t.nodes.forEach((function(r,i){px(e,r)||n.push(t.nodes[i])})),{nodes:n}};const gx={parseDirective:function(t,e,n){cC.parseDirective(this,t,e,n)},defaultConfig:function(){return Vv.flowchart},addVertex:function(t,e,n,r,i,a){var o,s=arguments.length>6&&void 0!==arguments[6]?arguments[6]:{},c=t;void 0!==c&&0!==c.trim().length&&(void 0===Q_[c]&&(Q_[c]={id:c,domId:G_+c+"-"+X_,styles:[],classes:[]}),X_++,void 0!==e?(Z_=Jv(),'"'===(o=Um.sanitizeText(e.trim(),Z_))[0]&&'"'===o[o.length-1]&&(o=o.substring(1,o.length-1)),Q_[c].text=o):void 0===Q_[c].text&&(Q_[c].text=t),void 0!==n&&(Q_[c].type=n),null!=r&&r.forEach((function(t){Q_[c].styles.push(t)})),null!=i&&i.forEach((function(t){Q_[c].classes.push(t)})),void 0!==a&&(Q_[c].dir=a),Q_[c].props=s)},lookUpDomId:ox,addLink:function(t,e,n,r){var i,a;for(i=0;i<t.length;i++)for(a=0;a<e.length;a++)sx(t[i],e[a],n,r)},updateLinkInterpolate:function(t,e){t.forEach((function(t){"default"===t?K_.defaultInterpolate=e:K_[t].interpolate=e}))},updateLink:function(t,e){t.forEach((function(t){"default"===t?K_.defaultStyle=e:(-1===Hv.isSubstringInArray("fill",e)&&e.push("fill:none"),K_[t].style=e)}))},addClass:function(t,e){void 0===J_[t]&&(J_[t]={id:t,styles:[],textStyles:[]}),null!=e&&e.forEach((function(e){if(e.match("color")){var n=e.replace("fill","bgFill").replace("color","fill");J_[t].textStyles.push(n)}J_[t].styles.push(e)}))},setDirection:function(t){(W_=t).match(/.*</)&&(W_="RL"),W_.match(/.*\^/)&&(W_="BT"),W_.match(/.*>/)&&(W_="LR"),W_.match(/.*v/)&&(W_="TB")},setClass:cx,setTooltip:function(t,e){t.split(",").forEach((function(t){void 0!==e&&(nx["gen-1"===V_?ox(t):t]=Um.sanitizeText(e,Z_))}))},getTooltip:function(t){return nx[t]},setClickEvent:function(t,e,n){t.split(",").forEach((function(t){!function(t,e,n){var r=ox(t);if("loose"===Jv().securityLevel&&void 0!==e){var i=[];if("string"==typeof n){i=n.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(var a=0;a<i.length;a++){var o=i[a].trim();'"'===o.charAt(0)&&'"'===o.charAt(o.length-1)&&(o=o.substr(1,o.length-2)),i[a]=o}}0===i.length&&i.push(t),void 0!==Q_[t]&&(Q_[t].haveCallback=!0,ax.push((function(){var t=document.querySelector('[id="'.concat(r,'"]'));null!==t&&t.addEventListener("click",(function(){var t;Hv.runFunc.apply(Hv,[e].concat(function(t){if(Array.isArray(t))return $_(t)}(t=i)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return $_(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?$_(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()))}),!1)})))}}(t,e,n)})),cx(t,"clickable")},setLink:function(t,e,n){t.split(",").forEach((function(t){void 0!==Q_[t]&&(Q_[t].link=Hv.formatUrl(e,Z_),Q_[t].linkTarget=n)})),cx(t,"clickable")},bindFunctions:function(t){ax.forEach((function(e){e(t)}))},getDirection:function(){return W_.trim()},getVertices:function(){return Q_},getEdges:function(){return K_},getClasses:function(){return J_},clear:function(t){Q_={},J_={},K_=[],(ax=[]).push(ux),tx=[],ex={},rx=0,nx=[],ix=!0,V_=t||"gen-1"},setGen:function(t){V_=t||"gen-1"},defaultStyle:function(){return"fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;"},addSubGraph:function(t,e,n){var r=t.trim(),i=n;t===n&&n.match(/\s/)&&(r=void 0);var a=[],s=function(t){var e,n={boolean:{},number:{},string:{}},r=[],i=t.filter((function(t){var i=H_(t);return t.stmt&&"dir"===t.stmt?(e=t.value,!1):""!==t.trim()&&(i in n?!n[i].hasOwnProperty(t)&&(n[i][t]=!0):!(r.indexOf(t)>=0)&&r.push(t))}));return{nodeList:i,dir:e}}(a.concat.apply(a,e)),c=s.nodeList,u=s.dir;if(a=c,"gen-1"===V_){o.warn("LOOKING UP");for(var l=0;l<a.length;l++)a[l]=ox(a[l])}r=r||"subGraph"+rx,i=i||"",i=Um.sanitizeText(i,Z_),rx+=1;var h={id:r,nodes:a,title:i.trim(),classes:[],dir:u};return o.info("Adding",h.id,h.nodes,h.dir),h.nodes=yx(h,tx).nodes,tx.push(h),ex[r]=h,r},getDepthFirstPos:function(t){return fx[t]},indexNodes:function(){hx=-1,tx.length>0&&dx("none",tx.length-1)},getSubGraphs:function(){return tx},destructLink:function(t,e){var n,r=function(t){var e=t.trim(),n=e.slice(0,-1),r="arrow_open";switch(e.slice(-1)){case"x":r="arrow_cross","x"===e[0]&&(r="double_"+r,n=n.slice(1));break;case">":r="arrow_point","<"===e[0]&&(r="double_"+r,n=n.slice(1));break;case"o":r="arrow_circle","o"===e[0]&&(r="double_"+r,n=n.slice(1))}var i="normal",a=n.length-1;"="===n[0]&&(i="thick");var o=function(t,e){for(var n=e.length,r=0,i=0;i<n;++i)"."===e[i]&&++r;return r}(0,n);return o&&(i="dotted",a=o),{type:r,stroke:i,length:a}}(t);if(e){if(n=function(t){var e=t.trim(),n="arrow_open";switch(e[0]){case"<":n="arrow_point",e=e.slice(1);break;case"x":n="arrow_cross",e=e.slice(1);break;case"o":n="arrow_circle",e=e.slice(1)}var r="normal";return-1!==e.indexOf("=")&&(r="thick"),-1!==e.indexOf(".")&&(r="dotted"),{type:n,stroke:r}}(e),n.stroke!==r.stroke)return{type:"INVALID",stroke:"INVALID"};if("arrow_open"===n.type)n.type=r.type;else{if(n.type!==r.type)return{type:"INVALID",stroke:"INVALID"};n.type="double_"+n.type}return"double_arrow"===n.type&&(n.type="double_arrow_point"),n.length=r.length,n}return r},lex:{firstGraph:function(){return!!ix&&(ix=!1,!0)}},exists:px,makeUniq:yx};var mx=n(3602),vx=n.n(mx),bx=n(4949),_x=n.n(bx),xx=n(8284),wx=n.n(xx);function kx(t,e,n){var r=.9*(e.width+e.height),i=[{x:r/2,y:0},{x:r,y:-r/2},{x:r/2,y:-r},{x:0,y:-r/2}],a=Lx(t,r,r,i);return n.intersect=function(t){return _x().intersect.polygon(n,i,t)},a}function Tx(t,e,n){var r=e.height,i=r/4,a=e.width+2*i,o=[{x:i,y:0},{x:a-i,y:0},{x:a,y:-r/2},{x:a-i,y:-r},{x:i,y:-r},{x:0,y:-r/2}],s=Lx(t,a,r,o);return n.intersect=function(t){return _x().intersect.polygon(n,o,t)},s}function Ex(t,e,n){var r=e.width,i=e.height,a=[{x:-i/2,y:0},{x:r,y:0},{x:r,y:-i},{x:-i/2,y:-i},{x:0,y:-i/2}],o=Lx(t,r,i,a);return n.intersect=function(t){return _x().intersect.polygon(n,a,t)},o}function Cx(t,e,n){var r=e.width,i=e.height,a=[{x:-2*i/6,y:0},{x:r-i/6,y:0},{x:r+2*i/6,y:-i},{x:i/6,y:-i}],o=Lx(t,r,i,a);return n.intersect=function(t){return _x().intersect.polygon(n,a,t)},o}function Sx(t,e,n){var r=e.width,i=e.height,a=[{x:2*i/6,y:0},{x:r+i/6,y:0},{x:r-2*i/6,y:-i},{x:-i/6,y:-i}],o=Lx(t,r,i,a);return n.intersect=function(t){return _x().intersect.polygon(n,a,t)},o}function Ax(t,e,n){var r=e.width,i=e.height,a=[{x:-2*i/6,y:0},{x:r+2*i/6,y:0},{x:r-i/6,y:-i},{x:i/6,y:-i}],o=Lx(t,r,i,a);return n.intersect=function(t){return _x().intersect.polygon(n,a,t)},o}function Mx(t,e,n){var r=e.width,i=e.height,a=[{x:i/6,y:0},{x:r-i/6,y:0},{x:r+2*i/6,y:-i},{x:-2*i/6,y:-i}],o=Lx(t,r,i,a);return n.intersect=function(t){return _x().intersect.polygon(n,a,t)},o}function Nx(t,e,n){var r=e.width,i=e.height,a=[{x:0,y:0},{x:r+i/2,y:0},{x:r,y:-i/2},{x:r+i/2,y:-i},{x:0,y:-i}],o=Lx(t,r,i,a);return n.intersect=function(t){return _x().intersect.polygon(n,a,t)},o}function Dx(t,e,n){var r=e.height,i=e.width+r/4,a=t.insert("rect",":first-child").attr("rx",r/2).attr("ry",r/2).attr("x",-i/2).attr("y",-r/2).attr("width",i).attr("height",r);return n.intersect=function(t){return _x().intersect.rect(n,t)},a}function Ox(t,e,n){var r=e.width,i=e.height,a=[{x:0,y:0},{x:r,y:0},{x:r,y:-i},{x:0,y:-i},{x:0,y:0},{x:-8,y:0},{x:r+8,y:0},{x:r+8,y:-i},{x:-8,y:-i},{x:-8,y:0}],o=Lx(t,r,i,a);return n.intersect=function(t){return _x().intersect.polygon(n,a,t)},o}function Bx(t,e,n){var r=e.width,i=r/2,a=i/(2.5+r/50),o=e.height+a,s="M 0,"+a+" a "+i+","+a+" 0,0,0 "+r+" 0 a "+i+","+a+" 0,0,0 "+-r+" 0 l 0,"+o+" a "+i+","+a+" 0,0,0 "+r+" 0 l 0,"+-o,c=t.attr("label-offset-y",a).insert("path",":first-child").attr("d",s).attr("transform","translate("+-r/2+","+-(o/2+a)+")");return n.intersect=function(t){var e=_x().intersect.rect(n,t),r=e.x-n.x;if(0!=i&&(Math.abs(r)<n.width/2||Math.abs(r)==n.width/2&&Math.abs(e.y-n.y)>n.height/2-a)){var o=a*a*(1-r*r/(i*i));0!=o&&(o=Math.sqrt(o)),o=a-o,t.y-n.y>0&&(o=-o),e.y+=o}return e},c}function Lx(t,e,n,r){return t.insert("polygon",":first-child").attr("points",r.map((function(t){return t.x+","+t.y})).join(" ")).attr("transform","translate("+-e/2+","+n/2+")")}const Ix=function(t){t.shapes().question=kx,t.shapes().hexagon=Tx,t.shapes().stadium=Dx,t.shapes().subroutine=Ox,t.shapes().cylinder=Bx,t.shapes().rect_left_inv_arrow=Ex,t.shapes().lean_right=Cx,t.shapes().lean_left=Sx,t.shapes().trapezoid=Ax,t.shapes().inv_trapezoid=Mx,t.shapes().rect_right_inv_arrow=Nx};var Rx={};const Fx=function(t){for(var e=Object.keys(t),n=0;n<e.length;n++)Rx[e[n]]=t[e[n]]},Px=function(t,e){o.info("Drawing flowchart"),gx.clear(),gx.setGen("gen-1");var n=vx().parser;n.yy=gx,n.parse(t);var r=gx.getDirection();void 0===r&&(r="TD");for(var i,a=Jv().flowchart,s=a.nodeSpacing||50,c=a.rankSpacing||50,u=new(kb().Graph)({multigraph:!0,compound:!0}).setGraph({rankdir:r,nodesep:s,ranksep:c,marginx:8,marginy:8}).setDefaultEdgeLabel((function(){return{}})),l=gx.getSubGraphs(),h=l.length-1;h>=0;h--)i=l[h],gx.addVertex(i.id,i.title,"group",void 0,i.classes);var f=gx.getVertices();o.warn("Get vertices",f);var d=gx.getEdges(),p=0;for(p=l.length-1;p>=0;p--){i=l[p],ou("cluster").append("text");for(var y=0;y<i.nodes.length;y++)o.warn("Setting subgraph",i.nodes[y],gx.lookUpDomId(i.nodes[y]),gx.lookUpDomId(i.id)),u.setParent(gx.lookUpDomId(i.nodes[y]),gx.lookUpDomId(i.id))}(function(t,e,n){var r=au('[id="'.concat(n,'"]'));Object.keys(t).forEach((function(n){var i=t[n],a="default";i.classes.length>0&&(a=i.classes.join(" "));var s,c=Nv(i.styles),u=void 0!==i.text?i.text:i.id;if(zm(Jv().flowchart.htmlLabels)){var l={label:u.replace(/fa[lrsb]?:fa-[\w-]+/g,(function(t){return"<i class='".concat(t.replace(":"," "),"'></i>")}))};(s=wx()(r,l).node()).parentNode.removeChild(s)}else{var h=document.createElementNS("http://www.w3.org/2000/svg","text");h.setAttribute("style",c.labelStyle.replace("color:","fill:"));for(var f=u.split(Um.lineBreakRegex),d=0;d<f.length;d++){var p=document.createElementNS("http://www.w3.org/2000/svg","tspan");p.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),p.setAttribute("dy","1em"),p.setAttribute("x","1"),p.textContent=f[d],h.appendChild(p)}s=h}var y=0,g="";switch(i.type){case"round":y=5,g="rect";break;case"square":case"group":default:g="rect";break;case"diamond":g="question";break;case"hexagon":g="hexagon";break;case"odd":case"odd_right":g="rect_left_inv_arrow";break;case"lean_right":g="lean_right";break;case"lean_left":g="lean_left";break;case"trapezoid":g="trapezoid";break;case"inv_trapezoid":g="inv_trapezoid";break;case"circle":g="circle";break;case"ellipse":g="ellipse";break;case"stadium":g="stadium";break;case"subroutine":g="subroutine";break;case"cylinder":g="cylinder"}o.warn("Adding node",i.id,i.domId),e.setNode(gx.lookUpDomId(i.id),{labelType:"svg",labelStyle:c.labelStyle,shape:g,label:s,rx:y,ry:y,class:a,style:c.style,id:gx.lookUpDomId(i.id)})}))})(f,u,e),function(t,e){var n,r,i=0;if(void 0!==t.defaultStyle){var a=Nv(t.defaultStyle);n=a.style,r=a.labelStyle}t.forEach((function(a){i++;var o="L-"+a.start+"-"+a.end,s="LS-"+a.start,c="LE-"+a.end,u={};"arrow_open"===a.type?u.arrowhead="none":u.arrowhead="normal";var l="",h="";if(void 0!==a.style){var f=Nv(a.style);l=f.style,h=f.labelStyle}else switch(a.stroke){case"normal":l="fill:none",void 0!==n&&(l=n),void 0!==r&&(h=r);break;case"dotted":l="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":l=" stroke-width: 3.5px;fill:none"}u.style=l,u.labelStyle=h,void 0!==a.interpolate?u.curve=Av(a.interpolate,Pu):void 0!==t.defaultInterpolate?u.curve=Av(t.defaultInterpolate,Pu):u.curve=Av(Rx.curve,Pu),void 0===a.text?void 0!==a.style&&(u.arrowheadStyle="fill: #333"):(u.arrowheadStyle="fill: #333",u.labelpos="c",zm(Jv().flowchart.htmlLabels)?(u.labelType="html",u.label='<span id="L-'.concat(o,'" class="edgeLabel L-').concat(s,"' L-").concat(c,'">').concat(a.text.replace(/fa[lrsb]?:fa-[\w-]+/g,(function(t){return"<i class='".concat(t.replace(":"," "),"'></i>")})),"</span>")):(u.labelType="text",u.label=a.text.replace(Um.lineBreakRegex,"\n"),void 0===a.style&&(u.style=u.style||"stroke: #333; stroke-width: 1.5px;fill:none"),u.labelStyle=u.labelStyle.replace("color:","fill:"))),u.id=o,u.class=s+" "+c,u.minlen=a.length||1,e.setEdge(gx.lookUpDomId(a.start),gx.lookUpDomId(a.end),u,i)}))}(d,u);var g=new(0,_x().render);Ix(g),g.arrows().none=function(t,e,n,r){var i=t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 0 L 0 0 L 0 0 z");_x().util.applyStyle(i,n[r+"Style"])},g.arrows().normal=function(t,e){t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").attr("class","arrowheadPath").style("stroke-width",1).style("stroke-dasharray","1,0")};var m=au('[id="'.concat(e,'"]'));m.attr("xmlns:xlink","http://www.w3.org/1999/xlink"),o.warn(u);var v=au("#"+e+" g");g(v,u),v.selectAll("g.node").attr("title",(function(){return gx.getTooltip(this.id)}));var b=a.diagramPadding,_=m.node().getBBox(),x=_.width+2*b,w=_.height+2*b;zv(m,w,x,a.useMaxWidth);var k="".concat(_.x-b," ").concat(_.y-b," ").concat(x," ").concat(w);for(o.debug("viewBox ".concat(k)),m.attr("viewBox",k),gx.indexNodes("subGraph"+p),p=0;p<l.length;p++)if("undefined"!==(i=l[p]).title){var T=document.querySelectorAll("#"+e+' [id="'+gx.lookUpDomId(i.id)+'"] rect'),E=document.querySelectorAll("#"+e+' [id="'+gx.lookUpDomId(i.id)+'"]'),C=T[0].x.baseVal.value,S=T[0].y.baseVal.value,A=T[0].width.baseVal.value,M=au(E[0]).select(".label");M.attr("transform","translate(".concat(C+A/2,", ").concat(S+14,")")),M.attr("id",e+"Text");for(var N=0;N<i.classes.length;N++)E[0].classList.add(i.classes[N])}zm(a.htmlLabels);for(var D=document.querySelectorAll('[id="'+e+'"] .edgeLabel .label'),O=0;O<D.length;O++){var B=D[O],L=B.getBBox(),I=document.createElementNS("http://www.w3.org/2000/svg","rect");I.setAttribute("rx",0),I.setAttribute("ry",0),I.setAttribute("width",L.width),I.setAttribute("height",L.height),B.insertBefore(I,B.firstChild)}Object.keys(f).forEach((function(t){var n=f[t];if(n.link){var r=au("#"+e+' [id="'+gx.lookUpDomId(t)+'"]');if(r){var i=document.createElementNS("http://www.w3.org/2000/svg","a");i.setAttributeNS("http://www.w3.org/2000/svg","class",n.classes.join(" ")),i.setAttributeNS("http://www.w3.org/2000/svg","href",n.link),i.setAttributeNS("http://www.w3.org/2000/svg","rel","noopener"),n.linkTarget&&i.setAttributeNS("http://www.w3.org/2000/svg","target",n.linkTarget);var a=r.insert((function(){return i}),":first-child"),o=r.select(".label-container");o&&a.append((function(){return o.node()}));var s=r.select(".label");s&&a.append((function(){return s.node()}))}}}))};var jx={};const Yx=function(t){for(var e=Object.keys(t),n=0;n<e.length;n++)jx[e[n]]=t[e[n]]},zx=function(t,e){o.info("Drawing flowchart"),gx.clear(),gx.setGen("gen-2");var n=vx().parser;n.yy=gx,n.parse(t);var r=gx.getDirection();void 0===r&&(r="TD");var i,a=Jv().flowchart,s=a.nodeSpacing||50,c=a.rankSpacing||50,u=new(kb().Graph)({multigraph:!0,compound:!0}).setGraph({rankdir:r,nodesep:s,ranksep:c,marginx:8,marginy:8}).setDefaultEdgeLabel((function(){return{}})),l=gx.getSubGraphs();o.info("Subgraphs - ",l);for(var h=l.length-1;h>=0;h--)i=l[h],o.info("Subgraph - ",i),gx.addVertex(i.id,i.title,"group",void 0,i.classes,i.dir);var f=gx.getVertices(),d=gx.getEdges();o.info(d);var p=0;for(p=l.length-1;p>=0;p--){i=l[p],ou("cluster").append("text");for(var y=0;y<i.nodes.length;y++)o.info("Setting up subgraphs",i.nodes[y],i.id),u.setParent(i.nodes[y],i.id)}(function(t,e,n){var r=au('[id="'.concat(n,'"]'));Object.keys(t).forEach((function(n){var i=t[n],a="default";i.classes.length>0&&(a=i.classes.join(" "));var s,c=Nv(i.styles),u=void 0!==i.text?i.text:i.id;if(zm(Jv().flowchart.htmlLabels)){var l={label:u.replace(/fa[lrsb]?:fa-[\w-]+/g,(function(t){return"<i class='".concat(t.replace(":"," "),"'></i>")}))};(s=wx()(r,l).node()).parentNode.removeChild(s)}else{var h=document.createElementNS("http://www.w3.org/2000/svg","text");h.setAttribute("style",c.labelStyle.replace("color:","fill:"));for(var f=u.split(Um.lineBreakRegex),d=0;d<f.length;d++){var p=document.createElementNS("http://www.w3.org/2000/svg","tspan");p.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),p.setAttribute("dy","1em"),p.setAttribute("x","1"),p.textContent=f[d],h.appendChild(p)}s=h}var y=0,g="";switch(i.type){case"round":y=5,g="rect";break;case"square":case"group":default:g="rect";break;case"diamond":g="question";break;case"hexagon":g="hexagon";break;case"odd":case"odd_right":g="rect_left_inv_arrow";break;case"lean_right":g="lean_right";break;case"lean_left":g="lean_left";break;case"trapezoid":g="trapezoid";break;case"inv_trapezoid":g="inv_trapezoid";break;case"circle":g="circle";break;case"ellipse":g="ellipse";break;case"stadium":g="stadium";break;case"subroutine":g="subroutine";break;case"cylinder":g="cylinder"}e.setNode(i.id,{labelStyle:c.labelStyle,shape:g,labelText:u,rx:y,ry:y,class:a,style:c.style,id:i.id,link:i.link,linkTarget:i.linkTarget,tooltip:gx.getTooltip(i.id)||"",domId:gx.lookUpDomId(i.id),haveCallback:i.haveCallback,width:"group"===i.type?500:void 0,dir:i.dir,type:i.type,props:i.props,padding:Jv().flowchart.padding}),o.info("setNode",{labelStyle:c.labelStyle,shape:g,labelText:u,rx:y,ry:y,class:a,style:c.style,id:i.id,domId:gx.lookUpDomId(i.id),width:"group"===i.type?500:void 0,type:i.type,dir:i.dir,props:i.props,padding:Jv().flowchart.padding})}))})(f,u,e),function(t,e){o.info("abc78 edges = ",t);var n,r,i=0,a={};if(void 0!==t.defaultStyle){var s=Nv(t.defaultStyle);n=s.style,r=s.labelStyle}t.forEach((function(s){i++;var c="L-"+s.start+"-"+s.end;void 0===a[c]?(a[c]=0,o.info("abc78 new entry",c,a[c])):(a[c]++,o.info("abc78 new entry",c,a[c]));var u=c+"-"+a[c];o.info("abc78 new link id to be used is",c,u,a[c]);var l="LS-"+s.start,h="LE-"+s.end,f={style:"",labelStyle:""};switch(f.minlen=s.length||1,"arrow_open"===s.type?f.arrowhead="none":f.arrowhead="normal",f.arrowTypeStart="arrow_open",f.arrowTypeEnd="arrow_open",s.type){case"double_arrow_cross":f.arrowTypeStart="arrow_cross";case"arrow_cross":f.arrowTypeEnd="arrow_cross";break;case"double_arrow_point":f.arrowTypeStart="arrow_point";case"arrow_point":f.arrowTypeEnd="arrow_point";break;case"double_arrow_circle":f.arrowTypeStart="arrow_circle";case"arrow_circle":f.arrowTypeEnd="arrow_circle"}var d="",p="";switch(s.stroke){case"normal":d="fill:none;",void 0!==n&&(d=n),void 0!==r&&(p=r),f.thickness="normal",f.pattern="solid";break;case"dotted":f.thickness="normal",f.pattern="dotted",f.style="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":f.thickness="thick",f.pattern="solid",f.style="stroke-width: 3.5px;fill:none;"}if(void 0!==s.style){var y=Nv(s.style);d=y.style,p=y.labelStyle}f.style=f.style+=d,f.labelStyle=f.labelStyle+=p,void 0!==s.interpolate?f.curve=Av(s.interpolate,Pu):void 0!==t.defaultInterpolate?f.curve=Av(t.defaultInterpolate,Pu):f.curve=Av(jx.curve,Pu),void 0===s.text?void 0!==s.style&&(f.arrowheadStyle="fill: #333"):(f.arrowheadStyle="fill: #333",f.labelpos="c"),f.labelType="text",f.label=s.text.replace(Um.lineBreakRegex,"\n"),void 0===s.style&&(f.style=f.style||"stroke: #333; stroke-width: 1.5px;fill:none;"),f.labelStyle=f.labelStyle.replace("color:","fill:"),f.id=u,f.classes="flowchart-link "+l+" "+h,e.setEdge(s.start,s.end,f,i)}))}(d,u);var g=au('[id="'.concat(e,'"]'));g.attr("xmlns:xlink","http://www.w3.org/1999/xlink");var m=au("#"+e+" g");S_(m,u,["point","circle","cross"],"flowchart",e);var v=a.diagramPadding,b=g.node().getBBox(),_=b.width+2*v,x=b.height+2*v;if(o.debug("new ViewBox 0 0 ".concat(_," ").concat(x),"translate(".concat(v-u._label.marginx,", ").concat(v-u._label.marginy,")")),zv(g,x,_,a.useMaxWidth),g.attr("viewBox","0 0 ".concat(_," ").concat(x)),g.select("g").attr("transform","translate(".concat(v-u._label.marginx,", ").concat(v-b.y,")")),gx.indexNodes("subGraph"+p),!a.htmlLabels)for(var w=document.querySelectorAll('[id="'+e+'"] .edgeLabel .label'),k=0;k<w.length;k++){var T=w[k],E=T.getBBox(),C=document.createElementNS("http://www.w3.org/2000/svg","rect");C.setAttribute("rx",0),C.setAttribute("ry",0),C.setAttribute("width",E.width),C.setAttribute("height",E.height),T.insertBefore(C,T.firstChild)}Object.keys(f).forEach((function(t){var n=f[t];if(n.link){var r=au("#"+e+' [id="'+t+'"]');if(r){var i=document.createElementNS("http://www.w3.org/2000/svg","a");i.setAttributeNS("http://www.w3.org/2000/svg","class",n.classes.join(" ")),i.setAttributeNS("http://www.w3.org/2000/svg","href",n.link),i.setAttributeNS("http://www.w3.org/2000/svg","rel","noopener"),n.linkTarget&&i.setAttributeNS("http://www.w3.org/2000/svg","target",n.linkTarget);var a=r.insert((function(){return i}),":first-child"),o=r.select(".label-container");o&&a.append((function(){return o.node()}));var s=r.select(".label");s&&a.append((function(){return s.node()}))}}}))};function Ux(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}var qx,Hx,$x="",Wx="",Vx="",Gx=[],Xx=[],Zx="",Qx=[],Kx=[],Jx="",tw=["active","done","crit","milestone"],ew=[],nw=!1,rw=!1,iw=0,aw=function(t,e,n,r){return!(r.indexOf(t.format(e.trim()))>=0)&&(t.isoWeekday()>=6&&n.indexOf("weekends")>=0||n.indexOf(t.format("dddd").toLowerCase())>=0||n.indexOf(t.format(e.trim()))>=0)},ow=function(t,e,n,r){if(n.length&&!t.manualEndTime){var a=i()(t.startTime,e,!0);a.add(1,"d");var o=i()(t.endTime,e,!0),s=sw(a,o,e,n,r);t.endTime=o.toDate(),t.renderEndTime=s}},sw=function(t,e,n,r,i){for(var a=!1,o=null;t<=e;)a||(o=e.toDate()),(a=aw(t,n,r,i))&&e.add(1,"d"),t.add(1,"d");return o},cw=function(t,e,n){n=n.trim();var r=/^after\s+([\d\w- ]+)/.exec(n.trim());if(null!==r){var a=null;if(r[1].split(" ").forEach((function(t){var e=yw(t);void 0!==e&&(a?e.endTime>a.endTime&&(a=e):a=e)})),a)return a.endTime;var s=new Date;return s.setHours(0,0,0,0),s}var c=i()(n,e.trim(),!0);return c.isValid()?c.toDate():(o.debug("Invalid date:"+n),o.debug("With date format:"+e.trim()),new Date)},uw=function(t,e){if(null!==t)switch(t[2]){case"s":e.add(t[1],"seconds");break;case"m":e.add(t[1],"minutes");break;case"h":e.add(t[1],"hours");break;case"d":e.add(t[1],"days");break;case"w":e.add(t[1],"weeks")}return e.toDate()},lw=function(t,e,n,r){r=r||!1,n=n.trim();var a=i()(n,e.trim(),!0);return a.isValid()?(r&&a.add(1,"d"),a.toDate()):uw(/^([\d]+)([wdhms])/.exec(n.trim()),i()(t))},hw=0,fw=function(t){return void 0===t?"task"+(hw+=1):t},dw=[],pw={},yw=function(t){var e=pw[t];return dw[e]},gw=function(){for(var t=function(t){var e=dw[t],n="";switch(dw[t].raw.startTime.type){case"prevTaskEnd":var r=yw(e.prevTaskId);e.startTime=r.endTime;break;case"getStartDate":(n=cw(0,$x,dw[t].raw.startTime.startData))&&(dw[t].startTime=n)}return dw[t].startTime&&(dw[t].endTime=lw(dw[t].startTime,$x,dw[t].raw.endTime.data,nw),dw[t].endTime&&(dw[t].processed=!0,dw[t].manualEndTime=i()(dw[t].raw.endTime.data,"YYYY-MM-DD",!0).isValid(),ow(dw[t],$x,Xx,Gx))),dw[t].processed},e=!0,n=0;n<dw.length;n++)t(n),e=e&&dw[n].processed;return e},mw=function(t,e){t.split(",").forEach((function(t){var n=yw(t);void 0!==n&&n.classes.push(e)}))},vw=function(t,e){ew.push((function(){var n=document.querySelector('[id="'.concat(t,'"]'));null!==n&&n.addEventListener("click",(function(){e()}))})),ew.push((function(){var n=document.querySelector('[id="'.concat(t,'-text"]'));null!==n&&n.addEventListener("click",(function(){e()}))}))};const bw={parseDirective:function(t,e,n){cC.parseDirective(this,t,e,n)},getConfig:function(){return Jv().gantt},clear:function(){Qx=[],Kx=[],Jx="",ew=[],Zx="",hw=0,qx=void 0,Hx=void 0,dw=[],$x="",Wx="",Vx="",Gx=[],Xx=[],nw=!1,rw=!1,iw=0},setDateFormat:function(t){$x=t},getDateFormat:function(){return $x},enableInclusiveEndDates:function(){nw=!0},endDatesAreInclusive:function(){return nw},enableTopAxis:function(){rw=!0},topAxisEnabled:function(){return rw},setAxisFormat:function(t){Wx=t},getAxisFormat:function(){return Wx},setTodayMarker:function(t){Vx=t},getTodayMarker:function(){return Vx},setTitle:function(t){Zx=t},getTitle:function(){return Zx},addSection:function(t){Jx=t,Qx.push(t)},getSections:function(){return Qx},getTasks:function(){for(var t=gw(),e=0;!t&&e<10;)t=gw(),e++;return Kx=dw},addTask:function(t,e){var n={section:Jx,type:Jx,processed:!1,manualEndTime:!1,renderEndTime:null,raw:{data:e},task:t,classes:[]},r=function(t,e){var n=(":"===e.substr(0,1)?e.substr(1,e.length):e).split(","),r={};_w(n,r,tw);for(var i=0;i<n.length;i++)n[i]=n[i].trim();switch(n.length){case 1:r.id=fw(),r.startTime={type:"prevTaskEnd",id:t},r.endTime={data:n[0]};break;case 2:r.id=fw(),r.startTime={type:"getStartDate",startData:n[0]},r.endTime={data:n[1]};break;case 3:r.id=fw(n[0]),r.startTime={type:"getStartDate",startData:n[1]},r.endTime={data:n[2]}}return r}(Hx,e);n.raw.startTime=r.startTime,n.raw.endTime=r.endTime,n.id=r.id,n.prevTaskId=Hx,n.active=r.active,n.done=r.done,n.crit=r.crit,n.milestone=r.milestone,n.order=iw,iw++;var i=dw.push(n);Hx=n.id,pw[n.id]=i-1},findTaskById:yw,addTaskOrg:function(t,e){var n={section:Jx,type:Jx,description:t,task:t,classes:[]},r=function(t,e){var n=(":"===e.substr(0,1)?e.substr(1,e.length):e).split(","),r={};_w(n,r,tw);for(var a=0;a<n.length;a++)n[a]=n[a].trim();var o="";switch(n.length){case 1:r.id=fw(),r.startTime=t.endTime,o=n[0];break;case 2:r.id=fw(),r.startTime=cw(0,$x,n[0]),o=n[1];break;case 3:r.id=fw(n[0]),r.startTime=cw(0,$x,n[1]),o=n[2]}return o&&(r.endTime=lw(r.startTime,$x,o,nw),r.manualEndTime=i()(o,"YYYY-MM-DD",!0).isValid(),ow(r,$x,Xx,Gx)),r}(qx,e);n.startTime=r.startTime,n.endTime=r.endTime,n.id=r.id,n.active=r.active,n.done=r.done,n.crit=r.crit,n.milestone=r.milestone,qx=n,Kx.push(n)},setIncludes:function(t){Gx=t.toLowerCase().split(/[\s,]+/)},getIncludes:function(){return Gx},setExcludes:function(t){Xx=t.toLowerCase().split(/[\s,]+/)},getExcludes:function(){return Xx},setClickEvent:function(t,e,n){t.split(",").forEach((function(t){!function(t,e,n){if("loose"===Jv().securityLevel&&void 0!==e){var r=[];if("string"==typeof n){r=n.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(var i=0;i<r.length;i++){var a=r[i].trim();'"'===a.charAt(0)&&'"'===a.charAt(a.length-1)&&(a=a.substr(1,a.length-2)),r[i]=a}}0===r.length&&r.push(t),void 0!==yw(t)&&vw(t,(function(){var t;Hv.runFunc.apply(Hv,[e].concat(function(t){if(Array.isArray(t))return Ux(t)}(t=r)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return Ux(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Ux(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()))}))}}(t,e,n)})),mw(t,"clickable")},setLink:function(t,e){var n=e;"loose"!==Jv().securityLevel&&(n=(0,Om.sanitizeUrl)(e)),t.split(",").forEach((function(t){void 0!==yw(t)&&vw(t,(function(){window.open(n,"_self")}))})),mw(t,"clickable")},bindFunctions:function(t){ew.forEach((function(e){e(t)}))},durationToDate:uw,isInvalidDate:aw};function _w(t,e,n){for(var r=!0;r;)r=!1,n.forEach((function(n){var i=new RegExp("^\\s*"+n+"\\s*$");t[0].match(i)&&(e[n]=!0,t.shift(1),r=!0)}))}var xw,ww=n(9959),kw=n.n(ww);ww.parser.yy=bw;const Tw=function(t,e){var n=Jv().gantt;ww.parser.yy.clear(),ww.parser.parse(t);var r=document.getElementById(e);void 0===(xw=r.parentElement.offsetWidth)&&(xw=1200),void 0!==n.useWidth&&(xw=n.useWidth);var a=ww.parser.yy.getTasks(),o=a.length*(n.barHeight+n.barGap)+2*n.topPadding;r.setAttribute("viewBox","0 0 "+xw+" "+o);for(var s=au('[id="'.concat(e,'"]')),c=function(){return Zi.apply(qs(mo,vo,Ga,Wa,Pa,Ra,La,Oa,Na,ko).domain([new Date(2e3,0,1),new Date(2e3,0,2)]),arguments)}().domain([l(a,(function(t){return t.startTime})),u(a,(function(t){return t.endTime}))]).rangeRound([0,xw-n.leftPadding-n.rightPadding]),h=[],f=0;f<a.length;f++)h.push(a[f].type);var d=h;h=function(t){for(var e={},n=[],r=0,i=t.length;r<i;++r)Object.prototype.hasOwnProperty.call(e,t[r])||(e[t[r]]=!0,n.push(t[r]));return n}(h),a.sort((function(t,e){var n=t.startTime,r=e.startTime,i=0;return n>r?i=1:n<r&&(i=-1),i})),function(t,e,r){var a=n.barHeight,o=a+n.barGap,u=n.topPadding,l=n.leftPadding;fa().domain([0,h.length]).range(["#00B9FA","#F95002"]).interpolate(jr),function(t,e,r,a,o,u,l,h){var f=u.reduce((function(t,e){var n=e.startTime;return t?Math.min(t,n):n}),0),d=u.reduce((function(t,e){var n=e.endTime;return t?Math.max(t,n):n}),0),p=ww.parser.yy.getDateFormat();if(f&&d){for(var y=[],g=null,m=i()(f);m.valueOf()<=d;)ww.parser.yy.isInvalidDate(m,p,l,h)?g?g.end=m.clone():g={start:m.clone(),end:m.clone()}:g&&(y.push(g),g=null),m.add(1,"d");s.append("g").selectAll("rect").data(y).enter().append("rect").attr("id",(function(t){return"exclude-"+t.start.format("YYYY-MM-DD")})).attr("x",(function(t){return c(t.start)+r})).attr("y",n.gridLineStartPadding).attr("width",(function(t){var e=t.end.clone().add(1,"day");return c(e)-c(t.start)})).attr("height",o-e-n.gridLineStartPadding).attr("transform-origin",(function(e,n){return(c(e.start)+r+.5*(c(e.end)-c(e.start))).toString()+"px "+(n*t+.5*o).toString()+"px"})).attr("class","exclude-range")}}(o,u,l,0,r,t,ww.parser.yy.getExcludes(),ww.parser.yy.getIncludes()),function(t,e,r,i){var a,o=(a=c,v(3,a)).tickSize(-i+e+n.gridLineStartPadding).tickFormat(Yl(ww.parser.yy.getAxisFormat()||n.axisFormat||"%Y-%m-%d"));if(s.append("g").attr("class","grid").attr("transform","translate("+t+", "+(i-50)+")").call(o).selectAll("text").style("text-anchor","middle").attr("fill","#000").attr("stroke","none").attr("font-size",10).attr("dy","1em"),bw.topAxisEnabled()||n.topAxis){var u=function(t){return v(1,t)}(c).tickSize(-i+e+n.gridLineStartPadding).tickFormat(Yl(ww.parser.yy.getAxisFormat()||n.axisFormat||"%Y-%m-%d"));s.append("g").attr("class","grid").attr("transform","translate("+t+", "+e+")").call(u).selectAll("text").style("text-anchor","middle").attr("fill","#000").attr("stroke","none").attr("font-size",10)}}(l,u,0,r),function(t,e,r,i,a,o,u){s.append("g").selectAll("rect").data(t).enter().append("rect").attr("x",0).attr("y",(function(t,n){return t.order*e+r-2})).attr("width",(function(){return u-n.rightPadding/2})).attr("height",e).attr("class",(function(t){for(var e=0;e<h.length;e++)if(t.type===h[e])return"section section"+e%n.numberSectionStyles;return"section section0"}));var l=s.append("g").selectAll("rect").data(t).enter();l.append("rect").attr("id",(function(t){return t.id})).attr("rx",3).attr("ry",3).attr("x",(function(t){return t.milestone?c(t.startTime)+i+.5*(c(t.endTime)-c(t.startTime))-.5*a:c(t.startTime)+i})).attr("y",(function(t,n){return t.order*e+r})).attr("width",(function(t){return t.milestone?a:c(t.renderEndTime||t.endTime)-c(t.startTime)})).attr("height",a).attr("transform-origin",(function(t,n){return n=t.order,(c(t.startTime)+i+.5*(c(t.endTime)-c(t.startTime))).toString()+"px "+(n*e+r+.5*a).toString()+"px"})).attr("class",(function(t){var e="";t.classes.length>0&&(e=t.classes.join(" "));for(var r=0,i=0;i<h.length;i++)t.type===h[i]&&(r=i%n.numberSectionStyles);var a="";return t.active?t.crit?a+=" activeCrit":a=" active":t.done?a=t.crit?" doneCrit":" done":t.crit&&(a+=" crit"),0===a.length&&(a=" task"),t.milestone&&(a=" milestone "+a),"task"+(a+=r)+" "+e})),l.append("text").attr("id",(function(t){return t.id+"-text"})).text((function(t){return t.task})).attr("font-size",n.fontSize).attr("x",(function(t){var e=c(t.startTime),r=c(t.renderEndTime||t.endTime);t.milestone&&(e+=.5*(c(t.endTime)-c(t.startTime))-.5*a),t.milestone&&(r=e+a);var o=this.getBBox().width;return o>r-e?r+o+1.5*n.leftPadding>u?e+i-5:r+i+5:(r-e)/2+e+i})).attr("y",(function(t,i){return t.order*e+n.barHeight/2+(n.fontSize/2-2)+r})).attr("text-height",a).attr("class",(function(t){var e=c(t.startTime),r=c(t.endTime);t.milestone&&(r=e+a);var i=this.getBBox().width,o="";t.classes.length>0&&(o=t.classes.join(" "));for(var s=0,l=0;l<h.length;l++)t.type===h[l]&&(s=l%n.numberSectionStyles);var f="";return t.active&&(f=t.crit?"activeCritText"+s:"activeText"+s),t.done?f=t.crit?f+" doneCritText"+s:f+" doneText"+s:t.crit&&(f=f+" critText"+s),t.milestone&&(f+=" milestoneText"),i>r-e?r+i+1.5*n.leftPadding>u?o+" taskTextOutsideLeft taskTextOutside"+s+" "+f:o+" taskTextOutsideRight taskTextOutside"+s+" "+f+" width-"+i:o+" taskText taskText"+s+" "+f+" width-"+i}))}(t,o,u,l,a,0,e),function(t,e){for(var r=[],i=0,a=0;a<h.length;a++)r[a]=[h[a],(o=h[a],c=d,function(t){for(var e=t.length,n={};e;)n[t[--e]]=(n[t[e]]||0)+1;return n}(c)[o]||0)];var o,c;s.append("g").selectAll("text").data(r).enter().append((function(t){var e=t[0].split(Um.lineBreakRegex),n=-(e.length-1)/2,r=document.createElementNS("http://www.w3.org/2000/svg","text");r.setAttribute("dy",n+"em");for(var i=0;i<e.length;i++){var a=document.createElementNS("http://www.w3.org/2000/svg","tspan");a.setAttribute("alignment-baseline","central"),a.setAttribute("x","10"),i>0&&a.setAttribute("dy","1em"),a.textContent=e[i],r.appendChild(a)}return r})).attr("x",10).attr("y",(function(n,a){if(!(a>0))return n[1]*t/2+e;for(var o=0;o<a;o++)return i+=r[a-1][1],n[1]*t/2+i*t+e})).attr("font-size",n.sectionFontSize).attr("font-size",n.sectionFontSize).attr("class",(function(t){for(var e=0;e<h.length;e++)if(t[0]===h[e])return"sectionTitle sectionTitle"+e%n.numberSectionStyles;return"sectionTitle"}))}(o,u),function(t,e,r,i){var a=bw.getTodayMarker();if("off"!==a){var o=s.append("g").attr("class","today"),u=new Date,l=o.append("line");l.attr("x1",c(u)+t).attr("x2",c(u)+t).attr("y1",n.titleTopMargin).attr("y2",i-n.titleTopMargin).attr("class","today"),""!==a&&l.attr("style",a.replace(/,/g,";"))}}(l,0,0,r)}(a,xw,o),zv(s,o,xw,n.useMaxWidth),s.append("text").text(ww.parser.yy.getTitle()).attr("x",xw/2).attr("y",n.titleTopMargin).attr("class","titleText")};var Ew={},Cw=null,Sw={master:Cw},Aw="master",Mw="LR",Nw=0;function Dw(){return Bv({length:7})}function Ow(t,e){o.debug("Entering isfastforwardable:",t.id,e.id);for(var n=0;t.seq<=e.seq&&t!==e&&n<1e3&&(n++,null!=e.parent);){if(Array.isArray(e.parent))return o.debug("In merge commit:",e.parent),Ow(t,Ew[e.parent[0]])||Ow(t,Ew[e.parent[1]]);e=Ew[e.parent]}return o.debug(t.id,e.id),t.id===e.id}var Bw={};function Lw(t,e,n){var r=t.indexOf(e);-1===r?t.push(n):t.splice(r,1,n)}function Iw(t){var e=t.reduce((function(t,e){return t.seq>e.seq?t:e}),t[0]),n="";t.forEach((function(t){n+=t===e?"\t*":"\t|"}));var r,i,a,s=[n,e.id,e.seq];for(var c in Sw)Sw[c]===e.id&&s.push(c);if(o.debug(s.join(" ")),Array.isArray(e.parent)){var u=Ew[e.parent[0]];Lw(t,e,u),t.push(Ew[e.parent[1]])}else{if(null==e.parent)return;var l=Ew[e.parent];Lw(t,e,l)}r=t,i=function(t){return t.id},a=Object.create(null),Iw(t=r.reduce((function(t,e){var n=i(e);return a[n]||(a[n]=!0,t.push(e)),t}),[]))}var Rw=function(){var t=Object.keys(Ew).map((function(t){return Ew[t]}));return t.forEach((function(t){o.debug(t.id)})),t.sort((function(t,e){return e.seq-t.seq})),t};const Fw={setDirection:function(t){Mw=t},setOptions:function(t){o.debug("options str",t),t=(t=t&&t.trim())||"{}";try{Bw=JSON.parse(t)}catch(t){o.error("error while parsing gitGraph options",t.message)}},getOptions:function(){return Bw},commit:function(t){var e={id:Dw(),message:t,seq:Nw++,parent:null==Cw?null:Cw.id};Cw=e,Ew[e.id]=e,Sw[Aw]=e.id,o.debug("in pushCommit "+e.id)},branch:function(t){Sw[t]=null!=Cw?Cw.id:null,o.debug("in createBranch")},merge:function(t){var e=Ew[Sw[Aw]],n=Ew[Sw[t]];if(function(t,e){return t.seq>e.seq&&Ow(e,t)}(e,n))o.debug("Already merged");else{if(Ow(e,n))Sw[Aw]=Sw[t],Cw=Ew[Sw[Aw]];else{var r={id:Dw(),message:"merged branch "+t+" into "+Aw,seq:Nw++,parent:[null==Cw?null:Cw.id,Sw[t]]};Cw=r,Ew[r.id]=r,Sw[Aw]=r.id}o.debug(Sw),o.debug("in mergeBranch")}},checkout:function(t){o.debug("in checkout");var e=Sw[Aw=t];Cw=Ew[e]},reset:function(t){o.debug("in reset",t);var e=t.split(":")[0],n=parseInt(t.split(":")[1]),r="HEAD"===e?Cw:Ew[Sw[e]];for(o.debug(r,n);n>0;)if(n--,!(r=Ew[r.parent])){var i="Critical error - unique parent commit not found during reset";throw o.error(i),i}Cw=r,Sw[Aw]=r.id},prettyPrint:function(){o.debug(Ew),Iw([Rw()[0]])},clear:function(){Ew={},Sw={master:Cw=null},Aw="master",Nw=0},getBranchesAsObjArray:function(){var t=[];for(var e in Sw)t.push({name:e,commit:Ew[Sw[e]]});return t},getBranches:function(){return Sw},getCommits:function(){return Ew},getCommitsArray:Rw,getCurrentBranch:function(){return Aw},getDirection:function(){return Mw},getHead:function(){return Cw}};var Pw,jw=n(2553),Yw=n.n(jw),zw={},Uw={nodeSpacing:150,nodeFillColor:"yellow",nodeStrokeWidth:2,nodeStrokeColor:"grey",lineStrokeWidth:4,branchOffset:50,lineColor:"grey",leftMargin:50,branchColors:["#442f74","#983351","#609732","#AA9A39"],nodeRadius:10,nodeLabel:{width:75,height:100,x:-25,y:0}},qw={};function Hw(t,e,n,r){var i=Av(r,Vu),a=Uw.branchColors[n%Uw.branchColors.length],o=zu().x((function(t){return Math.round(t.x)})).y((function(t){return Math.round(t.y)})).curve(i);t.append("svg:path").attr("d",o(e)).style("stroke",a).style("stroke-width",Uw.lineStrokeWidth).style("fill","none")}function $w(t,e){e=e||t.node().getBBox();var n=t.node().getCTM();return{left:n.e+e.x*n.a,top:n.f+e.y*n.d,width:e.width,height:e.height}}function Ww(t,e,n,r,i){o.debug("svgDrawLineForCommits: ",e,n);var a=$w(t.select("#node-"+e+" circle")),s=$w(t.select("#node-"+n+" circle"));switch(r){case"LR":if(a.left-s.left>Uw.nodeSpacing){var c={x:a.left-Uw.nodeSpacing,y:s.top+s.height/2};Hw(t,[c,{x:s.left+s.width,y:s.top+s.height/2}],i,"linear"),Hw(t,[{x:a.left,y:a.top+a.height/2},{x:a.left-Uw.nodeSpacing/2,y:a.top+a.height/2},{x:a.left-Uw.nodeSpacing/2,y:c.y},c],i)}else Hw(t,[{x:a.left,y:a.top+a.height/2},{x:a.left-Uw.nodeSpacing/2,y:a.top+a.height/2},{x:a.left-Uw.nodeSpacing/2,y:s.top+s.height/2},{x:s.left+s.width,y:s.top+s.height/2}],i);break;case"BT":if(s.top-a.top>Uw.nodeSpacing){var u={x:s.left+s.width/2,y:a.top+a.height+Uw.nodeSpacing};Hw(t,[u,{x:s.left+s.width/2,y:s.top}],i,"linear"),Hw(t,[{x:a.left+a.width/2,y:a.top+a.height},{x:a.left+a.width/2,y:a.top+a.height+Uw.nodeSpacing/2},{x:s.left+s.width/2,y:u.y-Uw.nodeSpacing/2},u],i)}else Hw(t,[{x:a.left+a.width/2,y:a.top+a.height},{x:a.left+a.width/2,y:a.top+Uw.nodeSpacing/2},{x:s.left+s.width/2,y:s.top-Uw.nodeSpacing/2},{x:s.left+s.width/2,y:s.top}],i)}}function Vw(t,e){return t.select(e).node().cloneNode(!0)}function Gw(t,e,n,r){var i,a=Object.keys(zw).length;if("string"==typeof e){var s=0;do{if(s++,i=zw[e],o.debug("in renderCommitHistory",i.id,i.seq),t.select("#node-"+e).size()>0)return;t.append((function(){return Vw(t,"#def-commit")})).attr("class","commit").attr("id",(function(){return"node-"+i.id})).attr("transform",(function(){switch(r){case"LR":return"translate("+(i.seq*Uw.nodeSpacing+Uw.leftMargin)+", "+Pw*Uw.branchOffset+")";case"BT":return"translate("+(Pw*Uw.branchOffset+Uw.leftMargin)+", "+(a-i.seq)*Uw.nodeSpacing+")"}})).attr("fill",Uw.nodeFillColor).attr("stroke",Uw.nodeStrokeColor).attr("stroke-width",Uw.nodeStrokeWidth);var c=void 0;for(var u in n)if(n[u].commit===i){c=n[u];break}c&&(o.debug("found branch ",c.name),t.select("#node-"+i.id+" p").append("xhtml:span").attr("class","branch-label").text(c.name+", ")),t.select("#node-"+i.id+" p").append("xhtml:span").attr("class","commit-id").text(i.id),""!==i.message&&"BT"===r&&t.select("#node-"+i.id+" p").append("xhtml:span").attr("class","commit-msg").text(", "+i.message),e=i.parent}while(e&&zw[e]&&s<1e3)}Array.isArray(e)&&(o.debug("found merge commmit",e),Gw(t,e[0],n,r),Pw++,Gw(t,e[1],n,r),Pw--)}function Xw(t,e,n,r){r=r||0;for(var i=0;e.seq>0&&!e.lineDrawn&&i<1e3;)i++,"string"==typeof e.parent?(Ww(t,e.id,e.parent,n,r),e.lineDrawn=!0,e=zw[e.parent]):Array.isArray(e.parent)&&(Ww(t,e.id,e.parent[0],n,r),Ww(t,e.id,e.parent[1],n,r+1),Xw(t,zw[e.parent[1]],n,r+1),e.lineDrawn=!0,e=zw[e.parent[0]])}const Zw=function(t){qw=t};var Qw="",Kw=!1;const Jw={setMessage:function(t){o.debug("Setting message to: "+t),Qw=t},getMessage:function(){return Qw},setInfo:function(t){Kw=t},getInfo:function(){return Kw}};var tk=n(6765),ek=n.n(tk),nk={};const rk=function(t){Object.keys(t).forEach((function(e){nk[e]=t[e]}))};var ik=n(7062),ak=n.n(ik),ok={},sk="",ck=!1;const uk={parseDirective:function(t,e,n){cC.parseDirective(this,t,e,n)},getConfig:function(){return Jv().pie},addSection:function(t,e){void 0===ok[t]&&(ok[t]=e,o.debug("Added new section :",t))},getSections:function(){return ok},cleanupValue:function(t){return":"===t.substring(0,1)?(t=t.substring(1).trim(),Number(t.trim())):Number(t.trim())},clear:function(){ok={},sk="",ck=!1},setTitle:function(t){sk=t},getTitle:function(){return sk},setShowData:function(t){ck=t},getShowData:function(){return ck}};var lk,hk=Jv();const fk=function(t,e){try{hk=Jv();var n=ak().parser;n.yy=uk,o.debug("Rendering info diagram\n"+t),n.yy.clear(),n.parse(t),o.debug("Parsed info diagram");var r=document.getElementById(e);void 0===(lk=r.parentElement.offsetWidth)&&(lk=1200),void 0!==hk.useWidth&&(lk=hk.useWidth),void 0!==hk.pie.useWidth&&(lk=hk.pie.useWidth);var i=au("#"+e);zv(i,450,lk,hk.pie.useMaxWidth),r.setAttribute("viewBox","0 0 "+lk+" 450");var a=Math.min(lk,450)/2-40,s=i.append("g").attr("transform","translate("+lk/2+",225)"),c=uk.getSections(),u=0;Object.keys(c).forEach((function(t){u+=c[t]}));var l=hk.themeVariables,h=[l.pie1,l.pie2,l.pie3,l.pie4,l.pie5,l.pie6,l.pie7,l.pie8,l.pie9,l.pie10,l.pie11,l.pie12],f=ma().range(h),d=function(){var t=qu,e=Uu,n=null,r=pu(0),i=pu(Eu),a=pu(0);function o(o){var s,c,u,l,h,f=(o=Ru(o)).length,d=0,p=new Array(f),y=new Array(f),g=+r.apply(this,arguments),m=Math.min(Eu,Math.max(-Eu,i.apply(this,arguments)-g)),v=Math.min(Math.abs(m)/f,a.apply(this,arguments)),b=v*(m<0?-1:1);for(s=0;s<f;++s)(h=y[p[s]=s]=+t(o[s],s,o))>0&&(d+=h);for(null!=e?p.sort((function(t,n){return e(y[t],y[n])})):null!=n&&p.sort((function(t,e){return n(o[t],o[e])})),s=0,u=d?(m-f*b)/d:0;s<f;++s,g=l)c=p[s],l=g+((h=y[c])>0?h*u:0)+b,y[c]={data:o[c],index:s,value:h,startAngle:g,endAngle:l,padAngle:v};return y}return o.value=function(e){return arguments.length?(t="function"==typeof e?e:pu(+e),o):t},o.sortValues=function(t){return arguments.length?(e=t,n=null,o):e},o.sort=function(t){return arguments.length?(n=t,e=null,o):n},o.startAngle=function(t){return arguments.length?(r="function"==typeof t?t:pu(+t),o):r},o.endAngle=function(t){return arguments.length?(i="function"==typeof t?t:pu(+t),o):i},o.padAngle=function(t){return arguments.length?(a="function"==typeof t?t:pu(+t),o):a},o}().value((function(t){return t[1]})),p=d(Object.entries(c)),y=Iu().innerRadius(0).outerRadius(a);s.selectAll("mySlices").data(p).enter().append("path").attr("d",y).attr("fill",(function(t){return f(t.data[0])})).attr("class","pieCircle"),s.selectAll("mySlices").data(p).enter().append("text").text((function(t){return(t.data[1]/u*100).toFixed(0)+"%"})).attr("transform",(function(t){return"translate("+y.centroid(t)+")"})).style("text-anchor","middle").attr("class","slice"),s.append("text").text(n.yy.getTitle()).attr("x",0).attr("y",-200).attr("class","pieTitleText");var g=s.selectAll(".legend").data(f.domain()).enter().append("g").attr("class","legend").attr("transform",(function(t,e){return"translate(216,"+(22*e-22*f.domain().length/2)+")"}));g.append("rect").attr("width",18).attr("height",18).style("fill",f).style("stroke",f),g.data(p).append("text").attr("x",22).attr("y",14).text((function(t){return n.yy.getShowData()||hk.showData||hk.pie.showData?t.data[0]+" ["+t.data[1]+"]":t.data[0]}))}catch(t){o.error("Error while rendering info diagram"),o.error(t)}};var dk=n(3176),pk=n.n(dk),yk=[],gk={},mk={},vk={},bk={};const _k={RequirementType:{REQUIREMENT:"Requirement",FUNCTIONAL_REQUIREMENT:"Functional Requirement",INTERFACE_REQUIREMENT:"Interface Requirement",PERFORMANCE_REQUIREMENT:"Performance Requirement",PHYSICAL_REQUIREMENT:"Physical Requirement",DESIGN_CONSTRAINT:"Design Constraint"},RiskLevel:{LOW_RISK:"Low",MED_RISK:"Medium",HIGH_RISK:"High"},VerifyType:{VERIFY_ANALYSIS:"Analysis",VERIFY_DEMONSTRATION:"Demonstration",VERIFY_INSPECTION:"Inspection",VERIFY_TEST:"Test"},Relationships:{CONTAINS:"contains",COPIES:"copies",DERIVES:"derives",SATISFIES:"satisfies",VERIFIES:"verifies",REFINES:"refines",TRACES:"traces"},parseDirective:function(t,e,n){cC.parseDirective(this,t,e,n)},getConfig:function(){return Jv().req},addRequirement:function(t,e){return void 0===mk[t]&&(mk[t]={name:t,type:e,id:gk.id,text:gk.text,risk:gk.risk,verifyMethod:gk.verifyMethod}),gk={},mk[t]},getRequirements:function(){return mk},setNewReqId:function(t){void 0!==gk&&(gk.id=t)},setNewReqText:function(t){void 0!==gk&&(gk.text=t)},setNewReqRisk:function(t){void 0!==gk&&(gk.risk=t)},setNewReqVerifyMethod:function(t){void 0!==gk&&(gk.verifyMethod=t)},addElement:function(t){return void 0===bk[t]&&(bk[t]={name:t,type:vk.type,docRef:vk.docRef},o.info("Added new requirement: ",t)),vk={},bk[t]},getElements:function(){return bk},setNewElementType:function(t){void 0!==vk&&(vk.type=t)},setNewElementDocRef:function(t){void 0!==vk&&(vk.docRef=t)},addRelationship:function(t,e,n){yk.push({type:t,src:e,dst:n})},getRelationships:function(){return yk},clear:function(){yk=[],gk={},mk={},vk={},bk={}}};var xk={CONTAINS:"contains",ARROW:"arrow"};const wk=xk;var kk={},Tk=0,Ek=function(t,e){return t.insert("rect","#"+e).attr("class","req reqBox").attr("x",0).attr("y",0).attr("width",kk.rect_min_width+"px").attr("height",kk.rect_min_height+"px")},Ck=function(t,e,n){var r=kk.rect_min_width/2,i=t.append("text").attr("class","req reqLabel reqTitle").attr("id",e).attr("x",r).attr("y",kk.rect_padding).attr("dominant-baseline","hanging"),a=0;n.forEach((function(t){0==a?i.append("tspan").attr("text-anchor","middle").attr("x",kk.rect_min_width/2).attr("dy",0).text(t):i.append("tspan").attr("text-anchor","middle").attr("x",kk.rect_min_width/2).attr("dy",.75*kk.line_height).text(t),a++}));var o=1.5*kk.rect_padding+a*kk.line_height*.75;return t.append("line").attr("class","req-title-line").attr("x1","0").attr("x2",kk.rect_min_width).attr("y1",o).attr("y2",o),{titleNode:i,y:o}},Sk=function(t,e,n,r){var i=t.append("text").attr("class","req reqLabel").attr("id",e).attr("x",kk.rect_padding).attr("y",r).attr("dominant-baseline","hanging"),a=0,o=[];return n.forEach((function(t){for(var e=t.length;e>30&&a<3;){var n=t.substring(0,30);e=(t=t.substring(30,t.length)).length,o[o.length]=n,a++}if(3==a){var r=o[o.length-1];o[o.length-1]=r.substring(0,r.length-4)+"..."}else o[o.length]=t;a=0})),o.forEach((function(t){i.append("tspan").attr("x",kk.rect_padding).attr("dy",kk.line_height).text(t)})),i},Ak=function(t){return t.replace(/\s/g,"").replace(/\./g,"_")};const Mk=function(t){if(void 0!==t)for(var e=Object.keys(t),n=0;n<e.length;n++)kk[e[n]]=t[e[n]]},Nk=function(t,e){dk.parser.yy=_k,dk.parser.yy.clear(),dk.parser.parse(t);var n=au("[id='".concat(e,"']"));!function(t,e){var n=t.append("defs").append("marker").attr("id",xk.CONTAINS+"_line_ending").attr("refX",0).attr("refY",e.line_height/2).attr("markerWidth",e.line_height).attr("markerHeight",e.line_height).attr("orient","auto").append("g");n.append("circle").attr("cx",e.line_height/2).attr("cy",e.line_height/2).attr("r",e.line_height/2).attr("fill","none"),n.append("line").attr("x1",0).attr("x2",e.line_height).attr("y1",e.line_height/2).attr("y2",e.line_height/2).attr("stroke-width",1),n.append("line").attr("y1",0).attr("y2",e.line_height).attr("x1",e.line_height/2).attr("x2",e.line_height/2).attr("stroke-width",1),t.append("defs").append("marker").attr("id",xk.ARROW+"_line_ending").attr("refX",e.line_height).attr("refY",.5*e.line_height).attr("markerWidth",e.line_height).attr("markerHeight",e.line_height).attr("orient","auto").append("path").attr("d","M0,0\n      L".concat(e.line_height,",").concat(e.line_height/2,"\n      M").concat(e.line_height,",").concat(e.line_height/2,"\n      L0,").concat(e.line_height)).attr("stroke-width",1)}(n,kk);var r=new(kb().Graph)({multigraph:!1,compound:!1,directed:!0}).setGraph({rankdir:kk.layoutDirection,marginx:20,marginy:20,nodesep:100,edgesep:100,ranksep:100}).setDefaultEdgeLabel((function(){return{}})),i=_k.getRequirements(),a=_k.getElements(),s=_k.getRelationships();!function(t,e,n){Object.keys(t).forEach((function(r){var i=t[r];r=Ak(r),o.info("Added new requirement: ",r);var a=n.append("g").attr("id",r),s=Ek(a,"req-"+r),c=[],u=Ck(a,r+"_title",["<<".concat(i.type,">>"),"".concat(i.name)]);c.push(u.titleNode);var l=Sk(a,r+"_body",["Id: ".concat(i.id),"Text: ".concat(i.text),"Risk: ".concat(i.risk),"Verification: ".concat(i.verifyMethod)],u.y);c.push(l);var h=s.node().getBBox();e.setNode(r,{width:h.width,height:h.height,shape:"rect",id:r})}))}(i,r,n),function(t,e,n){Object.keys(t).forEach((function(r){var i=t[r],a=Ak(r),o=n.append("g").attr("id",a),s="element-"+a,c=Ek(o,s),u=[],l=Ck(o,s+"_title",["<<Element>>","".concat(r)]);u.push(l.titleNode);var h=Sk(o,s+"_body",["Type: ".concat(i.type||"Not Specified"),"Doc Ref: ".concat(i.docRef||"None")],l.y);u.push(h);var f=c.node().getBBox();e.setNode(a,{width:f.width,height:f.height,shape:"rect",id:a})}))}(a,r,n),function(t,e){t.forEach((function(t){var n=Ak(t.src),r=Ak(t.dst);e.setEdge(n,r,{relationship:t})}))}(s,r),xb().layout(r),function(t,e){e.nodes().forEach((function(n){void 0!==n&&void 0!==e.node(n)&&(t.select("#"+n),t.select("#"+n).attr("transform","translate("+(e.node(n).x-e.node(n).width/2)+","+(e.node(n).y-e.node(n).height/2)+" )"))}))}(n,r),s.forEach((function(t){!function(t,e,n,r){var i=n.edge(Ak(e.src),Ak(e.dst)),a=zu().x((function(t){return t.x})).y((function(t){return t.y})),o=t.insert("path","#"+r).attr("class","er relationshipLine").attr("d",a(i.points)).attr("fill","none");e.type==_k.Relationships.CONTAINS?o.attr("marker-start","url("+Um.getUrl(kk.arrowMarkerAbsolute)+"#"+e.type+"_line_ending)"):(o.attr("stroke-dasharray","10,7"),o.attr("marker-end","url("+Um.getUrl(kk.arrowMarkerAbsolute)+"#"+wk.ARROW+"_line_ending)")),function(t,e,n,r){var i=e.node().getTotalLength(),a=e.node().getPointAtLength(.5*i),o="rel"+Tk;Tk++;var s=t.append("text").attr("class","req relationshipLabel").attr("id",o).attr("x",a.x).attr("y",a.y).attr("text-anchor","middle").attr("dominant-baseline","middle").text(r).node().getBBox();t.insert("rect","#"+o).attr("class","req reqLabelBox").attr("x",a.x-s.width/2).attr("y",a.y-s.height/2).attr("width",s.width).attr("height",s.height).attr("fill","white").attr("fill-opacity","85%")}(t,o,0,"<<".concat(e.type,">>"))}(n,t,r,e)}));var c=kk.rect_padding,u=n.node().getBBox(),l=u.width+2*c,h=u.height+2*c;zv(n,h,l,kk.useMaxWidth),n.attr("viewBox","".concat(u.x-c," ").concat(u.y-c," ").concat(l," ").concat(h))};var Dk=n(6876),Ok=n.n(Dk),Bk=void 0,Lk={},Ik=[],Rk=[],Fk="",Pk=!1,jk=!1,Yk=!1,zk=function(t,e,n,r){var i=Lk[t];i&&e===i.name&&null==n||(null!=n&&null!=n.text||(n={text:e,wrap:null,type:r}),null!=r&&null!=n.text||(n={text:e,wrap:null,type:r}),Lk[t]={name:e,description:n.text,wrap:void 0===n.wrap&&$k()||!!n.wrap,prevActor:Bk,links:{},properties:{},actorCnt:null,rectData:null,type:r||"participant"},Bk&&Lk[Bk]&&(Lk[Bk].nextActor=t),Bk=t)},Uk=function(t){var e,n=0;for(e=0;e<Ik.length;e++)Ik[e].type===Wk.ACTIVE_START&&Ik[e].from.actor===t&&n++,Ik[e].type===Wk.ACTIVE_END&&Ik[e].from.actor===t&&n--;return n},qk=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{text:void 0,wrap:void 0},r=arguments.length>3?arguments[3]:void 0;if(r===Wk.ACTIVE_END){var i=Uk(t.actor);if(i<1){var a=new Error("Trying to inactivate an inactive participant ("+t.actor+")");throw a.hash={text:"->>-",token:"->>-",line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["'ACTIVE_PARTICIPANT'"]},a}}return Ik.push({from:t,to:e,message:n.text,wrap:void 0===n.wrap&&$k()||!!n.wrap,type:r}),!0},Hk=function(t){return Lk[t]},$k=function(){return Yk},Wk={SOLID:0,DOTTED:1,NOTE:2,SOLID_CROSS:3,DOTTED_CROSS:4,SOLID_OPEN:5,DOTTED_OPEN:6,LOOP_START:10,LOOP_END:11,ALT_START:12,ALT_ELSE:13,ALT_END:14,OPT_START:15,OPT_END:16,ACTIVE_START:17,ACTIVE_END:18,PAR_START:19,PAR_AND:20,PAR_END:21,RECT_START:22,RECT_END:23,SOLID_POINT:24,DOTTED_POINT:25},Vk=function(t,e,n){var r={actor:t,placement:e,message:n.text,wrap:void 0===n.wrap&&$k()||!!n.wrap},i=[].concat(t,t);Rk.push(r),Ik.push({from:i[0],to:i[1],message:n.text,wrap:void 0===n.wrap&&$k()||!!n.wrap,type:Wk.NOTE,placement:e})},Gk=function(t,e){var n=Hk(t);try{var r=Fm(e.text,Jv());r=(r=r.replace(/&amp;/g,"&")).replace(/&equals;/g,"="),Xk(n,JSON.parse(r))}catch(t){o.error("error while parsing actor link text",t)}};function Xk(t,e){if(null==t.links)t.links=e;else for(var n in e)t.links[n]=e[n]}var Zk=function(t,e){var n=Hk(t);try{var r=Fm(e.text,Jv());Qk(n,JSON.parse(r))}catch(t){o.error("error while parsing actor properties text",t)}};function Qk(t,e){if(null==t.properties)t.properties=e;else for(var n in e)t.properties[n]=e[n]}var Kk=function(t,e){var n=Hk(t),r=document.getElementById(e.text);try{var i=r.innerHTML,a=JSON.parse(i);a.properties&&Qk(n,a.properties),a.links&&Xk(n,a.links)}catch(t){o.error("error while parsing actor details text",t)}},Jk=function(t){Fk=t.text,Pk=void 0===t.wrap&&$k()||!!t.wrap};const tT={addActor:zk,addMessage:function(t,e,n,r){Ik.push({from:t,to:e,message:n.text,wrap:void 0===n.wrap&&$k()||!!n.wrap,answer:r})},addSignal:qk,addLinks:Gk,addDetails:Kk,addProperties:Zk,autoWrap:$k,setWrap:function(t){Yk=t},enableSequenceNumbers:function(){jk=!0},showSequenceNumbers:function(){return jk},getMessages:function(){return Ik},getActors:function(){return Lk},getActor:Hk,getActorKeys:function(){return Object.keys(Lk)},getActorProperty:function(t,e){if(void 0!==t&&void 0!==t.properties)return t.properties[e]},getTitle:function(){return Fk},parseDirective:function(t,e,n){cC.parseDirective(this,t,e,n)},getConfig:function(){return Jv().sequence},getTitleWrapped:function(){return Pk},clear:function(){Lk={},Ik=[]},parseMessage:function(t){var e=t.trim(),n={text:e.replace(/^[:]?(?:no)?wrap:/,"").trim(),wrap:null!==e.match(/^[:]?wrap:/)||null===e.match(/^[:]?nowrap:/)&&void 0};return o.debug("parseMessage:",n),n},LINETYPE:Wk,ARROWTYPE:{FILLED:0,OPEN:1},PLACEMENT:{LEFTOF:0,RIGHTOF:1,OVER:2},addNote:Vk,setTitle:Jk,apply:function t(e){if(e instanceof Array)e.forEach((function(e){t(e)}));else switch(e.type){case"addParticipant":zk(e.actor,e.actor,e.description,"participant");break;case"addActor":zk(e.actor,e.actor,e.description,"actor");break;case"activeStart":case"activeEnd":qk(e.actor,void 0,void 0,e.signalType);break;case"addNote":Vk(e.actor,e.placement,e.text);break;case"addLinks":Gk(e.actor,e.text);break;case"addALink":!function(t,e){var n=Hk(t);try{var r={},i=Fm(e.text,Jv()),a=i.indexOf("@"),s=(i=(i=i.replace(/&amp;/g,"&")).replace(/&equals;/g,"=")).slice(0,a-1).trim(),c=i.slice(a+1).trim();r[s]=c,Xk(n,r)}catch(t){o.error("error while parsing actor link text",t)}}(e.actor,e.text);break;case"addProperties":Zk(e.actor,e.text);break;case"addDetails":Kk(e.actor,e.text);break;case"addMessage":qk(e.from,e.to,e.msg,e.signalType);break;case"loopStart":qk(void 0,void 0,e.loopText,e.signalType);break;case"loopEnd":case"rectEnd":case"optEnd":case"altEnd":case"parEnd":qk(void 0,void 0,void 0,e.signalType);break;case"rectStart":qk(void 0,void 0,e.color,e.signalType);break;case"optStart":qk(void 0,void 0,e.optText,e.signalType);break;case"altStart":case"else":qk(void 0,void 0,e.altText,e.signalType);break;case"setTitle":Jk(e.text);break;case"parStart":case"and":qk(void 0,void 0,e.parText,e.signalType)}}};var eT=[],nT=function(t,e){var n=t.append("rect");return n.attr("x",e.x),n.attr("y",e.y),n.attr("fill",e.fill),n.attr("stroke",e.stroke),n.attr("width",e.width),n.attr("height",e.height),n.attr("rx",e.rx),n.attr("ry",e.ry),void 0!==e.class&&n.attr("class",e.class),n},rT=function(t,e){var n;n=function(){var n=document.querySelectorAll(t);n[0].addEventListener("mouseover",(function(){oT("actor"+e+"_popup")})),n[0].addEventListener("mouseout",(function(){sT("actor"+e+"_popup")}))},eT.push(n)},iT=function(t,e,n,r){var i=t.append("image");i.attr("x",e),i.attr("y",n);var a=(0,Om.sanitizeUrl)(r);i.attr("xlink:href",a)},aT=function(t,e,n,r){var i=t.append("use");i.attr("x",e),i.attr("y",n);var a=(0,Om.sanitizeUrl)(r);i.attr("xlink:href","#"+a)},oT=function(t){var e=document.getElementById(t);null!=e&&(e.style.display="block")},sT=function(t){var e=document.getElementById(t);null!=e&&(e.style.display="none")},cT=function(t,e){var n=0,r=0,i=e.text.split(Um.lineBreakRegex),a=[],o=0,s=function(){return e.y};if(void 0!==e.valign&&void 0!==e.textMargin&&e.textMargin>0)switch(e.valign){case"top":case"start":s=function(){return Math.round(e.y+e.textMargin)};break;case"middle":case"center":s=function(){return Math.round(e.y+(n+r+e.textMargin)/2)};break;case"bottom":case"end":s=function(){return Math.round(e.y+(n+r+2*e.textMargin)-e.textMargin)}}if(void 0!==e.anchor&&void 0!==e.textMargin&&void 0!==e.width)switch(e.anchor){case"left":case"start":e.x=Math.round(e.x+e.textMargin),e.anchor="start",e.dominantBaseline="text-after-edge",e.alignmentBaseline="middle";break;case"middle":case"center":e.x=Math.round(e.x+e.width/2),e.anchor="middle",e.dominantBaseline="middle",e.alignmentBaseline="middle";break;case"right":case"end":e.x=Math.round(e.x+e.width-e.textMargin),e.anchor="end",e.dominantBaseline="text-before-edge",e.alignmentBaseline="middle"}for(var c=0;c<i.length;c++){var u=i[c];void 0!==e.textMargin&&0===e.textMargin&&void 0!==e.fontSize&&(o=c*e.fontSize);var l=t.append("text");if(l.attr("x",e.x),l.attr("y",s()),void 0!==e.anchor&&l.attr("text-anchor",e.anchor).attr("dominant-baseline",e.dominantBaseline).attr("alignment-baseline",e.alignmentBaseline),void 0!==e.fontFamily&&l.style("font-family",e.fontFamily),void 0!==e.fontSize&&l.style("font-size",e.fontSize),void 0!==e.fontWeight&&l.style("font-weight",e.fontWeight),void 0!==e.fill&&l.attr("fill",e.fill),void 0!==e.class&&l.attr("class",e.class),void 0!==e.dy?l.attr("dy",e.dy):0!==o&&l.attr("dy",o),e.tspan){var h=l.append("tspan");h.attr("x",e.x),void 0!==e.fill&&h.attr("fill",e.fill),h.text(u)}else l.text(u);void 0!==e.valign&&void 0!==e.textMargin&&e.textMargin>0&&(r+=(l._groups||l)[0][0].getBBox().height,n=r),a.push(l)}return a},uT=function(t,e){var n=t.append("polygon");return n.attr("points",function(t,e,n,r,i){return t+","+e+" "+(t+n)+","+e+" "+(t+n)+","+(e+r-7)+" "+(t+n-8.4)+","+(e+r)+" "+t+","+(e+r)}(e.x,e.y,e.width,e.height)),n.attr("class","labelBox"),e.y=e.y+e.height/2,cT(t,e),n},lT=-1,hT=function(t,e){t.selectAll&&t.selectAll(".actor-line").attr("class","200").attr("y2",e-55)},fT=function(){return{x:0,y:0,fill:void 0,anchor:void 0,style:"#666",width:void 0,height:void 0,textMargin:0,rx:0,ry:0,tspan:!0,valign:void 0}},dT=function(){return{x:0,y:0,fill:"#EDF2AE",stroke:"#666",width:100,anchor:"start",height:100,rx:0,ry:0}},pT=function(){function t(t,e,n,i,a,o,s){r(e.append("text").attr("x",n+a/2).attr("y",i+o/2+5).style("text-anchor","middle").text(t),s)}function e(t,e,n,i,a,o,s,c){for(var u=c.actorFontSize,l=c.actorFontFamily,h=c.actorFontWeight,f=t.split(Um.lineBreakRegex),d=0;d<f.length;d++){var p=d*u-u*(f.length-1)/2,y=e.append("text").attr("x",n+a/2).attr("y",i).style("text-anchor","middle").style("font-size",u).style("font-weight",h).style("font-family",l);y.append("tspan").attr("x",n+a/2).attr("dy",p).text(f[d]),y.attr("y",i+o/2).attr("dominant-baseline","central").attr("alignment-baseline","central"),r(y,s)}}function n(t,n,i,a,o,s,c,u){var l=n.append("switch"),h=l.append("foreignObject").attr("x",i).attr("y",a).attr("width",o).attr("height",s).append("xhtml:div").style("display","table").style("height","100%").style("width","100%");h.append("div").style("display","table-cell").style("text-align","center").style("vertical-align","middle").text(t),e(t,l,i,a,o,s,c,u),r(h,c)}function r(t,e){for(var n in e)e.hasOwnProperty(n)&&t.attr(n,e[n])}return function(r){return"fo"===r.textPlacement?n:"old"===r.textPlacement?t:e}}(),yT=function(){function t(t,e,n,i,a,o,s){r(e.append("text").attr("x",n).attr("y",i).style("text-anchor","start").text(t),s)}function e(t,e,n,i,a,o,s,c){for(var u=c.actorFontSize,l=c.actorFontFamily,h=c.actorFontWeight,f=t.split(Um.lineBreakRegex),d=0;d<f.length;d++){var p=d*u-u*(f.length-1)/2,y=e.append("text").attr("x",n).attr("y",i).style("text-anchor","start").style("font-size",u).style("font-weight",h).style("font-family",l);y.append("tspan").attr("x",n).attr("dy",p).text(f[d]),y.attr("y",i+o/2).attr("dominant-baseline","central").attr("alignment-baseline","central"),r(y,s)}}function n(t,n,i,a,o,s,c,u){var l=n.append("switch"),h=l.append("foreignObject").attr("x",i).attr("y",a).attr("width",o).attr("height",s).append("xhtml:div").style("display","table").style("height","100%").style("width","100%");h.append("div").style("display","table-cell").style("text-align","center").style("vertical-align","middle").text(t),e(t,l,i,a,0,s,c,u),r(h,c)}function r(t,e){for(var n in e)e.hasOwnProperty(n)&&t.attr(n,e[n])}return function(r){return"fo"===r.textPlacement?n:"old"===r.textPlacement?t:e}}();const gT=nT,mT=function(t,e,n){switch(e.type){case"actor":return function(t,e,n){var r=e.x+e.width/2;0===e.y&&(lT++,t.append("line").attr("id","actor"+lT).attr("x1",r).attr("y1",80).attr("x2",r).attr("y2",2e3).attr("class","actor-line").attr("stroke-width","0.5px").attr("stroke","#999"));var i=t.append("g");i.attr("class","actor-man");var a={x:0,y:0,fill:"#EDF2AE",stroke:"#666",width:100,anchor:"start",height:100,rx:0,ry:0};a.x=e.x,a.y=e.y,a.fill="#eaeaea",a.width=e.width,a.height=e.height,a.class="actor",a.rx=3,a.ry=3,i.append("line").attr("id","actor-man-torso"+lT).attr("x1",r).attr("y1",e.y+25).attr("x2",r).attr("y2",e.y+45),i.append("line").attr("id","actor-man-arms"+lT).attr("x1",r-18).attr("y1",e.y+33).attr("x2",r+18).attr("y2",e.y+33),i.append("line").attr("x1",r-18).attr("y1",e.y+60).attr("x2",r).attr("y2",e.y+45),i.append("line").attr("x1",r).attr("y1",e.y+45).attr("x2",r+16).attr("y2",e.y+60);var o=i.append("circle");o.attr("cx",e.x+e.width/2),o.attr("cy",e.y+10),o.attr("r",15),o.attr("width",e.width),o.attr("height",e.height);var s=i.node().getBBox();return e.height=s.height,pT(n)(e.description,i,a.x,a.y+35,a.width,a.height,{class:"actor"},n),e.height}(t,e,n);case"participant":return function(t,e,n){var r=e.x+e.width/2,i=t.append("g"),a=i;0===e.y&&(lT++,a.append("line").attr("id","actor"+lT).attr("x1",r).attr("y1",5).attr("x2",r).attr("y2",2e3).attr("class","actor-line").attr("stroke-width","0.5px").attr("stroke","#999"),a=i.append("g"),e.actorCnt=lT,null!=e.links&&(a.attr("id","root-"+lT),rT("#root-"+lT,lT)));var o={x:0,y:0,fill:"#EDF2AE",stroke:"#666",width:100,anchor:"start",height:100,rx:0,ry:0},s="actor";null!=e.properties&&e.properties.class?s=e.properties.class:o.fill="#eaeaea",o.x=e.x,o.y=e.y,o.width=e.width,o.height=e.height,o.class=s,o.rx=3,o.ry=3;var c=nT(a,o);if(e.rectData=o,null!=e.properties&&e.properties.icon){var u=e.properties.icon.trim();"@"===u.charAt(0)?aT(a,o.x+o.width-20,o.y+10,u.substr(1)):iT(a,o.x+o.width-20,o.y+10,u)}pT(n)(e.description,a,o.x,o.y,o.width,o.height,{class:"actor"},n);var l=e.height;if(c.node){var h=c.node().getBBox();e.height=h.height,l=h.height}return l}(t,e,n)}},vT=function(t,e,n,r,i){if(void 0===e.links||null===e.links||0===Object.keys(e.links).length)return{height:0,width:0};var a=e.links,o=e.actorCnt,s=e.rectData,c="none";i&&(c="block !important");var u=t.append("g");u.attr("id","actor"+o+"_popup"),u.attr("class","actorPopupMenu"),u.attr("display",c),rT("#actor"+o+"_popup",o);var l="";void 0!==s.class&&(l=" "+s.class);var h=s.width>n?s.width:n,f=u.append("rect");if(f.attr("class","actorPopupMenuPanel"+l),f.attr("x",s.x),f.attr("y",s.height),f.attr("fill",s.fill),f.attr("stroke",s.stroke),f.attr("width",h),f.attr("height",s.height),f.attr("rx",s.rx),f.attr("ry",s.ry),null!=a){var d=20;for(var p in a){var y=u.append("a"),g=(0,Om.sanitizeUrl)(a[p]);y.attr("xlink:href",g),y.attr("target","_blank"),yT(r)(p,y,s.x+10,s.height+d,h,20,{class:"actor"},r),d+=30}}return f.attr("height",d),{height:s.height+d,width:h}},bT=function(t){return t.append("g")},_T=function(t,e,n,r,i){var a={x:0,y:0,fill:"#EDF2AE",stroke:"#666",width:100,anchor:"start",height:100,rx:0,ry:0},o=e.anchored;a.x=e.startx,a.y=e.starty,a.class="activation"+i%3,a.width=e.stopx-e.startx,a.height=n-e.starty,nT(o,a)},xT=function(t,e,n,r){var i=r.boxMargin,a=r.boxTextMargin,o=r.labelBoxHeight,s=r.labelBoxWidth,c=r.messageFontFamily,u=r.messageFontSize,l=r.messageFontWeight,h=t.append("g"),f=function(t,e,n,r){return h.append("line").attr("x1",t).attr("y1",e).attr("x2",n).attr("y2",r).attr("class","loopLine")};f(e.startx,e.starty,e.stopx,e.starty),f(e.stopx,e.starty,e.stopx,e.stopy),f(e.startx,e.stopy,e.stopx,e.stopy),f(e.startx,e.starty,e.startx,e.stopy),void 0!==e.sections&&e.sections.forEach((function(t){f(e.startx,t.y,e.stopx,t.y).style("stroke-dasharray","3, 3")}));var d={x:0,y:0,fill:void 0,anchor:void 0,style:"#666",width:void 0,height:void 0,textMargin:0,rx:0,ry:0,tspan:!0,valign:void 0};d.text=n,d.x=e.startx,d.y=e.starty,d.fontFamily=c,d.fontSize=u,d.fontWeight=l,d.anchor="middle",d.valign="middle",d.tspan=!1,d.width=s||50,d.height=o||20,d.textMargin=a,d.class="labelText",uT(h,d),(d={x:0,y:0,fill:void 0,anchor:void 0,style:"#666",width:void 0,height:void 0,textMargin:0,rx:0,ry:0,tspan:!0,valign:void 0}).text=e.title,d.x=e.startx+s/2+(e.stopx-e.startx)/2,d.y=e.starty+i+a,d.anchor="middle",d.valign="middle",d.textMargin=a,d.class="loopText",d.fontFamily=c,d.fontSize=u,d.fontWeight=l,d.wrap=!0;var p=cT(h,d);return void 0!==e.sectionTitles&&e.sectionTitles.forEach((function(t,n){if(t.message){d.text=t.message,d.x=e.startx+(e.stopx-e.startx)/2,d.y=e.sections[n].y+i+a,d.class="loopText",d.anchor="middle",d.valign="middle",d.tspan=!1,d.fontFamily=c,d.fontSize=u,d.fontWeight=l,d.wrap=e.wrap,p=cT(h,d);var r=Math.round(p.map((function(t){return(t._groups||t)[0][0].getBBox().height})).reduce((function(t,e){return t+e})));e.sections[n].height+=r-(i+a)}})),e.height=Math.round(e.stopy-e.starty),h},wT=function(t,e){nT(t,{x:e.startx,y:e.starty,width:e.stopx-e.startx,height:e.stopy-e.starty,fill:e.fill,class:"rect"}).lower()},kT=function(t){t.append("defs").append("marker").attr("id","arrowhead").attr("refX",9).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z")},TT=function(t){t.append("defs").append("marker").attr("id","filled-head").attr("refX",18).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},ET=function(t){t.append("defs").append("marker").attr("id","sequencenumber").attr("refX",15).attr("refY",15).attr("markerWidth",60).attr("markerHeight",40).attr("orient","auto").append("circle").attr("cx",15).attr("cy",15).attr("r",6)},CT=function(t){var e=t.append("defs").append("marker").attr("id","crosshead").attr("markerWidth",15).attr("markerHeight",8).attr("orient","auto").attr("refX",16).attr("refY",4);e.append("path").attr("fill","black").attr("stroke","#000000").style("stroke-dasharray","0, 0").attr("stroke-width","1px").attr("d","M 9,2 V 6 L16,4 Z"),e.append("path").attr("fill","none").attr("stroke","#000000").style("stroke-dasharray","0, 0").attr("stroke-width","1px").attr("d","M 0,1 L 6,7 M 6,1 L 0,7")},ST=function(t){t.append("defs").append("symbol").attr("id","database").attr("fill-rule","evenodd").attr("clip-rule","evenodd").append("path").attr("transform","scale(.5)").attr("d","M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z")},AT=function(t){t.append("defs").append("symbol").attr("id","computer").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z")},MT=function(t){t.append("defs").append("symbol").attr("id","clock").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z")},NT=fT,DT=dT;Om.sanitizeUrl;Dk.parser.yy=tT;var OT={},BT={data:{startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},verticalPos:0,sequenceItems:[],activations:[],models:{getHeight:function(){return Math.max.apply(null,0===this.actors.length?[0]:this.actors.map((function(t){return t.height||0})))+(0===this.loops.length?0:this.loops.map((function(t){return t.height||0})).reduce((function(t,e){return t+e})))+(0===this.messages.length?0:this.messages.map((function(t){return t.height||0})).reduce((function(t,e){return t+e})))+(0===this.notes.length?0:this.notes.map((function(t){return t.height||0})).reduce((function(t,e){return t+e})))},clear:function(){this.actors=[],this.loops=[],this.messages=[],this.notes=[]},addActor:function(t){this.actors.push(t)},addLoop:function(t){this.loops.push(t)},addMessage:function(t){this.messages.push(t)},addNote:function(t){this.notes.push(t)},lastActor:function(){return this.actors[this.actors.length-1]},lastLoop:function(){return this.loops[this.loops.length-1]},lastMessage:function(){return this.messages[this.messages.length-1]},lastNote:function(){return this.notes[this.notes.length-1]},actors:[],loops:[],messages:[],notes:[]},init:function(){this.sequenceItems=[],this.activations=[],this.models.clear(),this.data={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},this.verticalPos=0,jT(Dk.parser.yy.getConfig())},updateVal:function(t,e,n,r){void 0===t[e]?t[e]=n:t[e]=r(n,t[e])},updateBounds:function(t,e,n,r){var i=this,a=0;function o(o){return function(s){a++;var c=i.sequenceItems.length-a+1;i.updateVal(s,"starty",e-c*OT.boxMargin,Math.min),i.updateVal(s,"stopy",r+c*OT.boxMargin,Math.max),i.updateVal(BT.data,"startx",t-c*OT.boxMargin,Math.min),i.updateVal(BT.data,"stopx",n+c*OT.boxMargin,Math.max),"activation"!==o&&(i.updateVal(s,"startx",t-c*OT.boxMargin,Math.min),i.updateVal(s,"stopx",n+c*OT.boxMargin,Math.max),i.updateVal(BT.data,"starty",e-c*OT.boxMargin,Math.min),i.updateVal(BT.data,"stopy",r+c*OT.boxMargin,Math.max))}}this.sequenceItems.forEach(o()),this.activations.forEach(o("activation"))},insert:function(t,e,n,r){var i=Math.min(t,n),a=Math.max(t,n),o=Math.min(e,r),s=Math.max(e,r);this.updateVal(BT.data,"startx",i,Math.min),this.updateVal(BT.data,"starty",o,Math.min),this.updateVal(BT.data,"stopx",a,Math.max),this.updateVal(BT.data,"stopy",s,Math.max),this.updateBounds(i,o,a,s)},newActivation:function(t,e,n){var r=n[t.from.actor],i=YT(t.from.actor).length||0,a=r.x+r.width/2+(i-1)*OT.activationWidth/2;this.activations.push({startx:a,starty:this.verticalPos+2,stopx:a+OT.activationWidth,stopy:void 0,actor:t.from.actor,anchored:bT(e)})},endActivation:function(t){var e=this.activations.map((function(t){return t.actor})).lastIndexOf(t.from.actor);return this.activations.splice(e,1)[0]},createLoop:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{message:void 0,wrap:!1,width:void 0},e=arguments.length>1?arguments[1]:void 0;return{startx:void 0,starty:this.verticalPos,stopx:void 0,stopy:void 0,title:t.message,wrap:t.wrap,width:t.width,height:0,fill:e}},newLoop:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{message:void 0,wrap:!1,width:void 0},e=arguments.length>1?arguments[1]:void 0;this.sequenceItems.push(this.createLoop(t,e))},endLoop:function(){return this.sequenceItems.pop()},addSectionToLoop:function(t){var e=this.sequenceItems.pop();e.sections=e.sections||[],e.sectionTitles=e.sectionTitles||[],e.sections.push({y:BT.getVerticalPos(),height:0}),e.sectionTitles.push(t),this.sequenceItems.push(e)},bumpVerticalPos:function(t){this.verticalPos=this.verticalPos+t,this.data.stopy=this.verticalPos},getVerticalPos:function(){return this.verticalPos},getBounds:function(){return{bounds:this.data,models:this.models}}},LT=function(t){return{fontFamily:t.messageFontFamily,fontSize:t.messageFontSize,fontWeight:t.messageFontWeight}},IT=function(t){return{fontFamily:t.noteFontFamily,fontSize:t.noteFontSize,fontWeight:t.noteFontWeight}},RT=function(t){return{fontFamily:t.actorFontFamily,fontSize:t.actorFontSize,fontWeight:t.actorFontWeight}},FT=function(t,e,n,r){for(var i=0,a=0,o=0,s=0;s<n.length;s++){var c=e[n[s]];c.width=c.width||OT.width,c.height=Math.max(c.height||OT.height,OT.height),c.margin=c.margin||OT.actorMargin,c.x=i+a,c.y=r;var u=mT(t,c,OT);o=Math.max(o,u),BT.insert(c.x,r,c.x+c.width,c.height),i+=c.width,a+=c.margin,BT.models.addActor(c)}BT.bumpVerticalPos(o)},PT=function(t,e,n){for(var r=0,i=0,a=0;a<n.length;a++){var o=e[n[a]],s=qT(o),c=vT(t,o,s,OT,OT.forceMenus);c.height>r&&(r=c.height),c.width+o.x>i&&(i=c.width+o.x)}return{maxHeight:r,maxWidth:i}},jT=function(t){Lv(OT,t),t.fontFamily&&(OT.actorFontFamily=OT.noteFontFamily=OT.messageFontFamily=t.fontFamily),t.fontSize&&(OT.actorFontSize=OT.noteFontSize=OT.messageFontSize=t.fontSize),t.fontWeight&&(OT.actorFontWeight=OT.noteFontWeight=OT.messageFontWeight=t.fontWeight)},YT=function(t){return BT.activations.filter((function(e){return e.actor===t}))},zT=function(t,e){var n=e[t],r=YT(t);return[r.reduce((function(t,e){return Math.min(t,e.startx)}),n.x+n.width/2),r.reduce((function(t,e){return Math.max(t,e.stopx)}),n.x+n.width/2)]};function UT(t,e,n,r,i){BT.bumpVerticalPos(n);var a=r;if(e.id&&e.message&&t[e.id]){var s=t[e.id].width,c=LT(OT);e.message=Hv.wrapLabel("[".concat(e.message,"]"),s-2*OT.wrapPadding,c),e.width=s,e.wrap=!0;var u=Hv.calculateTextDimensions(e.message,c),l=Math.max(u.height,OT.labelBoxHeight);a=r+l,o.debug("".concat(l," - ").concat(e.message))}i(e),BT.bumpVerticalPos(a)}var qT=function(t){var e=0,n=RT(OT);for(var r in t.links){var i=Hv.calculateTextDimensions(r,n).width+2*OT.wrapPadding+2*OT.boxMargin;e<i&&(e=i)}return e};const HT={bounds:BT,drawActors:FT,drawActorsPopup:PT,setConf:jT,draw:function(t,e){OT=Jv().sequence,Dk.parser.yy.clear(),Dk.parser.yy.setWrap(OT.wrap),Dk.parser.parse(t+"\n"),BT.init(),o.debug("C:".concat(JSON.stringify(OT,null,2)));var n=au('[id="'.concat(e,'"]')),r=Dk.parser.yy.getActors(),i=Dk.parser.yy.getActorKeys(),a=Dk.parser.yy.getMessages(),s=Dk.parser.yy.getTitle(),c=function(t,e){var n={};return e.forEach((function(e){if(t[e.to]&&t[e.from]){var r=t[e.to];if(e.placement===Dk.parser.yy.PLACEMENT.LEFTOF&&!r.prevActor)return;if(e.placement===Dk.parser.yy.PLACEMENT.RIGHTOF&&!r.nextActor)return;var i=void 0!==e.placement,a=!i,o=i?IT(OT):LT(OT),s=e.wrap?Hv.wrapLabel(e.message,OT.width-2*OT.wrapPadding,o):e.message,c=Hv.calculateTextDimensions(s,o).width+2*OT.wrapPadding;a&&e.from===r.nextActor?n[e.to]=Math.max(n[e.to]||0,c):a&&e.from===r.prevActor?n[e.from]=Math.max(n[e.from]||0,c):a&&e.from===e.to?(n[e.from]=Math.max(n[e.from]||0,c/2),n[e.to]=Math.max(n[e.to]||0,c/2)):e.placement===Dk.parser.yy.PLACEMENT.RIGHTOF?n[e.from]=Math.max(n[e.from]||0,c):e.placement===Dk.parser.yy.PLACEMENT.LEFTOF?n[r.prevActor]=Math.max(n[r.prevActor]||0,c):e.placement===Dk.parser.yy.PLACEMENT.OVER&&(r.prevActor&&(n[r.prevActor]=Math.max(n[r.prevActor]||0,c/2)),r.nextActor&&(n[e.from]=Math.max(n[e.from]||0,c/2)))}})),o.debug("maxMessageWidthPerActor:",n),n}(r,a);OT.height=function(t,e){var n=0;for(var r in Object.keys(t).forEach((function(e){var r=t[e];r.wrap&&(r.description=Hv.wrapLabel(r.description,OT.width-2*OT.wrapPadding,RT(OT)));var i=Hv.calculateTextDimensions(r.description,RT(OT));r.width=r.wrap?OT.width:Math.max(OT.width,i.width+2*OT.wrapPadding),r.height=r.wrap?Math.max(i.height,OT.height):OT.height,n=Math.max(n,r.height)})),e){var i=t[r];if(i){var a=t[i.nextActor];if(a){var o=e[r]+OT.actorMargin-i.width/2-a.width/2;i.margin=Math.max(o,OT.actorMargin)}}}return Math.max(n,OT.height)}(r,c),AT(n),ST(n),MT(n),FT(n,r,i,0);var u=function(t,e){var n,r,i,a={},s=[];return t.forEach((function(t){switch(t.id=Hv.random({length:10}),t.type){case Dk.parser.yy.LINETYPE.LOOP_START:case Dk.parser.yy.LINETYPE.ALT_START:case Dk.parser.yy.LINETYPE.OPT_START:case Dk.parser.yy.LINETYPE.PAR_START:s.push({id:t.id,msg:t.message,from:Number.MAX_SAFE_INTEGER,to:Number.MIN_SAFE_INTEGER,width:0});break;case Dk.parser.yy.LINETYPE.ALT_ELSE:case Dk.parser.yy.LINETYPE.PAR_AND:t.message&&(n=s.pop(),a[n.id]=n,a[t.id]=n,s.push(n));break;case Dk.parser.yy.LINETYPE.LOOP_END:case Dk.parser.yy.LINETYPE.ALT_END:case Dk.parser.yy.LINETYPE.OPT_END:case Dk.parser.yy.LINETYPE.PAR_END:n=s.pop(),a[n.id]=n;break;case Dk.parser.yy.LINETYPE.ACTIVE_START:var c=e[t.from?t.from.actor:t.to.actor],u=YT(t.from?t.from.actor:t.to.actor).length,l=c.x+c.width/2+(u-1)*OT.activationWidth/2,h={startx:l,stopx:l+OT.activationWidth,actor:t.from.actor,enabled:!0};BT.activations.push(h);break;case Dk.parser.yy.LINETYPE.ACTIVE_END:var f=BT.activations.map((function(t){return t.actor})).lastIndexOf(t.from.actor);delete BT.activations.splice(f,1)[0]}void 0!==t.placement?(r=function(t,e){var n=e[t.from].x,r=e[t.to].x,i=t.wrap&&t.message,a=Hv.calculateTextDimensions(i?Hv.wrapLabel(t.message,OT.width,IT(OT)):t.message,IT(OT)),s={width:i?OT.width:Math.max(OT.width,a.width+2*OT.noteMargin),height:0,startx:e[t.from].x,stopx:0,starty:0,stopy:0,message:t.message};return t.placement===Dk.parser.yy.PLACEMENT.RIGHTOF?(s.width=i?Math.max(OT.width,a.width):Math.max(e[t.from].width/2+e[t.to].width/2,a.width+2*OT.noteMargin),s.startx=n+(e[t.from].width+OT.actorMargin)/2):t.placement===Dk.parser.yy.PLACEMENT.LEFTOF?(s.width=i?Math.max(OT.width,a.width+2*OT.noteMargin):Math.max(e[t.from].width/2+e[t.to].width/2,a.width+2*OT.noteMargin),s.startx=n-s.width+(e[t.from].width-OT.actorMargin)/2):t.to===t.from?(a=Hv.calculateTextDimensions(i?Hv.wrapLabel(t.message,Math.max(OT.width,e[t.from].width),IT(OT)):t.message,IT(OT)),s.width=i?Math.max(OT.width,e[t.from].width):Math.max(e[t.from].width,OT.width,a.width+2*OT.noteMargin),s.startx=n+(e[t.from].width-s.width)/2):(s.width=Math.abs(n+e[t.from].width/2-(r+e[t.to].width/2))+OT.actorMargin,s.startx=n<r?n+e[t.from].width/2-OT.actorMargin/2:r+e[t.to].width/2-OT.actorMargin/2),i&&(s.message=Hv.wrapLabel(t.message,s.width-2*OT.wrapPadding,IT(OT))),o.debug("NM:[".concat(s.startx,",").concat(s.stopx,",").concat(s.starty,",").concat(s.stopy,":").concat(s.width,",").concat(s.height,"=").concat(t.message,"]")),s}(t,e),t.noteModel=r,s.forEach((function(t){(n=t).from=Math.min(n.from,r.startx),n.to=Math.max(n.to,r.startx+r.width),n.width=Math.max(n.width,Math.abs(n.from-n.to))-OT.labelBoxWidth}))):(i=function(t,e){var n=!1;if([Dk.parser.yy.LINETYPE.SOLID_OPEN,Dk.parser.yy.LINETYPE.DOTTED_OPEN,Dk.parser.yy.LINETYPE.SOLID,Dk.parser.yy.LINETYPE.DOTTED,Dk.parser.yy.LINETYPE.SOLID_CROSS,Dk.parser.yy.LINETYPE.DOTTED_CROSS,Dk.parser.yy.LINETYPE.SOLID_POINT,Dk.parser.yy.LINETYPE.DOTTED_POINT].includes(t.type)&&(n=!0),!n)return{};var r=zT(t.from,e),i=zT(t.to,e),a=r[0]<=i[0]?1:0,o=r[0]<i[0]?0:1,s=r.concat(i),c=Math.abs(i[o]-r[a]);t.wrap&&t.message&&(t.message=Hv.wrapLabel(t.message,Math.max(c+2*OT.wrapPadding,OT.width),LT(OT)));var u=Hv.calculateTextDimensions(t.message,LT(OT));return{width:Math.max(t.wrap?0:u.width+2*OT.wrapPadding,c+2*OT.wrapPadding,OT.width),height:0,startx:r[a],stopx:i[o],starty:0,stopy:0,message:t.message,type:t.type,wrap:t.wrap,fromBounds:Math.min.apply(null,s),toBounds:Math.max.apply(null,s)}}(t,e),t.msgModel=i,i.startx&&i.stopx&&s.length>0&&s.forEach((function(r){if(n=r,i.startx===i.stopx){var a=e[t.from],o=e[t.to];n.from=Math.min(a.x-i.width/2,a.x-a.width/2,n.from),n.to=Math.max(o.x+i.width/2,o.x+a.width/2,n.to),n.width=Math.max(n.width,Math.abs(n.to-n.from))-OT.labelBoxWidth}else n.from=Math.min(i.startx,n.from),n.to=Math.max(i.stopx,n.to),n.width=Math.max(n.width,i.width)-OT.labelBoxWidth})))})),BT.activations=[],o.debug("Loop type widths:",a),a}(a,r);kT(n),CT(n),TT(n),ET(n);var l=1;a.forEach((function(t){var e,i,a;switch(t.type){case Dk.parser.yy.LINETYPE.NOTE:i=t.noteModel,function(t,e){BT.bumpVerticalPos(OT.boxMargin),e.height=OT.boxMargin,e.starty=BT.getVerticalPos();var n=DT();n.x=e.startx,n.y=e.starty,n.width=e.width||OT.width,n.class="note";var r=t.append("g"),i=gT(r,n),a=NT();a.x=e.startx,a.y=e.starty,a.width=n.width,a.dy="1em",a.text=e.message,a.class="noteText",a.fontFamily=OT.noteFontFamily,a.fontSize=OT.noteFontSize,a.fontWeight=OT.noteFontWeight,a.anchor=OT.noteAlign,a.textMargin=OT.noteMargin,a.valign=OT.noteAlign;var o=cT(r,a),s=Math.round(o.map((function(t){return(t._groups||t)[0][0].getBBox().height})).reduce((function(t,e){return t+e})));i.attr("height",s+2*OT.noteMargin),e.height+=s+2*OT.noteMargin,BT.bumpVerticalPos(s+2*OT.noteMargin),e.stopy=e.starty+s+2*OT.noteMargin,e.stopx=e.startx+n.width,BT.insert(e.startx,e.starty,e.stopx,e.stopy),BT.models.addNote(e)}(n,i);break;case Dk.parser.yy.LINETYPE.ACTIVE_START:BT.newActivation(t,n,r);break;case Dk.parser.yy.LINETYPE.ACTIVE_END:!function(t,e){var r=BT.endActivation(t);r.starty+18>e&&(r.starty=e-6,e+=12),_T(n,r,e,OT,YT(t.from.actor).length),BT.insert(r.startx,e-10,r.stopx,e)}(t,BT.getVerticalPos());break;case Dk.parser.yy.LINETYPE.LOOP_START:UT(u,t,OT.boxMargin,OT.boxMargin+OT.boxTextMargin,(function(t){return BT.newLoop(t)}));break;case Dk.parser.yy.LINETYPE.LOOP_END:e=BT.endLoop(),xT(n,e,"loop",OT),BT.bumpVerticalPos(e.stopy-BT.getVerticalPos()),BT.models.addLoop(e);break;case Dk.parser.yy.LINETYPE.RECT_START:UT(u,t,OT.boxMargin,OT.boxMargin,(function(t){return BT.newLoop(void 0,t.message)}));break;case Dk.parser.yy.LINETYPE.RECT_END:e=BT.endLoop(),wT(n,e),BT.models.addLoop(e),BT.bumpVerticalPos(e.stopy-BT.getVerticalPos());break;case Dk.parser.yy.LINETYPE.OPT_START:UT(u,t,OT.boxMargin,OT.boxMargin+OT.boxTextMargin,(function(t){return BT.newLoop(t)}));break;case Dk.parser.yy.LINETYPE.OPT_END:e=BT.endLoop(),xT(n,e,"opt",OT),BT.bumpVerticalPos(e.stopy-BT.getVerticalPos()),BT.models.addLoop(e);break;case Dk.parser.yy.LINETYPE.ALT_START:UT(u,t,OT.boxMargin,OT.boxMargin+OT.boxTextMargin,(function(t){return BT.newLoop(t)}));break;case Dk.parser.yy.LINETYPE.ALT_ELSE:UT(u,t,OT.boxMargin+OT.boxTextMargin,OT.boxMargin,(function(t){return BT.addSectionToLoop(t)}));break;case Dk.parser.yy.LINETYPE.ALT_END:e=BT.endLoop(),xT(n,e,"alt",OT),BT.bumpVerticalPos(e.stopy-BT.getVerticalPos()),BT.models.addLoop(e);break;case Dk.parser.yy.LINETYPE.PAR_START:UT(u,t,OT.boxMargin,OT.boxMargin+OT.boxTextMargin,(function(t){return BT.newLoop(t)}));break;case Dk.parser.yy.LINETYPE.PAR_AND:UT(u,t,OT.boxMargin+OT.boxTextMargin,OT.boxMargin,(function(t){return BT.addSectionToLoop(t)}));break;case Dk.parser.yy.LINETYPE.PAR_END:e=BT.endLoop(),xT(n,e,"par",OT),BT.bumpVerticalPos(e.stopy-BT.getVerticalPos()),BT.models.addLoop(e);break;default:try{(a=t.msgModel).starty=BT.getVerticalPos(),a.sequenceIndex=l,function(t,e){BT.bumpVerticalPos(10);var n=e.startx,r=e.stopx,i=e.starty,a=e.message,o=e.type,s=e.sequenceIndex,c=Um.splitBreaks(a).length,u=Hv.calculateTextDimensions(a,LT(OT)),l=u.height/c;e.height+=l,BT.bumpVerticalPos(l);var h=NT();h.x=n,h.y=i+10,h.width=r-n,h.class="messageText",h.dy="1em",h.text=a,h.fontFamily=OT.messageFontFamily,h.fontSize=OT.messageFontSize,h.fontWeight=OT.messageFontWeight,h.anchor=OT.messageAlign,h.valign=OT.messageAlign,h.textMargin=OT.wrapPadding,h.tspan=!1,cT(t,h);var f,d,p=u.height-10,y=u.width;if(n===r){d=BT.getVerticalPos()+p,OT.rightAngles?f=t.append("path").attr("d","M  ".concat(n,",").concat(d," H ").concat(n+Math.max(OT.width/2,y/2)," V ").concat(d+25," H ").concat(n)):(p+=OT.boxMargin,d=BT.getVerticalPos()+p,f=t.append("path").attr("d","M "+n+","+d+" C "+(n+60)+","+(d-10)+" "+(n+60)+","+(d+30)+" "+n+","+(d+20))),p+=30;var g=Math.max(y/2,OT.width/2);BT.insert(n-g,BT.getVerticalPos()-10+p,r+g,BT.getVerticalPos()+30+p)}else p+=OT.boxMargin,d=BT.getVerticalPos()+p,(f=t.append("line")).attr("x1",n),f.attr("y1",d),f.attr("x2",r),f.attr("y2",d),BT.insert(n,d-10,r,d);o===Dk.parser.yy.LINETYPE.DOTTED||o===Dk.parser.yy.LINETYPE.DOTTED_CROSS||o===Dk.parser.yy.LINETYPE.DOTTED_POINT||o===Dk.parser.yy.LINETYPE.DOTTED_OPEN?(f.style("stroke-dasharray","3, 3"),f.attr("class","messageLine1")):f.attr("class","messageLine0");var m="";OT.arrowMarkerAbsolute&&(m=(m=(m=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search).replace(/\(/g,"\\(")).replace(/\)/g,"\\)")),f.attr("stroke-width",2),f.attr("stroke","none"),f.style("fill","none"),o!==Dk.parser.yy.LINETYPE.SOLID&&o!==Dk.parser.yy.LINETYPE.DOTTED||f.attr("marker-end","url("+m+"#arrowhead)"),o!==Dk.parser.yy.LINETYPE.SOLID_POINT&&o!==Dk.parser.yy.LINETYPE.DOTTED_POINT||f.attr("marker-end","url("+m+"#filled-head)"),o!==Dk.parser.yy.LINETYPE.SOLID_CROSS&&o!==Dk.parser.yy.LINETYPE.DOTTED_CROSS||f.attr("marker-end","url("+m+"#crosshead)"),(tT.showSequenceNumbers()||OT.showSequenceNumbers)&&(f.attr("marker-start","url("+m+"#sequencenumber)"),t.append("text").attr("x",n).attr("y",d+4).attr("font-family","sans-serif").attr("font-size","12px").attr("text-anchor","middle").attr("textLength","16px").attr("class","sequenceNumber").text(s)),BT.bumpVerticalPos(p),e.height+=p,e.stopy=e.starty+e.height,BT.insert(e.fromBounds,e.starty,e.toBounds,e.stopy)}(n,a),BT.models.addMessage(a)}catch(t){o.error("error while drawing message",t)}}[Dk.parser.yy.LINETYPE.SOLID_OPEN,Dk.parser.yy.LINETYPE.DOTTED_OPEN,Dk.parser.yy.LINETYPE.SOLID,Dk.parser.yy.LINETYPE.DOTTED,Dk.parser.yy.LINETYPE.SOLID_CROSS,Dk.parser.yy.LINETYPE.DOTTED_CROSS,Dk.parser.yy.LINETYPE.SOLID_POINT,Dk.parser.yy.LINETYPE.DOTTED_POINT].includes(t.type)&&l++})),OT.mirrorActors&&(BT.bumpVerticalPos(2*OT.boxMargin),FT(n,r,i,BT.getVerticalPos()),BT.bumpVerticalPos(OT.boxMargin),hT(n,BT.getVerticalPos()));var h=PT(n,r,i),f=BT.getBounds().bounds;o.debug("For line height fix Querying: #"+e+" .actor-line"),ou("#"+e+" .actor-line").attr("y2",f.stopy);var d=f.stopy-f.starty;d<h.maxHeight&&(d=h.maxHeight);var p=d+2*OT.diagramMarginY;OT.mirrorActors&&(p=p-OT.boxMargin+OT.bottomMarginAdj);var y=f.stopx-f.startx;y<h.maxWidth&&(y=h.maxWidth);var g=y+2*OT.diagramMarginX;s&&n.append("text").text(s).attr("x",(f.stopx-f.startx)/2-2*OT.diagramMarginX).attr("y",-25),zv(n,p,g,OT.useMaxWidth);var m=s?40:0;n.attr("viewBox",f.startx-OT.diagramMarginX+" -"+(OT.diagramMarginY+m)+" "+g+" "+(p+m)),o.debug("models:",BT.models)}};var $T=n(3584),WT=n.n($T);function VT(t){return VT="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},VT(t)}var GT=function(t){return JSON.parse(JSON.stringify(t))},XT=[],ZT=function t(e,n,r){if("relation"===n.stmt)t(e,n.state1,!0),t(e,n.state2,!1);else if("state"===n.stmt&&"[*]"===n.id&&(n.id=r?e.id+"_start":e.id+"_end",n.start=r),n.doc){var i=[],a=0,o=[];for(a=0;a<n.doc.length;a++)if("divider"===n.doc[a].type){var s=GT(n.doc[a]);s.doc=GT(o),i.push(s),o=[]}else o.push(n.doc[a]);if(i.length>0&&o.length>0){var c={stmt:"state",id:Ov(),type:"divider",doc:GT(o)};i.push(GT(c)),n.doc=i}n.doc.forEach((function(e){return t(n,e,!0)}))}},QT={root:{relations:[],states:{},documents:{}}},KT=QT.root,JT=0,tE=function(t,e,n,r,i){void 0===KT.states[t]?KT.states[t]={id:t,descriptions:[],type:e,doc:n,note:i}:(KT.states[t].doc||(KT.states[t].doc=n),KT.states[t].type||(KT.states[t].type=e)),r&&(o.info("Adding state ",t,r),"string"==typeof r&&rE(t,r.trim()),"object"===VT(r)&&r.forEach((function(e){return rE(t,e.trim())}))),i&&(KT.states[t].note=i,KT.states[t].note.text=Um.sanitizeText(KT.states[t].note.text,Jv()))},eE=function(){KT=(QT={root:{relations:[],states:{},documents:{}}}).root,KT=QT.root,JT=0,aE=[]},nE=function(t,e,n){var r=t,i=e,a="default",o="default";"[*]"===t&&(r="start"+ ++JT,a="start"),"[*]"===e&&(i="end"+JT,o="end"),tE(r,a),tE(i,o),KT.relations.push({id1:r,id2:i,title:Um.sanitizeText(n,Jv())})},rE=function(t,e){var n=KT.states[t],r=e;":"===r[0]&&(r=r.substr(1).trim()),n.descriptions.push(Um.sanitizeText(r,Jv()))},iE=0,aE=[],oE="TB";const sE={parseDirective:function(t,e,n){cC.parseDirective(this,t,e,n)},getConfig:function(){return Jv().state},addState:tE,clear:eE,getState:function(t){return KT.states[t]},getStates:function(){return KT.states},getRelations:function(){return KT.relations},getClasses:function(){return aE},getDirection:function(){return oE},addRelation:nE,getDividerId:function(){return"divider-id-"+ ++iE},setDirection:function(t){oE=t},cleanupLabel:function(t){return":"===t.substring(0,1)?t.substr(2).trim():t.trim()},lineType:{LINE:0,DOTTED_LINE:1},relationType:{AGGREGATION:0,EXTENSION:1,COMPOSITION:2,DEPENDENCY:3},logDocuments:function(){o.info("Documents = ",QT)},getRootDoc:function(){return XT},setRootDoc:function(t){o.info("Setting root doc",t),XT=t},getRootDocV2:function(){return ZT({id:"root"},{id:"root",doc:XT},!0),{id:"root",doc:XT}},extract:function(t){var e;e=t.doc?t.doc:t,o.info(e),eE(),o.info("Extract",e),e.forEach((function(t){"state"===t.stmt&&tE(t.id,t.type,t.doc,t.description,t.note),"relation"===t.stmt&&nE(t.state1.id,t.state2.id,t.description)}))},trimColon:function(t){return t&&":"===t[0]?t.substr(1).trim():t.trim()}};var cE={};function uE(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}var lE,hE=function(t,e,n){var r,i=Jv().state.padding,a=2*Jv().state.padding,o=t.node().getBBox(),s=o.width,c=o.x,u=t.append("text").attr("x",0).attr("y",Jv().state.titleShift).attr("font-size",Jv().state.fontSize).attr("class","state-title").text(e.id),l=u.node().getBBox().width+a,h=Math.max(l,s);h===s&&(h+=a);var f=t.node().getBBox();e.doc,r=c-i,l>s&&(r=(s-h)/2+i),Math.abs(c-f.x)<i&&l>s&&(r=c-(l-s)/2);var d=1-Jv().state.textHeight;return t.insert("rect",":first-child").attr("x",r).attr("y",d).attr("class",n?"alt-composit":"composit").attr("width",h).attr("height",f.height+Jv().state.textHeight+Jv().state.titleShift+1).attr("rx","0"),u.attr("x",r+i),l<=s&&u.attr("x",c+(h-a)/2-l/2+i),t.insert("rect",":first-child").attr("x",r).attr("y",Jv().state.titleShift-Jv().state.textHeight-Jv().state.padding).attr("width",h).attr("height",3*Jv().state.textHeight).attr("rx",Jv().state.radius),t.insert("rect",":first-child").attr("x",r).attr("y",Jv().state.titleShift-Jv().state.textHeight-Jv().state.padding).attr("width",h).attr("height",f.height+3+2*Jv().state.textHeight).attr("rx",Jv().state.radius),t},fE=function(t,e){e.attr("class","state-note");var n=e.append("rect").attr("x",0).attr("y",Jv().state.padding),r=function(t,e,n,r){var i=0,a=r.append("text");a.style("text-anchor","start"),a.attr("class","noteText");var o,s=t.replace(/\r\n/g,"<br/>"),c=(s=s.replace(/\n/g,"<br/>")).split(Um.lineBreakRegex),u=1.25*Jv().state.noteMargin,l=function(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=function(t,e){if(t){if("string"==typeof t)return uE(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?uE(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){n&&(t=n);var r=0,i=function(){};return{s:i,n:function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,o=!0,s=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return o=t.done,t},e:function(t){s=!0,a=t},f:function(){try{o||null==n.return||n.return()}finally{if(s)throw a}}}}(c);try{for(l.s();!(o=l.n()).done;){var h=o.value.trim();if(h.length>0){var f=a.append("tspan");f.text(h),0===u&&(u+=f.node().getBBox().height),i+=u,f.attr("x",0+Jv().state.noteMargin),f.attr("y",0+i+1.25*Jv().state.noteMargin)}}}catch(t){l.e(t)}finally{l.f()}return{textWidth:a.node().getBBox().width,textHeight:i}}(t,0,0,e.append("g")),i=r.textWidth,a=r.textHeight;return n.attr("height",a+2*Jv().state.noteMargin),n.attr("width",i+2*Jv().state.noteMargin),n},dE=function(t,e){var n=e.id,r={id:n,label:e.id,width:0,height:0},i=t.append("g").attr("id",n).attr("class","stateGroup");"start"===e.type&&function(t){t.append("circle").attr("class","start-state").attr("r",Jv().state.sizeUnit).attr("cx",Jv().state.padding+Jv().state.sizeUnit).attr("cy",Jv().state.padding+Jv().state.sizeUnit)}(i),"end"===e.type&&function(t){t.append("circle").attr("class","end-state-outer").attr("r",Jv().state.sizeUnit+Jv().state.miniPadding).attr("cx",Jv().state.padding+Jv().state.sizeUnit+Jv().state.miniPadding).attr("cy",Jv().state.padding+Jv().state.sizeUnit+Jv().state.miniPadding),t.append("circle").attr("class","end-state-inner").attr("r",Jv().state.sizeUnit).attr("cx",Jv().state.padding+Jv().state.sizeUnit+2).attr("cy",Jv().state.padding+Jv().state.sizeUnit+2)}(i),"fork"!==e.type&&"join"!==e.type||function(t,e){var n=Jv().state.forkWidth,r=Jv().state.forkHeight;if(e.parentId){var i=n;n=r,r=i}t.append("rect").style("stroke","black").style("fill","black").attr("width",n).attr("height",r).attr("x",Jv().state.padding).attr("y",Jv().state.padding)}(i,e),"note"===e.type&&fE(e.note.text,i),"divider"===e.type&&function(t){t.append("line").style("stroke","grey").style("stroke-dasharray","3").attr("x1",Jv().state.textHeight).attr("class","divider").attr("x2",2*Jv().state.textHeight).attr("y1",0).attr("y2",0)}(i),"default"===e.type&&0===e.descriptions.length&&function(t,e){var n=t.append("text").attr("x",2*Jv().state.padding).attr("y",Jv().state.textHeight+2*Jv().state.padding).attr("font-size",Jv().state.fontSize).attr("class","state-title").text(e.id).node().getBBox();t.insert("rect",":first-child").attr("x",Jv().state.padding).attr("y",Jv().state.padding).attr("width",n.width+2*Jv().state.padding).attr("height",n.height+2*Jv().state.padding).attr("rx",Jv().state.radius)}(i,e),"default"===e.type&&e.descriptions.length>0&&function(t,e){var n=t.append("text").attr("x",2*Jv().state.padding).attr("y",Jv().state.textHeight+1.3*Jv().state.padding).attr("font-size",Jv().state.fontSize).attr("class","state-title").text(e.descriptions[0]).node().getBBox(),r=n.height,i=t.append("text").attr("x",Jv().state.padding).attr("y",r+.4*Jv().state.padding+Jv().state.dividerMargin+Jv().state.textHeight).attr("class","state-description"),a=!0,o=!0;e.descriptions.forEach((function(t){a||(function(t,e,n){var r=t.append("tspan").attr("x",2*Jv().state.padding).text(e);n||r.attr("dy",Jv().state.textHeight)}(i,t,o),o=!1),a=!1}));var s=t.append("line").attr("x1",Jv().state.padding).attr("y1",Jv().state.padding+r+Jv().state.dividerMargin/2).attr("y2",Jv().state.padding+r+Jv().state.dividerMargin/2).attr("class","descr-divider"),c=i.node().getBBox(),u=Math.max(c.width,n.width);s.attr("x2",u+3*Jv().state.padding),t.insert("rect",":first-child").attr("x",Jv().state.padding).attr("y",Jv().state.padding).attr("width",u+2*Jv().state.padding).attr("height",c.height+r+2*Jv().state.padding).attr("rx",Jv().state.radius)}(i,e);var a,o=i.node().getBBox();return r.width=o.width+2*Jv().state.padding,r.height=o.height+2*Jv().state.padding,a=r,cE[n]=a,r},pE=0;$T.parser.yy=sE;var yE={},gE=function t(e,n,r,i){var a,s=new(kb().Graph)({compound:!0,multigraph:!0}),c=!0;for(a=0;a<e.length;a++)if("relation"===e[a].stmt){c=!1;break}r?s.setGraph({rankdir:"LR",multigraph:!0,compound:!0,ranker:"tight-tree",ranksep:c?1:lE.edgeLengthFactor,nodeSep:c?1:50,isMultiGraph:!0}):s.setGraph({rankdir:"TB",multigraph:!0,compound:!0,ranksep:c?1:lE.edgeLengthFactor,nodeSep:c?1:50,ranker:"tight-tree",isMultiGraph:!0}),s.setDefaultEdgeLabel((function(){return{}})),sE.extract(e);for(var u=sE.getStates(),l=sE.getRelations(),h=Object.keys(u),f=0;f<h.length;f++){var d=u[h[f]];r&&(d.parentId=r);var p=void 0;if(d.doc){var y=n.append("g").attr("id",d.id).attr("class","stateGroup");p=t(d.doc,y,d.id,!i);var g=(y=hE(y,d,i)).node().getBBox();p.width=g.width,p.height=g.height+lE.padding/2,yE[d.id]={y:lE.compositTitleSize}}else p=dE(n,d);if(d.note){var m={descriptions:[],id:d.id+"-note",note:d.note,type:"note"},v=dE(n,m);"left of"===d.note.position?(s.setNode(p.id+"-note",v),s.setNode(p.id,p)):(s.setNode(p.id,p),s.setNode(p.id+"-note",v)),s.setParent(p.id,p.id+"-group"),s.setParent(p.id+"-note",p.id+"-group")}else s.setNode(p.id,p)}o.debug("Count=",s.nodeCount(),s);var b=0;l.forEach((function(t){var e;b++,o.debug("Setting edge",t),s.setEdge(t.id1,t.id2,{relation:t,width:(e=t.title,e?e.length*lE.fontSizeFactor:1),height:lE.labelHeight*Um.getRows(t.title).length,labelpos:"c"},"id"+b)})),xb().layout(s),o.debug("Graph after layout",s.nodes());var _=n.node();s.nodes().forEach((function(t){void 0!==t&&void 0!==s.node(t)?(o.warn("Node "+t+": "+JSON.stringify(s.node(t))),au("#"+_.id+" #"+t).attr("transform","translate("+(s.node(t).x-s.node(t).width/2)+","+(s.node(t).y+(yE[t]?yE[t].y:0)-s.node(t).height/2)+" )"),au("#"+_.id+" #"+t).attr("data-x-shift",s.node(t).x-s.node(t).width/2),document.querySelectorAll("#"+_.id+" #"+t+" .divider").forEach((function(t){var e=t.parentElement,n=0,r=0;e&&(e.parentElement&&(n=e.parentElement.getBBox().width),r=parseInt(e.getAttribute("data-x-shift"),10),Number.isNaN(r)&&(r=0)),t.setAttribute("x1",0-r+8),t.setAttribute("x2",n-r-8)}))):o.debug("No Node "+t+": "+JSON.stringify(s.node(t)))}));var x=_.getBBox();s.edges().forEach((function(t){void 0!==t&&void 0!==s.edge(t)&&(o.debug("Edge "+t.v+" -> "+t.w+": "+JSON.stringify(s.edge(t))),function(t,e,n){e.points=e.points.filter((function(t){return!Number.isNaN(t.y)}));var r=e.points,i=zu().x((function(t){return t.x})).y((function(t){return t.y})).curve(Vu),a=t.append("path").attr("d",i(r)).attr("id","edge"+pE).attr("class","transition"),s="";if(Jv().state.arrowMarkerAbsolute&&(s=(s=(s=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search).replace(/\(/g,"\\(")).replace(/\)/g,"\\)")),a.attr("marker-end","url("+s+"#"+function(t){switch(t){case sE.relationType.AGGREGATION:return"aggregation";case sE.relationType.EXTENSION:return"extension";case sE.relationType.COMPOSITION:return"composition";case sE.relationType.DEPENDENCY:return"dependency"}}(sE.relationType.DEPENDENCY)+"End)"),void 0!==n.title){for(var c=t.append("g").attr("class","stateLabel"),u=Hv.calcLabelPosition(e.points),l=u.x,h=u.y,f=Um.getRows(n.title),d=0,p=[],y=0,g=0,m=0;m<=f.length;m++){var v=c.append("text").attr("text-anchor","middle").text(f[m]).attr("x",l).attr("y",h+d),b=v.node().getBBox();if(y=Math.max(y,b.width),g=Math.min(g,b.x),o.info(b.x,l,h+d),0===d){var _=v.node().getBBox();d=_.height,o.info("Title height",d,h)}p.push(v)}var x=d*f.length;if(f.length>1){var w=(f.length-1)*d*.5;p.forEach((function(t,e){return t.attr("y",h+e*d-w)})),x=d*f.length}var k=c.node().getBBox();c.insert("rect",":first-child").attr("class","box").attr("x",l-y/2-Jv().state.padding/2).attr("y",h-x/2-Jv().state.padding/2-3.5).attr("width",y+Jv().state.padding).attr("height",x+Jv().state.padding),o.info(k)}pE++}(n,s.edge(t),s.edge(t).relation))})),x=_.getBBox();var w={id:r||"root",label:r||"root",width:0,height:0};return w.width=x.width+2*lE.padding,w.height=x.height+2*lE.padding,o.debug("Doc rendered",w,s),w};const mE=function(t,e){lE=Jv().state,$T.parser.yy.clear(),$T.parser.parse(t),o.debug("Rendering diagram "+t);var n=au("[id='".concat(e,"']"));n.append("defs").append("marker").attr("id","dependencyEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z"),new(kb().Graph)({multigraph:!0,compound:!0,rankdir:"RL"}).setDefaultEdgeLabel((function(){return{}}));var r=sE.getRootDoc();gE(r,n,void 0,!1);var i=lE.padding,a=n.node().getBBox(),s=a.width+2*i,c=a.height+2*i;zv(n,c,1.75*s,lE.useMaxWidth),n.attr("viewBox","".concat(a.x-lE.padding,"  ").concat(a.y-lE.padding," ")+s+" "+c)};var vE={},bE={},_E=function(t,e,n,r){if("root"!==n.id){var i="rect";!0===n.start&&(i="start"),!1===n.start&&(i="end"),"default"!==n.type&&(i=n.type),bE[n.id]||(bE[n.id]={id:n.id,shape:i,description:Um.sanitizeText(n.id,Jv()),classes:"statediagram-state"}),n.description&&(Array.isArray(bE[n.id].description)?(bE[n.id].shape="rectWithTitle",bE[n.id].description.push(n.description)):bE[n.id].description.length>0?(bE[n.id].shape="rectWithTitle",bE[n.id].description===n.id?bE[n.id].description=[n.description]:bE[n.id].description=[bE[n.id].description,n.description]):(bE[n.id].shape="rect",bE[n.id].description=n.description),bE[n.id].description=Um.sanitizeTextOrArray(bE[n.id].description,Jv())),1===bE[n.id].description.length&&"rectWithTitle"===bE[n.id].shape&&(bE[n.id].shape="rect"),!bE[n.id].type&&n.doc&&(o.info("Setting cluster for ",n.id,kE(n)),bE[n.id].type="group",bE[n.id].dir=kE(n),bE[n.id].shape="divider"===n.type?"divider":"roundedWithTitle",bE[n.id].classes=bE[n.id].classes+" "+(r?"statediagram-cluster statediagram-cluster-alt":"statediagram-cluster"));var a={labelStyle:"",shape:bE[n.id].shape,labelText:bE[n.id].description,classes:bE[n.id].classes,style:"",id:n.id,dir:bE[n.id].dir,domId:"state-"+n.id+"-"+xE,type:bE[n.id].type,padding:15};if(n.note){var s={labelStyle:"",shape:"note",labelText:n.note.text,classes:"statediagram-note",style:"",id:n.id+"----note-"+xE,domId:"state-"+n.id+"----note-"+xE,type:bE[n.id].type,padding:15},c={labelStyle:"",shape:"noteGroup",labelText:n.note.text,classes:bE[n.id].classes,style:"",id:n.id+"----parent",domId:"state-"+n.id+"----parent-"+xE,type:"group",padding:0};xE++,t.setNode(n.id+"----parent",c),t.setNode(s.id,s),t.setNode(n.id,a),t.setParent(n.id,n.id+"----parent"),t.setParent(s.id,n.id+"----parent");var u=n.id,l=s.id;"left of"===n.note.position&&(u=s.id,l=n.id),t.setEdge(u,l,{arrowhead:"none",arrowType:"",style:"fill:none",labelStyle:"",classes:"transition note-edge",arrowheadStyle:"fill: #333",labelpos:"c",labelType:"text",thickness:"normal"})}else t.setNode(n.id,a)}e&&"root"!==e.id&&(o.trace("Setting node ",n.id," to be child of its parent ",e.id),t.setParent(n.id,e.id)),n.doc&&(o.trace("Adding nodes children "),wE(t,n,n.doc,!r))},xE=0,wE=function(t,e,n,r){o.trace("items",n),n.forEach((function(n){if("state"===n.stmt||"default"===n.stmt)_E(t,e,n,r);else if("relation"===n.stmt){_E(t,e,n.state1,r),_E(t,e,n.state2,r);var i={id:"edge"+xE,arrowhead:"normal",arrowTypeEnd:"arrow_barb",style:"fill:none",labelStyle:"",label:Um.sanitizeText(n.description,Jv()),arrowheadStyle:"fill: #333",labelpos:"c",labelType:"text",thickness:"normal",classes:"transition"},a=n.state1.id,o=n.state2.id;t.setEdge(a,o,i,xE),xE++}}))},kE=function(t,e){var n=e||"TB";if(t.doc)for(var r=0;r<t.doc.length;r++){var i=t.doc[r];"dir"===i.stmt&&(n=i.value)}return n};const TE=function(t){for(var e=Object.keys(t),n=0;n<e.length;n++)vE[e[n]]=t[e[n]]};function EE(t){return function(t){if(Array.isArray(t))return CE(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return CE(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?CE(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function CE(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}var SE="",AE="",ME=[],NE=[],DE=[],OE=function(){for(var t=!0,e=0;e<DE.length;e++)DE[e].processed,t=t&&DE[e].processed;return t};const BE={parseDirective:function(t,e,n){cC.parseDirective(this,t,e,n)},getConfig:function(){return Jv().journey},clear:function(){ME.length=0,NE.length=0,AE="",SE="",DE.length=0},setTitle:function(t){SE=t},getTitle:function(){return SE},addSection:function(t){AE=t,ME.push(t)},getSections:function(){return ME},getTasks:function(){for(var t=OE(),e=0;!t&&e<100;)t=OE(),e++;return NE.push.apply(NE,DE),NE},addTask:function(t,e){var n=e.substr(1).split(":"),r=0,i=[];1===n.length?(r=Number(n[0]),i=[]):(r=Number(n[0]),i=n[1].split(","));var a=i.map((function(t){return t.trim()})),o={section:AE,type:AE,people:a,task:t,score:r};DE.push(o)},addTaskOrg:function(t){var e={section:AE,type:AE,description:t,task:t,classes:[]};NE.push(e)},getActors:function(){return t=[],NE.forEach((function(e){e.people&&t.push.apply(t,EE(e.people))})),EE(new Set(t)).sort();var t}};var LE=n(9763),IE=n.n(LE),RE=function(t,e){var n=t.append("rect");return n.attr("x",e.x),n.attr("y",e.y),n.attr("fill",e.fill),n.attr("stroke",e.stroke),n.attr("width",e.width),n.attr("height",e.height),n.attr("rx",e.rx),n.attr("ry",e.ry),void 0!==e.class&&n.attr("class",e.class),n},FE=function(t,e){var n=t.append("circle");return n.attr("cx",e.cx),n.attr("cy",e.cy),n.attr("class","actor-"+e.pos),n.attr("fill",e.fill),n.attr("stroke",e.stroke),n.attr("r",e.r),void 0!==n.class&&n.attr("class",n.class),void 0!==e.title&&n.append("title").text(e.title),n},PE=-1,jE=function(){function t(t,e,n,i,a,o,s,c){r(e.append("text").attr("x",n+a/2).attr("y",i+o/2+5).style("font-color",c).style("text-anchor","middle").text(t),s)}function e(t,e,n,i,a,o,s,c,u){for(var l=c.taskFontSize,h=c.taskFontFamily,f=t.split(/<br\s*\/?>/gi),d=0;d<f.length;d++){var p=d*l-l*(f.length-1)/2,y=e.append("text").attr("x",n+a/2).attr("y",i).attr("fill",u).style("text-anchor","middle").style("font-size",l).style("font-family",h);y.append("tspan").attr("x",n+a/2).attr("dy",p).text(f[d]),y.attr("y",i+o/2).attr("dominant-baseline","central").attr("alignment-baseline","central"),r(y,s)}}function n(t,n,i,a,o,s,c,u){var l=n.append("switch"),h=l.append("foreignObject").attr("x",i).attr("y",a).attr("width",o).attr("height",s).attr("position","fixed").append("xhtml:div").style("display","table").style("height","100%").style("width","100%");h.append("div").attr("class","label").style("display","table-cell").style("text-align","center").style("vertical-align","middle").text(t),e(t,l,i,a,o,s,c,u),r(h,c)}function r(t,e){for(var n in e)n in e&&t.attr(n,e[n])}return function(r){return"fo"===r.textPlacement?n:"old"===r.textPlacement?t:e}}();const YE=FE,zE=function(t,e,n){var r=t.append("g"),i={x:0,y:0,width:100,anchor:"start",height:100,rx:0,ry:0};i.x=e.x,i.y=e.y,i.fill=e.fill,i.width=n.width,i.height=n.height,i.class="journey-section section-type-"+e.num,i.rx=3,i.ry=3,RE(r,i),jE(n)(e.text,r,i.x,i.y,i.width,i.height,{class:"journey-section section-type-"+e.num},n,e.colour)},UE=function(t,e){var n=e.text.replace(/<br\s*\/?>/gi," "),r=t.append("text");r.attr("x",e.x),r.attr("y",e.y),r.attr("class","legend"),r.style("text-anchor",e.anchor),void 0!==e.class&&r.attr("class",e.class);var i=r.append("tspan");return i.attr("x",e.x+2*e.textMargin),i.text(n),r},qE=function(t,e,n){var r,i,a,o=e.x+n.width/2,s=t.append("g");PE++,s.append("line").attr("id","task"+PE).attr("x1",o).attr("y1",e.y).attr("x2",o).attr("y2",450).attr("class","task-line").attr("stroke-width","1px").attr("stroke-dasharray","4 2").attr("stroke","#666"),r=s,i={cx:o,cy:300+30*(5-e.score),score:e.score},r.append("circle").attr("cx",i.cx).attr("cy",i.cy).attr("class","face").attr("r",15).attr("stroke-width",2).attr("overflow","visible"),(a=r.append("g")).append("circle").attr("cx",i.cx-5).attr("cy",i.cy-5).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666"),a.append("circle").attr("cx",i.cx+5).attr("cy",i.cy-5).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666"),i.score>3?function(t){var e=Iu().startAngle(Math.PI/2).endAngle(Math.PI/2*3).innerRadius(7.5).outerRadius(15/2.2);t.append("path").attr("class","mouth").attr("d",e).attr("transform","translate("+i.cx+","+(i.cy+2)+")")}(a):i.score<3?function(t){var e=Iu().startAngle(3*Math.PI/2).endAngle(Math.PI/2*5).innerRadius(7.5).outerRadius(15/2.2);t.append("path").attr("class","mouth").attr("d",e).attr("transform","translate("+i.cx+","+(i.cy+7)+")")}(a):function(t){t.append("line").attr("class","mouth").attr("stroke",2).attr("x1",i.cx-5).attr("y1",i.cy+7).attr("x2",i.cx+5).attr("y2",i.cy+7).attr("class","mouth").attr("stroke-width","1px").attr("stroke","#666")}(a);var c={x:0,y:0,width:100,anchor:"start",height:100,rx:0,ry:0};c.x=e.x,c.y=e.y,c.fill=e.fill,c.width=n.width,c.height=n.height,c.class="task task-type-"+e.num,c.rx=3,c.ry=3,RE(s,c);var u=e.x+14;e.people.forEach((function(t){var n=e.actors[t].color,r={cx:u,cy:e.y,r:7,fill:n,stroke:"#000",title:t,pos:e.actors[t].position};FE(s,r),u+=10})),jE(n)(e.task,s,c.x,c.y,c.width,c.height,{class:"task"},n,e.colour)};LE.parser.yy=BE;var HE={},$E=Jv().journey,WE=Jv().journey.leftMargin,VE={data:{startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},verticalPos:0,sequenceItems:[],init:function(){this.sequenceItems=[],this.data={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},this.verticalPos=0},updateVal:function(t,e,n,r){void 0===t[e]?t[e]=n:t[e]=r(n,t[e])},updateBounds:function(t,e,n,r){var i=Jv().journey,a=this,o=0;this.sequenceItems.forEach((function(s){o++;var c=a.sequenceItems.length-o+1;a.updateVal(s,"starty",e-c*i.boxMargin,Math.min),a.updateVal(s,"stopy",r+c*i.boxMargin,Math.max),a.updateVal(VE.data,"startx",t-c*i.boxMargin,Math.min),a.updateVal(VE.data,"stopx",n+c*i.boxMargin,Math.max),a.updateVal(s,"startx",t-c*i.boxMargin,Math.min),a.updateVal(s,"stopx",n+c*i.boxMargin,Math.max),a.updateVal(VE.data,"starty",e-c*i.boxMargin,Math.min),a.updateVal(VE.data,"stopy",r+c*i.boxMargin,Math.max)}))},insert:function(t,e,n,r){var i=Math.min(t,n),a=Math.max(t,n),o=Math.min(e,r),s=Math.max(e,r);this.updateVal(VE.data,"startx",i,Math.min),this.updateVal(VE.data,"starty",o,Math.min),this.updateVal(VE.data,"stopx",a,Math.max),this.updateVal(VE.data,"stopy",s,Math.max),this.updateBounds(i,o,a,s)},bumpVerticalPos:function(t){this.verticalPos=this.verticalPos+t,this.data.stopy=this.verticalPos},getVerticalPos:function(){return this.verticalPos},getBounds:function(){return this.data}},GE=$E.sectionFills,XE=$E.sectionColours;const ZE=function(t){Object.keys(t).forEach((function(e){$E[e]=t[e]}))},QE=function(t,e){var n=Jv().journey;LE.parser.yy.clear(),LE.parser.parse(t+"\n"),VE.init();var r=au("#"+e);r.attr("xmlns:xlink","http://www.w3.org/1999/xlink"),r.append("defs").append("marker").attr("id","arrowhead").attr("refX",5).attr("refY",2).attr("markerWidth",6).attr("markerHeight",4).attr("orient","auto").append("path").attr("d","M 0,0 V 4 L6,2 Z");var i=LE.parser.yy.getTasks(),a=LE.parser.yy.getTitle(),o=LE.parser.yy.getActors();for(var s in HE)delete HE[s];var c=0;o.forEach((function(t){HE[t]={color:n.actorColours[c%n.actorColours.length],position:c},c++})),function(t){var e=Jv().journey,n=60;Object.keys(HE).forEach((function(r){var i=HE[r].color,a={cx:20,cy:n,r:7,fill:i,stroke:"#000",pos:HE[r].position};YE(t,a);var o={x:40,y:n+7,fill:"#666",text:r,textMargin:5|e.boxTextMargin};UE(t,o),n+=20}))}(r),VE.insert(0,0,WE,50*Object.keys(HE).length),function(t,e,n){for(var r=Jv().journey,i="",a=n+(2*r.height+r.diagramMarginY),o=0,s="#CCC",c="black",u=0,l=0;l<e.length;l++){var h=e[l];if(i!==h.section){s=GE[o%GE.length],u=o%GE.length,c=XE[o%XE.length];var f={x:l*r.taskMargin+l*r.width+WE,y:50,text:h.section,fill:s,num:u,colour:c};zE(t,f,r),i=h.section,o++}var d=h.people.reduce((function(t,e){return HE[e]&&(t[e]=HE[e]),t}),{});h.x=l*r.taskMargin+l*r.width+WE,h.y=a,h.width=r.diagramMarginX,h.height=r.diagramMarginY,h.colour=c,h.fill=s,h.num=u,h.actors=d,qE(t,h,r),VE.insert(h.x,h.y,h.x+h.width+r.taskMargin,450)}}(r,i,0);var u=VE.getBounds();a&&r.append("text").text(a).attr("x",WE).attr("font-size","4ex").attr("font-weight","bold").attr("y",25);var l=u.stopy-u.starty+2*n.diagramMarginY,h=WE+u.stopx+2*n.diagramMarginX;zv(r,l,h,n.useMaxWidth),r.append("line").attr("x1",WE).attr("y1",4*n.height).attr("x2",h-WE-4).attr("y2",4*n.height).attr("stroke-width",4).attr("stroke","black").attr("marker-end","url(#arrowhead)");var f=a?70:0;r.attr("viewBox","".concat(u.startx," -25 ").concat(h," ").concat(l+f)),r.attr("preserveAspectRatio","xMinYMin meet"),r.attr("height",l+f+25)};var KE={};const JE=function(t){return"g.classGroup text {\n  fill: ".concat(t.nodeBorder,";\n  fill: ").concat(t.classText,";\n  stroke: none;\n  font-family: ").concat(t.fontFamily,";\n  font-size: 10px;\n\n  .title {\n    font-weight: bolder;\n  }\n\n}\n\n.nodeLabel, .edgeLabel {\n  color: ").concat(t.classText,";\n}\n.edgeLabel .label rect {\n  fill: ").concat(t.mainBkg,";\n}\n.label text {\n  fill: ").concat(t.classText,";\n}\n.edgeLabel .label span {\n  background: ").concat(t.mainBkg,";\n}\n\n.classTitle {\n  font-weight: bolder;\n}\n.node rect,\n  .node circle,\n  .node ellipse,\n  .node polygon,\n  .node path {\n    fill: ").concat(t.mainBkg,";\n    stroke: ").concat(t.nodeBorder,";\n    stroke-width: 1px;\n  }\n\n\n.divider {\n  stroke: ").concat(t.nodeBorder,";\n  stroke: 1;\n}\n\ng.clickable {\n  cursor: pointer;\n}\n\ng.classGroup rect {\n  fill: ").concat(t.mainBkg,";\n  stroke: ").concat(t.nodeBorder,";\n}\n\ng.classGroup line {\n  stroke: ").concat(t.nodeBorder,";\n  stroke-width: 1;\n}\n\n.classLabel .box {\n  stroke: none;\n  stroke-width: 0;\n  fill: ").concat(t.mainBkg,";\n  opacity: 0.5;\n}\n\n.classLabel .label {\n  fill: ").concat(t.nodeBorder,";\n  font-size: 10px;\n}\n\n.relation {\n  stroke: ").concat(t.lineColor,";\n  stroke-width: 1;\n  fill: none;\n}\n\n.dashed-line{\n  stroke-dasharray: 3;\n}\n\n#compositionStart, .composition {\n  fill: ").concat(t.lineColor," !important;\n  stroke: ").concat(t.lineColor," !important;\n  stroke-width: 1;\n}\n\n#compositionEnd, .composition {\n  fill: ").concat(t.lineColor," !important;\n  stroke: ").concat(t.lineColor," !important;\n  stroke-width: 1;\n}\n\n#dependencyStart, .dependency {\n  fill: ").concat(t.lineColor," !important;\n  stroke: ").concat(t.lineColor," !important;\n  stroke-width: 1;\n}\n\n#dependencyStart, .dependency {\n  fill: ").concat(t.lineColor," !important;\n  stroke: ").concat(t.lineColor," !important;\n  stroke-width: 1;\n}\n\n#extensionStart, .extension {\n  fill: ").concat(t.lineColor," !important;\n  stroke: ").concat(t.lineColor," !important;\n  stroke-width: 1;\n}\n\n#extensionEnd, .extension {\n  fill: ").concat(t.lineColor," !important;\n  stroke: ").concat(t.lineColor," !important;\n  stroke-width: 1;\n}\n\n#aggregationStart, .aggregation {\n  fill: ").concat(t.mainBkg," !important;\n  stroke: ").concat(t.lineColor," !important;\n  stroke-width: 1;\n}\n\n#aggregationEnd, .aggregation {\n  fill: ").concat(t.mainBkg," !important;\n  stroke: ").concat(t.lineColor," !important;\n  stroke-width: 1;\n}\n\n.edgeTerminals {\n  font-size: 11px;\n}\n\n")},tC=function(t){return".label {\n    font-family: ".concat(t.fontFamily,";\n    color: ").concat(t.nodeTextColor||t.textColor,";\n  }\n  .cluster-label text {\n    fill: ").concat(t.titleColor,";\n  }\n  .cluster-label span {\n    color: ").concat(t.titleColor,";\n  }\n\n  .label text,span {\n    fill: ").concat(t.nodeTextColor||t.textColor,";\n    color: ").concat(t.nodeTextColor||t.textColor,";\n  }\n\n  .node rect,\n  .node circle,\n  .node ellipse,\n  .node polygon,\n  .node path {\n    fill: ").concat(t.mainBkg,";\n    stroke: ").concat(t.nodeBorder,";\n    stroke-width: 1px;\n  }\n\n  .node .label {\n    text-align: center;\n  }\n  .node.clickable {\n    cursor: pointer;\n  }\n\n  .arrowheadPath {\n    fill: ").concat(t.arrowheadColor,";\n  }\n\n  .edgePath .path {\n    stroke: ").concat(t.lineColor,";\n    stroke-width: 2.0px;\n  }\n\n  .flowchart-link {\n    stroke: ").concat(t.lineColor,";\n    fill: none;\n  }\n\n  .edgeLabel {\n    background-color: ").concat(t.edgeLabelBackground,";\n    rect {\n      opacity: 0.5;\n      background-color: ").concat(t.edgeLabelBackground,";\n      fill: ").concat(t.edgeLabelBackground,";\n    }\n    text-align: center;\n  }\n\n  .cluster rect {\n    fill: ").concat(t.clusterBkg,";\n    stroke: ").concat(t.clusterBorder,";\n    stroke-width: 1px;\n  }\n\n  .cluster text {\n    fill: ").concat(t.titleColor,";\n  }\n\n  .cluster span {\n    color: ").concat(t.titleColor,";\n  }\n  /* .cluster div {\n    color: ").concat(t.titleColor,";\n  } */\n\n  div.mermaidTooltip {\n    position: absolute;\n    text-align: center;\n    max-width: 200px;\n    padding: 2px;\n    font-family: ").concat(t.fontFamily,";\n    font-size: 12px;\n    background: ").concat(t.tertiaryColor,";\n    border: 1px solid ").concat(t.border2,";\n    border-radius: 2px;\n    pointer-events: none;\n    z-index: 100;\n  }\n")},eC=function(t){return"\ndefs #statediagram-barbEnd {\n    fill: ".concat(t.transitionColor,";\n    stroke: ").concat(t.transitionColor,";\n  }\ng.stateGroup text {\n  fill: ").concat(t.nodeBorder,";\n  stroke: none;\n  font-size: 10px;\n}\ng.stateGroup text {\n  fill: ").concat(t.textColor,";\n  stroke: none;\n  font-size: 10px;\n\n}\ng.stateGroup .state-title {\n  font-weight: bolder;\n  fill: ").concat(t.stateLabelColor,";\n}\n\ng.stateGroup rect {\n  fill: ").concat(t.mainBkg,";\n  stroke: ").concat(t.nodeBorder,";\n}\n\ng.stateGroup line {\n  stroke: ").concat(t.lineColor,";\n  stroke-width: 1;\n}\n\n.transition {\n  stroke: ").concat(t.transitionColor,";\n  stroke-width: 1;\n  fill: none;\n}\n\n.stateGroup .composit {\n  fill: ").concat(t.background,";\n  border-bottom: 1px\n}\n\n.stateGroup .alt-composit {\n  fill: #e0e0e0;\n  border-bottom: 1px\n}\n\n.state-note {\n  stroke: ").concat(t.noteBorderColor,";\n  fill: ").concat(t.noteBkgColor,";\n\n  text {\n    fill: ").concat(t.noteTextColor,";\n    stroke: none;\n    font-size: 10px;\n  }\n}\n\n.stateLabel .box {\n  stroke: none;\n  stroke-width: 0;\n  fill: ").concat(t.mainBkg,";\n  opacity: 0.5;\n}\n\n.edgeLabel .label rect {\n  fill: ").concat(t.labelBackgroundColor,";\n  opacity: 0.5;\n}\n.edgeLabel .label text {\n  fill: ").concat(t.transitionLabelColor||t.tertiaryTextColor,";\n}\n.label div .edgeLabel {\n  color: ").concat(t.transitionLabelColor||t.tertiaryTextColor,";\n}\n\n.stateLabel text {\n  fill: ").concat(t.stateLabelColor,";\n  font-size: 10px;\n  font-weight: bold;\n}\n\n.node circle.state-start {\n  fill: ").concat(t.specialStateColor,";\n  stroke: ").concat(t.specialStateColor,";\n}\n\n.node .fork-join {\n  fill: ").concat(t.specialStateColor,";\n  stroke: ").concat(t.specialStateColor,";\n}\n\n.node circle.state-end {\n  fill: ").concat(t.innerEndBackground,";\n  stroke: ").concat(t.background,";\n  stroke-width: 1.5\n}\n.end-state-inner {\n  fill: ").concat(t.compositeBackground||t.background,";\n  // stroke: ").concat(t.background,";\n  stroke-width: 1.5\n}\n\n.node rect {\n  fill: ").concat(t.stateBkg||t.mainBkg,";\n  stroke: ").concat(t.stateBorder||t.nodeBorder,";\n  stroke-width: 1px;\n}\n.node polygon {\n  fill: ").concat(t.mainBkg,";\n  stroke: ").concat(t.stateBorder||t.nodeBorder,";;\n  stroke-width: 1px;\n}\n#statediagram-barbEnd {\n  fill: ").concat(t.lineColor,";\n}\n\n.statediagram-cluster rect {\n  fill: ").concat(t.compositeTitleBackground,";\n  stroke: ").concat(t.stateBorder||t.nodeBorder,";\n  stroke-width: 1px;\n}\n\n.cluster-label, .nodeLabel {\n  color: ").concat(t.stateLabelColor,";\n}\n\n.statediagram-cluster rect.outer {\n  rx: 5px;\n  ry: 5px;\n}\n.statediagram-state .divider {\n  stroke: ").concat(t.stateBorder||t.nodeBorder,";\n}\n\n.statediagram-state .title-state {\n  rx: 5px;\n  ry: 5px;\n}\n.statediagram-cluster.statediagram-cluster .inner {\n  fill: ").concat(t.compositeBackground||t.background,";\n}\n.statediagram-cluster.statediagram-cluster-alt .inner {\n  fill: ").concat(t.altBackground?t.altBackground:"#efefef",";\n}\n\n.statediagram-cluster .inner {\n  rx:0;\n  ry:0;\n}\n\n.statediagram-state rect.basic {\n  rx: 5px;\n  ry: 5px;\n}\n.statediagram-state rect.divider {\n  stroke-dasharray: 10,10;\n  fill: ").concat(t.altBackground?t.altBackground:"#efefef",";\n}\n\n.note-edge {\n  stroke-dasharray: 5;\n}\n\n.statediagram-note rect {\n  fill: ").concat(t.noteBkgColor,";\n  stroke: ").concat(t.noteBorderColor,";\n  stroke-width: 1px;\n  rx: 0;\n  ry: 0;\n}\n.statediagram-note rect {\n  fill: ").concat(t.noteBkgColor,";\n  stroke: ").concat(t.noteBorderColor,";\n  stroke-width: 1px;\n  rx: 0;\n  ry: 0;\n}\n\n.statediagram-note text {\n  fill: ").concat(t.noteTextColor,";\n}\n\n.statediagram-note .nodeLabel {\n  color: ").concat(t.noteTextColor,";\n}\n.statediagram .edgeLabel {\n  color: red; // ").concat(t.noteTextColor,";\n}\n\n#dependencyStart, #dependencyEnd {\n  fill: ").concat(t.lineColor,";\n  stroke: ").concat(t.lineColor,";\n  stroke-width: 1;\n}\n")};var nC={flowchart:tC,"flowchart-v2":tC,sequence:function(t){return".actor {\n    stroke: ".concat(t.actorBorder,";\n    fill: ").concat(t.actorBkg,";\n  }\n\n  text.actor > tspan {\n    fill: ").concat(t.actorTextColor,";\n    stroke: none;\n  }\n\n  .actor-line {\n    stroke: ").concat(t.actorLineColor,";\n  }\n\n  .messageLine0 {\n    stroke-width: 1.5;\n    stroke-dasharray: none;\n    stroke: ").concat(t.signalColor,";\n  }\n\n  .messageLine1 {\n    stroke-width: 1.5;\n    stroke-dasharray: 2, 2;\n    stroke: ").concat(t.signalColor,";\n  }\n\n  #arrowhead path {\n    fill: ").concat(t.signalColor,";\n    stroke: ").concat(t.signalColor,";\n  }\n\n  .sequenceNumber {\n    fill: ").concat(t.sequenceNumberColor,";\n  }\n\n  #sequencenumber {\n    fill: ").concat(t.signalColor,";\n  }\n\n  #crosshead path {\n    fill: ").concat(t.signalColor,";\n    stroke: ").concat(t.signalColor,";\n  }\n\n  .messageText {\n    fill: ").concat(t.signalTextColor,";\n    stroke: ").concat(t.signalTextColor,";\n  }\n\n  .labelBox {\n    stroke: ").concat(t.labelBoxBorderColor,";\n    fill: ").concat(t.labelBoxBkgColor,";\n  }\n\n  .labelText, .labelText > tspan {\n    fill: ").concat(t.labelTextColor,";\n    stroke: none;\n  }\n\n  .loopText, .loopText > tspan {\n    fill: ").concat(t.loopTextColor,";\n    stroke: none;\n  }\n\n  .loopLine {\n    stroke-width: 2px;\n    stroke-dasharray: 2, 2;\n    stroke: ").concat(t.labelBoxBorderColor,";\n    fill: ").concat(t.labelBoxBorderColor,";\n  }\n\n  .note {\n    //stroke: #decc93;\n    stroke: ").concat(t.noteBorderColor,";\n    fill: ").concat(t.noteBkgColor,";\n  }\n\n  .noteText, .noteText > tspan {\n    fill: ").concat(t.noteTextColor,";\n    stroke: none;\n  }\n\n  .activation0 {\n    fill: ").concat(t.activationBkgColor,";\n    stroke: ").concat(t.activationBorderColor,";\n  }\n\n  .activation1 {\n    fill: ").concat(t.activationBkgColor,";\n    stroke: ").concat(t.activationBorderColor,";\n  }\n\n  .activation2 {\n    fill: ").concat(t.activationBkgColor,";\n    stroke: ").concat(t.activationBorderColor,";\n  }\n\n  .actorPopupMenu {\n    position: absolute;\n  }\n\n  .actorPopupMenuPanel {\n    position: absolute;\n    fill: ").concat(t.actorBkg,";\n    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);\n    filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));\n}\n  .actor-man line {\n    stroke: ").concat(t.actorBorder,";\n    fill: ").concat(t.actorBkg,";\n  }\n  .actor-man circle, line {\n    stroke: ").concat(t.actorBorder,";\n    fill: ").concat(t.actorBkg,";\n    stroke-width: 2px;\n  }\n")},gantt:function(t){return'\n  .mermaid-main-font {\n    font-family: "trebuchet ms", verdana, arial, sans-serif;\n    font-family: var(--mermaid-font-family);\n  }\n  .exclude-range {\n    fill: '.concat(t.excludeBkgColor,";\n  }\n\n  .section {\n    stroke: none;\n    opacity: 0.2;\n  }\n\n  .section0 {\n    fill: ").concat(t.sectionBkgColor,";\n  }\n\n  .section2 {\n    fill: ").concat(t.sectionBkgColor2,";\n  }\n\n  .section1,\n  .section3 {\n    fill: ").concat(t.altSectionBkgColor,";\n    opacity: 0.2;\n  }\n\n  .sectionTitle0 {\n    fill: ").concat(t.titleColor,";\n  }\n\n  .sectionTitle1 {\n    fill: ").concat(t.titleColor,";\n  }\n\n  .sectionTitle2 {\n    fill: ").concat(t.titleColor,";\n  }\n\n  .sectionTitle3 {\n    fill: ").concat(t.titleColor,";\n  }\n\n  .sectionTitle {\n    text-anchor: start;\n    // font-size: ").concat(t.ganttFontSize,";\n    // text-height: 14px;\n    font-family: 'trebuchet ms', verdana, arial, sans-serif;\n    font-family: var(--mermaid-font-family);\n\n  }\n\n\n  /* Grid and axis */\n\n  .grid .tick {\n    stroke: ").concat(t.gridColor,";\n    opacity: 0.8;\n    shape-rendering: crispEdges;\n    text {\n      font-family: ").concat(t.fontFamily,";\n      fill: ").concat(t.textColor,";\n    }\n  }\n\n  .grid path {\n    stroke-width: 0;\n  }\n\n\n  /* Today line */\n\n  .today {\n    fill: none;\n    stroke: ").concat(t.todayLineColor,";\n    stroke-width: 2px;\n  }\n\n\n  /* Task styling */\n\n  /* Default task */\n\n  .task {\n    stroke-width: 2;\n  }\n\n  .taskText {\n    text-anchor: middle;\n    font-family: 'trebuchet ms', verdana, arial, sans-serif;\n    font-family: var(--mermaid-font-family);\n  }\n\n  // .taskText:not([font-size]) {\n  //   font-size: ").concat(t.ganttFontSize,";\n  // }\n\n  .taskTextOutsideRight {\n    fill: ").concat(t.taskTextDarkColor,";\n    text-anchor: start;\n    // font-size: ").concat(t.ganttFontSize,";\n    font-family: 'trebuchet ms', verdana, arial, sans-serif;\n    font-family: var(--mermaid-font-family);\n\n  }\n\n  .taskTextOutsideLeft {\n    fill: ").concat(t.taskTextDarkColor,";\n    text-anchor: end;\n    // font-size: ").concat(t.ganttFontSize,";\n  }\n\n  /* Special case clickable */\n  .task.clickable {\n    cursor: pointer;\n  }\n  .taskText.clickable {\n    cursor: pointer;\n    fill: ").concat(t.taskTextClickableColor," !important;\n    font-weight: bold;\n  }\n\n  .taskTextOutsideLeft.clickable {\n    cursor: pointer;\n    fill: ").concat(t.taskTextClickableColor," !important;\n    font-weight: bold;\n  }\n\n  .taskTextOutsideRight.clickable {\n    cursor: pointer;\n    fill: ").concat(t.taskTextClickableColor," !important;\n    font-weight: bold;\n  }\n\n  /* Specific task settings for the sections*/\n\n  .taskText0,\n  .taskText1,\n  .taskText2,\n  .taskText3 {\n    fill: ").concat(t.taskTextColor,";\n  }\n\n  .task0,\n  .task1,\n  .task2,\n  .task3 {\n    fill: ").concat(t.taskBkgColor,";\n    stroke: ").concat(t.taskBorderColor,";\n  }\n\n  .taskTextOutside0,\n  .taskTextOutside2\n  {\n    fill: ").concat(t.taskTextOutsideColor,";\n  }\n\n  .taskTextOutside1,\n  .taskTextOutside3 {\n    fill: ").concat(t.taskTextOutsideColor,";\n  }\n\n\n  /* Active task */\n\n  .active0,\n  .active1,\n  .active2,\n  .active3 {\n    fill: ").concat(t.activeTaskBkgColor,";\n    stroke: ").concat(t.activeTaskBorderColor,";\n  }\n\n  .activeText0,\n  .activeText1,\n  .activeText2,\n  .activeText3 {\n    fill: ").concat(t.taskTextDarkColor," !important;\n  }\n\n\n  /* Completed task */\n\n  .done0,\n  .done1,\n  .done2,\n  .done3 {\n    stroke: ").concat(t.doneTaskBorderColor,";\n    fill: ").concat(t.doneTaskBkgColor,";\n    stroke-width: 2;\n  }\n\n  .doneText0,\n  .doneText1,\n  .doneText2,\n  .doneText3 {\n    fill: ").concat(t.taskTextDarkColor," !important;\n  }\n\n\n  /* Tasks on the critical line */\n\n  .crit0,\n  .crit1,\n  .crit2,\n  .crit3 {\n    stroke: ").concat(t.critBorderColor,";\n    fill: ").concat(t.critBkgColor,";\n    stroke-width: 2;\n  }\n\n  .activeCrit0,\n  .activeCrit1,\n  .activeCrit2,\n  .activeCrit3 {\n    stroke: ").concat(t.critBorderColor,";\n    fill: ").concat(t.activeTaskBkgColor,";\n    stroke-width: 2;\n  }\n\n  .doneCrit0,\n  .doneCrit1,\n  .doneCrit2,\n  .doneCrit3 {\n    stroke: ").concat(t.critBorderColor,";\n    fill: ").concat(t.doneTaskBkgColor,";\n    stroke-width: 2;\n    cursor: pointer;\n    shape-rendering: crispEdges;\n  }\n\n  .milestone {\n    transform: rotate(45deg) scale(0.8,0.8);\n  }\n\n  .milestoneText {\n    font-style: italic;\n  }\n  .doneCritText0,\n  .doneCritText1,\n  .doneCritText2,\n  .doneCritText3 {\n    fill: ").concat(t.taskTextDarkColor," !important;\n  }\n\n  .activeCritText0,\n  .activeCritText1,\n  .activeCritText2,\n  .activeCritText3 {\n    fill: ").concat(t.taskTextDarkColor," !important;\n  }\n\n  .titleText {\n    text-anchor: middle;\n    font-size: 18px;\n    fill: ").concat(t.textColor,"    ;\n    font-family: 'trebuchet ms', verdana, arial, sans-serif;\n    font-family: var(--mermaid-font-family);\n  }\n")},classDiagram:JE,"classDiagram-v2":JE,class:JE,stateDiagram:eC,state:eC,git:function(){return"\n  .commit-id,\n  .commit-msg,\n  .branch-label {\n    fill: lightgrey;\n    color: lightgrey;\n    font-family: 'trebuchet ms', verdana, arial, sans-serif;\n    font-family: var(--mermaid-font-family);\n  }\n"},info:function(){return""},pie:function(t){return"\n  .pieCircle{\n    stroke: ".concat(t.pieStrokeColor,";\n    stroke-width : ").concat(t.pieStrokeWidth,";\n    opacity : ").concat(t.pieOpacity,";\n  }\n  .pieTitleText {\n    text-anchor: middle;\n    font-size: ").concat(t.pieTitleTextSize,";\n    fill: ").concat(t.pieTitleTextColor,";\n    font-family: ").concat(t.fontFamily,";\n  }\n  .slice {\n    font-family: ").concat(t.fontFamily,";\n    fill: ").concat(t.pieSectionTextColor,";\n    font-size:").concat(t.pieSectionTextSize,";\n    // fill: white;\n  }\n  .legend text {\n    fill: ").concat(t.pieLegendTextColor,";\n    font-family: ").concat(t.fontFamily,";\n    font-size: ").concat(t.pieLegendTextSize,";\n  }\n")},er:function(t){return"\n  .entityBox {\n    fill: ".concat(t.mainBkg,";\n    stroke: ").concat(t.nodeBorder,";\n  }\n\n  .attributeBoxOdd {\n    fill: #ffffff;\n    stroke: ").concat(t.nodeBorder,";\n  }\n\n  .attributeBoxEven {\n    fill: #f2f2f2;\n    stroke: ").concat(t.nodeBorder,";\n  }\n\n  .relationshipLabelBox {\n    fill: ").concat(t.tertiaryColor,";\n    opacity: 0.7;\n    background-color: ").concat(t.tertiaryColor,";\n      rect {\n        opacity: 0.5;\n      }\n  }\n\n    .relationshipLine {\n      stroke: ").concat(t.lineColor,";\n    }\n")},journey:function(t){return".label {\n    font-family: 'trebuchet ms', verdana, arial, sans-serif;\n    font-family: var(--mermaid-font-family);\n    color: ".concat(t.textColor,";\n  }\n  .mouth {\n    stroke: #666;\n  }\n\n  line {\n    stroke: ").concat(t.textColor,"\n  }\n\n  .legend {\n    fill: ").concat(t.textColor,";\n  }\n\n  .label text {\n    fill: #333;\n  }\n  .label {\n    color: ").concat(t.textColor,"\n  }\n\n  .face {\n    ").concat(t.faceColor?"fill: ".concat(t.faceColor):"fill: #FFF8DC",";\n    stroke: #999;\n  }\n\n  .node rect,\n  .node circle,\n  .node ellipse,\n  .node polygon,\n  .node path {\n    fill: ").concat(t.mainBkg,";\n    stroke: ").concat(t.nodeBorder,";\n    stroke-width: 1px;\n  }\n\n  .node .label {\n    text-align: center;\n  }\n  .node.clickable {\n    cursor: pointer;\n  }\n\n  .arrowheadPath {\n    fill: ").concat(t.arrowheadColor,";\n  }\n\n  .edgePath .path {\n    stroke: ").concat(t.lineColor,";\n    stroke-width: 1.5px;\n  }\n\n  .flowchart-link {\n    stroke: ").concat(t.lineColor,";\n    fill: none;\n  }\n\n  .edgeLabel {\n    background-color: ").concat(t.edgeLabelBackground,";\n    rect {\n      opacity: 0.5;\n    }\n    text-align: center;\n  }\n\n  .cluster rect {\n  }\n\n  .cluster text {\n    fill: ").concat(t.titleColor,";\n  }\n\n  div.mermaidTooltip {\n    position: absolute;\n    text-align: center;\n    max-width: 200px;\n    padding: 2px;\n    font-family: 'trebuchet ms', verdana, arial, sans-serif;\n    font-family: var(--mermaid-font-family);\n    font-size: 12px;\n    background: ").concat(t.tertiaryColor,";\n    border: 1px solid ").concat(t.border2,";\n    border-radius: 2px;\n    pointer-events: none;\n    z-index: 100;\n  }\n\n  .task-type-0, .section-type-0  {\n    ").concat(t.fillType0?"fill: ".concat(t.fillType0):"",";\n  }\n  .task-type-1, .section-type-1  {\n    ").concat(t.fillType0?"fill: ".concat(t.fillType1):"",";\n  }\n  .task-type-2, .section-type-2  {\n    ").concat(t.fillType0?"fill: ".concat(t.fillType2):"",";\n  }\n  .task-type-3, .section-type-3  {\n    ").concat(t.fillType0?"fill: ".concat(t.fillType3):"",";\n  }\n  .task-type-4, .section-type-4  {\n    ").concat(t.fillType0?"fill: ".concat(t.fillType4):"",";\n  }\n  .task-type-5, .section-type-5  {\n    ").concat(t.fillType0?"fill: ".concat(t.fillType5):"",";\n  }\n  .task-type-6, .section-type-6  {\n    ").concat(t.fillType0?"fill: ".concat(t.fillType6):"",";\n  }\n  .task-type-7, .section-type-7  {\n    ").concat(t.fillType0?"fill: ".concat(t.fillType7):"",";\n  }\n\n  .actor-0 {\n    ").concat(t.actor0?"fill: ".concat(t.actor0):"",";\n  }\n  .actor-1 {\n    ").concat(t.actor1?"fill: ".concat(t.actor1):"",";\n  }\n  .actor-2 {\n    ").concat(t.actor2?"fill: ".concat(t.actor2):"",";\n  }\n  .actor-3 {\n    ").concat(t.actor3?"fill: ".concat(t.actor3):"",";\n  }\n  .actor-4 {\n    ").concat(t.actor4?"fill: ".concat(t.actor4):"",";\n  }\n  .actor-5 {\n    ").concat(t.actor5?"fill: ".concat(t.actor5):"",";\n  }\n\n  }\n")},requirement:function(t){return"\n\n  marker {\n    fill: ".concat(t.relationColor,";\n    stroke: ").concat(t.relationColor,";\n  }\n\n  marker.cross {\n    stroke: ").concat(t.lineColor,";\n  }\n\n  svg {\n    font-family: ").concat(t.fontFamily,";\n    font-size: ").concat(t.fontSize,";\n  }\n\n  .reqBox {\n    fill: ").concat(t.requirementBackground,";\n    fill-opacity: 100%;\n    stroke: ").concat(t.requirementBorderColor,";\n    stroke-width: ").concat(t.requirementBorderSize,";\n  }\n  \n  .reqTitle, .reqLabel{\n    fill:  ").concat(t.requirementTextColor,";\n  }\n  .reqLabelBox {\n    fill: ").concat(t.relationLabelBackground,";\n    fill-opacity: 100%;\n  }\n\n  .req-title-line {\n    stroke: ").concat(t.requirementBorderColor,";\n    stroke-width: ").concat(t.requirementBorderSize,";\n  }\n  .relationshipLine {\n    stroke: ").concat(t.relationColor,";\n    stroke-width: 1;\n  }\n  .relationshipLabel {\n    fill: ").concat(t.relationLabelColor,";\n  }\n\n")}};function rC(t){return rC="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},rC(t)}var iC=function(t){var e=t;return(e=(e=e.replace(/fl°°/g,(function(){return"&#"}))).replace(/fl°/g,(function(){return"&"}))).replace(/¶ß/g,(function(){return";"}))},aC={};function oC(t){var e;Zw(t.git),Fx(t.flowchart),Yx(t.flowchart),void 0!==t.sequenceDiagram&&HT.setConf(Lv(t.sequence,t.sequenceDiagram)),HT.setConf(t.sequence),t.gantt,Pb(t.class),t.state,TE(t.state),rk(t.class),U_(t.er),ZE(t.journey),Mk(t.requirement),e=t.class,Object.keys(e).forEach((function(t){KE[t]=e[t]}))}var sC=Object.freeze({render:function(t,e,n,r){nb();var i=e,a=Hv.detectInit(i);a&&(Uv(a),eb(a));var s=Jv();if(e.length>s.maxTextSize&&(i="graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa"),void 0!==r)r.innerHTML="",au(r).append("div").attr("id","d"+t).attr("style","font-family: "+s.fontFamily).append("svg").attr("id",t).attr("width","100%").attr("xmlns","http://www.w3.org/2000/svg").append("g");else{var c=document.getElementById(t);c&&c.remove();var u=document.querySelector("#d"+t);u&&u.remove(),au("body").append("div").attr("id","d"+t).append("svg").attr("id",t).attr("width","100%").attr("xmlns","http://www.w3.org/2000/svg").append("g")}window.txt=i,i=i.replace(/style.*:\S*#.*;/g,(function(t){return t.substring(0,t.length-1)})).replace(/classDef.*:\S*#.*;/g,(function(t){return t.substring(0,t.length-1)})).replace(/#\w+;/g,(function(t){var e=t.substring(1,t.length-1);return/^\+?\d+$/.test(e)?"fl°°"+e+"¶ß":"fl°"+e+"¶ß"}));var l=au("#d"+t).node(),h=Hv.detectType(i,s),f=l.firstChild,d=f.firstChild,p="";if(void 0!==s.themeCSS&&(p+="\n".concat(s.themeCSS)),void 0!==s.fontFamily&&(p+="\n:root { --mermaid-font-family: ".concat(s.fontFamily,"}")),void 0!==s.altFontFamily&&(p+="\n:root { --mermaid-alt-font-family: ".concat(s.altFontFamily,"}")),"flowchart"===h||"flowchart-v2"===h||"graph"===h){var y=function(t){o.info("Extracting classes"),gx.clear();try{var e=vx().parser;return e.yy=gx,e.parse(t),gx.getClasses()}catch(t){return}}(i),g=s.htmlLabels||s.flowchart.htmlLabels;for(var m in y)g?(p+="\n.".concat(m," > * { ").concat(y[m].styles.join(" !important; ")," !important; }"),p+="\n.".concat(m," span { ").concat(y[m].styles.join(" !important; ")," !important; }")):(p+="\n.".concat(m," path { ").concat(y[m].styles.join(" !important; ")," !important; }"),p+="\n.".concat(m," rect { ").concat(y[m].styles.join(" !important; ")," !important; }"),p+="\n.".concat(m," polygon { ").concat(y[m].styles.join(" !important; ")," !important; }"),p+="\n.".concat(m," ellipse { ").concat(y[m].styles.join(" !important; ")," !important; }"),p+="\n.".concat(m," circle { ").concat(y[m].styles.join(" !important; ")," !important; }"),y[m].textStyles&&(p+="\n.".concat(m," tspan { ").concat(y[m].textStyles.join(" !important; ")," !important; }")))}var v=function(t,e){return am(Cm("".concat(t,"{").concat(e,"}")),om)}("#".concat(t),function(t,e,n){return" {\n    font-family: ".concat(n.fontFamily,";\n    font-size: ").concat(n.fontSize,";\n    fill: ").concat(n.textColor,"\n  }\n\n  /* Classes common for multiple diagrams */\n\n  .error-icon {\n    fill: ").concat(n.errorBkgColor,";\n  }\n  .error-text {\n    fill: ").concat(n.errorTextColor,";\n    stroke: ").concat(n.errorTextColor,";\n  }\n\n  .edge-thickness-normal {\n    stroke-width: 2px;\n  }\n  .edge-thickness-thick {\n    stroke-width: 3.5px\n  }\n  .edge-pattern-solid {\n    stroke-dasharray: 0;\n  }\n\n  .edge-pattern-dashed{\n    stroke-dasharray: 3;\n  }\n  .edge-pattern-dotted {\n    stroke-dasharray: 2;\n  }\n\n  .marker {\n    fill: ").concat(n.lineColor,";\n    stroke: ").concat(n.lineColor,";\n  }\n  .marker.cross {\n    stroke: ").concat(n.lineColor,";\n  }\n\n  svg {\n    font-family: ").concat(n.fontFamily,";\n    font-size: ").concat(n.fontSize,";\n  }\n\n  ").concat(nC[t](n),"\n\n  ").concat(e,"\n")}(h,p,s.themeVariables)),b=document.createElement("style");b.innerHTML="#".concat(t," ")+v,f.insertBefore(b,d);try{switch(h){case"git":s.flowchart.arrowMarkerAbsolute=s.arrowMarkerAbsolute,Zw(s.git),function(t,e,n){try{var r=Yw().parser;r.yy=Fw,r.yy.clear(),o.debug("in gitgraph renderer",t+"\n","id:",e,n),r.parse(t+"\n"),Uw=Object.assign(Uw,qw,Fw.getOptions()),o.debug("effective options",Uw);var i=Fw.getDirection();zw=Fw.getCommits();var a=Fw.getBranchesAsObjArray();"BT"===i&&(Uw.nodeLabel.x=a.length*Uw.branchOffset,Uw.nodeLabel.width="100%",Uw.nodeLabel.y=-2*Uw.nodeRadius);var s=au('[id="'.concat(e,'"]'));for(var c in function(t){t.append("defs").append("g").attr("id","def-commit").append("circle").attr("r",Uw.nodeRadius).attr("cx",0).attr("cy",0),t.select("#def-commit").append("foreignObject").attr("width",Uw.nodeLabel.width).attr("height",Uw.nodeLabel.height).attr("x",Uw.nodeLabel.x).attr("y",Uw.nodeLabel.y).attr("class","node-label").attr("requiredFeatures","http://www.w3.org/TR/SVG11/feature#Extensibility").append("p").html("")}(s),Pw=1,a){var u=a[c];Gw(s,u.commit.id,a,i),Xw(s,u.commit,i),Pw++}s.attr("height",(function(){return"BT"===i?Object.keys(zw).length*Uw.nodeSpacing:(a.length+1)*Uw.branchOffset}))}catch(t){o.error("Error while rendering gitgraph"),o.error(t.message)}}(i,t,!1);break;case"flowchart":s.flowchart.arrowMarkerAbsolute=s.arrowMarkerAbsolute,Fx(s.flowchart),Px(i,t);break;case"flowchart-v2":s.flowchart.arrowMarkerAbsolute=s.arrowMarkerAbsolute,Yx(s.flowchart),zx(i,t);break;case"sequence":s.sequence.arrowMarkerAbsolute=s.arrowMarkerAbsolute,s.sequenceDiagram?(HT.setConf(Object.assign(s.sequence,s.sequenceDiagram)),console.error("`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.")):HT.setConf(s.sequence),HT.draw(i,t);break;case"gantt":s.gantt.arrowMarkerAbsolute=s.arrowMarkerAbsolute,s.gantt,Tw(i,t);break;case"class":s.class.arrowMarkerAbsolute=s.arrowMarkerAbsolute,Pb(s.class),jb(i,t);break;case"classDiagram":s.class.arrowMarkerAbsolute=s.arrowMarkerAbsolute,function(t){Object.keys(t).forEach((function(e){A_[e]=t[e]}))}(s.class),function(t,e){o.info("Drawing class"),bb.clear(),Tb.parser.parse(t);var n=Jv().flowchart;o.info("config:",n);var r=n.nodeSpacing||50,i=n.rankSpacing||50,a=new(kb().Graph)({multigraph:!0,compound:!0}).setGraph({rankdir:bb.getDirection(),nodesep:r,ranksep:i,marginx:8,marginy:8}).setDefaultEdgeLabel((function(){return{}})),s=bb.getClasses(),c=bb.getRelations();o.info(c),function(t,e){var n=Object.keys(t);o.info("keys:",n),o.info(t),n.forEach((function(n){var r=t[n],i="";r.cssClasses.length>0&&(i=i+" "+r.cssClasses.join(" "));var a,s,c={labelStyle:""},u=void 0!==r.text?r.text:r.id;r.type,s="class_box",e.setNode(r.id,{labelStyle:c.labelStyle,shape:s,labelText:(a=u,Um.sanitizeText(a,Jv())),classData:r,rx:0,ry:0,class:i,style:c.style,id:r.id,domId:r.domId,haveCallback:r.haveCallback,link:r.link,width:"group"===r.type?500:void 0,type:r.type,padding:Jv().flowchart.padding}),o.info("setNode",{labelStyle:c.labelStyle,shape:s,labelText:u,rx:0,ry:0,class:i,style:c.style,id:r.id,width:"group"===r.type?500:void 0,type:r.type,padding:Jv().flowchart.padding})}))}(s,a),function(t,e){var n=0;t.forEach((function(r){n++;var i={classes:"relation"};i.pattern=1==r.relation.lineType?"dashed":"solid",i.id="id"+n,"arrow_open"===r.type?i.arrowhead="none":i.arrowhead="normal",o.info(i,r),i.startLabelRight="none"===r.relationTitle1?"":r.relationTitle1,i.endLabelLeft="none"===r.relationTitle2?"":r.relationTitle2,i.arrowTypeStart=M_(r.relation.type1),i.arrowTypeEnd=M_(r.relation.type2);var a="",s="";if(void 0!==r.style){var c=Nv(r.style);a=c.style,s=c.labelStyle}else a="fill:none";i.style=a,i.labelStyle=s,void 0!==r.interpolate?i.curve=Av(r.interpolate,Pu):void 0!==t.defaultInterpolate?i.curve=Av(t.defaultInterpolate,Pu):i.curve=Av(A_.curve,Pu),r.text=r.title,void 0===r.text?void 0!==r.style&&(i.arrowheadStyle="fill: #333"):(i.arrowheadStyle="fill: #333",i.labelpos="c",Jv().flowchart.htmlLabels?(i.labelType="html",i.label='<span class="edgeLabel">'+r.text+"</span>"):(i.labelType="text",i.label=r.text.replace(Um.lineBreakRegex,"\n"),void 0===r.style&&(i.style=i.style||"stroke: #333; stroke-width: 1.5px;fill:none"),i.labelStyle=i.labelStyle.replace("color:","fill:"))),e.setEdge(r.id1,r.id2,i,n)}))}(c,a);var u=au('[id="'.concat(e,'"]'));u.attr("xmlns:xlink","http://www.w3.org/1999/xlink");var l=au("#"+e+" g");S_(l,a,["aggregation","extension","composition","dependency"],"classDiagram",e);var h=u.node().getBBox(),f=h.width+16,d=h.height+16;if(o.debug("new ViewBox 0 0 ".concat(f," ").concat(d),"translate(".concat(8-a._label.marginx,", ").concat(8-a._label.marginy,")")),zv(u,d,f,n.useMaxWidth),u.attr("viewBox","0 0 ".concat(f," ").concat(d)),u.select("g").attr("transform","translate(".concat(8-a._label.marginx,", ").concat(8-h.y,")")),!n.htmlLabels)for(var p=document.querySelectorAll('[id="'+e+'"] .edgeLabel .label'),y=0;y<p.length;y++){var g=p[y],m=g.getBBox(),v=document.createElementNS("http://www.w3.org/2000/svg","rect");v.setAttribute("rx",0),v.setAttribute("ry",0),v.setAttribute("width",m.width),v.setAttribute("height",m.height),g.insertBefore(v,g.firstChild)}}(i,t);break;case"state":s.class.arrowMarkerAbsolute=s.arrowMarkerAbsolute,s.state,mE(i,t);break;case"stateDiagram":s.class.arrowMarkerAbsolute=s.arrowMarkerAbsolute,TE(s.state),function(t,e){o.info("Drawing state diagram (v2)",e),sE.clear(),bE={};var n=WT().parser;n.yy=sE,n.parse(t);var r=sE.getDirection();void 0===r&&(r="LR");var i=Jv().state,a=i.nodeSpacing||50,s=i.rankSpacing||50;o.info(sE.getRootDocV2()),sE.extract(sE.getRootDocV2()),o.info(sE.getRootDocV2());var c=new(kb().Graph)({multigraph:!0,compound:!0}).setGraph({rankdir:kE(sE.getRootDocV2()),nodesep:a,ranksep:s,marginx:8,marginy:8}).setDefaultEdgeLabel((function(){return{}}));_E(c,void 0,sE.getRootDocV2(),!0);var u=au('[id="'.concat(e,'"]')),l=au("#"+e+" g");S_(l,c,["barb"],"statediagram",e);var h=u.node().getBBox(),f=h.width+16,d=h.height+16;u.attr("class","statediagram");var p=u.node().getBBox();zv(u,d,1.75*f,i.useMaxWidth);var y="".concat(p.x-8," ").concat(p.y-8," ").concat(f," ").concat(d);o.debug("viewBox ".concat(y)),u.attr("viewBox",y);for(var g=document.querySelectorAll('[id="'+e+'"] .edgeLabel .label'),m=0;m<g.length;m++){var v=g[m],b=v.getBBox(),_=document.createElementNS("http://www.w3.org/2000/svg","rect");_.setAttribute("rx",0),_.setAttribute("ry",0),_.setAttribute("width",b.width),_.setAttribute("height",b.height),v.insertBefore(_,v.firstChild)}}(i,t);break;case"info":s.class.arrowMarkerAbsolute=s.arrowMarkerAbsolute,rk(s.class),function(t,e,n){try{var r=ek().parser;r.yy=Jw,o.debug("Renering info diagram\n"+t),r.parse(t),o.debug("Parsed info diagram");var i=au("#"+e);i.append("g").append("text").attr("x",100).attr("y",40).attr("class","version").attr("font-size","32px").style("text-anchor","middle").text("v "+n),i.attr("height",100),i.attr("width",400)}catch(t){o.error("Error while rendering info diagram"),o.error(t.message)}}(i,t,Dm);break;case"pie":fk(i,t);break;case"er":U_(s.er),q_(i,t);break;case"journey":ZE(s.journey),QE(i,t);break;case"requirement":Mk(s.requirement),Nk(i,t)}}catch(e){throw function(t,e){try{o.debug("Renering svg for syntax error\n");var n=au("#"+t),r=n.append("g");r.append("path").attr("class","error-icon").attr("d","m411.313,123.313c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32-9.375,9.375-20.688-20.688c-12.484-12.5-32.766-12.5-45.25,0l-16,16c-1.261,1.261-2.304,2.648-3.31,4.051-21.739-8.561-45.324-13.426-70.065-13.426-105.867,0-192,86.133-192,192s86.133,192 192,192 192-86.133 192-192c0-24.741-4.864-48.327-13.426-70.065 1.402-1.007 2.79-2.049 4.051-3.31l16-16c12.5-12.492 12.5-32.758 0-45.25l-20.688-20.688 9.375-9.375 32.001-31.999zm-219.313,100.687c-52.938,0-96,43.063-96,96 0,8.836-7.164,16-16,16s-16-7.164-16-16c0-70.578 57.422-128 128-128 8.836,0 16,7.164 16,16s-7.164,16-16,16z"),r.append("path").attr("class","error-icon").attr("d","m459.02,148.98c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l16,16c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16.001-16z"),r.append("path").attr("class","error-icon").attr("d","m340.395,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16-16c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l15.999,16z"),r.append("path").attr("class","error-icon").attr("d","m400,64c8.844,0 16-7.164 16-16v-32c0-8.836-7.156-16-16-16-8.844,0-16,7.164-16,16v32c0,8.836 7.156,16 16,16z"),r.append("path").attr("class","error-icon").attr("d","m496,96.586h-32c-8.844,0-16,7.164-16,16 0,8.836 7.156,16 16,16h32c8.844,0 16-7.164 16-16 0-8.836-7.156-16-16-16z"),r.append("path").attr("class","error-icon").attr("d","m436.98,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688l32-32c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32c-6.251,6.25-6.251,16.375-0.001,22.625z"),r.append("text").attr("class","error-text").attr("x",1240).attr("y",250).attr("font-size","150px").style("text-anchor","middle").text("Syntax error in graph"),r.append("text").attr("class","error-text").attr("x",1050).attr("y",400).attr("font-size","100px").style("text-anchor","middle").text("mermaid version "+e),n.attr("height",100),n.attr("width",400),n.attr("viewBox","768 0 512 512")}catch(t){o.error("Error while rendering info diagram"),o.error(t.message)}}(t,Dm),e}au('[id="'.concat(t,'"]')).selectAll("foreignobject > *").attr("xmlns","http://www.w3.org/1999/xhtml");var _=au("#d"+t).node().innerHTML;if(o.debug("cnf.arrowMarkerAbsolute",s.arrowMarkerAbsolute),s.arrowMarkerAbsolute&&"false"!==s.arrowMarkerAbsolute||(_=_.replace(/marker-end="url\(.*?#/g,'marker-end="url(#',"g")),_=(_=iC(_)).replace(/<br>/g,"<br/>"),void 0!==n)switch(h){case"flowchart":case"flowchart-v2":n(_,gx.bindFunctions);break;case"gantt":n(_,bw.bindFunctions);break;case"class":case"classDiagram":n(_,bb.bindFunctions);break;default:n(_)}else o.debug("CB = undefined!");eT.forEach((function(t){t()})),eT=[];var x=au("#d"+t).node();return null!==x&&"function"==typeof x.remove&&au("#d"+t).node().remove(),_},parse:function(t){var e=Jv(),n=Hv.detectInit(t,e);n&&o.debug("reinit ",n);var r,i=Hv.detectType(t,e);switch(o.debug("Type "+i),i){case"git":(r=Yw()).parser.yy=Fw;break;case"flowchart":case"flowchart-v2":gx.clear(),(r=vx()).parser.yy=gx;break;case"sequence":(r=Ok()).parser.yy=tT;break;case"gantt":(r=kw()).parser.yy=bw;break;case"class":case"classDiagram":(r=Eb()).parser.yy=bb;break;case"state":case"stateDiagram":(r=WT()).parser.yy=sE;break;case"info":o.debug("info info info"),(r=ek()).parser.yy=Jw;break;case"pie":o.debug("pie"),(r=ak()).parser.yy=uk;break;case"er":o.debug("er"),(r=R_()).parser.yy=L_;break;case"journey":o.debug("Journey"),(r=IE()).parser.yy=BE;break;case"requirement":case"requirementDiagram":o.debug("RequirementDiagram"),(r=pk()).parser.yy=_k}return r.parser.yy.graphType=i,r.parser.yy.parseError=function(t,e){throw{str:t,hash:e}},r.parse(t),r},parseDirective:function(t,e,n,r){try{if(void 0!==e)switch(e=e.trim(),n){case"open_directive":aC={};break;case"type_directive":aC.type=e.toLowerCase();break;case"arg_directive":aC.args=JSON.parse(e);break;case"close_directive":(function(t,e,n){switch(o.debug("Directive type=".concat(e.type," with args:"),e.args),e.type){case"init":case"initialize":["config"].forEach((function(t){void 0!==e.args[t]&&("flowchart-v2"===n&&(n="flowchart"),e.args[n]=e.args[t],delete e.args[t])})),o.debug("sanitize in handleDirective",e.args),Uv(e.args),o.debug("sanitize in handleDirective (done)",e.args),e.args,eb(e.args);break;case"wrap":case"nowrap":t&&t.setWrap&&t.setWrap("wrap"===e.type);break;case"themeCss":o.warn("themeCss encountered");break;default:o.warn("Unhandled directive: source: '%%{".concat(e.type,": ").concat(JSON.stringify(e.args?e.args:{}),"}%%"),e)}})(t,aC,r),aC=null}}catch(t){o.error("Error while rendering sequenceDiagram directive: ".concat(e," jison context: ").concat(n)),o.error(t.message)}},initialize:function(t){t&&t.fontFamily&&(t.themeVariables&&t.themeVariables.fontFamily||(t.themeVariables={fontFamily:t.fontFamily})),function(t){Wv=Lv({},t)}(t),t&&t.theme&&ov[t.theme]?t.themeVariables=ov[t.theme].getThemeVariables(t.themeVariables):t&&(t.themeVariables=ov.default.getThemeVariables(t.themeVariables));var e="object"===rC(t)?function(t){return Gv=Lv({},Vv),Gv=Lv(Gv,t),t.theme&&(Gv.themeVariables=ov[t.theme].getThemeVariables(t.themeVariables)),Zv=Qv(Gv,Xv),Gv}(t):Kv();oC(e),s(e.logLevel)},reinitialize:function(){},getConfig:Jv,setConfig:function(t){return Lv(Zv,t),Jv()},getSiteConfig:Kv,updateSiteConfig:function(t){return Gv=Lv(Gv,t),Qv(Gv,Xv),Gv},reset:function(){nb()},globalReset:function(){nb(),oC(Jv())},defaultConfig:Vv});s(Jv().logLevel),nb(Jv());const cC=sC;var uC=function(){lC.startOnLoad?cC.getConfig().startOnLoad&&lC.init():void 0===lC.startOnLoad&&(o.debug("In start, no config"),cC.getConfig().startOnLoad&&lC.init())};"undefined"!=typeof document&&window.addEventListener("load",(function(){uC()}),!1);var lC={startOnLoad:!0,htmlLabels:!0,mermaidAPI:cC,parse:cC.parse,render:cC.render,init:function(){var t,e,n=this,r=cC.getConfig();arguments.length>=2?(void 0!==arguments[0]&&(lC.sequenceConfig=arguments[0]),t=arguments[1]):t=arguments[0],"function"==typeof arguments[arguments.length-1]?(e=arguments[arguments.length-1],o.debug("Callback function found")):void 0!==r.mermaid&&("function"==typeof r.mermaid.callback?(e=r.mermaid.callback,o.debug("Callback function found")):o.debug("No Callback function found")),t=void 0===t?document.querySelectorAll(".mermaid"):"string"==typeof t?document.querySelectorAll(t):t instanceof window.Node?[t]:t,o.debug("Start On Load before: "+lC.startOnLoad),void 0!==lC.startOnLoad&&(o.debug("Start On Load inner: "+lC.startOnLoad),cC.updateSiteConfig({startOnLoad:lC.startOnLoad})),void 0!==lC.ganttConfig&&cC.updateSiteConfig({gantt:lC.ganttConfig});for(var i,a=new Hv.initIdGeneratior(r.deterministicIds,r.deterministicIDSeed),s=function(r){var s=t[r];if(s.getAttribute("data-processed"))return"continue";s.setAttribute("data-processed",!0);var c="mermaid-".concat(a.next());i=s.innerHTML,i=Hv.entityDecode(i).trim().replace(/<br\s*\/?>/gi,"<br/>");var u=Hv.detectInit(i);u&&o.debug("Detected early reinit: ",u);try{cC.render(c,i,(function(t,n){s.innerHTML=t,void 0!==e&&e(c),n&&n(s)}),s)}catch(t){o.warn("Syntax Error rendering"),o.warn(t),n.parseError&&n.parseError(t)}},c=0;c<t.length;c++)s(c)},initialize:function(t){void 0!==t.mermaid&&(void 0!==t.mermaid.startOnLoad&&(lC.startOnLoad=t.mermaid.startOnLoad),void 0!==t.mermaid.htmlLabels&&(lC.htmlLabels="false"!==t.mermaid.htmlLabels&&!1!==t.mermaid.htmlLabels)),cC.initialize(t)},contentLoaded:uC};const hC=lC},4949:(t,e,n)=>{t.exports={graphlib:n(6614),dagre:n(1463),intersect:n(8114),render:n(5787),util:n(8355),version:n(5689)}},9144:(t,e,n)=>{var r=n(8355);function i(t,e,n,i){var a=t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").style("stroke-width",1).style("stroke-dasharray","1,0");r.applyStyle(a,n[i+"Style"]),n[i+"Class"]&&a.attr("class",n[i+"Class"])}t.exports={default:i,normal:i,vee:function(t,e,n,i){var a=t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 L 4 5 z").style("stroke-width",1).style("stroke-dasharray","1,0");r.applyStyle(a,n[i+"Style"]),n[i+"Class"]&&a.attr("class",n[i+"Class"])},undirected:function(t,e,n,i){var a=t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto").append("path").attr("d","M 0 5 L 10 5").style("stroke-width",1).style("stroke-dasharray","1,0");r.applyStyle(a,n[i+"Style"]),n[i+"Class"]&&a.attr("class",n[i+"Class"])}}},5632:(t,e,n)=>{var r=n(8355),i=n(4322),a=n(1322);t.exports=function(t,e){var n,o=e.nodes().filter((function(t){return r.isSubgraph(e,t)})),s=t.selectAll("g.cluster").data(o,(function(t){return t}));return s.selectAll("*").remove(),s.enter().append("g").attr("class","cluster").attr("id",(function(t){return e.node(t).id})).style("opacity",0),s=t.selectAll("g.cluster"),r.applyTransition(s,e).style("opacity",1),s.each((function(t){var n=e.node(t),r=i.select(this);i.select(this).append("rect");var o=r.append("g").attr("class","label");a(o,n,n.clusterLabelPos)})),s.selectAll("rect").each((function(t){var n=e.node(t),a=i.select(this);r.applyStyle(a,n.style)})),n=s.exit?s.exit():s.selectAll(null),r.applyTransition(n,e).style("opacity",0).remove(),s}},6315:(t,e,n)=>{"use strict";var r=n(1034),i=n(1322),a=n(8355),o=n(4322);t.exports=function(t,e){var n,s=t.selectAll("g.edgeLabel").data(e.edges(),(function(t){return a.edgeToId(t)})).classed("update",!0);return s.exit().remove(),s.enter().append("g").classed("edgeLabel",!0).style("opacity",0),(s=t.selectAll("g.edgeLabel")).each((function(t){var n=o.select(this);n.select(".label").remove();var a=e.edge(t),s=i(n,e.edge(t),0,0).classed("label",!0),c=s.node().getBBox();a.labelId&&s.attr("id",a.labelId),r.has(a,"width")||(a.width=c.width),r.has(a,"height")||(a.height=c.height)})),n=s.exit?s.exit():s.selectAll(null),a.applyTransition(n,e).style("opacity",0).remove(),s}},940:(t,e,n)=>{"use strict";var r=n(1034),i=n(7584),a=n(8355),o=n(4322);function s(t,e){var n=(o.line||o.svg.line)().x((function(t){return t.x})).y((function(t){return t.y}));return(n.curve||n.interpolate)(t.curve),n(e)}t.exports=function(t,e,n){var c=t.selectAll("g.edgePath").data(e.edges(),(function(t){return a.edgeToId(t)})).classed("update",!0),u=function(t,e){var n=t.enter().append("g").attr("class","edgePath").style("opacity",0);return n.append("path").attr("class","path").attr("d",(function(t){var n=e.edge(t),i=e.node(t.v).elem;return s(n,r.range(n.points.length).map((function(){return e=(t=i).getBBox(),{x:(n=t.ownerSVGElement.getScreenCTM().inverse().multiply(t.getScreenCTM()).translate(e.width/2,e.height/2)).e,y:n.f};var t,e,n})))})),n.append("defs"),n}(c,e);!function(t,e){var n=t.exit();a.applyTransition(n,e).style("opacity",0).remove()}(c,e);var l=void 0!==c.merge?c.merge(u):c;return a.applyTransition(l,e).style("opacity",1),l.each((function(t){var n=o.select(this),r=e.edge(t);r.elem=this,r.id&&n.attr("id",r.id),a.applyClass(n,r.class,(n.classed("update")?"update ":"")+"edgePath")})),l.selectAll("path.path").each((function(t){var n=e.edge(t);n.arrowheadId=r.uniqueId("arrowhead");var c=o.select(this).attr("marker-end",(function(){return"url("+(t=location.href,e=n.arrowheadId,t.split("#")[0]+"#"+e+")");var t,e})).style("fill","none");a.applyTransition(c,e).attr("d",(function(t){return function(t,e){var n=t.edge(e),r=t.node(e.v),a=t.node(e.w),o=n.points.slice(1,n.points.length-1);return o.unshift(i(r,o[0])),o.push(i(a,o[o.length-1])),s(n,o)}(e,t)})),a.applyStyle(c,n.style)})),l.selectAll("defs *").remove(),l.selectAll("defs").each((function(t){var r=e.edge(t);(0,n[r.arrowhead])(o.select(this),r.arrowheadId,r,"arrowhead")})),l}},607:(t,e,n)=>{"use strict";var r=n(1034),i=n(1322),a=n(8355),o=n(4322);t.exports=function(t,e,n){var s,c=e.nodes().filter((function(t){return!a.isSubgraph(e,t)})),u=t.selectAll("g.node").data(c,(function(t){return t})).classed("update",!0);return u.exit().remove(),u.enter().append("g").attr("class","node").style("opacity",0),(u=t.selectAll("g.node")).each((function(t){var s=e.node(t),c=o.select(this);a.applyClass(c,s.class,(c.classed("update")?"update ":"")+"node"),c.select("g.label").remove();var u=c.append("g").attr("class","label"),l=i(u,s),h=n[s.shape],f=r.pick(l.node().getBBox(),"width","height");s.elem=this,s.id&&c.attr("id",s.id),s.labelId&&u.attr("id",s.labelId),r.has(s,"width")&&(f.width=s.width),r.has(s,"height")&&(f.height=s.height),f.width+=s.paddingLeft+s.paddingRight,f.height+=s.paddingTop+s.paddingBottom,u.attr("transform","translate("+(s.paddingLeft-s.paddingRight)/2+","+(s.paddingTop-s.paddingBottom)/2+")");var d=o.select(this);d.select(".label-container").remove();var p=h(d,f,s).classed("label-container",!0);a.applyStyle(p,s.style);var y=p.node().getBBox();s.width=y.width,s.height=y.height})),s=u.exit?u.exit():u.selectAll(null),a.applyTransition(s,e).style("opacity",0).remove(),u}},4322:(t,e,n)=>{var r;if(!r)try{r=n(7188)}catch(t){}r||(r=window.d3),t.exports=r},1463:(t,e,n)=>{var r;try{r=n(681)}catch(t){}r||(r=window.dagre),t.exports=r},6614:(t,e,n)=>{var r;try{r=n(8282)}catch(t){}r||(r=window.graphlib),t.exports=r},8114:(t,e,n)=>{t.exports={node:n(7584),circle:n(6587),ellipse:n(3260),polygon:n(5337),rect:n(8049)}},6587:(t,e,n)=>{var r=n(3260);t.exports=function(t,e,n){return r(t,e,e,n)}},3260:t=>{t.exports=function(t,e,n,r){var i=t.x,a=t.y,o=i-r.x,s=a-r.y,c=Math.sqrt(e*e*s*s+n*n*o*o),u=Math.abs(e*n*o/c);r.x<i&&(u=-u);var l=Math.abs(e*n*s/c);return r.y<a&&(l=-l),{x:i+u,y:a+l}}},6808:t=>{function e(t,e){return t*e>0}t.exports=function(t,n,r,i){var a,o,s,c,u,l,h,f,d,p,y,g,m;if(!(a=n.y-t.y,s=t.x-n.x,u=n.x*t.y-t.x*n.y,d=a*r.x+s*r.y+u,p=a*i.x+s*i.y+u,0!==d&&0!==p&&e(d,p)||(o=i.y-r.y,c=r.x-i.x,l=i.x*r.y-r.x*i.y,h=o*t.x+c*t.y+l,f=o*n.x+c*n.y+l,0!==h&&0!==f&&e(h,f)||0==(y=a*c-o*s))))return g=Math.abs(y/2),{x:(m=s*l-c*u)<0?(m-g)/y:(m+g)/y,y:(m=o*u-a*l)<0?(m-g)/y:(m+g)/y}}},7584:t=>{t.exports=function(t,e){return t.intersect(e)}},5337:(t,e,n)=>{var r=n(6808);t.exports=function(t,e,n){var i=t.x,a=t.y,o=[],s=Number.POSITIVE_INFINITY,c=Number.POSITIVE_INFINITY;e.forEach((function(t){s=Math.min(s,t.x),c=Math.min(c,t.y)}));for(var u=i-t.width/2-s,l=a-t.height/2-c,h=0;h<e.length;h++){var f=e[h],d=e[h<e.length-1?h+1:0],p=r(t,n,{x:u+f.x,y:l+f.y},{x:u+d.x,y:l+d.y});p&&o.push(p)}return o.length?(o.length>1&&o.sort((function(t,e){var r=t.x-n.x,i=t.y-n.y,a=Math.sqrt(r*r+i*i),o=e.x-n.x,s=e.y-n.y,c=Math.sqrt(o*o+s*s);return a<c?-1:a===c?0:1})),o[0]):(console.log("NO INTERSECTION FOUND, RETURN NODE CENTER",t),t)}},8049:t=>{t.exports=function(t,e){var n,r,i=t.x,a=t.y,o=e.x-i,s=e.y-a,c=t.width/2,u=t.height/2;return Math.abs(s)*c>Math.abs(o)*u?(s<0&&(u=-u),n=0===s?0:u*o/s,r=u):(o<0&&(c=-c),n=c,r=0===o?0:c*s/o),{x:i+n,y:a+r}}},8284:(t,e,n)=>{var r=n(8355);t.exports=function(t,e){var n=t.append("foreignObject").attr("width","100000"),i=n.append("xhtml:div");i.attr("xmlns","http://www.w3.org/1999/xhtml");var a=e.label;switch(typeof a){case"function":i.insert(a);break;case"object":i.insert((function(){return a}));break;default:i.html(a)}r.applyStyle(i,e.labelStyle),i.style("display","inline-block"),i.style("white-space","nowrap");var o=i.node().getBoundingClientRect();return n.attr("width",o.width).attr("height",o.height),n}},1322:(t,e,n)=>{var r=n(7318),i=n(8284),a=n(8287);t.exports=function(t,e,n){var o=e.label,s=t.append("g");"svg"===e.labelType?a(s,e):"string"!=typeof o||"html"===e.labelType?i(s,e):r(s,e);var c,u=s.node().getBBox();switch(n){case"top":c=-e.height/2;break;case"bottom":c=e.height/2-u.height;break;default:c=-u.height/2}return s.attr("transform","translate("+-u.width/2+","+c+")"),s}},8287:(t,e,n)=>{var r=n(8355);t.exports=function(t,e){var n=t;return n.node().appendChild(e.label),r.applyStyle(n,e.labelStyle),n}},7318:(t,e,n)=>{var r=n(8355);t.exports=function(t,e){for(var n=t.append("text"),i=function(t){for(var e,n="",r=!1,i=0;i<t.length;++i)e=t[i],r?(n+="n"===e?"\n":e,r=!1):"\\"===e?r=!0:n+=e;return n}(e.label).split("\n"),a=0;a<i.length;a++)n.append("tspan").attr("xml:space","preserve").attr("dy","1em").attr("x","1").text(i[a]);return r.applyStyle(n,e.labelStyle),n}},1034:(t,e,n)=>{var r;try{r={defaults:n(1747),each:n(6073),isFunction:n(3560),isPlainObject:n(8630),pick:n(9722),has:n(8721),range:n(6026),uniqueId:n(3955)}}catch(t){}r||(r=window._),t.exports=r},6381:(t,e,n)=>{"use strict";var r=n(8355),i=n(4322);t.exports=function(t,e){var n=t.filter((function(){return!i.select(this).classed("update")}));function a(t){var n=e.node(t);return"translate("+n.x+","+n.y+")"}n.attr("transform",a),r.applyTransition(t,e).style("opacity",1).attr("transform",a),r.applyTransition(n.selectAll("rect"),e).attr("width",(function(t){return e.node(t).width})).attr("height",(function(t){return e.node(t).height})).attr("x",(function(t){return-e.node(t).width/2})).attr("y",(function(t){return-e.node(t).height/2}))}},4577:(t,e,n)=>{"use strict";var r=n(8355),i=n(4322),a=n(1034);t.exports=function(t,e){function n(t){var n=e.edge(t);return a.has(n,"x")?"translate("+n.x+","+n.y+")":""}t.filter((function(){return!i.select(this).classed("update")})).attr("transform",n),r.applyTransition(t,e).style("opacity",1).attr("transform",n)}},4849:(t,e,n)=>{"use strict";var r=n(8355),i=n(4322);t.exports=function(t,e){function n(t){var n=e.node(t);return"translate("+n.x+","+n.y+")"}t.filter((function(){return!i.select(this).classed("update")})).attr("transform",n),r.applyTransition(t,e).style("opacity",1).attr("transform",n)}},5787:(t,e,n)=>{var r=n(1034),i=n(4322),a=n(1463).layout;t.exports=function(){var t=n(607),e=n(5632),i=n(6315),u=n(940),l=n(4849),h=n(4577),f=n(6381),d=n(4418),p=n(9144),y=function(n,y){!function(t){t.nodes().forEach((function(e){var n=t.node(e);r.has(n,"label")||t.children(e).length||(n.label=e),r.has(n,"paddingX")&&r.defaults(n,{paddingLeft:n.paddingX,paddingRight:n.paddingX}),r.has(n,"paddingY")&&r.defaults(n,{paddingTop:n.paddingY,paddingBottom:n.paddingY}),r.has(n,"padding")&&r.defaults(n,{paddingLeft:n.padding,paddingRight:n.padding,paddingTop:n.padding,paddingBottom:n.padding}),r.defaults(n,o),r.each(["paddingLeft","paddingRight","paddingTop","paddingBottom"],(function(t){n[t]=Number(n[t])})),r.has(n,"width")&&(n._prevWidth=n.width),r.has(n,"height")&&(n._prevHeight=n.height)})),t.edges().forEach((function(e){var n=t.edge(e);r.has(n,"label")||(n.label=""),r.defaults(n,s)}))}(y);var g=c(n,"output"),m=c(g,"clusters"),v=c(g,"edgePaths"),b=i(c(g,"edgeLabels"),y),_=t(c(g,"nodes"),y,d);a(y),l(_,y),h(b,y),u(v,y,p);var x=e(m,y);f(x,y),function(t){r.each(t.nodes(),(function(e){var n=t.node(e);r.has(n,"_prevWidth")?n.width=n._prevWidth:delete n.width,r.has(n,"_prevHeight")?n.height=n._prevHeight:delete n.height,delete n._prevWidth,delete n._prevHeight}))}(y)};return y.createNodes=function(e){return arguments.length?(t=e,y):t},y.createClusters=function(t){return arguments.length?(e=t,y):e},y.createEdgeLabels=function(t){return arguments.length?(i=t,y):i},y.createEdgePaths=function(t){return arguments.length?(u=t,y):u},y.shapes=function(t){return arguments.length?(d=t,y):d},y.arrows=function(t){return arguments.length?(p=t,y):p},y};var o={paddingLeft:10,paddingRight:10,paddingTop:10,paddingBottom:10,rx:0,ry:0,shape:"rect"},s={arrowhead:"normal",curve:i.curveLinear};function c(t,e){var n=t.select("g."+e);return n.empty()&&(n=t.append("g").attr("class",e)),n}},4418:(t,e,n)=>{"use strict";var r=n(8049),i=n(3260),a=n(6587),o=n(5337);t.exports={rect:function(t,e,n){var i=t.insert("rect",":first-child").attr("rx",n.rx).attr("ry",n.ry).attr("x",-e.width/2).attr("y",-e.height/2).attr("width",e.width).attr("height",e.height);return n.intersect=function(t){return r(n,t)},i},ellipse:function(t,e,n){var r=e.width/2,a=e.height/2,o=t.insert("ellipse",":first-child").attr("x",-e.width/2).attr("y",-e.height/2).attr("rx",r).attr("ry",a);return n.intersect=function(t){return i(n,r,a,t)},o},circle:function(t,e,n){var r=Math.max(e.width,e.height)/2,i=t.insert("circle",":first-child").attr("x",-e.width/2).attr("y",-e.height/2).attr("r",r);return n.intersect=function(t){return a(n,r,t)},i},diamond:function(t,e,n){var r=e.width*Math.SQRT2/2,i=e.height*Math.SQRT2/2,a=[{x:0,y:-i},{x:-r,y:0},{x:0,y:i},{x:r,y:0}],s=t.insert("polygon",":first-child").attr("points",a.map((function(t){return t.x+","+t.y})).join(" "));return n.intersect=function(t){return o(n,a,t)},s}}},8355:(t,e,n)=>{var r=n(1034);t.exports={isSubgraph:function(t,e){return!!t.children(e).length},edgeToId:function(t){return a(t.v)+":"+a(t.w)+":"+a(t.name)},applyStyle:function(t,e){e&&t.attr("style",e)},applyClass:function(t,e,n){e&&t.attr("class",e).attr("class",n+" "+t.attr("class"))},applyTransition:function(t,e){var n=e.graph();if(r.isPlainObject(n)){var i=n.transition;if(r.isFunction(i))return i(t)}return t}};var i=/:/g;function a(t){return t?String(t).replace(i,"\\:"):""}},5689:t=>{t.exports="0.6.4"},7188:(t,e,n)=>{"use strict";n.r(e),n.d(e,{FormatSpecifier:()=>uc,active:()=>Jr,arc:()=>fx,area:()=>vx,areaRadial:()=>Sx,ascending:()=>i,autoType:()=>Fo,axisBottom:()=>it,axisLeft:()=>at,axisRight:()=>rt,axisTop:()=>nt,bisect:()=>u,bisectLeft:()=>c,bisectRight:()=>s,bisector:()=>a,blob:()=>ms,brush:()=>Ai,brushSelection:()=>Ei,brushX:()=>Ci,brushY:()=>Si,buffer:()=>bs,chord:()=>Fi,clientPoint:()=>Dn,cluster:()=>Sd,color:()=>Ve,contourDensity:()=>oo,contours:()=>to,create:()=>j_,creator:()=>ie,cross:()=>f,csv:()=>Ts,csvFormat:()=>To,csvFormatBody:()=>Eo,csvFormatRow:()=>So,csvFormatRows:()=>Co,csvFormatValue:()=>Ao,csvParse:()=>wo,csvParseRows:()=>ko,cubehelix:()=>Ha,curveBasis:()=>sw,curveBasisClosed:()=>uw,curveBasisOpen:()=>hw,curveBundle:()=>dw,curveCardinal:()=>gw,curveCardinalClosed:()=>vw,curveCardinalOpen:()=>_w,curveCatmullRom:()=>kw,curveCatmullRomClosed:()=>Ew,curveCatmullRomOpen:()=>Sw,curveLinear:()=>px,curveLinearClosed:()=>Mw,curveMonotoneX:()=>Fw,curveMonotoneY:()=>Pw,curveNatural:()=>zw,curveStep:()=>qw,curveStepAfter:()=>$w,curveStepBefore:()=>Hw,customEvent:()=>ge,descending:()=>d,deviation:()=>g,dispatch:()=>ft,drag:()=>po,dragDisable:()=>Se,dragEnable:()=>Ae,dsv:()=>ks,dsvFormat:()=>_o,easeBack:()=>hs,easeBackIn:()=>us,easeBackInOut:()=>hs,easeBackOut:()=>ls,easeBounce:()=>os,easeBounceIn:()=>as,easeBounceInOut:()=>ss,easeBounceOut:()=>os,easeCircle:()=>rs,easeCircleIn:()=>es,easeCircleInOut:()=>rs,easeCircleOut:()=>ns,easeCubic:()=>Xr,easeCubicIn:()=>Vr,easeCubicInOut:()=>Xr,easeCubicOut:()=>Gr,easeElastic:()=>ps,easeElasticIn:()=>ds,easeElasticInOut:()=>ys,easeElasticOut:()=>ps,easeExp:()=>ts,easeExpIn:()=>Ko,easeExpInOut:()=>ts,easeExpOut:()=>Jo,easeLinear:()=>jo,easePoly:()=>$o,easePolyIn:()=>qo,easePolyInOut:()=>$o,easePolyOut:()=>Ho,easeQuad:()=>Uo,easeQuadIn:()=>Yo,easeQuadInOut:()=>Uo,easeQuadOut:()=>zo,easeSin:()=>Zo,easeSinIn:()=>Go,easeSinInOut:()=>Zo,easeSinOut:()=>Xo,entries:()=>pa,event:()=>le,extent:()=>m,forceCenter:()=>Bs,forceCollide:()=>Ws,forceLink:()=>Xs,forceManyBody:()=>tc,forceRadial:()=>ec,forceSimulation:()=>Js,forceX:()=>nc,forceY:()=>rc,format:()=>pc,formatDefaultLocale:()=>bc,formatLocale:()=>vc,formatPrefix:()=>yc,formatSpecifier:()=>cc,geoAlbers:()=>Uf,geoAlbersUsa:()=>qf,geoArea:()=>yu,geoAzimuthalEqualArea:()=>Vf,geoAzimuthalEqualAreaRaw:()=>Wf,geoAzimuthalEquidistant:()=>Xf,geoAzimuthalEquidistantRaw:()=>Gf,geoBounds:()=>sl,geoCentroid:()=>bl,geoCircle:()=>Nl,geoClipAntimeridian:()=>Ul,geoClipCircle:()=>ql,geoClipExtent:()=>Vl,geoClipRectangle:()=>Wl,geoConicConformal:()=>ed,geoConicConformalRaw:()=>td,geoConicEqualArea:()=>zf,geoConicEqualAreaRaw:()=>Yf,geoConicEquidistant:()=>ad,geoConicEquidistantRaw:()=>id,geoContains:()=>ph,geoDistance:()=>ah,geoEqualEarth:()=>fd,geoEqualEarthRaw:()=>hd,geoEquirectangular:()=>rd,geoEquirectangularRaw:()=>nd,geoGnomonic:()=>pd,geoGnomonicRaw:()=>dd,geoGraticule:()=>mh,geoGraticule10:()=>vh,geoIdentity:()=>yd,geoInterpolate:()=>bh,geoLength:()=>nh,geoMercator:()=>Qf,geoMercatorRaw:()=>Zf,geoNaturalEarth1:()=>md,geoNaturalEarth1Raw:()=>gd,geoOrthographic:()=>bd,geoOrthographicRaw:()=>vd,geoPath:()=>kf,geoProjection:()=>Ff,geoProjectionMutator:()=>Pf,geoRotation:()=>Sl,geoStereographic:()=>xd,geoStereographicRaw:()=>_d,geoStream:()=>nu,geoTransform:()=>Tf,geoTransverseMercator:()=>kd,geoTransverseMercatorRaw:()=>wd,gray:()=>ka,hcl:()=>Oa,hierarchy:()=>Md,histogram:()=>D,hsl:()=>an,html:()=>Ds,image:()=>Cs,interpolate:()=>Mn,interpolateArray:()=>xn,interpolateBasis:()=>un,interpolateBasisClosed:()=>ln,interpolateBlues:()=>f_,interpolateBrBG:()=>Tb,interpolateBuGn:()=>Ub,interpolateBuPu:()=>Hb,interpolateCividis:()=>k_,interpolateCool:()=>C_,interpolateCubehelix:()=>zp,interpolateCubehelixDefault:()=>T_,interpolateCubehelixLong:()=>Up,interpolateDate:()=>kn,interpolateDiscrete:()=>Sp,interpolateGnBu:()=>Wb,interpolateGreens:()=>p_,interpolateGreys:()=>g_,interpolateHcl:()=>Pp,interpolateHclLong:()=>jp,interpolateHsl:()=>Lp,interpolateHslLong:()=>Ip,interpolateHue:()=>Ap,interpolateInferno:()=>F_,interpolateLab:()=>Rp,interpolateMagma:()=>R_,interpolateNumber:()=>Tn,interpolateNumberArray:()=>bn,interpolateObject:()=>En,interpolateOrRd:()=>Gb,interpolateOranges:()=>w_,interpolatePRGn:()=>Cb,interpolatePiYG:()=>Ab,interpolatePlasma:()=>P_,interpolatePuBu:()=>Kb,interpolatePuBuGn:()=>Zb,interpolatePuOr:()=>Nb,interpolatePuRd:()=>t_,interpolatePurples:()=>v_,interpolateRainbow:()=>A_,interpolateRdBu:()=>Ob,interpolateRdGy:()=>Lb,interpolateRdPu:()=>n_,interpolateRdYlBu:()=>Rb,interpolateRdYlGn:()=>Pb,interpolateReds:()=>__,interpolateRgb:()=>yn,interpolateRgbBasis:()=>mn,interpolateRgbBasisClosed:()=>vn,interpolateRound:()=>Mp,interpolateSinebow:()=>O_,interpolateSpectral:()=>Yb,interpolateString:()=>An,interpolateTransformCss:()=>pr,interpolateTransformSvg:()=>yr,interpolateTurbo:()=>B_,interpolateViridis:()=>I_,interpolateWarm:()=>E_,interpolateYlGn:()=>o_,interpolateYlGnBu:()=>i_,interpolateYlOrBr:()=>c_,interpolateYlOrRd:()=>l_,interpolateZoom:()=>Op,interrupt:()=>ar,interval:()=>fk,isoFormat:()=>uk,isoParse:()=>hk,json:()=>As,keys:()=>fa,lab:()=>Ta,lch:()=>Da,line:()=>mx,lineRadial:()=>Cx,linkHorizontal:()=>Rx,linkRadial:()=>Px,linkVertical:()=>Fx,local:()=>z_,map:()=>na,matcher:()=>mt,max:()=>I,mean:()=>R,median:()=>F,merge:()=>P,min:()=>j,mouse:()=>Bn,namespace:()=>Et,namespaces:()=>Tt,nest:()=>ra,now:()=>Hn,pack:()=>tp,packEnclose:()=>Id,packSiblings:()=>Gd,pairs:()=>l,partition:()=>op,path:()=>Wi,permute:()=>Y,pie:()=>xx,piecewise:()=>qp,pointRadial:()=>Ax,polygonArea:()=>$p,polygonCentroid:()=>Wp,polygonContains:()=>Qp,polygonHull:()=>Zp,polygonLength:()=>Kp,precisionFixed:()=>_c,precisionPrefix:()=>xc,precisionRound:()=>wc,quadtree:()=>Ys,quantile:()=>O,quantize:()=>Hp,radialArea:()=>Sx,radialLine:()=>Cx,randomBates:()=>iy,randomExponential:()=>ay,randomIrwinHall:()=>ry,randomLogNormal:()=>ny,randomNormal:()=>ey,randomUniform:()=>ty,range:()=>k,rgb:()=>Qe,ribbon:()=>Ki,scaleBand:()=>dy,scaleDiverging:()=>ob,scaleDivergingLog:()=>sb,scaleDivergingPow:()=>ub,scaleDivergingSqrt:()=>lb,scaleDivergingSymlog:()=>cb,scaleIdentity:()=>My,scaleImplicit:()=>hy,scaleLinear:()=>Ay,scaleLog:()=>Py,scaleOrdinal:()=>fy,scalePoint:()=>yy,scalePow:()=>Vy,scaleQuantile:()=>Xy,scaleQuantize:()=>Zy,scaleSequential:()=>Jv,scaleSequentialLog:()=>tb,scaleSequentialPow:()=>nb,scaleSequentialQuantile:()=>ib,scaleSequentialSqrt:()=>rb,scaleSequentialSymlog:()=>eb,scaleSqrt:()=>Gy,scaleSymlog:()=>Uy,scaleThreshold:()=>Qy,scaleTime:()=>Yv,scaleUtc:()=>Zv,scan:()=>z,schemeAccent:()=>db,schemeBlues:()=>h_,schemeBrBG:()=>kb,schemeBuGn:()=>zb,schemeBuPu:()=>qb,schemeCategory10:()=>fb,schemeDark2:()=>pb,schemeGnBu:()=>$b,schemeGreens:()=>d_,schemeGreys:()=>y_,schemeOrRd:()=>Vb,schemeOranges:()=>x_,schemePRGn:()=>Eb,schemePaired:()=>yb,schemePastel1:()=>gb,schemePastel2:()=>mb,schemePiYG:()=>Sb,schemePuBu:()=>Qb,schemePuBuGn:()=>Xb,schemePuOr:()=>Mb,schemePuRd:()=>Jb,schemePurples:()=>m_,schemeRdBu:()=>Db,schemeRdGy:()=>Bb,schemeRdPu:()=>e_,schemeRdYlBu:()=>Ib,schemeRdYlGn:()=>Fb,schemeReds:()=>b_,schemeSet1:()=>vb,schemeSet2:()=>bb,schemeSet3:()=>_b,schemeSpectral:()=>jb,schemeTableau10:()=>xb,schemeYlGn:()=>a_,schemeYlGnBu:()=>r_,schemeYlOrBr:()=>s_,schemeYlOrRd:()=>u_,select:()=>Te,selectAll:()=>q_,selection:()=>ke,selector:()=>pt,selectorAll:()=>gt,set:()=>ha,shuffle:()=>U,stack:()=>Xw,stackOffsetDiverging:()=>Qw,stackOffsetExpand:()=>Zw,stackOffsetNone:()=>Ww,stackOffsetSilhouette:()=>Kw,stackOffsetWiggle:()=>Jw,stackOrderAppearance:()=>tk,stackOrderAscending:()=>nk,stackOrderDescending:()=>ik,stackOrderInsideOut:()=>ak,stackOrderNone:()=>Vw,stackOrderReverse:()=>ok,stratify:()=>hp,style:()=>Rt,sum:()=>q,svg:()=>Os,symbol:()=>rw,symbolCircle:()=>jx,symbolCross:()=>Yx,symbolDiamond:()=>qx,symbolSquare:()=>Gx,symbolStar:()=>Vx,symbolTriangle:()=>Zx,symbolWye:()=>ew,symbols:()=>nw,text:()=>xs,thresholdFreedmanDiaconis:()=>B,thresholdScott:()=>L,thresholdSturges:()=>N,tickFormat:()=>Cy,tickIncrement:()=>A,tickStep:()=>M,ticks:()=>S,timeDay:()=>Ag,timeDays:()=>Mg,timeFormat:()=>pm,timeFormatDefaultLocale:()=>Iv,timeFormatLocale:()=>fm,timeFriday:()=>vg,timeFridays:()=>Eg,timeHour:()=>Dg,timeHours:()=>Og,timeInterval:()=>tg,timeMillisecond:()=>Yg,timeMilliseconds:()=>zg,timeMinute:()=>Lg,timeMinutes:()=>Ig,timeMonday:()=>pg,timeMondays:()=>xg,timeMonth:()=>ag,timeMonths:()=>og,timeParse:()=>ym,timeSaturday:()=>bg,timeSaturdays:()=>Cg,timeSecond:()=>Fg,timeSeconds:()=>Pg,timeSunday:()=>dg,timeSundays:()=>_g,timeThursday:()=>mg,timeThursdays:()=>Tg,timeTuesday:()=>yg,timeTuesdays:()=>wg,timeWednesday:()=>gg,timeWednesdays:()=>kg,timeWeek:()=>dg,timeWeeks:()=>_g,timeYear:()=>ng,timeYears:()=>rg,timeout:()=>Kn,timer:()=>Vn,timerFlush:()=>Gn,touch:()=>On,touches:()=>H_,transition:()=>Hr,transpose:()=>H,tree:()=>vp,treemap:()=>kp,treemapBinary:()=>Tp,treemapDice:()=>ap,treemapResquarify:()=>Cp,treemapSlice:()=>bp,treemapSliceDice:()=>Ep,treemapSquarify:()=>wp,tsv:()=>Es,tsvFormat:()=>Oo,tsvFormatBody:()=>Bo,tsvFormatRow:()=>Io,tsvFormatRows:()=>Lo,tsvFormatValue:()=>Ro,tsvParse:()=>No,tsvParseRows:()=>Do,utcDay:()=>im,utcDays:()=>am,utcFormat:()=>gm,utcFriday:()=>Gg,utcFridays:()=>em,utcHour:()=>$v,utcHours:()=>Wv,utcMillisecond:()=>Yg,utcMilliseconds:()=>zg,utcMinute:()=>Gv,utcMinutes:()=>Xv,utcMonday:()=>Hg,utcMondays:()=>Qg,utcMonth:()=>Uv,utcMonths:()=>qv,utcParse:()=>mm,utcSaturday:()=>Xg,utcSaturdays:()=>nm,utcSecond:()=>Fg,utcSeconds:()=>Pg,utcSunday:()=>qg,utcSundays:()=>Zg,utcThursday:()=>Vg,utcThursdays:()=>tm,utcTuesday:()=>$g,utcTuesdays:()=>Kg,utcWednesday:()=>Wg,utcWednesdays:()=>Jg,utcWeek:()=>qg,utcWeeks:()=>Zg,utcYear:()=>sm,utcYears:()=>cm,values:()=>da,variance:()=>y,version:()=>r,voronoi:()=>Kk,window:()=>Ot,xml:()=>Ns,zip:()=>W,zoom:()=>fT,zoomIdentity:()=>nT,zoomTransform:()=>rT});var r="5.16.0";function i(t,e){return t<e?-1:t>e?1:t>=e?0:NaN}function a(t){var e;return 1===t.length&&(e=t,t=function(t,n){return i(e(t),n)}),{left:function(e,n,r,i){for(null==r&&(r=0),null==i&&(i=e.length);r<i;){var a=r+i>>>1;t(e[a],n)<0?r=a+1:i=a}return r},right:function(e,n,r,i){for(null==r&&(r=0),null==i&&(i=e.length);r<i;){var a=r+i>>>1;t(e[a],n)>0?i=a:r=a+1}return r}}}var o=a(i),s=o.right,c=o.left;const u=s;function l(t,e){null==e&&(e=h);for(var n=0,r=t.length-1,i=t[0],a=new Array(r<0?0:r);n<r;)a[n]=e(i,i=t[++n]);return a}function h(t,e){return[t,e]}function f(t,e,n){var r,i,a,o,s=t.length,c=e.length,u=new Array(s*c);for(null==n&&(n=h),r=a=0;r<s;++r)for(o=t[r],i=0;i<c;++i,++a)u[a]=n(o,e[i]);return u}function d(t,e){return e<t?-1:e>t?1:e>=t?0:NaN}function p(t){return null===t?NaN:+t}function y(t,e){var n,r,i=t.length,a=0,o=-1,s=0,c=0;if(null==e)for(;++o<i;)isNaN(n=p(t[o]))||(c+=(r=n-s)*(n-(s+=r/++a)));else for(;++o<i;)isNaN(n=p(e(t[o],o,t)))||(c+=(r=n-s)*(n-(s+=r/++a)));if(a>1)return c/(a-1)}function g(t,e){var n=y(t,e);return n?Math.sqrt(n):n}function m(t,e){var n,r,i,a=t.length,o=-1;if(null==e){for(;++o<a;)if(null!=(n=t[o])&&n>=n)for(r=i=n;++o<a;)null!=(n=t[o])&&(r>n&&(r=n),i<n&&(i=n))}else for(;++o<a;)if(null!=(n=e(t[o],o,t))&&n>=n)for(r=i=n;++o<a;)null!=(n=e(t[o],o,t))&&(r>n&&(r=n),i<n&&(i=n));return[r,i]}var v=Array.prototype,b=v.slice,_=v.map;function x(t){return function(){return t}}function w(t){return t}function k(t,e,n){t=+t,e=+e,n=(i=arguments.length)<2?(e=t,t=0,1):i<3?1:+n;for(var r=-1,i=0|Math.max(0,Math.ceil((e-t)/n)),a=new Array(i);++r<i;)a[r]=t+r*n;return a}var T=Math.sqrt(50),E=Math.sqrt(10),C=Math.sqrt(2);function S(t,e,n){var r,i,a,o,s=-1;if(n=+n,(t=+t)==(e=+e)&&n>0)return[t];if((r=e<t)&&(i=t,t=e,e=i),0===(o=A(t,e,n))||!isFinite(o))return[];if(o>0)for(t=Math.ceil(t/o),e=Math.floor(e/o),a=new Array(i=Math.ceil(e-t+1));++s<i;)a[s]=(t+s)*o;else for(t=Math.floor(t*o),e=Math.ceil(e*o),a=new Array(i=Math.ceil(t-e+1));++s<i;)a[s]=(t-s)/o;return r&&a.reverse(),a}function A(t,e,n){var r=(e-t)/Math.max(0,n),i=Math.floor(Math.log(r)/Math.LN10),a=r/Math.pow(10,i);return i>=0?(a>=T?10:a>=E?5:a>=C?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(a>=T?10:a>=E?5:a>=C?2:1)}function M(t,e,n){var r=Math.abs(e-t)/Math.max(0,n),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),a=r/i;return a>=T?i*=10:a>=E?i*=5:a>=C&&(i*=2),e<t?-i:i}function N(t){return Math.ceil(Math.log(t.length)/Math.LN2)+1}function D(){var t=w,e=m,n=N;function r(r){var i,a,o=r.length,s=new Array(o);for(i=0;i<o;++i)s[i]=t(r[i],i,r);var c=e(s),l=c[0],h=c[1],f=n(s,l,h);Array.isArray(f)||(f=M(l,h,f),f=k(Math.ceil(l/f)*f,h,f));for(var d=f.length;f[0]<=l;)f.shift(),--d;for(;f[d-1]>h;)f.pop(),--d;var p,y=new Array(d+1);for(i=0;i<=d;++i)(p=y[i]=[]).x0=i>0?f[i-1]:l,p.x1=i<d?f[i]:h;for(i=0;i<o;++i)l<=(a=s[i])&&a<=h&&y[u(f,a,0,d)].push(r[i]);return y}return r.value=function(e){return arguments.length?(t="function"==typeof e?e:x(e),r):t},r.domain=function(t){return arguments.length?(e="function"==typeof t?t:x([t[0],t[1]]),r):e},r.thresholds=function(t){return arguments.length?(n="function"==typeof t?t:Array.isArray(t)?x(b.call(t)):x(t),r):n},r}function O(t,e,n){if(null==n&&(n=p),r=t.length){if((e=+e)<=0||r<2)return+n(t[0],0,t);if(e>=1)return+n(t[r-1],r-1,t);var r,i=(r-1)*e,a=Math.floor(i),o=+n(t[a],a,t);return o+(+n(t[a+1],a+1,t)-o)*(i-a)}}function B(t,e,n){return t=_.call(t,p).sort(i),Math.ceil((n-e)/(2*(O(t,.75)-O(t,.25))*Math.pow(t.length,-1/3)))}function L(t,e,n){return Math.ceil((n-e)/(3.5*g(t)*Math.pow(t.length,-1/3)))}function I(t,e){var n,r,i=t.length,a=-1;if(null==e){for(;++a<i;)if(null!=(n=t[a])&&n>=n)for(r=n;++a<i;)null!=(n=t[a])&&n>r&&(r=n)}else for(;++a<i;)if(null!=(n=e(t[a],a,t))&&n>=n)for(r=n;++a<i;)null!=(n=e(t[a],a,t))&&n>r&&(r=n);return r}function R(t,e){var n,r=t.length,i=r,a=-1,o=0;if(null==e)for(;++a<r;)isNaN(n=p(t[a]))?--i:o+=n;else for(;++a<r;)isNaN(n=p(e(t[a],a,t)))?--i:o+=n;if(i)return o/i}function F(t,e){var n,r=t.length,a=-1,o=[];if(null==e)for(;++a<r;)isNaN(n=p(t[a]))||o.push(n);else for(;++a<r;)isNaN(n=p(e(t[a],a,t)))||o.push(n);return O(o.sort(i),.5)}function P(t){for(var e,n,r,i=t.length,a=-1,o=0;++a<i;)o+=t[a].length;for(n=new Array(o);--i>=0;)for(e=(r=t[i]).length;--e>=0;)n[--o]=r[e];return n}function j(t,e){var n,r,i=t.length,a=-1;if(null==e){for(;++a<i;)if(null!=(n=t[a])&&n>=n)for(r=n;++a<i;)null!=(n=t[a])&&r>n&&(r=n)}else for(;++a<i;)if(null!=(n=e(t[a],a,t))&&n>=n)for(r=n;++a<i;)null!=(n=e(t[a],a,t))&&r>n&&(r=n);return r}function Y(t,e){for(var n=e.length,r=new Array(n);n--;)r[n]=t[e[n]];return r}function z(t,e){if(n=t.length){var n,r,a=0,o=0,s=t[o];for(null==e&&(e=i);++a<n;)(e(r=t[a],s)<0||0!==e(s,s))&&(s=r,o=a);return 0===e(s,s)?o:void 0}}function U(t,e,n){for(var r,i,a=(null==n?t.length:n)-(e=null==e?0:+e);a;)i=Math.random()*a--|0,r=t[a+e],t[a+e]=t[i+e],t[i+e]=r;return t}function q(t,e){var n,r=t.length,i=-1,a=0;if(null==e)for(;++i<r;)(n=+t[i])&&(a+=n);else for(;++i<r;)(n=+e(t[i],i,t))&&(a+=n);return a}function H(t){if(!(i=t.length))return[];for(var e=-1,n=j(t,$),r=new Array(n);++e<n;)for(var i,a=-1,o=r[e]=new Array(i);++a<i;)o[a]=t[a][e];return r}function $(t){return t.length}function W(){return H(arguments)}var V=Array.prototype.slice;function G(t){return t}var X=1e-6;function Z(t){return"translate("+(t+.5)+",0)"}function Q(t){return"translate(0,"+(t+.5)+")"}function K(t){return function(e){return+t(e)}}function J(t){var e=Math.max(0,t.bandwidth()-1)/2;return t.round()&&(e=Math.round(e)),function(n){return+t(n)+e}}function tt(){return!this.__axis}function et(t,e){var n=[],r=null,i=null,a=6,o=6,s=3,c=1===t||4===t?-1:1,u=4===t||2===t?"x":"y",l=1===t||3===t?Z:Q;function h(h){var f=null==r?e.ticks?e.ticks.apply(e,n):e.domain():r,d=null==i?e.tickFormat?e.tickFormat.apply(e,n):G:i,p=Math.max(a,0)+s,y=e.range(),g=+y[0]+.5,m=+y[y.length-1]+.5,v=(e.bandwidth?J:K)(e.copy()),b=h.selection?h.selection():h,_=b.selectAll(".domain").data([null]),x=b.selectAll(".tick").data(f,e).order(),w=x.exit(),k=x.enter().append("g").attr("class","tick"),T=x.select("line"),E=x.select("text");_=_.merge(_.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),x=x.merge(k),T=T.merge(k.append("line").attr("stroke","currentColor").attr(u+"2",c*a)),E=E.merge(k.append("text").attr("fill","currentColor").attr(u,c*p).attr("dy",1===t?"0em":3===t?"0.71em":"0.32em")),h!==b&&(_=_.transition(h),x=x.transition(h),T=T.transition(h),E=E.transition(h),w=w.transition(h).attr("opacity",X).attr("transform",(function(t){return isFinite(t=v(t))?l(t):this.getAttribute("transform")})),k.attr("opacity",X).attr("transform",(function(t){var e=this.parentNode.__axis;return l(e&&isFinite(e=e(t))?e:v(t))}))),w.remove(),_.attr("d",4===t||2==t?o?"M"+c*o+","+g+"H0.5V"+m+"H"+c*o:"M0.5,"+g+"V"+m:o?"M"+g+","+c*o+"V0.5H"+m+"V"+c*o:"M"+g+",0.5H"+m),x.attr("opacity",1).attr("transform",(function(t){return l(v(t))})),T.attr(u+"2",c*a),E.attr(u,c*p).text(d),b.filter(tt).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",2===t?"start":4===t?"end":"middle"),b.each((function(){this.__axis=v}))}return h.scale=function(t){return arguments.length?(e=t,h):e},h.ticks=function(){return n=V.call(arguments),h},h.tickArguments=function(t){return arguments.length?(n=null==t?[]:V.call(t),h):n.slice()},h.tickValues=function(t){return arguments.length?(r=null==t?null:V.call(t),h):r&&r.slice()},h.tickFormat=function(t){return arguments.length?(i=t,h):i},h.tickSize=function(t){return arguments.length?(a=o=+t,h):a},h.tickSizeInner=function(t){return arguments.length?(a=+t,h):a},h.tickSizeOuter=function(t){return arguments.length?(o=+t,h):o},h.tickPadding=function(t){return arguments.length?(s=+t,h):s},h}function nt(t){return et(1,t)}function rt(t){return et(2,t)}function it(t){return et(3,t)}function at(t){return et(4,t)}var ot={value:function(){}};function st(){for(var t,e=0,n=arguments.length,r={};e<n;++e){if(!(t=arguments[e]+"")||t in r||/[\s.]/.test(t))throw new Error("illegal type: "+t);r[t]=[]}return new ct(r)}function ct(t){this._=t}function ut(t,e){return t.trim().split(/^|\s+/).map((function(t){var n="",r=t.indexOf(".");if(r>=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function lt(t,e){for(var n,r=0,i=t.length;r<i;++r)if((n=t[r]).name===e)return n.value}function ht(t,e,n){for(var r=0,i=t.length;r<i;++r)if(t[r].name===e){t[r]=ot,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=n&&t.push({name:e,value:n}),t}ct.prototype=st.prototype={constructor:ct,on:function(t,e){var n,r=this._,i=ut(t+"",r),a=-1,o=i.length;if(!(arguments.length<2)){if(null!=e&&"function"!=typeof e)throw new Error("invalid callback: "+e);for(;++a<o;)if(n=(t=i[a]).type)r[n]=ht(r[n],t.name,e);else if(null==e)for(n in r)r[n]=ht(r[n],t.name,null);return this}for(;++a<o;)if((n=(t=i[a]).type)&&(n=lt(r[n],t.name)))return n},copy:function(){var t={},e=this._;for(var n in e)t[n]=e[n].slice();return new ct(t)},call:function(t,e){if((n=arguments.length-2)>0)for(var n,r,i=new Array(n),a=0;a<n;++a)i[a]=arguments[a+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(a=0,n=(r=this._[t]).length;a<n;++a)r[a].value.apply(e,i)},apply:function(t,e,n){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,a=r.length;i<a;++i)r[i].value.apply(e,n)}};const ft=st;function dt(){}function pt(t){return null==t?dt:function(){return this.querySelector(t)}}function yt(){return[]}function gt(t){return null==t?yt:function(){return this.querySelectorAll(t)}}function mt(t){return function(){return this.matches(t)}}function vt(t){return new Array(t.length)}function bt(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}function _t(t,e,n,r,i,a){for(var o,s=0,c=e.length,u=a.length;s<u;++s)(o=e[s])?(o.__data__=a[s],r[s]=o):n[s]=new bt(t,a[s]);for(;s<c;++s)(o=e[s])&&(i[s]=o)}function xt(t,e,n,r,i,a,o){var s,c,u,l={},h=e.length,f=a.length,d=new Array(h);for(s=0;s<h;++s)(c=e[s])&&(d[s]=u="$"+o.call(c,c.__data__,s,e),u in l?i[s]=c:l[u]=c);for(s=0;s<f;++s)(c=l[u="$"+o.call(t,a[s],s,a)])?(r[s]=c,c.__data__=a[s],l[u]=null):n[s]=new bt(t,a[s]);for(s=0;s<h;++s)(c=e[s])&&l[d[s]]===c&&(i[s]=c)}function wt(t,e){return t<e?-1:t>e?1:t>=e?0:NaN}bt.prototype={constructor:bt,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var kt="http://www.w3.org/1999/xhtml";const Tt={svg:"http://www.w3.org/2000/svg",xhtml:kt,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function Et(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),Tt.hasOwnProperty(e)?{space:Tt[e],local:t}:t}function Ct(t){return function(){this.removeAttribute(t)}}function St(t){return function(){this.removeAttributeNS(t.space,t.local)}}function At(t,e){return function(){this.setAttribute(t,e)}}function Mt(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function Nt(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function Dt(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function Ot(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function Bt(t){return function(){this.style.removeProperty(t)}}function Lt(t,e,n){return function(){this.style.setProperty(t,e,n)}}function It(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function Rt(t,e){return t.style.getPropertyValue(e)||Ot(t).getComputedStyle(t,null).getPropertyValue(e)}function Ft(t){return function(){delete this[t]}}function Pt(t,e){return function(){this[t]=e}}function jt(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function Yt(t){return t.trim().split(/^|\s+/)}function zt(t){return t.classList||new Ut(t)}function Ut(t){this._node=t,this._names=Yt(t.getAttribute("class")||"")}function qt(t,e){for(var n=zt(t),r=-1,i=e.length;++r<i;)n.add(e[r])}function Ht(t,e){for(var n=zt(t),r=-1,i=e.length;++r<i;)n.remove(e[r])}function $t(t){return function(){qt(this,t)}}function Wt(t){return function(){Ht(this,t)}}function Vt(t,e){return function(){(e.apply(this,arguments)?qt:Ht)(this,t)}}function Gt(){this.textContent=""}function Xt(t){return function(){this.textContent=t}}function Zt(t){return function(){var e=t.apply(this,arguments);this.textContent=null==e?"":e}}function Qt(){this.innerHTML=""}function Kt(t){return function(){this.innerHTML=t}}function Jt(t){return function(){var e=t.apply(this,arguments);this.innerHTML=null==e?"":e}}function te(){this.nextSibling&&this.parentNode.appendChild(this)}function ee(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function ne(t){return function(){var e=this.ownerDocument,n=this.namespaceURI;return n===kt&&e.documentElement.namespaceURI===kt?e.createElement(t):e.createElementNS(n,t)}}function re(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function ie(t){var e=Et(t);return(e.local?re:ne)(e)}function ae(){return null}function oe(){var t=this.parentNode;t&&t.removeChild(this)}function se(){var t=this.cloneNode(!1),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}function ce(){var t=this.cloneNode(!0),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}Ut.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var ue={},le=null;function he(t,e,n){return t=fe(t,e,n),function(e){var n=e.relatedTarget;n&&(n===this||8&n.compareDocumentPosition(this))||t.call(this,e)}}function fe(t,e,n){return function(r){var i=le;le=r;try{t.call(this,this.__data__,e,n)}finally{le=i}}}function de(t){return t.trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");return n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function pe(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r<a;++r)n=e[r],t.type&&n.type!==t.type||n.name!==t.name?e[++i]=n:this.removeEventListener(n.type,n.listener,n.capture);++i?e.length=i:delete this.__on}}}function ye(t,e,n){var r=ue.hasOwnProperty(t.type)?he:fe;return function(i,a,o){var s,c=this.__on,u=r(e,a,o);if(c)for(var l=0,h=c.length;l<h;++l)if((s=c[l]).type===t.type&&s.name===t.name)return this.removeEventListener(s.type,s.listener,s.capture),this.addEventListener(s.type,s.listener=u,s.capture=n),void(s.value=e);this.addEventListener(t.type,u,n),s={type:t.type,name:t.name,value:e,listener:u,capture:n},c?c.push(s):this.__on=[s]}}function ge(t,e,n,r){var i=le;t.sourceEvent=le,le=t;try{return e.apply(n,r)}finally{le=i}}function me(t,e,n){var r=Ot(t),i=r.CustomEvent;"function"==typeof i?i=new i(e,n):(i=r.document.createEvent("Event"),n?(i.initEvent(e,n.bubbles,n.cancelable),i.detail=n.detail):i.initEvent(e,!1,!1)),t.dispatchEvent(i)}function ve(t,e){return function(){return me(this,t,e)}}function be(t,e){return function(){return me(this,t,e.apply(this,arguments))}}"undefined"!=typeof document&&("onmouseenter"in document.documentElement||(ue={mouseenter:"mouseover",mouseleave:"mouseout"}));var _e=[null];function xe(t,e){this._groups=t,this._parents=e}function we(){return new xe([[document.documentElement]],_e)}xe.prototype=we.prototype={constructor:xe,select:function(t){"function"!=typeof t&&(t=pt(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o,s=e[i],c=s.length,u=r[i]=new Array(c),l=0;l<c;++l)(a=s[l])&&(o=t.call(a,a.__data__,l,s))&&("__data__"in a&&(o.__data__=a.__data__),u[l]=o);return new xe(r,this._parents)},selectAll:function(t){"function"!=typeof t&&(t=gt(t));for(var e=this._groups,n=e.length,r=[],i=[],a=0;a<n;++a)for(var o,s=e[a],c=s.length,u=0;u<c;++u)(o=s[u])&&(r.push(t.call(o,o.__data__,u,s)),i.push(o));return new xe(r,i)},filter:function(t){"function"!=typeof t&&(t=mt(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o=e[i],s=o.length,c=r[i]=[],u=0;u<s;++u)(a=o[u])&&t.call(a,a.__data__,u,o)&&c.push(a);return new xe(r,this._parents)},data:function(t,e){if(!t)return p=new Array(this.size()),l=-1,this.each((function(t){p[++l]=t})),p;var n,r=e?xt:_t,i=this._parents,a=this._groups;"function"!=typeof t&&(n=t,t=function(){return n});for(var o=a.length,s=new Array(o),c=new Array(o),u=new Array(o),l=0;l<o;++l){var h=i[l],f=a[l],d=f.length,p=t.call(h,h&&h.__data__,l,i),y=p.length,g=c[l]=new Array(y),m=s[l]=new Array(y);r(h,f,g,m,u[l]=new Array(d),p,e);for(var v,b,_=0,x=0;_<y;++_)if(v=g[_]){for(_>=x&&(x=_+1);!(b=m[x])&&++x<y;);v._next=b||null}}return(s=new xe(s,i))._enter=c,s._exit=u,s},enter:function(){return new xe(this._enter||this._groups.map(vt),this._parents)},exit:function(){return new xe(this._exit||this._groups.map(vt),this._parents)},join:function(t,e,n){var r=this.enter(),i=this,a=this.exit();return r="function"==typeof t?t(r):r.append(t+""),null!=e&&(i=e(i)),null==n?a.remove():n(a),r&&i?r.merge(i).order():i},merge:function(t){for(var e=this._groups,n=t._groups,r=e.length,i=n.length,a=Math.min(r,i),o=new Array(r),s=0;s<a;++s)for(var c,u=e[s],l=n[s],h=u.length,f=o[s]=new Array(h),d=0;d<h;++d)(c=u[d]||l[d])&&(f[d]=c);for(;s<r;++s)o[s]=e[s];return new xe(o,this._parents)},order:function(){for(var t=this._groups,e=-1,n=t.length;++e<n;)for(var r,i=t[e],a=i.length-1,o=i[a];--a>=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=wt);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a<r;++a){for(var o,s=n[a],c=s.length,u=i[a]=new Array(c),l=0;l<c;++l)(o=s[l])&&(u[l]=o);u.sort(e)}return new xe(i,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){var t=new Array(this.size()),e=-1;return this.each((function(){t[++e]=this})),t},node:function(){for(var t=this._groups,e=0,n=t.length;e<n;++e)for(var r=t[e],i=0,a=r.length;i<a;++i){var o=r[i];if(o)return o}return null},size:function(){var t=0;return this.each((function(){++t})),t},empty:function(){return!this.node()},each:function(t){for(var e=this._groups,n=0,r=e.length;n<r;++n)for(var i,a=e[n],o=0,s=a.length;o<s;++o)(i=a[o])&&t.call(i,i.__data__,o,a);return this},attr:function(t,e){var n=Et(t);if(arguments.length<2){var r=this.node();return n.local?r.getAttributeNS(n.space,n.local):r.getAttribute(n)}return this.each((null==e?n.local?St:Ct:"function"==typeof e?n.local?Dt:Nt:n.local?Mt:At)(n,e))},style:function(t,e,n){return arguments.length>1?this.each((null==e?Bt:"function"==typeof e?It:Lt)(t,e,null==n?"":n)):Rt(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?Ft:"function"==typeof e?jt:Pt)(t,e)):this.node()[t]},classed:function(t,e){var n=Yt(t+"");if(arguments.length<2){for(var r=zt(this.node()),i=-1,a=n.length;++i<a;)if(!r.contains(n[i]))return!1;return!0}return this.each(("function"==typeof e?Vt:e?$t:Wt)(n,e))},text:function(t){return arguments.length?this.each(null==t?Gt:("function"==typeof t?Zt:Xt)(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?Qt:("function"==typeof t?Jt:Kt)(t)):this.node().innerHTML},raise:function(){return this.each(te)},lower:function(){return this.each(ee)},append:function(t){var e="function"==typeof t?t:ie(t);return this.select((function(){return this.appendChild(e.apply(this,arguments))}))},insert:function(t,e){var n="function"==typeof t?t:ie(t),r=null==e?ae:"function"==typeof e?e:pt(e);return this.select((function(){return this.insertBefore(n.apply(this,arguments),r.apply(this,arguments)||null)}))},remove:function(){return this.each(oe)},clone:function(t){return this.select(t?ce:se)},datum:function(t){return arguments.length?this.property("__data__",t):this.node().__data__},on:function(t,e,n){var r,i,a=de(t+""),o=a.length;if(!(arguments.length<2)){for(s=e?ye:pe,null==n&&(n=!1),r=0;r<o;++r)this.each(s(a[r],e,n));return this}var s=this.node().__on;if(s)for(var c,u=0,l=s.length;u<l;++u)for(r=0,c=s[u];r<o;++r)if((i=a[r]).type===c.type&&i.name===c.name)return c.value},dispatch:function(t,e){return this.each(("function"==typeof e?be:ve)(t,e))}};const ke=we;function Te(t){return"string"==typeof t?new xe([[document.querySelector(t)]],[document.documentElement]):new xe([[t]],_e)}function Ee(){le.stopImmediatePropagation()}function Ce(){le.preventDefault(),le.stopImmediatePropagation()}function Se(t){var e=t.document.documentElement,n=Te(t).on("dragstart.drag",Ce,!0);"onselectstart"in e?n.on("selectstart.drag",Ce,!0):(e.__noselect=e.style.MozUserSelect,e.style.MozUserSelect="none")}function Ae(t,e){var n=t.document.documentElement,r=Te(t).on("dragstart.drag",null);e&&(r.on("click.drag",Ce,!0),setTimeout((function(){r.on("click.drag",null)}),0)),"onselectstart"in n?r.on("selectstart.drag",null):(n.style.MozUserSelect=n.__noselect,delete n.__noselect)}function Me(t,e,n){t.prototype=e.prototype=n,n.constructor=t}function Ne(t,e){var n=Object.create(t.prototype);for(var r in e)n[r]=e[r];return n}function De(){}var Oe=.7,Be=1/Oe,Le="\\s*([+-]?\\d+)\\s*",Ie="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",Re="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",Fe=/^#([0-9a-f]{3,8})$/,Pe=new RegExp("^rgb\\("+[Le,Le,Le]+"\\)$"),je=new RegExp("^rgb\\("+[Re,Re,Re]+"\\)$"),Ye=new RegExp("^rgba\\("+[Le,Le,Le,Ie]+"\\)$"),ze=new RegExp("^rgba\\("+[Re,Re,Re,Ie]+"\\)$"),Ue=new RegExp("^hsl\\("+[Ie,Re,Re]+"\\)$"),qe=new RegExp("^hsla\\("+[Ie,Re,Re,Ie]+"\\)$"),He={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function $e(){return this.rgb().formatHex()}function We(){return this.rgb().formatRgb()}function Ve(t){var e,n;return t=(t+"").trim().toLowerCase(),(e=Fe.exec(t))?(n=e[1].length,e=parseInt(e[1],16),6===n?Ge(e):3===n?new Ke(e>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?Xe(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?Xe(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Pe.exec(t))?new Ke(e[1],e[2],e[3],1):(e=je.exec(t))?new Ke(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Ye.exec(t))?Xe(e[1],e[2],e[3],e[4]):(e=ze.exec(t))?Xe(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=Ue.exec(t))?nn(e[1],e[2]/100,e[3]/100,1):(e=qe.exec(t))?nn(e[1],e[2]/100,e[3]/100,e[4]):He.hasOwnProperty(t)?Ge(He[t]):"transparent"===t?new Ke(NaN,NaN,NaN,0):null}function Ge(t){return new Ke(t>>16&255,t>>8&255,255&t,1)}function Xe(t,e,n,r){return r<=0&&(t=e=n=NaN),new Ke(t,e,n,r)}function Ze(t){return t instanceof De||(t=Ve(t)),t?new Ke((t=t.rgb()).r,t.g,t.b,t.opacity):new Ke}function Qe(t,e,n,r){return 1===arguments.length?Ze(t):new Ke(t,e,n,null==r?1:r)}function Ke(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function Je(){return"#"+en(this.r)+en(this.g)+en(this.b)}function tn(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function en(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function nn(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new on(t,e,n,r)}function rn(t){if(t instanceof on)return new on(t.h,t.s,t.l,t.opacity);if(t instanceof De||(t=Ve(t)),!t)return new on;if(t instanceof on)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n<r):n===a?(r-e)/s+2:(e-n)/s+4,s/=c<.5?a+i:2-a-i,o*=60):s=c>0&&c<1?0:o,new on(o,s,c,t.opacity)}function an(t,e,n,r){return 1===arguments.length?rn(t):new on(t,e,n,null==r?1:r)}function on(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function sn(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function cn(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}function un(t){var e=t.length-1;return function(n){var r=n<=0?n=0:n>=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=r<e-1?t[r+2]:2*a-i;return cn((n-r/e)*e,o,i,a,s)}}function ln(t){var e=t.length;return function(n){var r=Math.floor(((n%=1)<0?++n:n)*e),i=t[(r+e-1)%e],a=t[r%e],o=t[(r+1)%e],s=t[(r+2)%e];return cn((n-r/e)*e,i,a,o,s)}}function hn(t){return function(){return t}}function fn(t,e){return function(n){return t+n*e}}function dn(t,e){var n=e-t;return n?fn(t,n>180||n<-180?n-360*Math.round(n/360):n):hn(isNaN(t)?e:t)}function pn(t,e){var n=e-t;return n?fn(t,n):hn(isNaN(t)?e:t)}Me(De,Ve,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:$e,formatHex:$e,formatHsl:function(){return rn(this).formatHsl()},formatRgb:We,toString:We}),Me(Ke,Qe,Ne(De,{brighter:function(t){return t=null==t?Be:Math.pow(Be,t),new Ke(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?Oe:Math.pow(Oe,t),new Ke(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Je,formatHex:Je,formatRgb:tn,toString:tn})),Me(on,an,Ne(De,{brighter:function(t){return t=null==t?Be:Math.pow(Be,t),new on(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Oe:Math.pow(Oe,t),new on(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new Ke(sn(t>=240?t-240:t+120,i,r),sn(t,i,r),sn(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const yn=function t(e){var n=function(t){return 1==(t=+t)?pn:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):hn(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=Qe(t)).r,(e=Qe(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=pn(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function gn(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n<i;++n)r=Qe(e[n]),a[n]=r.r||0,o[n]=r.g||0,s[n]=r.b||0;return a=t(a),o=t(o),s=t(s),r.opacity=1,function(t){return r.r=a(t),r.g=o(t),r.b=s(t),r+""}}}var mn=gn(un),vn=gn(ln);function bn(t,e){e||(e=[]);var n,r=t?Math.min(e.length,t.length):0,i=e.slice();return function(a){for(n=0;n<r;++n)i[n]=t[n]*(1-a)+e[n]*a;return i}}function _n(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function xn(t,e){return(_n(e)?bn:wn)(t,e)}function wn(t,e){var n,r=e?e.length:0,i=t?Math.min(r,t.length):0,a=new Array(i),o=new Array(r);for(n=0;n<i;++n)a[n]=Mn(t[n],e[n]);for(;n<r;++n)o[n]=e[n];return function(t){for(n=0;n<i;++n)o[n]=a[n](t);return o}}function kn(t,e){var n=new Date;return t=+t,e=+e,function(r){return n.setTime(t*(1-r)+e*r),n}}function Tn(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}function En(t,e){var n,r={},i={};for(n in null!==t&&"object"==typeof t||(t={}),null!==e&&"object"==typeof e||(e={}),e)n in t?r[n]=Mn(t[n],e[n]):i[n]=e[n];return function(t){for(n in r)i[n]=r[n](t);return i}}var Cn=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Sn=new RegExp(Cn.source,"g");function An(t,e){var n,r,i,a=Cn.lastIndex=Sn.lastIndex=0,o=-1,s=[],c=[];for(t+="",e+="";(n=Cn.exec(t))&&(r=Sn.exec(e));)(i=r.index)>a&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:Tn(n,r)})),a=Sn.lastIndex;return a<e.length&&(i=e.slice(a),s[o]?s[o]+=i:s[++o]=i),s.length<2?c[0]?function(t){return function(e){return t(e)+""}}(c[0].x):function(t){return function(){return t}}(e):(e=c.length,function(t){for(var n,r=0;r<e;++r)s[(n=c[r]).i]=n.x(t);return s.join("")})}function Mn(t,e){var n,r=typeof e;return null==e||"boolean"===r?hn(e):("number"===r?Tn:"string"===r?(n=Ve(e))?(e=n,yn):An:e instanceof Ve?yn:e instanceof Date?kn:_n(e)?bn:Array.isArray(e)?wn:"function"!=typeof e.valueOf&&"function"!=typeof e.toString||isNaN(e)?En:Tn)(t,e)}function Nn(){for(var t,e=le;t=e.sourceEvent;)e=t;return e}function Dn(t,e){var n=t.ownerSVGElement||t;if(n.createSVGPoint){var r=n.createSVGPoint();return r.x=e.clientX,r.y=e.clientY,[(r=r.matrixTransform(t.getScreenCTM().inverse())).x,r.y]}var i=t.getBoundingClientRect();return[e.clientX-i.left-t.clientLeft,e.clientY-i.top-t.clientTop]}function On(t,e,n){arguments.length<3&&(n=e,e=Nn().changedTouches);for(var r,i=0,a=e?e.length:0;i<a;++i)if((r=e[i]).identifier===n)return Dn(t,r);return null}function Bn(t){var e=Nn();return e.changedTouches&&(e=e.changedTouches[0]),Dn(t,e)}var Ln,In,Rn=0,Fn=0,Pn=0,jn=0,Yn=0,zn=0,Un="object"==typeof performance&&performance.now?performance:Date,qn="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function Hn(){return Yn||(qn($n),Yn=Un.now()+zn)}function $n(){Yn=0}function Wn(){this._call=this._time=this._next=null}function Vn(t,e,n){var r=new Wn;return r.restart(t,e,n),r}function Gn(){Hn(),++Rn;for(var t,e=Ln;e;)(t=Yn-e._time)>=0&&e._call.call(null,t),e=e._next;--Rn}function Xn(){Yn=(jn=Un.now())+zn,Rn=Fn=0;try{Gn()}finally{Rn=0,function(){for(var t,e,n=Ln,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:Ln=e);In=t,Qn(r)}(),Yn=0}}function Zn(){var t=Un.now(),e=t-jn;e>1e3&&(zn-=e,jn=t)}function Qn(t){Rn||(Fn&&(Fn=clearTimeout(Fn)),t-Yn>24?(t<1/0&&(Fn=setTimeout(Xn,t-Un.now()-zn)),Pn&&(Pn=clearInterval(Pn))):(Pn||(jn=Un.now(),Pn=setInterval(Zn,1e3)),Rn=1,qn(Xn)))}function Kn(t,e,n){var r=new Wn;return e=null==e?0:+e,r.restart((function(n){r.stop(),t(n+e)}),e,n),r}Wn.prototype=Vn.prototype={constructor:Wn,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?Hn():+n)+(null==e?0:+e),this._next||In===this||(In?In._next=this:Ln=this,In=this),this._call=t,this._time=n,Qn()},stop:function(){this._call&&(this._call=null,this._time=1/0,Qn())}};var Jn=ft("start","end","cancel","interrupt"),tr=[];function er(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return Kn(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u<e&&(f.state=6,f.timer.stop(),f.on.call("cancel",t,t.__data__,f.index,f.group),delete i[u])}if(Kn((function(){3===n.state&&(n.state=4,n.timer.restart(o,n.delay,n.time),o(c))})),n.state=2,n.on.call("start",t,t.__data__,n.index,n.group),2===n.state){for(n.state=3,r=new Array(h=n.tween.length),u=0,l=-1;u<h;++u)(f=n.tween[u].value.call(t,t.__data__,n.index,n.group))&&(r[++l]=f);r.length=l+1}}function o(e){for(var i=e<n.duration?n.ease.call(null,e/n.duration):(n.timer.restart(s),n.state=5,1),a=-1,o=r.length;++a<o;)r[a].call(t,i);5===n.state&&(n.on.call("end",t,t.__data__,n.index,n.group),s())}function s(){for(var r in n.state=6,n.timer.stop(),delete i[e],i)return;delete t.__transition}i[e]=n,n.timer=Vn((function(t){n.state=1,n.timer.restart(a,n.delay,n.time),n.delay<=t&&a(t-n.delay)}),0,n.time)}(t,n,{name:e,index:r,group:i,on:Jn,tween:tr,time:a.time,delay:a.delay,duration:a.duration,ease:a.ease,timer:null,state:0})}function nr(t,e){var n=ir(t,e);if(n.state>0)throw new Error("too late; already scheduled");return n}function rr(t,e){var n=ir(t,e);if(n.state>3)throw new Error("too late; already running");return n}function ir(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function ar(t,e){var n,r,i,a=t.__transition,o=!0;if(a){for(i in e=null==e?null:e+"",a)(n=a[i]).name===e?(r=n.state>2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}var or,sr,cr,ur,lr=180/Math.PI,hr={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function fr(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r<e*n&&(t=-t,e=-e,c=-c,o=-o),{translateX:i,translateY:a,rotate:Math.atan2(e,t)*lr,skewX:Math.atan(c)*lr,scaleX:o,scaleY:s}}function dr(t,e,n,r){function i(t){return t.length?t.pop()+" ":""}return function(a,o){var s=[],c=[];return a=t(a),o=t(o),function(t,r,i,a,o,s){if(t!==i||r!==a){var c=o.push("translate(",null,e,null,n);s.push({i:c-4,x:Tn(t,i)},{i:c-2,x:Tn(r,a)})}else(i||a)&&o.push("translate("+i+e+a+n)}(a.translateX,a.translateY,o.translateX,o.translateY,s,c),function(t,e,n,a){t!==e?(t-e>180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:Tn(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:Tn(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:Tn(t,n)},{i:s-2,x:Tn(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n<r;)s[(e=c[n]).i]=e.x(t);return s.join("")}}}var pr=dr((function(t){return"none"===t?hr:(or||(or=document.createElement("DIV"),sr=document.documentElement,cr=document.defaultView),or.style.transform=t,t=cr.getComputedStyle(sr.appendChild(or),null).getPropertyValue("transform"),sr.removeChild(or),fr(+(t=t.slice(7,-1).split(","))[0],+t[1],+t[2],+t[3],+t[4],+t[5]))}),"px, ","px)","deg)"),yr=dr((function(t){return null==t?hr:(ur||(ur=document.createElementNS("http://www.w3.org/2000/svg","g")),ur.setAttribute("transform",t),(t=ur.transform.baseVal.consolidate())?fr((t=t.matrix).a,t.b,t.c,t.d,t.e,t.f):hr)}),", ",")",")");function gr(t,e){var n,r;return function(){var i=rr(this,t),a=i.tween;if(a!==n)for(var o=0,s=(r=n=a).length;o<s;++o)if(r[o].name===e){(r=r.slice()).splice(o,1);break}i.tween=r}}function mr(t,e,n){var r,i;if("function"!=typeof n)throw new Error;return function(){var a=rr(this,t),o=a.tween;if(o!==r){i=(r=o).slice();for(var s={name:e,value:n},c=0,u=i.length;c<u;++c)if(i[c].name===e){i[c]=s;break}c===u&&i.push(s)}a.tween=i}}function vr(t,e,n){var r=t._id;return t.each((function(){var t=rr(this,r);(t.value||(t.value={}))[e]=n.apply(this,arguments)})),function(t){return ir(t,r).value[e]}}function br(t,e){var n;return("number"==typeof e?Tn:e instanceof Ve?yn:(n=Ve(e))?(e=n,yn):An)(t,e)}function _r(t){return function(){this.removeAttribute(t)}}function xr(t){return function(){this.removeAttributeNS(t.space,t.local)}}function wr(t,e,n){var r,i,a=n+"";return function(){var o=this.getAttribute(t);return o===a?null:o===r?i:i=e(r=o,n)}}function kr(t,e,n){var r,i,a=n+"";return function(){var o=this.getAttributeNS(t.space,t.local);return o===a?null:o===r?i:i=e(r=o,n)}}function Tr(t,e,n){var r,i,a;return function(){var o,s,c=n(this);if(null!=c)return(o=this.getAttribute(t))===(s=c+"")?null:o===r&&s===i?a:(i=s,a=e(r=o,c));this.removeAttribute(t)}}function Er(t,e,n){var r,i,a;return function(){var o,s,c=n(this);if(null!=c)return(o=this.getAttributeNS(t.space,t.local))===(s=c+"")?null:o===r&&s===i?a:(i=s,a=e(r=o,c));this.removeAttributeNS(t.space,t.local)}}function Cr(t,e){return function(n){this.setAttribute(t,e.call(this,n))}}function Sr(t,e){return function(n){this.setAttributeNS(t.space,t.local,e.call(this,n))}}function Ar(t,e){var n,r;function i(){var i=e.apply(this,arguments);return i!==r&&(n=(r=i)&&Sr(t,i)),n}return i._value=e,i}function Mr(t,e){var n,r;function i(){var i=e.apply(this,arguments);return i!==r&&(n=(r=i)&&Cr(t,i)),n}return i._value=e,i}function Nr(t,e){return function(){nr(this,t).delay=+e.apply(this,arguments)}}function Dr(t,e){return e=+e,function(){nr(this,t).delay=e}}function Or(t,e){return function(){rr(this,t).duration=+e.apply(this,arguments)}}function Br(t,e){return e=+e,function(){rr(this,t).duration=e}}function Lr(t,e){if("function"!=typeof e)throw new Error;return function(){rr(this,t).ease=e}}function Ir(t,e,n){var r,i,a=function(t){return(t+"").trim().split(/^|\s+/).every((function(t){var e=t.indexOf(".");return e>=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?nr:rr;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var Rr=ke.prototype.constructor;function Fr(t){return function(){this.style.removeProperty(t)}}function Pr(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function jr(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&Pr(t,a,n)),r}return a._value=e,a}function Yr(t){return function(e){this.textContent=t.call(this,e)}}function zr(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&Yr(r)),e}return r._value=t,r}var Ur=0;function qr(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function Hr(t){return ke().transition(t)}function $r(){return++Ur}var Wr=ke.prototype;function Vr(t){return t*t*t}function Gr(t){return--t*t*t+1}function Xr(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}qr.prototype=Hr.prototype={constructor:qr,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=pt(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o<i;++o)for(var s,c,u=r[o],l=u.length,h=a[o]=new Array(l),f=0;f<l;++f)(s=u[f])&&(c=t.call(s,s.__data__,f,u))&&("__data__"in s&&(c.__data__=s.__data__),h[f]=c,er(h[f],e,n,f,h,ir(s,n)));return new qr(a,this._parents,e,n)},selectAll:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=gt(t));for(var r=this._groups,i=r.length,a=[],o=[],s=0;s<i;++s)for(var c,u=r[s],l=u.length,h=0;h<l;++h)if(c=u[h]){for(var f,d=t.call(c,c.__data__,h,u),p=ir(c,n),y=0,g=d.length;y<g;++y)(f=d[y])&&er(f,e,n,y,d,p);a.push(d),o.push(c)}return new qr(a,o,e,n)},filter:function(t){"function"!=typeof t&&(t=mt(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i<n;++i)for(var a,o=e[i],s=o.length,c=r[i]=[],u=0;u<s;++u)(a=o[u])&&t.call(a,a.__data__,u,o)&&c.push(a);return new qr(r,this._parents,this._name,this._id)},merge:function(t){if(t._id!==this._id)throw new Error;for(var e=this._groups,n=t._groups,r=e.length,i=n.length,a=Math.min(r,i),o=new Array(r),s=0;s<a;++s)for(var c,u=e[s],l=n[s],h=u.length,f=o[s]=new Array(h),d=0;d<h;++d)(c=u[d]||l[d])&&(f[d]=c);for(;s<r;++s)o[s]=e[s];return new qr(o,this._parents,this._name,this._id)},selection:function(){return new Rr(this._groups,this._parents)},transition:function(){for(var t=this._name,e=this._id,n=$r(),r=this._groups,i=r.length,a=0;a<i;++a)for(var o,s=r[a],c=s.length,u=0;u<c;++u)if(o=s[u]){var l=ir(o,e);er(o,t,n,u,s,{time:l.time+l.delay+l.duration,delay:0,duration:l.duration,ease:l.ease})}return new qr(r,this._parents,t,n)},call:Wr.call,nodes:Wr.nodes,node:Wr.node,size:Wr.size,empty:Wr.empty,each:Wr.each,on:function(t,e){var n=this._id;return arguments.length<2?ir(this.node(),n).on.on(t):this.each(Ir(n,t,e))},attr:function(t,e){var n=Et(t),r="transform"===n?yr:br;return this.attrTween(t,"function"==typeof e?(n.local?Er:Tr)(n,r,vr(this,"attr."+t,e)):null==e?(n.local?xr:_r)(n):(n.local?kr:wr)(n,r,e))},attrTween:function(t,e){var n="attr."+t;if(arguments.length<2)return(n=this.tween(n))&&n._value;if(null==e)return this.tween(n,null);if("function"!=typeof e)throw new Error;var r=Et(t);return this.tween(n,(r.local?Ar:Mr)(r,e))},style:function(t,e,n){var r="transform"==(t+="")?pr:br;return null==e?this.styleTween(t,function(t,e){var n,r,i;return function(){var a=Rt(this,t),o=(this.style.removeProperty(t),Rt(this,t));return a===o?null:a===n&&o===r?i:i=e(n=a,r=o)}}(t,r)).on("end.style."+t,Fr(t)):"function"==typeof e?this.styleTween(t,function(t,e,n){var r,i,a;return function(){var o=Rt(this,t),s=n(this),c=s+"";return null==s&&(this.style.removeProperty(t),c=s=Rt(this,t)),o===c?null:o===r&&c===i?a:(i=c,a=e(r=o,s))}}(t,r,vr(this,"style."+t,e))).each(function(t,e){var n,r,i,a,o="style."+e,s="end."+o;return function(){var c=rr(this,t),u=c.on,l=null==c.value[o]?a||(a=Fr(e)):void 0;u===n&&i===l||(r=(n=u).copy()).on(s,i=l),c.on=r}}(this._id,t)):this.styleTween(t,function(t,e,n){var r,i,a=n+"";return function(){var o=Rt(this,t);return o===a?null:o===r?i:i=e(r=o,n)}}(t,r,e),n).on("end.style."+t,null)},styleTween:function(t,e,n){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==e)return this.tween(r,null);if("function"!=typeof e)throw new Error;return this.tween(r,jr(t,e,null==n?"":n))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var e=t(this);this.textContent=null==e?"":e}}(vr(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},textTween:function(t){var e="text";if(arguments.length<1)return(e=this.tween(e))&&e._value;if(null==t)return this.tween(e,null);if("function"!=typeof t)throw new Error;return this.tween(e,zr(t))},remove:function(){return this.on("end.remove",function(t){return function(){var e=this.parentNode;for(var n in this.__transition)if(+n!==t)return;e&&e.removeChild(this)}}(this._id))},tween:function(t,e){var n=this._id;if(t+="",arguments.length<2){for(var r,i=ir(this.node(),n).tween,a=0,o=i.length;a<o;++a)if((r=i[a]).name===t)return r.value;return null}return this.each((null==e?gr:mr)(n,t,e))},delay:function(t){var e=this._id;return arguments.length?this.each(("function"==typeof t?Nr:Dr)(e,t)):ir(this.node(),e).delay},duration:function(t){var e=this._id;return arguments.length?this.each(("function"==typeof t?Or:Br)(e,t)):ir(this.node(),e).duration},ease:function(t){var e=this._id;return arguments.length?this.each(Lr(e,t)):ir(this.node(),e).ease},end:function(){var t,e,n=this,r=n._id,i=n.size();return new Promise((function(a,o){var s={value:o},c={value:function(){0==--i&&a()}};n.each((function(){var n=rr(this,r),i=n.on;i!==t&&((e=(t=i).copy())._.cancel.push(s),e._.interrupt.push(s),e._.end.push(c)),n.on=e}))}))}};var Zr={time:null,delay:0,duration:250,ease:Xr};function Qr(t,e){for(var n;!(n=t.__transition)||!(n=n[e]);)if(!(t=t.parentNode))return Zr.time=Hn(),Zr;return n}ke.prototype.interrupt=function(t){return this.each((function(){ar(this,t)}))},ke.prototype.transition=function(t){var e,n;t instanceof qr?(e=t._id,t=t._name):(e=$r(),(n=Zr).time=Hn(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;a<i;++a)for(var o,s=r[a],c=s.length,u=0;u<c;++u)(o=s[u])&&er(o,t,e,u,s,n||Qr(o,e));return new qr(r,this._parents,t,e)};var Kr=[null];function Jr(t,e){var n,r,i=t.__transition;if(i)for(r in e=null==e?null:e+"",i)if((n=i[r]).state>1&&n.name===e)return new qr([[t]],Kr,e,+r);return null}function ti(t){return function(){return t}}function ei(t,e,n){this.target=t,this.type=e,this.selection=n}function ni(){le.stopImmediatePropagation()}function ri(){le.preventDefault(),le.stopImmediatePropagation()}var ii={name:"drag"},ai={name:"space"},oi={name:"handle"},si={name:"center"};function ci(t){return[+t[0],+t[1]]}function ui(t){return[ci(t[0]),ci(t[1])]}function li(t){return function(e){return On(e,le.touches,t)}}var hi={name:"x",handles:["w","e"].map(bi),input:function(t,e){return null==t?null:[[+t[0],e[0][1]],[+t[1],e[1][1]]]},output:function(t){return t&&[t[0][0],t[1][0]]}},fi={name:"y",handles:["n","s"].map(bi),input:function(t,e){return null==t?null:[[e[0][0],+t[0]],[e[1][0],+t[1]]]},output:function(t){return t&&[t[0][1],t[1][1]]}},di={name:"xy",handles:["n","w","e","s","nw","ne","sw","se"].map(bi),input:function(t){return null==t?null:ui(t)},output:function(t){return t}},pi={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},yi={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"},gi={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"},mi={overlay:1,selection:1,n:null,e:1,s:null,w:-1,nw:-1,ne:1,se:1,sw:-1},vi={overlay:1,selection:1,n:-1,e:null,s:1,w:null,nw:-1,ne:-1,se:1,sw:1};function bi(t){return{type:t}}function _i(){return!le.ctrlKey&&!le.button}function xi(){var t=this.ownerSVGElement||this;return t.hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]}function wi(){return navigator.maxTouchPoints||"ontouchstart"in this}function ki(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__brush}function Ti(t){return t[0][0]===t[1][0]||t[0][1]===t[1][1]}function Ei(t){var e=t.__brush;return e?e.dim.output(e.selection):null}function Ci(){return Mi(hi)}function Si(){return Mi(fi)}function Ai(){return Mi(di)}function Mi(t){var e,n=xi,r=_i,i=wi,a=!0,o=ft("start","brush","end"),s=6;function c(e){var n=e.property("__brush",y).selectAll(".overlay").data([bi("overlay")]);n.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",pi.overlay).merge(n).each((function(){var t=ki(this).extent;Te(this).attr("x",t[0][0]).attr("y",t[0][1]).attr("width",t[1][0]-t[0][0]).attr("height",t[1][1]-t[0][1])})),e.selectAll(".selection").data([bi("selection")]).enter().append("rect").attr("class","selection").attr("cursor",pi.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var r=e.selectAll(".handle").data(t.handles,(function(t){return t.type}));r.exit().remove(),r.enter().append("rect").attr("class",(function(t){return"handle handle--"+t.type})).attr("cursor",(function(t){return pi[t.type]})),e.each(u).attr("fill","none").attr("pointer-events","all").on("mousedown.brush",f).filter(i).on("touchstart.brush",f).on("touchmove.brush",d).on("touchend.brush touchcancel.brush",p).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function u(){var t=Te(this),e=ki(this).selection;e?(t.selectAll(".selection").style("display",null).attr("x",e[0][0]).attr("y",e[0][1]).attr("width",e[1][0]-e[0][0]).attr("height",e[1][1]-e[0][1]),t.selectAll(".handle").style("display",null).attr("x",(function(t){return"e"===t.type[t.type.length-1]?e[1][0]-s/2:e[0][0]-s/2})).attr("y",(function(t){return"s"===t.type[0]?e[1][1]-s/2:e[0][1]-s/2})).attr("width",(function(t){return"n"===t.type||"s"===t.type?e[1][0]-e[0][0]+s:s})).attr("height",(function(t){return"e"===t.type||"w"===t.type?e[1][1]-e[0][1]+s:s}))):t.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}function l(t,e,n){var r=t.__brush.emitter;return!r||n&&r.clean?new h(t,e,n):r}function h(t,e,n){this.that=t,this.args=e,this.state=t.__brush,this.active=0,this.clean=n}function f(){if((!e||le.touches)&&r.apply(this,arguments)){var n,i,o,s,c,h,f,d,p,y,g,m=this,v=le.target.__data__.type,b="selection"===(a&&le.metaKey?v="overlay":v)?ii:a&&le.altKey?si:oi,_=t===fi?null:mi[v],x=t===hi?null:vi[v],w=ki(m),k=w.extent,T=w.selection,E=k[0][0],C=k[0][1],S=k[1][0],A=k[1][1],M=0,N=0,D=_&&x&&a&&le.shiftKey,O=le.touches?li(le.changedTouches[0].identifier):Bn,B=O(m),L=B,I=l(m,arguments,!0).beforestart();"overlay"===v?(T&&(p=!0),w.selection=T=[[n=t===fi?E:B[0],o=t===hi?C:B[1]],[c=t===fi?S:n,f=t===hi?A:o]]):(n=T[0][0],o=T[0][1],c=T[1][0],f=T[1][1]),i=n,s=o,h=c,d=f;var R=Te(m).attr("pointer-events","none"),F=R.selectAll(".overlay").attr("cursor",pi[v]);if(le.touches)I.moved=j,I.ended=z;else{var P=Te(le.view).on("mousemove.brush",j,!0).on("mouseup.brush",z,!0);a&&P.on("keydown.brush",U,!0).on("keyup.brush",q,!0),Se(le.view)}ni(),ar(m),u.call(m),I.start()}function j(){var t=O(m);!D||y||g||(Math.abs(t[0]-L[0])>Math.abs(t[1]-L[1])?g=!0:y=!0),L=t,p=!0,ri(),Y()}function Y(){var t;switch(M=L[0]-B[0],N=L[1]-B[1],b){case ai:case ii:_&&(M=Math.max(E-n,Math.min(S-c,M)),i=n+M,h=c+M),x&&(N=Math.max(C-o,Math.min(A-f,N)),s=o+N,d=f+N);break;case oi:_<0?(M=Math.max(E-n,Math.min(S-n,M)),i=n+M,h=c):_>0&&(M=Math.max(E-c,Math.min(S-c,M)),i=n,h=c+M),x<0?(N=Math.max(C-o,Math.min(A-o,N)),s=o+N,d=f):x>0&&(N=Math.max(C-f,Math.min(A-f,N)),s=o,d=f+N);break;case si:_&&(i=Math.max(E,Math.min(S,n-M*_)),h=Math.max(E,Math.min(S,c+M*_))),x&&(s=Math.max(C,Math.min(A,o-N*x)),d=Math.max(C,Math.min(A,f+N*x)))}h<i&&(_*=-1,t=n,n=c,c=t,t=i,i=h,h=t,v in yi&&F.attr("cursor",pi[v=yi[v]])),d<s&&(x*=-1,t=o,o=f,f=t,t=s,s=d,d=t,v in gi&&F.attr("cursor",pi[v=gi[v]])),w.selection&&(T=w.selection),y&&(i=T[0][0],h=T[1][0]),g&&(s=T[0][1],d=T[1][1]),T[0][0]===i&&T[0][1]===s&&T[1][0]===h&&T[1][1]===d||(w.selection=[[i,s],[h,d]],u.call(m),I.brush())}function z(){if(ni(),le.touches){if(le.touches.length)return;e&&clearTimeout(e),e=setTimeout((function(){e=null}),500)}else Ae(le.view,p),P.on("keydown.brush keyup.brush mousemove.brush mouseup.brush",null);R.attr("pointer-events","all"),F.attr("cursor",pi.overlay),w.selection&&(T=w.selection),Ti(T)&&(w.selection=null,u.call(m)),I.end()}function U(){switch(le.keyCode){case 16:D=_&&x;break;case 18:b===oi&&(_&&(c=h-M*_,n=i+M*_),x&&(f=d-N*x,o=s+N*x),b=si,Y());break;case 32:b!==oi&&b!==si||(_<0?c=h-M:_>0&&(n=i-M),x<0?f=d-N:x>0&&(o=s-N),b=ai,F.attr("cursor",pi.selection),Y());break;default:return}ri()}function q(){switch(le.keyCode){case 16:D&&(y=g=D=!1,Y());break;case 18:b===si&&(_<0?c=h:_>0&&(n=i),x<0?f=d:x>0&&(o=s),b=oi,Y());break;case 32:b===ai&&(le.altKey?(_&&(c=h-M*_,n=i+M*_),x&&(f=d-N*x,o=s+N*x),b=si):(_<0?c=h:_>0&&(n=i),x<0?f=d:x>0&&(o=s),b=oi),F.attr("cursor",pi[v]),Y());break;default:return}ri()}}function d(){l(this,arguments).moved()}function p(){l(this,arguments).ended()}function y(){var e=this.__brush||{selection:null};return e.extent=ui(n.apply(this,arguments)),e.dim=t,e}return c.move=function(e,n){e.selection?e.on("start.brush",(function(){l(this,arguments).beforestart().start()})).on("interrupt.brush end.brush",(function(){l(this,arguments).end()})).tween("brush",(function(){var e=this,r=e.__brush,i=l(e,arguments),a=r.selection,o=t.input("function"==typeof n?n.apply(this,arguments):n,r.extent),s=Mn(a,o);function c(t){r.selection=1===t&&null===o?null:s(t),u.call(e),i.brush()}return null!==a&&null!==o?c:c(1)})):e.each((function(){var e=this,r=arguments,i=e.__brush,a=t.input("function"==typeof n?n.apply(e,r):n,i.extent),o=l(e,r).beforestart();ar(e),i.selection=null===a?null:a,u.call(e),o.start().brush().end()}))},c.clear=function(t){c.move(t,null)},h.prototype={beforestart:function(){return 1==++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(){return this.starting?(this.starting=!1,this.emit("start")):this.emit("brush"),this},brush:function(){return this.emit("brush"),this},end:function(){return 0==--this.active&&(delete this.state.emitter,this.emit("end")),this},emit:function(e){ge(new ei(c,e,t.output(this.state.selection)),o.apply,o,[e,this.that,this.args])}},c.extent=function(t){return arguments.length?(n="function"==typeof t?t:ti(ui(t)),c):n},c.filter=function(t){return arguments.length?(r="function"==typeof t?t:ti(!!t),c):r},c.touchable=function(t){return arguments.length?(i="function"==typeof t?t:ti(!!t),c):i},c.handleSize=function(t){return arguments.length?(s=+t,c):s},c.keyModifiers=function(t){return arguments.length?(a=!!t,c):a},c.on=function(){var t=o.on.apply(o,arguments);return t===o?c:t},c}var Ni=Math.cos,Di=Math.sin,Oi=Math.PI,Bi=Oi/2,Li=2*Oi,Ii=Math.max;function Ri(t){return function(e,n){return t(e.source.value+e.target.value,n.source.value+n.target.value)}}function Fi(){var t=0,e=null,n=null,r=null;function i(i){var a,o,s,c,u,l,h=i.length,f=[],d=k(h),p=[],y=[],g=y.groups=new Array(h),m=new Array(h*h);for(a=0,u=-1;++u<h;){for(o=0,l=-1;++l<h;)o+=i[u][l];f.push(o),p.push(k(h)),a+=o}for(e&&d.sort((function(t,n){return e(f[t],f[n])})),n&&p.forEach((function(t,e){t.sort((function(t,r){return n(i[e][t],i[e][r])}))})),c=(a=Ii(0,Li-t*h)/a)?t:Li/h,o=0,u=-1;++u<h;){for(s=o,l=-1;++l<h;){var v=d[u],b=p[v][l],_=i[v][b],x=o,w=o+=_*a;m[b*h+v]={index:v,subindex:b,startAngle:x,endAngle:w,value:_}}g[v]={index:v,startAngle:s,endAngle:o,value:f[v]},o+=c}for(u=-1;++u<h;)for(l=u-1;++l<h;){var T=m[l*h+u],E=m[u*h+l];(T.value||E.value)&&y.push(T.value<E.value?{source:E,target:T}:{source:T,target:E})}return r?y.sort(r):y}return i.padAngle=function(e){return arguments.length?(t=Ii(0,e),i):t},i.sortGroups=function(t){return arguments.length?(e=t,i):e},i.sortSubgroups=function(t){return arguments.length?(n=t,i):n},i.sortChords=function(t){return arguments.length?(null==t?r=null:(r=Ri(t))._=t,i):r&&r._},i}var Pi=Array.prototype.slice;function ji(t){return function(){return t}}var Yi=Math.PI,zi=2*Yi,Ui=1e-6,qi=zi-Ui;function Hi(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function $i(){return new Hi}Hi.prototype=$i.prototype={constructor:Hi,moveTo:function(t,e){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)},closePath:function(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,e){this._+="L"+(this._x1=+t)+","+(this._y1=+e)},quadraticCurveTo:function(t,e,n,r){this._+="Q"+ +t+","+ +e+","+(this._x1=+n)+","+(this._y1=+r)},bezierCurveTo:function(t,e,n,r,i,a){this._+="C"+ +t+","+ +e+","+ +n+","+ +r+","+(this._x1=+i)+","+(this._y1=+a)},arcTo:function(t,e,n,r,i){t=+t,e=+e,n=+n,r=+r,i=+i;var a=this._x1,o=this._y1,s=n-t,c=r-e,u=a-t,l=o-e,h=u*u+l*l;if(i<0)throw new Error("negative radius: "+i);if(null===this._x1)this._+="M"+(this._x1=t)+","+(this._y1=e);else if(h>Ui)if(Math.abs(l*s-c*u)>Ui&&i){var f=n-a,d=r-o,p=s*s+c*c,y=f*f+d*d,g=Math.sqrt(p),m=Math.sqrt(h),v=i*Math.tan((Yi-Math.acos((p+h-y)/(2*g*m)))/2),b=v/m,_=v/g;Math.abs(b-1)>Ui&&(this._+="L"+(t+b*u)+","+(e+b*l)),this._+="A"+i+","+i+",0,0,"+ +(l*f>u*d)+","+(this._x1=t+_*s)+","+(this._y1=e+_*c)}else this._+="L"+(this._x1=t)+","+(this._y1=e)},arc:function(t,e,n,r,i,a){t=+t,e=+e,a=!!a;var o=(n=+n)*Math.cos(r),s=n*Math.sin(r),c=t+o,u=e+s,l=1^a,h=a?r-i:i-r;if(n<0)throw new Error("negative radius: "+n);null===this._x1?this._+="M"+c+","+u:(Math.abs(this._x1-c)>Ui||Math.abs(this._y1-u)>Ui)&&(this._+="L"+c+","+u),n&&(h<0&&(h=h%zi+zi),h>qi?this._+="A"+n+","+n+",0,1,"+l+","+(t-o)+","+(e-s)+"A"+n+","+n+",0,1,"+l+","+(this._x1=c)+","+(this._y1=u):h>Ui&&(this._+="A"+n+","+n+",0,"+ +(h>=Yi)+","+l+","+(this._x1=t+n*Math.cos(i))+","+(this._y1=e+n*Math.sin(i))))},rect:function(t,e,n,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +n+"v"+ +r+"h"+-n+"Z"},toString:function(){return this._}};const Wi=$i;function Vi(t){return t.source}function Gi(t){return t.target}function Xi(t){return t.radius}function Zi(t){return t.startAngle}function Qi(t){return t.endAngle}function Ki(){var t=Vi,e=Gi,n=Xi,r=Zi,i=Qi,a=null;function o(){var o,s=Pi.call(arguments),c=t.apply(this,s),u=e.apply(this,s),l=+n.apply(this,(s[0]=c,s)),h=r.apply(this,s)-Bi,f=i.apply(this,s)-Bi,d=l*Ni(h),p=l*Di(h),y=+n.apply(this,(s[0]=u,s)),g=r.apply(this,s)-Bi,m=i.apply(this,s)-Bi;if(a||(a=o=Wi()),a.moveTo(d,p),a.arc(0,0,l,h,f),h===g&&f===m||(a.quadraticCurveTo(0,0,y*Ni(g),y*Di(g)),a.arc(0,0,y,g,m)),a.quadraticCurveTo(0,0,d,p),a.closePath(),o)return a=null,o+""||null}return o.radius=function(t){return arguments.length?(n="function"==typeof t?t:ji(+t),o):n},o.startAngle=function(t){return arguments.length?(r="function"==typeof t?t:ji(+t),o):r},o.endAngle=function(t){return arguments.length?(i="function"==typeof t?t:ji(+t),o):i},o.source=function(e){return arguments.length?(t=e,o):t},o.target=function(t){return arguments.length?(e=t,o):e},o.context=function(t){return arguments.length?(a=null==t?null:t,o):a},o}var Ji="$";function ta(){}function ea(t,e){var n=new ta;if(t instanceof ta)t.each((function(t,e){n.set(e,t)}));else if(Array.isArray(t)){var r,i=-1,a=t.length;if(null==e)for(;++i<a;)n.set(i,t[i]);else for(;++i<a;)n.set(e(r=t[i],i,t),r)}else if(t)for(var o in t)n.set(o,t[o]);return n}ta.prototype=ea.prototype={constructor:ta,has:function(t){return Ji+t in this},get:function(t){return this[Ji+t]},set:function(t,e){return this[Ji+t]=e,this},remove:function(t){var e=Ji+t;return e in this&&delete this[e]},clear:function(){for(var t in this)t[0]===Ji&&delete this[t]},keys:function(){var t=[];for(var e in this)e[0]===Ji&&t.push(e.slice(1));return t},values:function(){var t=[];for(var e in this)e[0]===Ji&&t.push(this[e]);return t},entries:function(){var t=[];for(var e in this)e[0]===Ji&&t.push({key:e.slice(1),value:this[e]});return t},size:function(){var t=0;for(var e in this)e[0]===Ji&&++t;return t},empty:function(){for(var t in this)if(t[0]===Ji)return!1;return!0},each:function(t){for(var e in this)e[0]===Ji&&t(this[e],e.slice(1),this)}};const na=ea;function ra(){var t,e,n,r=[],i=[];function a(n,i,o,s){if(i>=r.length)return null!=t&&n.sort(t),null!=e?e(n):n;for(var c,u,l,h=-1,f=n.length,d=r[i++],p=na(),y=o();++h<f;)(l=p.get(c=d(u=n[h])+""))?l.push(u):p.set(c,[u]);return p.each((function(t,e){s(y,e,a(t,i,o,s))})),y}function o(t,n){if(++n>r.length)return t;var a,s=i[n-1];return null!=e&&n>=r.length?a=t.entries():(a=[],t.each((function(t,e){a.push({key:e,values:o(t,n)})}))),null!=s?a.sort((function(t,e){return s(t.key,e.key)})):a}return n={object:function(t){return a(t,0,ia,aa)},map:function(t){return a(t,0,oa,sa)},entries:function(t){return o(a(t,0,oa,sa),0)},key:function(t){return r.push(t),n},sortKeys:function(t){return i[r.length-1]=t,n},sortValues:function(e){return t=e,n},rollup:function(t){return e=t,n}}}function ia(){return{}}function aa(t,e,n){t[e]=n}function oa(){return na()}function sa(t,e,n){t.set(e,n)}function ca(){}var ua=na.prototype;function la(t,e){var n=new ca;if(t instanceof ca)t.each((function(t){n.add(t)}));else if(t){var r=-1,i=t.length;if(null==e)for(;++r<i;)n.add(t[r]);else for(;++r<i;)n.add(e(t[r],r,t))}return n}ca.prototype=la.prototype={constructor:ca,has:ua.has,add:function(t){return this[Ji+(t+="")]=t,this},remove:ua.remove,clear:ua.clear,values:ua.keys,size:ua.size,empty:ua.empty,each:ua.each};const ha=la;function fa(t){var e=[];for(var n in t)e.push(n);return e}function da(t){var e=[];for(var n in t)e.push(t[n]);return e}function pa(t){var e=[];for(var n in t)e.push({key:n,value:t[n]});return e}var ya=Math.PI/180,ga=180/Math.PI,ma=.96422,va=.82521,ba=4/29,_a=6/29,xa=3*_a*_a;function wa(t){if(t instanceof Ea)return new Ea(t.l,t.a,t.b,t.opacity);if(t instanceof Ba)return La(t);t instanceof Ke||(t=Ze(t));var e,n,r=Ma(t.r),i=Ma(t.g),a=Ma(t.b),o=Ca((.2225045*r+.7168786*i+.0606169*a)/1);return r===i&&i===a?e=n=o:(e=Ca((.4360747*r+.3850649*i+.1430804*a)/ma),n=Ca((.0139322*r+.0971045*i+.7141733*a)/va)),new Ea(116*o-16,500*(e-o),200*(o-n),t.opacity)}function ka(t,e){return new Ea(t,0,0,null==e?1:e)}function Ta(t,e,n,r){return 1===arguments.length?wa(t):new Ea(t,e,n,null==r?1:r)}function Ea(t,e,n,r){this.l=+t,this.a=+e,this.b=+n,this.opacity=+r}function Ca(t){return t>.008856451679035631?Math.pow(t,1/3):t/xa+ba}function Sa(t){return t>_a?t*t*t:xa*(t-ba)}function Aa(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Ma(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Na(t){if(t instanceof Ba)return new Ba(t.h,t.c,t.l,t.opacity);if(t instanceof Ea||(t=wa(t)),0===t.a&&0===t.b)return new Ba(NaN,0<t.l&&t.l<100?0:NaN,t.l,t.opacity);var e=Math.atan2(t.b,t.a)*ga;return new Ba(e<0?e+360:e,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function Da(t,e,n,r){return 1===arguments.length?Na(t):new Ba(n,e,t,null==r?1:r)}function Oa(t,e,n,r){return 1===arguments.length?Na(t):new Ba(t,e,n,null==r?1:r)}function Ba(t,e,n,r){this.h=+t,this.c=+e,this.l=+n,this.opacity=+r}function La(t){if(isNaN(t.h))return new Ea(t.l,0,0,t.opacity);var e=t.h*ya;return new Ea(t.l,Math.cos(e)*t.c,Math.sin(e)*t.c,t.opacity)}Me(Ea,Ta,Ne(De,{brighter:function(t){return new Ea(this.l+18*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new Ea(this.l-18*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,e=isNaN(this.a)?t:t+this.a/500,n=isNaN(this.b)?t:t-this.b/200;return new Ke(Aa(3.1338561*(e=ma*Sa(e))-1.6168667*(t=1*Sa(t))-.4906146*(n=va*Sa(n))),Aa(-.9787684*e+1.9161415*t+.033454*n),Aa(.0719453*e-.2289914*t+1.4052427*n),this.opacity)}})),Me(Ba,Oa,Ne(De,{brighter:function(t){return new Ba(this.h,this.c,this.l+18*(null==t?1:t),this.opacity)},darker:function(t){return new Ba(this.h,this.c,this.l-18*(null==t?1:t),this.opacity)},rgb:function(){return La(this).rgb()}}));var Ia=-.14861,Ra=1.78277,Fa=-.29227,Pa=-.90649,ja=1.97294,Ya=ja*Pa,za=ja*Ra,Ua=Ra*Fa-Pa*Ia;function qa(t){if(t instanceof $a)return new $a(t.h,t.s,t.l,t.opacity);t instanceof Ke||(t=Ze(t));var e=t.r/255,n=t.g/255,r=t.b/255,i=(Ua*r+Ya*e-za*n)/(Ua+Ya-za),a=r-i,o=(ja*(n-i)-Fa*a)/Pa,s=Math.sqrt(o*o+a*a)/(ja*i*(1-i)),c=s?Math.atan2(o,a)*ga-120:NaN;return new $a(c<0?c+360:c,s,i,t.opacity)}function Ha(t,e,n,r){return 1===arguments.length?qa(t):new $a(t,e,n,null==r?1:r)}function $a(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}Me($a,Ha,Ne(De,{brighter:function(t){return t=null==t?Be:Math.pow(Be,t),new $a(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Oe:Math.pow(Oe,t),new $a(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*ya,e=+this.l,n=isNaN(this.s)?0:this.s*e*(1-e),r=Math.cos(t),i=Math.sin(t);return new Ke(255*(e+n*(Ia*r+Ra*i)),255*(e+n*(Fa*r+Pa*i)),255*(e+n*(ja*r)),this.opacity)}}));var Wa=Array.prototype.slice;function Va(t,e){return t-e}function Ga(t){return function(){return t}}function Xa(t,e){for(var n,r=-1,i=e.length;++r<i;)if(n=Za(t,e[r]))return n;return 0}function Za(t,e){for(var n=e[0],r=e[1],i=-1,a=0,o=t.length,s=o-1;a<o;s=a++){var c=t[a],u=c[0],l=c[1],h=t[s],f=h[0],d=h[1];if(Qa(c,h,e))return 0;l>r!=d>r&&n<(f-u)*(r-l)/(d-l)+u&&(i=-i)}return i}function Qa(t,e,n){var r,i,a,o;return function(t,e,n){return(e[0]-t[0])*(n[1]-t[1])==(n[0]-t[0])*(e[1]-t[1])}(t,e,n)&&(i=t[r=+(t[0]===e[0])],a=n[r],o=e[r],i<=a&&a<=o||o<=a&&a<=i)}function Ka(){}var Ja=[[],[[[1,1.5],[.5,1]]],[[[1.5,1],[1,1.5]]],[[[1.5,1],[.5,1]]],[[[1,.5],[1.5,1]]],[[[1,1.5],[.5,1]],[[1,.5],[1.5,1]]],[[[1,.5],[1,1.5]]],[[[1,.5],[.5,1]]],[[[.5,1],[1,.5]]],[[[1,1.5],[1,.5]]],[[[.5,1],[1,.5]],[[1.5,1],[1,1.5]]],[[[1.5,1],[1,.5]]],[[[.5,1],[1.5,1]]],[[[1,1.5],[1.5,1]]],[[[.5,1],[1,1.5]]],[]];function to(){var t=1,e=1,n=N,r=s;function i(t){var e=n(t);if(Array.isArray(e))e=e.slice().sort(Va);else{var r=m(t),i=r[0],o=r[1];e=M(i,o,e),e=k(Math.floor(i/e)*e,Math.floor(o/e)*e,e)}return e.map((function(e){return a(t,e)}))}function a(n,i){var a=[],s=[];return function(n,r,i){var a,s,c,u,l,h,f=new Array,d=new Array;for(a=s=-1,u=n[0]>=r,Ja[u<<1].forEach(p);++a<t-1;)c=u,u=n[a+1]>=r,Ja[c|u<<1].forEach(p);for(Ja[u<<0].forEach(p);++s<e-1;){for(a=-1,u=n[s*t+t]>=r,l=n[s*t]>=r,Ja[u<<1|l<<2].forEach(p);++a<t-1;)c=u,u=n[s*t+t+a+1]>=r,h=l,l=n[s*t+a+1]>=r,Ja[c|u<<1|l<<2|h<<3].forEach(p);Ja[u|l<<3].forEach(p)}for(a=-1,l=n[s*t]>=r,Ja[l<<2].forEach(p);++a<t-1;)h=l,l=n[s*t+a+1]>=r,Ja[l<<2|h<<3].forEach(p);function p(t){var e,n,r=[t[0][0]+a,t[0][1]+s],c=[t[1][0]+a,t[1][1]+s],u=o(r),l=o(c);(e=d[u])?(n=f[l])?(delete d[e.end],delete f[n.start],e===n?(e.ring.push(c),i(e.ring)):f[e.start]=d[n.end]={start:e.start,end:n.end,ring:e.ring.concat(n.ring)}):(delete d[e.end],e.ring.push(c),d[e.end=l]=e):(e=f[l])?(n=d[u])?(delete f[e.start],delete d[n.end],e===n?(e.ring.push(c),i(e.ring)):f[n.start]=d[e.end]={start:n.start,end:e.end,ring:n.ring.concat(e.ring)}):(delete f[e.start],e.ring.unshift(r),f[e.start=u]=e):f[u]=d[l]={start:u,end:l,ring:[r,c]}}Ja[l<<3].forEach(p)}(n,i,(function(t){r(t,n,i),function(t){for(var e=0,n=t.length,r=t[n-1][1]*t[0][0]-t[n-1][0]*t[0][1];++e<n;)r+=t[e-1][1]*t[e][0]-t[e-1][0]*t[e][1];return r}(t)>0?a.push([t]):s.push(t)})),s.forEach((function(t){for(var e,n=0,r=a.length;n<r;++n)if(-1!==Xa((e=a[n])[0],t))return void e.push(t)})),{type:"MultiPolygon",value:i,coordinates:a}}function o(e){return 2*e[0]+e[1]*(t+1)*4}function s(n,r,i){n.forEach((function(n){var a,o=n[0],s=n[1],c=0|o,u=0|s,l=r[u*t+c];o>0&&o<t&&c===o&&(a=r[u*t+c-1],n[0]=o+(i-a)/(l-a)-.5),s>0&&s<e&&u===s&&(a=r[(u-1)*t+c],n[1]=s+(i-a)/(l-a)-.5)}))}return i.contour=a,i.size=function(n){if(!arguments.length)return[t,e];var r=Math.ceil(n[0]),a=Math.ceil(n[1]);if(!(r>0&&a>0))throw new Error("invalid size");return t=r,e=a,i},i.thresholds=function(t){return arguments.length?(n="function"==typeof t?t:Array.isArray(t)?Ga(Wa.call(t)):Ga(t),i):n},i.smooth=function(t){return arguments.length?(r=t?s:Ka,i):r===s},i}function eo(t,e,n){for(var r=t.width,i=t.height,a=1+(n<<1),o=0;o<i;++o)for(var s=0,c=0;s<r+n;++s)s<r&&(c+=t.data[s+o*r]),s>=n&&(s>=a&&(c-=t.data[s-a+o*r]),e.data[s-n+o*r]=c/Math.min(s+1,r-1+a-s,a))}function no(t,e,n){for(var r=t.width,i=t.height,a=1+(n<<1),o=0;o<r;++o)for(var s=0,c=0;s<i+n;++s)s<i&&(c+=t.data[o+s*r]),s>=n&&(s>=a&&(c-=t.data[o+(s-a)*r]),e.data[o+(s-n)*r]=c/Math.min(s+1,i-1+a-s,a))}function ro(t){return t[0]}function io(t){return t[1]}function ao(){return 1}function oo(){var t=ro,e=io,n=ao,r=960,i=500,a=20,o=2,s=3*a,c=r+2*s>>o,u=i+2*s>>o,l=Ga(20);function h(r){var i=new Float32Array(c*u),h=new Float32Array(c*u);r.forEach((function(r,a,l){var h=+t(r,a,l)+s>>o,f=+e(r,a,l)+s>>o,d=+n(r,a,l);h>=0&&h<c&&f>=0&&f<u&&(i[h+f*c]+=d)})),eo({width:c,height:u,data:i},{width:c,height:u,data:h},a>>o),no({width:c,height:u,data:h},{width:c,height:u,data:i},a>>o),eo({width:c,height:u,data:i},{width:c,height:u,data:h},a>>o),no({width:c,height:u,data:h},{width:c,height:u,data:i},a>>o),eo({width:c,height:u,data:i},{width:c,height:u,data:h},a>>o),no({width:c,height:u,data:h},{width:c,height:u,data:i},a>>o);var d=l(i);if(!Array.isArray(d)){var p=I(i);d=M(0,p,d),(d=k(0,Math.floor(p/d)*d,d)).shift()}return to().thresholds(d).size([c,u])(i).map(f)}function f(t){return t.value*=Math.pow(2,-2*o),t.coordinates.forEach(d),t}function d(t){t.forEach(p)}function p(t){t.forEach(y)}function y(t){t[0]=t[0]*Math.pow(2,o)-s,t[1]=t[1]*Math.pow(2,o)-s}function g(){return c=r+2*(s=3*a)>>o,u=i+2*s>>o,h}return h.x=function(e){return arguments.length?(t="function"==typeof e?e:Ga(+e),h):t},h.y=function(t){return arguments.length?(e="function"==typeof t?t:Ga(+t),h):e},h.weight=function(t){return arguments.length?(n="function"==typeof t?t:Ga(+t),h):n},h.size=function(t){if(!arguments.length)return[r,i];var e=Math.ceil(t[0]),n=Math.ceil(t[1]);if(!(e>=0||e>=0))throw new Error("invalid size");return r=e,i=n,g()},h.cellSize=function(t){if(!arguments.length)return 1<<o;if(!((t=+t)>=1))throw new Error("invalid cell size");return o=Math.floor(Math.log(t)/Math.LN2),g()},h.thresholds=function(t){return arguments.length?(l="function"==typeof t?t:Array.isArray(t)?Ga(Wa.call(t)):Ga(t),h):l},h.bandwidth=function(t){if(!arguments.length)return Math.sqrt(a*(a+1));if(!((t=+t)>=0))throw new Error("invalid bandwidth");return a=Math.round((Math.sqrt(4*t*t+1)-1)/2),g()},h}function so(t){return function(){return t}}function co(t,e,n,r,i,a,o,s,c,u){this.target=t,this.type=e,this.subject=n,this.identifier=r,this.active=i,this.x=a,this.y=o,this.dx=s,this.dy=c,this._=u}function uo(){return!le.ctrlKey&&!le.button}function lo(){return this.parentNode}function ho(t){return null==t?{x:le.x,y:le.y}:t}function fo(){return navigator.maxTouchPoints||"ontouchstart"in this}function po(){var t,e,n,r,i=uo,a=lo,o=ho,s=fo,c={},u=ft("start","drag","end"),l=0,h=0;function f(t){t.on("mousedown.drag",d).filter(s).on("touchstart.drag",g).on("touchmove.drag",m).on("touchend.drag touchcancel.drag",v).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function d(){if(!r&&i.apply(this,arguments)){var o=b("mouse",a.apply(this,arguments),Bn,this,arguments);o&&(Te(le.view).on("mousemove.drag",p,!0).on("mouseup.drag",y,!0),Se(le.view),Ee(),n=!1,t=le.clientX,e=le.clientY,o("start"))}}function p(){if(Ce(),!n){var r=le.clientX-t,i=le.clientY-e;n=r*r+i*i>h}c.mouse("drag")}function y(){Te(le.view).on("mousemove.drag mouseup.drag",null),Ae(le.view,n),Ce(),c.mouse("end")}function g(){if(i.apply(this,arguments)){var t,e,n=le.changedTouches,r=a.apply(this,arguments),o=n.length;for(t=0;t<o;++t)(e=b(n[t].identifier,r,On,this,arguments))&&(Ee(),e("start"))}}function m(){var t,e,n=le.changedTouches,r=n.length;for(t=0;t<r;++t)(e=c[n[t].identifier])&&(Ce(),e("drag"))}function v(){var t,e,n=le.changedTouches,i=n.length;for(r&&clearTimeout(r),r=setTimeout((function(){r=null}),500),t=0;t<i;++t)(e=c[n[t].identifier])&&(Ee(),e("end"))}function b(t,e,n,r,i){var a,s,h,d=n(e,t),p=u.copy();if(ge(new co(f,"beforestart",a,t,l,d[0],d[1],0,0,p),(function(){return null!=(le.subject=a=o.apply(r,i))&&(s=a.x-d[0]||0,h=a.y-d[1]||0,!0)})))return function o(u){var y,g=d;switch(u){case"start":c[t]=o,y=l++;break;case"end":delete c[t],--l;case"drag":d=n(e,t),y=l}ge(new co(f,u,a,t,y,d[0]+s,d[1]+h,d[0]-g[0],d[1]-g[1],p),p.apply,p,[u,r,i])}}return f.filter=function(t){return arguments.length?(i="function"==typeof t?t:so(!!t),f):i},f.container=function(t){return arguments.length?(a="function"==typeof t?t:so(t),f):a},f.subject=function(t){return arguments.length?(o="function"==typeof t?t:so(t),f):o},f.touchable=function(t){return arguments.length?(s="function"==typeof t?t:so(!!t),f):s},f.on=function(){var t=u.on.apply(u,arguments);return t===u?f:t},f.clickDistance=function(t){return arguments.length?(h=(t=+t)*t,f):Math.sqrt(h)},f}co.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var yo={},go={};function mo(t){return new Function("d","return {"+t.map((function(t,e){return JSON.stringify(t)+": d["+e+'] || ""'})).join(",")+"}")}function vo(t){var e=Object.create(null),n=[];return t.forEach((function(t){for(var r in t)r in e||n.push(e[r]=r)})),n}function bo(t,e){var n=t+"",r=n.length;return r<e?new Array(e-r+1).join(0)+n:n}function _o(t){var e=new RegExp('["'+t+"\n\r]"),n=t.charCodeAt(0);function r(t,e){var r,i=[],a=t.length,o=0,s=0,c=a<=0,u=!1;function l(){if(c)return go;if(u)return u=!1,yo;var e,r,i=o;if(34===t.charCodeAt(i)){for(;o++<a&&34!==t.charCodeAt(o)||34===t.charCodeAt(++o););return(e=o)>=a?c=!0:10===(r=t.charCodeAt(o++))?u=!0:13===r&&(u=!0,10===t.charCodeAt(o)&&++o),t.slice(i+1,e-1).replace(/""/g,'"')}for(;o<a;){if(10===(r=t.charCodeAt(e=o++)))u=!0;else if(13===r)u=!0,10===t.charCodeAt(o)&&++o;else if(r!==n)continue;return t.slice(i,e)}return c=!0,t.slice(i,a)}for(10===t.charCodeAt(a-1)&&--a,13===t.charCodeAt(a-1)&&--a;(r=l())!==go;){for(var h=[];r!==yo&&r!==go;)h.push(r),r=l();e&&null==(h=e(h,s++))||i.push(h)}return i}function i(e,n){return e.map((function(e){return n.map((function(t){return o(e[t])})).join(t)}))}function a(e){return e.map(o).join(t)}function o(t){return null==t?"":t instanceof Date?function(t){var e=t.getUTCHours(),n=t.getUTCMinutes(),r=t.getUTCSeconds(),i=t.getUTCMilliseconds();return isNaN(t)?"Invalid Date":function(t){return t<0?"-"+bo(-t,6):t>9999?"+"+bo(t,6):bo(t,4)}(t.getUTCFullYear())+"-"+bo(t.getUTCMonth()+1,2)+"-"+bo(t.getUTCDate(),2)+(i?"T"+bo(e,2)+":"+bo(n,2)+":"+bo(r,2)+"."+bo(i,3)+"Z":r?"T"+bo(e,2)+":"+bo(n,2)+":"+bo(r,2)+"Z":n||e?"T"+bo(e,2)+":"+bo(n,2)+"Z":"")}(t):e.test(t+="")?'"'+t.replace(/"/g,'""')+'"':t}return{parse:function(t,e){var n,i,a=r(t,(function(t,r){if(n)return n(t,r-1);i=t,n=e?function(t,e){var n=mo(t);return function(r,i){return e(n(r),i,t)}}(t,e):mo(t)}));return a.columns=i||[],a},parseRows:r,format:function(e,n){return null==n&&(n=vo(e)),[n.map(o).join(t)].concat(i(e,n)).join("\n")},formatBody:function(t,e){return null==e&&(e=vo(t)),i(t,e).join("\n")},formatRows:function(t){return t.map(a).join("\n")},formatRow:a,formatValue:o}}var xo=_o(","),wo=xo.parse,ko=xo.parseRows,To=xo.format,Eo=xo.formatBody,Co=xo.formatRows,So=xo.formatRow,Ao=xo.formatValue,Mo=_o("\t"),No=Mo.parse,Do=Mo.parseRows,Oo=Mo.format,Bo=Mo.formatBody,Lo=Mo.formatRows,Io=Mo.formatRow,Ro=Mo.formatValue;function Fo(t){for(var e in t){var n,r,i=t[e].trim();if(i)if("true"===i)i=!0;else if("false"===i)i=!1;else if("NaN"===i)i=NaN;else if(isNaN(n=+i)){if(!(r=i.match(/^([-+]\d{2})?\d{4}(-\d{2}(-\d{2})?)?(T\d{2}:\d{2}(:\d{2}(\.\d{3})?)?(Z|[-+]\d{2}:\d{2})?)?$/)))continue;Po&&r[4]&&!r[7]&&(i=i.replace(/-/g,"/").replace(/T/," ")),i=new Date(i)}else i=n;else i=null;t[e]=i}return t}var Po=new Date("2019-01-01T00:00").getHours()||new Date("2019-07-01T00:00").getHours();function jo(t){return+t}function Yo(t){return t*t}function zo(t){return t*(2-t)}function Uo(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}var qo=function t(e){function n(t){return Math.pow(t,e)}return e=+e,n.exponent=t,n}(3),Ho=function t(e){function n(t){return 1-Math.pow(1-t,e)}return e=+e,n.exponent=t,n}(3),$o=function t(e){function n(t){return((t*=2)<=1?Math.pow(t,e):2-Math.pow(2-t,e))/2}return e=+e,n.exponent=t,n}(3),Wo=Math.PI,Vo=Wo/2;function Go(t){return 1==+t?1:1-Math.cos(t*Vo)}function Xo(t){return Math.sin(t*Vo)}function Zo(t){return(1-Math.cos(Wo*t))/2}function Qo(t){return 1.0009775171065494*(Math.pow(2,-10*t)-.0009765625)}function Ko(t){return Qo(1-+t)}function Jo(t){return 1-Qo(t)}function ts(t){return((t*=2)<=1?Qo(1-t):2-Qo(t-1))/2}function es(t){return 1-Math.sqrt(1-t*t)}function ns(t){return Math.sqrt(1- --t*t)}function rs(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+1)/2}var is=7.5625;function as(t){return 1-os(1-t)}function os(t){return(t=+t)<.36363636363636365?is*t*t:t<.7272727272727273?is*(t-=.5454545454545454)*t+.75:t<.9090909090909091?is*(t-=.8181818181818182)*t+.9375:is*(t-=.9545454545454546)*t+.984375}function ss(t){return((t*=2)<=1?1-os(1-t):os(t-1)+1)/2}var cs=1.70158,us=function t(e){function n(t){return(t=+t)*t*(e*(t-1)+t)}return e=+e,n.overshoot=t,n}(cs),ls=function t(e){function n(t){return--t*t*((t+1)*e+t)+1}return e=+e,n.overshoot=t,n}(cs),hs=function t(e){function n(t){return((t*=2)<1?t*t*((e+1)*t-e):(t-=2)*t*((e+1)*t+e)+2)/2}return e=+e,n.overshoot=t,n}(cs),fs=2*Math.PI,ds=function t(e,n){var r=Math.asin(1/(e=Math.max(1,e)))*(n/=fs);function i(t){return e*Qo(- --t)*Math.sin((r-t)/n)}return i.amplitude=function(e){return t(e,n*fs)},i.period=function(n){return t(e,n)},i}(1,.3),ps=function t(e,n){var r=Math.asin(1/(e=Math.max(1,e)))*(n/=fs);function i(t){return 1-e*Qo(t=+t)*Math.sin((t+r)/n)}return i.amplitude=function(e){return t(e,n*fs)},i.period=function(n){return t(e,n)},i}(1,.3),ys=function t(e,n){var r=Math.asin(1/(e=Math.max(1,e)))*(n/=fs);function i(t){return((t=2*t-1)<0?e*Qo(-t)*Math.sin((r-t)/n):2-e*Qo(t)*Math.sin((r+t)/n))/2}return i.amplitude=function(e){return t(e,n*fs)},i.period=function(n){return t(e,n)},i}(1,.3);function gs(t){if(!t.ok)throw new Error(t.status+" "+t.statusText);return t.blob()}function ms(t,e){return fetch(t,e).then(gs)}function vs(t){if(!t.ok)throw new Error(t.status+" "+t.statusText);return t.arrayBuffer()}function bs(t,e){return fetch(t,e).then(vs)}function _s(t){if(!t.ok)throw new Error(t.status+" "+t.statusText);return t.text()}function xs(t,e){return fetch(t,e).then(_s)}function ws(t){return function(e,n,r){return 2===arguments.length&&"function"==typeof n&&(r=n,n=void 0),xs(e,n).then((function(e){return t(e,r)}))}}function ks(t,e,n,r){3===arguments.length&&"function"==typeof n&&(r=n,n=void 0);var i=_o(t);return xs(e,n).then((function(t){return i.parse(t,r)}))}var Ts=ws(wo),Es=ws(No);function Cs(t,e){return new Promise((function(n,r){var i=new Image;for(var a in e)i[a]=e[a];i.onerror=r,i.onload=function(){n(i)},i.src=t}))}function Ss(t){if(!t.ok)throw new Error(t.status+" "+t.statusText);if(204!==t.status&&205!==t.status)return t.json()}function As(t,e){return fetch(t,e).then(Ss)}function Ms(t){return function(e,n){return xs(e,n).then((function(e){return(new DOMParser).parseFromString(e,t)}))}}const Ns=Ms("application/xml");var Ds=Ms("text/html"),Os=Ms("image/svg+xml");function Bs(t,e){var n;function r(){var r,i,a=n.length,o=0,s=0;for(r=0;r<a;++r)o+=(i=n[r]).x,s+=i.y;for(o=o/a-t,s=s/a-e,r=0;r<a;++r)(i=n[r]).x-=o,i.y-=s}return null==t&&(t=0),null==e&&(e=0),r.initialize=function(t){n=t},r.x=function(e){return arguments.length?(t=+e,r):t},r.y=function(t){return arguments.length?(e=+t,r):e},r}function Ls(t){return function(){return t}}function Is(){return 1e-6*(Math.random()-.5)}function Rs(t,e,n,r){if(isNaN(e)||isNaN(n))return t;var i,a,o,s,c,u,l,h,f,d=t._root,p={data:r},y=t._x0,g=t._y0,m=t._x1,v=t._y1;if(!d)return t._root=p,t;for(;d.length;)if((u=e>=(a=(y+m)/2))?y=a:m=a,(l=n>=(o=(g+v)/2))?g=o:v=o,i=d,!(d=d[h=l<<1|u]))return i[h]=p,t;if(s=+t._x.call(null,d.data),c=+t._y.call(null,d.data),e===s&&n===c)return p.next=d,i?i[h]=p:t._root=p,t;do{i=i?i[h]=new Array(4):t._root=new Array(4),(u=e>=(a=(y+m)/2))?y=a:m=a,(l=n>=(o=(g+v)/2))?g=o:v=o}while((h=l<<1|u)==(f=(c>=o)<<1|s>=a));return i[f]=d,i[h]=p,t}function Fs(t,e,n,r,i){this.node=t,this.x0=e,this.y0=n,this.x1=r,this.y1=i}function Ps(t){return t[0]}function js(t){return t[1]}function Ys(t,e,n){var r=new zs(null==e?Ps:e,null==n?js:n,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function zs(t,e,n,r,i,a){this._x=t,this._y=e,this._x0=n,this._y0=r,this._x1=i,this._y1=a,this._root=void 0}function Us(t){for(var e={data:t.data},n=e;t=t.next;)n=n.next={data:t.data};return e}var qs=Ys.prototype=zs.prototype;function Hs(t){return t.x+t.vx}function $s(t){return t.y+t.vy}function Ws(t){var e,n,r=1,i=1;function a(){for(var t,a,s,c,u,l,h,f=e.length,d=0;d<i;++d)for(a=Ys(e,Hs,$s).visitAfter(o),t=0;t<f;++t)s=e[t],l=n[s.index],h=l*l,c=s.x+s.vx,u=s.y+s.vy,a.visit(p);function p(t,e,n,i,a){var o=t.data,f=t.r,d=l+f;if(!o)return e>c+d||i<c-d||n>u+d||a<u-d;if(o.index>s.index){var p=c-o.x-o.vx,y=u-o.y-o.vy,g=p*p+y*y;g<d*d&&(0===p&&(g+=(p=Is())*p),0===y&&(g+=(y=Is())*y),g=(d-(g=Math.sqrt(g)))/g*r,s.vx+=(p*=g)*(d=(f*=f)/(h+f)),s.vy+=(y*=g)*d,o.vx-=p*(d=1-d),o.vy-=y*d)}}}function o(t){if(t.data)return t.r=n[t.data.index];for(var e=t.r=0;e<4;++e)t[e]&&t[e].r>t.r&&(t.r=t[e].r)}function s(){if(e){var r,i,a=e.length;for(n=new Array(a),r=0;r<a;++r)i=e[r],n[i.index]=+t(i,r,e)}}return"function"!=typeof t&&(t=Ls(null==t?1:+t)),a.initialize=function(t){e=t,s()},a.iterations=function(t){return arguments.length?(i=+t,a):i},a.strength=function(t){return arguments.length?(r=+t,a):r},a.radius=function(e){return arguments.length?(t="function"==typeof e?e:Ls(+e),s(),a):t},a}function Vs(t){return t.index}function Gs(t,e){var n=t.get(e);if(!n)throw new Error("missing: "+e);return n}function Xs(t){var e,n,r,i,a,o=Vs,s=function(t){return 1/Math.min(i[t.source.index],i[t.target.index])},c=Ls(30),u=1;function l(r){for(var i=0,o=t.length;i<u;++i)for(var s,c,l,h,f,d,p,y=0;y<o;++y)c=(s=t[y]).source,h=(l=s.target).x+l.vx-c.x-c.vx||Is(),f=l.y+l.vy-c.y-c.vy||Is(),h*=d=((d=Math.sqrt(h*h+f*f))-n[y])/d*r*e[y],f*=d,l.vx-=h*(p=a[y]),l.vy-=f*p,c.vx+=h*(p=1-p),c.vy+=f*p}function h(){if(r){var s,c,u=r.length,l=t.length,h=na(r,o);for(s=0,i=new Array(u);s<l;++s)(c=t[s]).index=s,"object"!=typeof c.source&&(c.source=Gs(h,c.source)),"object"!=typeof c.target&&(c.target=Gs(h,c.target)),i[c.source.index]=(i[c.source.index]||0)+1,i[c.target.index]=(i[c.target.index]||0)+1;for(s=0,a=new Array(l);s<l;++s)c=t[s],a[s]=i[c.source.index]/(i[c.source.index]+i[c.target.index]);e=new Array(l),f(),n=new Array(l),d()}}function f(){if(r)for(var n=0,i=t.length;n<i;++n)e[n]=+s(t[n],n,t)}function d(){if(r)for(var e=0,i=t.length;e<i;++e)n[e]=+c(t[e],e,t)}return null==t&&(t=[]),l.initialize=function(t){r=t,h()},l.links=function(e){return arguments.length?(t=e,h(),l):t},l.id=function(t){return arguments.length?(o=t,l):o},l.iterations=function(t){return arguments.length?(u=+t,l):u},l.strength=function(t){return arguments.length?(s="function"==typeof t?t:Ls(+t),f(),l):s},l.distance=function(t){return arguments.length?(c="function"==typeof t?t:Ls(+t),d(),l):c},l}function Zs(t){return t.x}function Qs(t){return t.y}qs.copy=function(){var t,e,n=new zs(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return n;if(!r.length)return n._root=Us(r),n;for(t=[{source:r,target:n._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(e=r.source[i])&&(e.length?t.push({source:e,target:r.target[i]=new Array(4)}):r.target[i]=Us(e));return n},qs.add=function(t){var e=+this._x.call(null,t),n=+this._y.call(null,t);return Rs(this.cover(e,n),e,n,t)},qs.addAll=function(t){var e,n,r,i,a=t.length,o=new Array(a),s=new Array(a),c=1/0,u=1/0,l=-1/0,h=-1/0;for(n=0;n<a;++n)isNaN(r=+this._x.call(null,e=t[n]))||isNaN(i=+this._y.call(null,e))||(o[n]=r,s[n]=i,r<c&&(c=r),r>l&&(l=r),i<u&&(u=i),i>h&&(h=i));if(c>l||u>h)return this;for(this.cover(c,u).cover(l,h),n=0;n<a;++n)Rs(this,o[n],s[n],t[n]);return this},qs.cover=function(t,e){if(isNaN(t=+t)||isNaN(e=+e))return this;var n=this._x0,r=this._y0,i=this._x1,a=this._y1;if(isNaN(n))i=(n=Math.floor(t))+1,a=(r=Math.floor(e))+1;else{for(var o,s,c=i-n,u=this._root;n>t||t>=i||r>e||e>=a;)switch(s=(e<r)<<1|t<n,(o=new Array(4))[s]=u,u=o,c*=2,s){case 0:i=n+c,a=r+c;break;case 1:n=i-c,a=r+c;break;case 2:i=n+c,r=a-c;break;case 3:n=i-c,r=a-c}this._root&&this._root.length&&(this._root=u)}return this._x0=n,this._y0=r,this._x1=i,this._y1=a,this},qs.data=function(){var t=[];return this.visit((function(e){if(!e.length)do{t.push(e.data)}while(e=e.next)})),t},qs.extent=function(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]},qs.find=function(t,e,n){var r,i,a,o,s,c,u,l=this._x0,h=this._y0,f=this._x1,d=this._y1,p=[],y=this._root;for(y&&p.push(new Fs(y,l,h,f,d)),null==n?n=1/0:(l=t-n,h=e-n,f=t+n,d=e+n,n*=n);c=p.pop();)if(!(!(y=c.node)||(i=c.x0)>f||(a=c.y0)>d||(o=c.x1)<l||(s=c.y1)<h))if(y.length){var g=(i+o)/2,m=(a+s)/2;p.push(new Fs(y[3],g,m,o,s),new Fs(y[2],i,m,g,s),new Fs(y[1],g,a,o,m),new Fs(y[0],i,a,g,m)),(u=(e>=m)<<1|t>=g)&&(c=p[p.length-1],p[p.length-1]=p[p.length-1-u],p[p.length-1-u]=c)}else{var v=t-+this._x.call(null,y.data),b=e-+this._y.call(null,y.data),_=v*v+b*b;if(_<n){var x=Math.sqrt(n=_);l=t-x,h=e-x,f=t+x,d=e+x,r=y.data}}return r},qs.remove=function(t){if(isNaN(a=+this._x.call(null,t))||isNaN(o=+this._y.call(null,t)))return this;var e,n,r,i,a,o,s,c,u,l,h,f,d=this._root,p=this._x0,y=this._y0,g=this._x1,m=this._y1;if(!d)return this;if(d.length)for(;;){if((u=a>=(s=(p+g)/2))?p=s:g=s,(l=o>=(c=(y+m)/2))?y=c:m=c,e=d,!(d=d[h=l<<1|u]))return this;if(!d.length)break;(e[h+1&3]||e[h+2&3]||e[h+3&3])&&(n=e,f=h)}for(;d.data!==t;)if(r=d,!(d=d.next))return this;return(i=d.next)&&delete d.next,r?(i?r.next=i:delete r.next,this):e?(i?e[h]=i:delete e[h],(d=e[0]||e[1]||e[2]||e[3])&&d===(e[3]||e[2]||e[1]||e[0])&&!d.length&&(n?n[f]=d:this._root=d),this):(this._root=i,this)},qs.removeAll=function(t){for(var e=0,n=t.length;e<n;++e)this.remove(t[e]);return this},qs.root=function(){return this._root},qs.size=function(){var t=0;return this.visit((function(e){if(!e.length)do{++t}while(e=e.next)})),t},qs.visit=function(t){var e,n,r,i,a,o,s=[],c=this._root;for(c&&s.push(new Fs(c,this._x0,this._y0,this._x1,this._y1));e=s.pop();)if(!t(c=e.node,r=e.x0,i=e.y0,a=e.x1,o=e.y1)&&c.length){var u=(r+a)/2,l=(i+o)/2;(n=c[3])&&s.push(new Fs(n,u,l,a,o)),(n=c[2])&&s.push(new Fs(n,r,l,u,o)),(n=c[1])&&s.push(new Fs(n,u,i,a,l)),(n=c[0])&&s.push(new Fs(n,r,i,u,l))}return this},qs.visitAfter=function(t){var e,n=[],r=[];for(this._root&&n.push(new Fs(this._root,this._x0,this._y0,this._x1,this._y1));e=n.pop();){var i=e.node;if(i.length){var a,o=e.x0,s=e.y0,c=e.x1,u=e.y1,l=(o+c)/2,h=(s+u)/2;(a=i[0])&&n.push(new Fs(a,o,s,l,h)),(a=i[1])&&n.push(new Fs(a,l,s,c,h)),(a=i[2])&&n.push(new Fs(a,o,h,l,u)),(a=i[3])&&n.push(new Fs(a,l,h,c,u))}r.push(e)}for(;e=r.pop();)t(e.node,e.x0,e.y0,e.x1,e.y1);return this},qs.x=function(t){return arguments.length?(this._x=t,this):this._x},qs.y=function(t){return arguments.length?(this._y=t,this):this._y};var Ks=Math.PI*(3-Math.sqrt(5));function Js(t){var e,n=1,r=.001,i=1-Math.pow(r,1/300),a=0,o=.6,s=na(),c=Vn(l),u=ft("tick","end");function l(){h(),u.call("tick",e),n<r&&(c.stop(),u.call("end",e))}function h(r){var c,u,l=t.length;void 0===r&&(r=1);for(var h=0;h<r;++h)for(n+=(a-n)*i,s.each((function(t){t(n)})),c=0;c<l;++c)null==(u=t[c]).fx?u.x+=u.vx*=o:(u.x=u.fx,u.vx=0),null==u.fy?u.y+=u.vy*=o:(u.y=u.fy,u.vy=0);return e}function f(){for(var e,n=0,r=t.length;n<r;++n){if((e=t[n]).index=n,null!=e.fx&&(e.x=e.fx),null!=e.fy&&(e.y=e.fy),isNaN(e.x)||isNaN(e.y)){var i=10*Math.sqrt(n),a=n*Ks;e.x=i*Math.cos(a),e.y=i*Math.sin(a)}(isNaN(e.vx)||isNaN(e.vy))&&(e.vx=e.vy=0)}}function d(e){return e.initialize&&e.initialize(t),e}return null==t&&(t=[]),f(),e={tick:h,restart:function(){return c.restart(l),e},stop:function(){return c.stop(),e},nodes:function(n){return arguments.length?(t=n,f(),s.each(d),e):t},alpha:function(t){return arguments.length?(n=+t,e):n},alphaMin:function(t){return arguments.length?(r=+t,e):r},alphaDecay:function(t){return arguments.length?(i=+t,e):+i},alphaTarget:function(t){return arguments.length?(a=+t,e):a},velocityDecay:function(t){return arguments.length?(o=1-t,e):1-o},force:function(t,n){return arguments.length>1?(null==n?s.remove(t):s.set(t,d(n)),e):s.get(t)},find:function(e,n,r){var i,a,o,s,c,u=0,l=t.length;for(null==r?r=1/0:r*=r,u=0;u<l;++u)(o=(i=e-(s=t[u]).x)*i+(a=n-s.y)*a)<r&&(c=s,r=o);return c},on:function(t,n){return arguments.length>1?(u.on(t,n),e):u.on(t)}}}function tc(){var t,e,n,r,i=Ls(-30),a=1,o=1/0,s=.81;function c(r){var i,a=t.length,o=Ys(t,Zs,Qs).visitAfter(l);for(n=r,i=0;i<a;++i)e=t[i],o.visit(h)}function u(){if(t){var e,n,a=t.length;for(r=new Array(a),e=0;e<a;++e)n=t[e],r[n.index]=+i(n,e,t)}}function l(t){var e,n,i,a,o,s=0,c=0;if(t.length){for(i=a=o=0;o<4;++o)(e=t[o])&&(n=Math.abs(e.value))&&(s+=e.value,c+=n,i+=n*e.x,a+=n*e.y);t.x=i/c,t.y=a/c}else{(e=t).x=e.data.x,e.y=e.data.y;do{s+=r[e.data.index]}while(e=e.next)}t.value=s}function h(t,i,c,u){if(!t.value)return!0;var l=t.x-e.x,h=t.y-e.y,f=u-i,d=l*l+h*h;if(f*f/s<d)return d<o&&(0===l&&(d+=(l=Is())*l),0===h&&(d+=(h=Is())*h),d<a&&(d=Math.sqrt(a*d)),e.vx+=l*t.value*n/d,e.vy+=h*t.value*n/d),!0;if(!(t.length||d>=o)){(t.data!==e||t.next)&&(0===l&&(d+=(l=Is())*l),0===h&&(d+=(h=Is())*h),d<a&&(d=Math.sqrt(a*d)));do{t.data!==e&&(f=r[t.data.index]*n/d,e.vx+=l*f,e.vy+=h*f)}while(t=t.next)}}return c.initialize=function(e){t=e,u()},c.strength=function(t){return arguments.length?(i="function"==typeof t?t:Ls(+t),u(),c):i},c.distanceMin=function(t){return arguments.length?(a=t*t,c):Math.sqrt(a)},c.distanceMax=function(t){return arguments.length?(o=t*t,c):Math.sqrt(o)},c.theta=function(t){return arguments.length?(s=t*t,c):Math.sqrt(s)},c}function ec(t,e,n){var r,i,a,o=Ls(.1);function s(t){for(var o=0,s=r.length;o<s;++o){var c=r[o],u=c.x-e||1e-6,l=c.y-n||1e-6,h=Math.sqrt(u*u+l*l),f=(a[o]-h)*i[o]*t/h;c.vx+=u*f,c.vy+=l*f}}function c(){if(r){var e,n=r.length;for(i=new Array(n),a=new Array(n),e=0;e<n;++e)a[e]=+t(r[e],e,r),i[e]=isNaN(a[e])?0:+o(r[e],e,r)}}return"function"!=typeof t&&(t=Ls(+t)),null==e&&(e=0),null==n&&(n=0),s.initialize=function(t){r=t,c()},s.strength=function(t){return arguments.length?(o="function"==typeof t?t:Ls(+t),c(),s):o},s.radius=function(e){return arguments.length?(t="function"==typeof e?e:Ls(+e),c(),s):t},s.x=function(t){return arguments.length?(e=+t,s):e},s.y=function(t){return arguments.length?(n=+t,s):n},s}function nc(t){var e,n,r,i=Ls(.1);function a(t){for(var i,a=0,o=e.length;a<o;++a)(i=e[a]).vx+=(r[a]-i.x)*n[a]*t}function o(){if(e){var a,o=e.length;for(n=new Array(o),r=new Array(o),a=0;a<o;++a)n[a]=isNaN(r[a]=+t(e[a],a,e))?0:+i(e[a],a,e)}}return"function"!=typeof t&&(t=Ls(null==t?0:+t)),a.initialize=function(t){e=t,o()},a.strength=function(t){return arguments.length?(i="function"==typeof t?t:Ls(+t),o(),a):i},a.x=function(e){return arguments.length?(t="function"==typeof e?e:Ls(+e),o(),a):t},a}function rc(t){var e,n,r,i=Ls(.1);function a(t){for(var i,a=0,o=e.length;a<o;++a)(i=e[a]).vy+=(r[a]-i.y)*n[a]*t}function o(){if(e){var a,o=e.length;for(n=new Array(o),r=new Array(o),a=0;a<o;++a)n[a]=isNaN(r[a]=+t(e[a],a,e))?0:+i(e[a],a,e)}}return"function"!=typeof t&&(t=Ls(null==t?0:+t)),a.initialize=function(t){e=t,o()},a.strength=function(t){return arguments.length?(i="function"==typeof t?t:Ls(+t),o(),a):i},a.y=function(e){return arguments.length?(t="function"==typeof e?e:Ls(+e),o(),a):t},a}function ic(t,e){if((n=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var n,r=t.slice(0,n);return[r.length>1?r[0]+r.slice(2):r,+t.slice(n+1)]}function ac(t){return(t=ic(Math.abs(t)))?t[1]:NaN}var oc,sc=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function cc(t){if(!(e=sc.exec(t)))throw new Error("invalid format: "+t);var e;return new uc({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function uc(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function lc(t,e){var n=ic(t,e);if(!n)return t+"";var r=n[0],i=n[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}cc.prototype=uc.prototype,uc.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};const hc={"%":function(t,e){return(100*t).toFixed(e)},b:function(t){return Math.round(t).toString(2)},c:function(t){return t+""},d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:function(t,e){return t.toExponential(e)},f:function(t,e){return t.toFixed(e)},g:function(t,e){return t.toPrecision(e)},o:function(t){return Math.round(t).toString(8)},p:function(t,e){return lc(100*t,e)},r:lc,s:function(t,e){var n=ic(t,e);if(!n)return t+"";var r=n[0],i=n[1],a=i-(oc=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,o=r.length;return a===o?r:a>o?r+new Array(a-o+1).join("0"):a>0?r.slice(0,a)+"."+r.slice(a):"0."+new Array(1-a).join("0")+ic(t,Math.max(0,e+a-1))[0]},X:function(t){return Math.round(t).toString(16).toUpperCase()},x:function(t){return Math.round(t).toString(16)}};function fc(t){return t}var dc,pc,yc,gc=Array.prototype.map,mc=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function vc(t){var e,n,r=void 0===t.grouping||void 0===t.thousands?fc:(e=gc.call(t.grouping,Number),n=t.thousands+"",function(t,r){for(var i=t.length,a=[],o=0,s=e[0],c=0;i>0&&s>0&&(c+s+1>r&&(s=Math.max(1,r-c)),a.push(t.substring(i-=s,i+s)),!((c+=s+1)>r));)s=e[o=(o+1)%e.length];return a.reverse().join(n)}),i=void 0===t.currency?"":t.currency[0]+"",a=void 0===t.currency?"":t.currency[1]+"",o=void 0===t.decimal?".":t.decimal+"",s=void 0===t.numerals?fc:function(t){return function(e){return e.replace(/[0-9]/g,(function(e){return t[+e]}))}}(gc.call(t.numerals,String)),c=void 0===t.percent?"%":t.percent+"",u=void 0===t.minus?"-":t.minus+"",l=void 0===t.nan?"NaN":t.nan+"";function h(t){var e=(t=cc(t)).fill,n=t.align,h=t.sign,f=t.symbol,d=t.zero,p=t.width,y=t.comma,g=t.precision,m=t.trim,v=t.type;"n"===v?(y=!0,v="g"):hc[v]||(void 0===g&&(g=12),m=!0,v="g"),(d||"0"===e&&"="===n)&&(d=!0,e="0",n="=");var b="$"===f?i:"#"===f&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",_="$"===f?a:/[%p]/.test(v)?c:"",x=hc[v],w=/[defgprs%]/.test(v);function k(t){var i,a,c,f=b,k=_;if("c"===v)k=x(t)+k,t="";else{var T=(t=+t)<0||1/t<0;if(t=isNaN(t)?l:x(Math.abs(t),g),m&&(t=function(t){t:for(var e,n=t.length,r=1,i=-1;r<n;++r)switch(t[r]){case".":i=e=r;break;case"0":0===i&&(i=r),e=r;break;default:if(!+t[r])break t;i>0&&(i=0)}return i>0?t.slice(0,i)+t.slice(e+1):t}(t)),T&&0==+t&&"+"!==h&&(T=!1),f=(T?"("===h?h:u:"-"===h||"("===h?"":h)+f,k=("s"===v?mc[8+oc/3]:"")+k+(T&&"("===h?")":""),w)for(i=-1,a=t.length;++i<a;)if(48>(c=t.charCodeAt(i))||c>57){k=(46===c?o+t.slice(i+1):t.slice(i))+k,t=t.slice(0,i);break}}y&&!d&&(t=r(t,1/0));var E=f.length+t.length+k.length,C=E<p?new Array(p-E+1).join(e):"";switch(y&&d&&(t=r(C+t,C.length?p-k.length:1/0),C=""),n){case"<":t=f+t+k+C;break;case"=":t=f+C+t+k;break;case"^":t=C.slice(0,E=C.length>>1)+f+t+k+C.slice(E);break;default:t=C+f+t+k}return s(t)}return g=void 0===g?6:/[gprs]/.test(v)?Math.max(1,Math.min(21,g)):Math.max(0,Math.min(20,g)),k.toString=function(){return t+""},k}return{format:h,formatPrefix:function(t,e){var n=h(((t=cc(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(ac(e)/3))),i=Math.pow(10,-r),a=mc[8+r/3];return function(t){return n(i*t)+a}}}}function bc(t){return dc=vc(t),pc=dc.format,yc=dc.formatPrefix,dc}function _c(t){return Math.max(0,-ac(Math.abs(t)))}function xc(t,e){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(ac(e)/3)))-ac(Math.abs(t)))}function wc(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,ac(e)-ac(t))+1}function kc(){return new Tc}function Tc(){this.reset()}bc({decimal:".",thousands:",",grouping:[3],currency:["$",""],minus:"-"}),Tc.prototype={constructor:Tc,reset:function(){this.s=this.t=0},add:function(t){Cc(Ec,t,this.t),Cc(this,Ec.s,this.s),this.s?this.t+=Ec.t:this.s=Ec.t},valueOf:function(){return this.s}};var Ec=new Tc;function Cc(t,e,n){var r=t.s=e+n,i=r-e,a=r-i;t.t=e-a+(n-i)}var Sc=1e-6,Ac=1e-12,Mc=Math.PI,Nc=Mc/2,Dc=Mc/4,Oc=2*Mc,Bc=180/Mc,Lc=Mc/180,Ic=Math.abs,Rc=Math.atan,Fc=Math.atan2,Pc=Math.cos,jc=Math.ceil,Yc=Math.exp,zc=(Math.floor,Math.log),Uc=Math.pow,qc=Math.sin,Hc=Math.sign||function(t){return t>0?1:t<0?-1:0},$c=Math.sqrt,Wc=Math.tan;function Vc(t){return t>1?0:t<-1?Mc:Math.acos(t)}function Gc(t){return t>1?Nc:t<-1?-Nc:Math.asin(t)}function Xc(t){return(t=qc(t/2))*t}function Zc(){}function Qc(t,e){t&&Jc.hasOwnProperty(t.type)&&Jc[t.type](t,e)}var Kc={Feature:function(t,e){Qc(t.geometry,e)},FeatureCollection:function(t,e){for(var n=t.features,r=-1,i=n.length;++r<i;)Qc(n[r].geometry,e)}},Jc={Sphere:function(t,e){e.sphere()},Point:function(t,e){t=t.coordinates,e.point(t[0],t[1],t[2])},MultiPoint:function(t,e){for(var n=t.coordinates,r=-1,i=n.length;++r<i;)t=n[r],e.point(t[0],t[1],t[2])},LineString:function(t,e){tu(t.coordinates,e,0)},MultiLineString:function(t,e){for(var n=t.coordinates,r=-1,i=n.length;++r<i;)tu(n[r],e,0)},Polygon:function(t,e){eu(t.coordinates,e)},MultiPolygon:function(t,e){for(var n=t.coordinates,r=-1,i=n.length;++r<i;)eu(n[r],e)},GeometryCollection:function(t,e){for(var n=t.geometries,r=-1,i=n.length;++r<i;)Qc(n[r],e)}};function tu(t,e,n){var r,i=-1,a=t.length-n;for(e.lineStart();++i<a;)r=t[i],e.point(r[0],r[1],r[2]);e.lineEnd()}function eu(t,e){var n=-1,r=t.length;for(e.polygonStart();++n<r;)tu(t[n],e,1);e.polygonEnd()}function nu(t,e){t&&Kc.hasOwnProperty(t.type)?Kc[t.type](t,e):Qc(t,e)}var ru,iu,au,ou,su,cu=kc(),uu=kc(),lu={point:Zc,lineStart:Zc,lineEnd:Zc,polygonStart:function(){cu.reset(),lu.lineStart=hu,lu.lineEnd=fu},polygonEnd:function(){var t=+cu;uu.add(t<0?Oc+t:t),this.lineStart=this.lineEnd=this.point=Zc},sphere:function(){uu.add(Oc)}};function hu(){lu.point=du}function fu(){pu(ru,iu)}function du(t,e){lu.point=pu,ru=t,iu=e,au=t*=Lc,ou=Pc(e=(e*=Lc)/2+Dc),su=qc(e)}function pu(t,e){var n=(t*=Lc)-au,r=n>=0?1:-1,i=r*n,a=Pc(e=(e*=Lc)/2+Dc),o=qc(e),s=su*o,c=ou*a+s*Pc(i),u=s*r*qc(i);cu.add(Fc(u,c)),au=t,ou=a,su=o}function yu(t){return uu.reset(),nu(t,lu),2*uu}function gu(t){return[Fc(t[1],t[0]),Gc(t[2])]}function mu(t){var e=t[0],n=t[1],r=Pc(n);return[r*Pc(e),r*qc(e),qc(n)]}function vu(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function bu(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function _u(t,e){t[0]+=e[0],t[1]+=e[1],t[2]+=e[2]}function xu(t,e){return[t[0]*e,t[1]*e,t[2]*e]}function wu(t){var e=$c(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=e,t[1]/=e,t[2]/=e}var ku,Tu,Eu,Cu,Su,Au,Mu,Nu,Du,Ou,Bu,Lu,Iu,Ru,Fu,Pu,ju,Yu,zu,Uu,qu,Hu,$u,Wu,Vu,Gu,Xu=kc(),Zu={point:Qu,lineStart:Ju,lineEnd:tl,polygonStart:function(){Zu.point=el,Zu.lineStart=nl,Zu.lineEnd=rl,Xu.reset(),lu.polygonStart()},polygonEnd:function(){lu.polygonEnd(),Zu.point=Qu,Zu.lineStart=Ju,Zu.lineEnd=tl,cu<0?(ku=-(Eu=180),Tu=-(Cu=90)):Xu>Sc?Cu=90:Xu<-1e-6&&(Tu=-90),Ou[0]=ku,Ou[1]=Eu},sphere:function(){ku=-(Eu=180),Tu=-(Cu=90)}};function Qu(t,e){Du.push(Ou=[ku=t,Eu=t]),e<Tu&&(Tu=e),e>Cu&&(Cu=e)}function Ku(t,e){var n=mu([t*Lc,e*Lc]);if(Nu){var r=bu(Nu,n),i=bu([r[1],-r[0],0],r);wu(i),i=gu(i);var a,o=t-Su,s=o>0?1:-1,c=i[0]*Bc*s,u=Ic(o)>180;u^(s*Su<c&&c<s*t)?(a=i[1]*Bc)>Cu&&(Cu=a):u^(s*Su<(c=(c+360)%360-180)&&c<s*t)?(a=-i[1]*Bc)<Tu&&(Tu=a):(e<Tu&&(Tu=e),e>Cu&&(Cu=e)),u?t<Su?il(ku,t)>il(ku,Eu)&&(Eu=t):il(t,Eu)>il(ku,Eu)&&(ku=t):Eu>=ku?(t<ku&&(ku=t),t>Eu&&(Eu=t)):t>Su?il(ku,t)>il(ku,Eu)&&(Eu=t):il(t,Eu)>il(ku,Eu)&&(ku=t)}else Du.push(Ou=[ku=t,Eu=t]);e<Tu&&(Tu=e),e>Cu&&(Cu=e),Nu=n,Su=t}function Ju(){Zu.point=Ku}function tl(){Ou[0]=ku,Ou[1]=Eu,Zu.point=Qu,Nu=null}function el(t,e){if(Nu){var n=t-Su;Xu.add(Ic(n)>180?n+(n>0?360:-360):n)}else Au=t,Mu=e;lu.point(t,e),Ku(t,e)}function nl(){lu.lineStart()}function rl(){el(Au,Mu),lu.lineEnd(),Ic(Xu)>Sc&&(ku=-(Eu=180)),Ou[0]=ku,Ou[1]=Eu,Nu=null}function il(t,e){return(e-=t)<0?e+360:e}function al(t,e){return t[0]-e[0]}function ol(t,e){return t[0]<=t[1]?t[0]<=e&&e<=t[1]:e<t[0]||t[1]<e}function sl(t){var e,n,r,i,a,o,s;if(Cu=Eu=-(ku=Tu=1/0),Du=[],nu(t,Zu),n=Du.length){for(Du.sort(al),e=1,a=[r=Du[0]];e<n;++e)ol(r,(i=Du[e])[0])||ol(r,i[1])?(il(r[0],i[1])>il(r[0],r[1])&&(r[1]=i[1]),il(i[0],r[1])>il(r[0],r[1])&&(r[0]=i[0])):a.push(r=i);for(o=-1/0,e=0,r=a[n=a.length-1];e<=n;r=i,++e)i=a[e],(s=il(r[1],i[0]))>o&&(o=s,ku=i[0],Eu=r[1])}return Du=Ou=null,ku===1/0||Tu===1/0?[[NaN,NaN],[NaN,NaN]]:[[ku,Tu],[Eu,Cu]]}var cl={sphere:Zc,point:ul,lineStart:hl,lineEnd:pl,polygonStart:function(){cl.lineStart=yl,cl.lineEnd=gl},polygonEnd:function(){cl.lineStart=hl,cl.lineEnd=pl}};function ul(t,e){t*=Lc;var n=Pc(e*=Lc);ll(n*Pc(t),n*qc(t),qc(e))}function ll(t,e,n){++Bu,Iu+=(t-Iu)/Bu,Ru+=(e-Ru)/Bu,Fu+=(n-Fu)/Bu}function hl(){cl.point=fl}function fl(t,e){t*=Lc;var n=Pc(e*=Lc);Wu=n*Pc(t),Vu=n*qc(t),Gu=qc(e),cl.point=dl,ll(Wu,Vu,Gu)}function dl(t,e){t*=Lc;var n=Pc(e*=Lc),r=n*Pc(t),i=n*qc(t),a=qc(e),o=Fc($c((o=Vu*a-Gu*i)*o+(o=Gu*r-Wu*a)*o+(o=Wu*i-Vu*r)*o),Wu*r+Vu*i+Gu*a);Lu+=o,Pu+=o*(Wu+(Wu=r)),ju+=o*(Vu+(Vu=i)),Yu+=o*(Gu+(Gu=a)),ll(Wu,Vu,Gu)}function pl(){cl.point=ul}function yl(){cl.point=ml}function gl(){vl(Hu,$u),cl.point=ul}function ml(t,e){Hu=t,$u=e,t*=Lc,e*=Lc,cl.point=vl;var n=Pc(e);Wu=n*Pc(t),Vu=n*qc(t),Gu=qc(e),ll(Wu,Vu,Gu)}function vl(t,e){t*=Lc;var n=Pc(e*=Lc),r=n*Pc(t),i=n*qc(t),a=qc(e),o=Vu*a-Gu*i,s=Gu*r-Wu*a,c=Wu*i-Vu*r,u=$c(o*o+s*s+c*c),l=Gc(u),h=u&&-l/u;zu+=h*o,Uu+=h*s,qu+=h*c,Lu+=l,Pu+=l*(Wu+(Wu=r)),ju+=l*(Vu+(Vu=i)),Yu+=l*(Gu+(Gu=a)),ll(Wu,Vu,Gu)}function bl(t){Bu=Lu=Iu=Ru=Fu=Pu=ju=Yu=zu=Uu=qu=0,nu(t,cl);var e=zu,n=Uu,r=qu,i=e*e+n*n+r*r;return i<Ac&&(e=Pu,n=ju,r=Yu,Lu<Sc&&(e=Iu,n=Ru,r=Fu),(i=e*e+n*n+r*r)<Ac)?[NaN,NaN]:[Fc(n,e)*Bc,Gc(r/$c(i))*Bc]}function _l(t){return function(){return t}}function xl(t,e){function n(n,r){return n=t(n,r),e(n[0],n[1])}return t.invert&&e.invert&&(n.invert=function(n,r){return(n=e.invert(n,r))&&t.invert(n[0],n[1])}),n}function wl(t,e){return[Ic(t)>Mc?t+Math.round(-t/Oc)*Oc:t,e]}function kl(t,e,n){return(t%=Oc)?e||n?xl(El(t),Cl(e,n)):El(t):e||n?Cl(e,n):wl}function Tl(t){return function(e,n){return[(e+=t)>Mc?e-Oc:e<-Mc?e+Oc:e,n]}}function El(t){var e=Tl(t);return e.invert=Tl(-t),e}function Cl(t,e){var n=Pc(t),r=qc(t),i=Pc(e),a=qc(e);function o(t,e){var o=Pc(e),s=Pc(t)*o,c=qc(t)*o,u=qc(e),l=u*n+s*r;return[Fc(c*i-l*a,s*n-u*r),Gc(l*i+c*a)]}return o.invert=function(t,e){var o=Pc(e),s=Pc(t)*o,c=qc(t)*o,u=qc(e),l=u*i-c*a;return[Fc(c*i+u*a,s*n+l*r),Gc(l*n-s*r)]},o}function Sl(t){function e(e){return(e=t(e[0]*Lc,e[1]*Lc))[0]*=Bc,e[1]*=Bc,e}return t=kl(t[0]*Lc,t[1]*Lc,t.length>2?t[2]*Lc:0),e.invert=function(e){return(e=t.invert(e[0]*Lc,e[1]*Lc))[0]*=Bc,e[1]*=Bc,e},e}function Al(t,e,n,r,i,a){if(n){var o=Pc(e),s=qc(e),c=r*n;null==i?(i=e+r*Oc,a=e-c/2):(i=Ml(o,i),a=Ml(o,a),(r>0?i<a:i>a)&&(i+=r*Oc));for(var u,l=i;r>0?l>a:l<a;l-=c)u=gu([o,-s*Pc(l),-s*qc(l)]),t.point(u[0],u[1])}}function Ml(t,e){(e=mu(e))[0]-=t,wu(e);var n=Vc(-e[1]);return((-e[2]<0?-n:n)+Oc-Sc)%Oc}function Nl(){var t,e,n=_l([0,0]),r=_l(90),i=_l(6),a={point:function(n,r){t.push(n=e(n,r)),n[0]*=Bc,n[1]*=Bc}};function o(){var o=n.apply(this,arguments),s=r.apply(this,arguments)*Lc,c=i.apply(this,arguments)*Lc;return t=[],e=kl(-o[0]*Lc,-o[1]*Lc,0).invert,Al(a,s,c,1),o={type:"Polygon",coordinates:[t]},t=e=null,o}return o.center=function(t){return arguments.length?(n="function"==typeof t?t:_l([+t[0],+t[1]]),o):n},o.radius=function(t){return arguments.length?(r="function"==typeof t?t:_l(+t),o):r},o.precision=function(t){return arguments.length?(i="function"==typeof t?t:_l(+t),o):i},o}function Dl(){var t,e=[];return{point:function(e,n,r){t.push([e,n,r])},lineStart:function(){e.push(t=[])},lineEnd:Zc,rejoin:function(){e.length>1&&e.push(e.pop().concat(e.shift()))},result:function(){var n=e;return e=[],t=null,n}}}function Ol(t,e){return Ic(t[0]-e[0])<Sc&&Ic(t[1]-e[1])<Sc}function Bl(t,e,n,r){this.x=t,this.z=e,this.o=n,this.e=r,this.v=!1,this.n=this.p=null}function Ll(t,e,n,r,i){var a,o,s=[],c=[];if(t.forEach((function(t){if(!((e=t.length-1)<=0)){var e,n,r=t[0],o=t[e];if(Ol(r,o)){if(!r[2]&&!o[2]){for(i.lineStart(),a=0;a<e;++a)i.point((r=t[a])[0],r[1]);return void i.lineEnd()}o[0]+=2e-6}s.push(n=new Bl(r,t,null,!0)),c.push(n.o=new Bl(r,null,n,!1)),s.push(n=new Bl(o,t,null,!1)),c.push(n.o=new Bl(o,null,n,!0))}})),s.length){for(c.sort(e),Il(s),Il(c),a=0,o=c.length;a<o;++a)c[a].e=n=!n;for(var u,l,h=s[0];;){for(var f=h,d=!0;f.v;)if((f=f.n)===h)return;u=f.z,i.lineStart();do{if(f.v=f.o.v=!0,f.e){if(d)for(a=0,o=u.length;a<o;++a)i.point((l=u[a])[0],l[1]);else r(f.x,f.n.x,1,i);f=f.n}else{if(d)for(u=f.p.z,a=u.length-1;a>=0;--a)i.point((l=u[a])[0],l[1]);else r(f.x,f.p.x,-1,i);f=f.p}u=(f=f.o).z,d=!d}while(!f.v);i.lineEnd()}}}function Il(t){if(e=t.length){for(var e,n,r=0,i=t[0];++r<e;)i.n=n=t[r],n.p=i,i=n;i.n=n=t[0],n.p=i}}wl.invert=wl;var Rl=kc();function Fl(t){return Ic(t[0])<=Mc?t[0]:Hc(t[0])*((Ic(t[0])+Mc)%Oc-Mc)}function Pl(t,e){var n=Fl(e),r=e[1],i=qc(r),a=[qc(n),-Pc(n),0],o=0,s=0;Rl.reset(),1===i?r=Nc+Sc:-1===i&&(r=-Nc-Sc);for(var c=0,u=t.length;c<u;++c)if(h=(l=t[c]).length)for(var l,h,f=l[h-1],d=Fl(f),p=f[1]/2+Dc,y=qc(p),g=Pc(p),m=0;m<h;++m,d=b,y=x,g=w,f=v){var v=l[m],b=Fl(v),_=v[1]/2+Dc,x=qc(_),w=Pc(_),k=b-d,T=k>=0?1:-1,E=T*k,C=E>Mc,S=y*x;if(Rl.add(Fc(S*T*qc(E),g*w+S*Pc(E))),o+=C?k+T*Oc:k,C^d>=n^b>=n){var A=bu(mu(f),mu(v));wu(A);var M=bu(a,A);wu(M);var N=(C^k>=0?-1:1)*Gc(M[2]);(r>N||r===N&&(A[0]||A[1]))&&(s+=C^k>=0?1:-1)}}return(o<-1e-6||o<Sc&&Rl<-1e-6)^1&s}function jl(t,e,n,r){return function(i){var a,o,s,c=e(i),u=Dl(),l=e(u),h=!1,f={point:d,lineStart:y,lineEnd:g,polygonStart:function(){f.point=m,f.lineStart=v,f.lineEnd=b,o=[],a=[]},polygonEnd:function(){f.point=d,f.lineStart=y,f.lineEnd=g,o=P(o);var t=Pl(a,r);o.length?(h||(i.polygonStart(),h=!0),Ll(o,zl,t,n,i)):t&&(h||(i.polygonStart(),h=!0),i.lineStart(),n(null,null,1,i),i.lineEnd()),h&&(i.polygonEnd(),h=!1),o=a=null},sphere:function(){i.polygonStart(),i.lineStart(),n(null,null,1,i),i.lineEnd(),i.polygonEnd()}};function d(e,n){t(e,n)&&i.point(e,n)}function p(t,e){c.point(t,e)}function y(){f.point=p,c.lineStart()}function g(){f.point=d,c.lineEnd()}function m(t,e){s.push([t,e]),l.point(t,e)}function v(){l.lineStart(),s=[]}function b(){m(s[0][0],s[0][1]),l.lineEnd();var t,e,n,r,c=l.clean(),f=u.result(),d=f.length;if(s.pop(),a.push(s),s=null,d)if(1&c){if((e=(n=f[0]).length-1)>0){for(h||(i.polygonStart(),h=!0),i.lineStart(),t=0;t<e;++t)i.point((r=n[t])[0],r[1]);i.lineEnd()}}else d>1&&2&c&&f.push(f.pop().concat(f.shift())),o.push(f.filter(Yl))}return f}}function Yl(t){return t.length>1}function zl(t,e){return((t=t.x)[0]<0?t[1]-Nc-Sc:Nc-t[1])-((e=e.x)[0]<0?e[1]-Nc-Sc:Nc-e[1])}const Ul=jl((function(){return!0}),(function(t){var e,n=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),e=1},point:function(a,o){var s=a>0?Mc:-Mc,c=Ic(a-n);Ic(c-Mc)<Sc?(t.point(n,r=(r+o)/2>0?Nc:-Nc),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(s,r),t.point(a,r),e=0):i!==s&&c>=Mc&&(Ic(n-i)<Sc&&(n-=i*Sc),Ic(a-s)<Sc&&(a-=s*Sc),r=function(t,e,n,r){var i,a,o=qc(t-n);return Ic(o)>Sc?Rc((qc(e)*(a=Pc(r))*qc(n)-qc(r)*(i=Pc(e))*qc(t))/(i*a*o)):(e+r)/2}(n,r,a,o),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(s,r),e=0),t.point(n=a,r=o),i=s},lineEnd:function(){t.lineEnd(),n=r=NaN},clean:function(){return 2-e}}}),(function(t,e,n,r){var i;if(null==t)i=n*Nc,r.point(-Mc,i),r.point(0,i),r.point(Mc,i),r.point(Mc,0),r.point(Mc,-i),r.point(0,-i),r.point(-Mc,-i),r.point(-Mc,0),r.point(-Mc,i);else if(Ic(t[0]-e[0])>Sc){var a=t[0]<e[0]?Mc:-Mc;i=n*a/2,r.point(-a,i),r.point(0,i),r.point(a,i)}else r.point(e[0],e[1])}),[-Mc,-Nc]);function ql(t){var e=Pc(t),n=6*Lc,r=e>0,i=Ic(e)>Sc;function a(t,n){return Pc(t)*Pc(n)>e}function o(t,n,r){var i=[1,0,0],a=bu(mu(t),mu(n)),o=vu(a,a),s=a[0],c=o-s*s;if(!c)return!r&&t;var u=e*o/c,l=-e*s/c,h=bu(i,a),f=xu(i,u);_u(f,xu(a,l));var d=h,p=vu(f,d),y=vu(d,d),g=p*p-y*(vu(f,f)-1);if(!(g<0)){var m=$c(g),v=xu(d,(-p-m)/y);if(_u(v,f),v=gu(v),!r)return v;var b,_=t[0],x=n[0],w=t[1],k=n[1];x<_&&(b=_,_=x,x=b);var T=x-_,E=Ic(T-Mc)<Sc;if(!E&&k<w&&(b=w,w=k,k=b),E||T<Sc?E?w+k>0^v[1]<(Ic(v[0]-_)<Sc?w:k):w<=v[1]&&v[1]<=k:T>Mc^(_<=v[0]&&v[0]<=x)){var C=xu(d,(-p+m)/y);return _u(C,f),[v,gu(C)]}}}function s(e,n){var i=r?t:Mc-t,a=0;return e<-i?a|=1:e>i&&(a|=2),n<-i?a|=4:n>i&&(a|=8),a}return jl(a,(function(t){var e,n,c,u,l;return{lineStart:function(){u=c=!1,l=1},point:function(h,f){var d,p=[h,f],y=a(h,f),g=r?y?0:s(h,f):y?s(h+(h<0?Mc:-Mc),f):0;if(!e&&(u=c=y)&&t.lineStart(),y!==c&&(!(d=o(e,p))||Ol(e,d)||Ol(p,d))&&(p[2]=1),y!==c)l=0,y?(t.lineStart(),d=o(p,e),t.point(d[0],d[1])):(d=o(e,p),t.point(d[0],d[1],2),t.lineEnd()),e=d;else if(i&&e&&r^y){var m;g&n||!(m=o(p,e,!0))||(l=0,r?(t.lineStart(),t.point(m[0][0],m[0][1]),t.point(m[1][0],m[1][1]),t.lineEnd()):(t.point(m[1][0],m[1][1]),t.lineEnd(),t.lineStart(),t.point(m[0][0],m[0][1],3)))}!y||e&&Ol(e,p)||t.point(p[0],p[1]),e=p,c=y,n=g},lineEnd:function(){c&&t.lineEnd(),e=null},clean:function(){return l|(u&&c)<<1}}}),(function(e,r,i,a){Al(a,t,n,i,e,r)}),r?[0,-t]:[-Mc,t-Mc])}var Hl=1e9,$l=-Hl;function Wl(t,e,n,r){function i(i,a){return t<=i&&i<=n&&e<=a&&a<=r}function a(i,a,s,u){var l=0,h=0;if(null==i||(l=o(i,s))!==(h=o(a,s))||c(i,a)<0^s>0)do{u.point(0===l||3===l?t:n,l>1?r:e)}while((l=(l+s+4)%4)!==h);else u.point(a[0],a[1])}function o(r,i){return Ic(r[0]-t)<Sc?i>0?0:3:Ic(r[0]-n)<Sc?i>0?2:1:Ic(r[1]-e)<Sc?i>0?1:0:i>0?3:2}function s(t,e){return c(t.x,e.x)}function c(t,e){var n=o(t,1),r=o(e,1);return n!==r?n-r:0===n?e[1]-t[1]:1===n?t[0]-e[0]:2===n?t[1]-e[1]:e[0]-t[0]}return function(o){var c,u,l,h,f,d,p,y,g,m,v,b=o,_=Dl(),x={point:w,lineStart:function(){x.point=k,u&&u.push(l=[]),m=!0,g=!1,p=y=NaN},lineEnd:function(){c&&(k(h,f),d&&g&&_.rejoin(),c.push(_.result())),x.point=w,g&&b.lineEnd()},polygonStart:function(){b=_,c=[],u=[],v=!0},polygonEnd:function(){var e=function(){for(var e=0,n=0,i=u.length;n<i;++n)for(var a,o,s=u[n],c=1,l=s.length,h=s[0],f=h[0],d=h[1];c<l;++c)a=f,o=d,f=(h=s[c])[0],d=h[1],o<=r?d>r&&(f-a)*(r-o)>(d-o)*(t-a)&&++e:d<=r&&(f-a)*(r-o)<(d-o)*(t-a)&&--e;return e}(),n=v&&e,i=(c=P(c)).length;(n||i)&&(o.polygonStart(),n&&(o.lineStart(),a(null,null,1,o),o.lineEnd()),i&&Ll(c,s,e,a,o),o.polygonEnd()),b=o,c=u=l=null}};function w(t,e){i(t,e)&&b.point(t,e)}function k(a,o){var s=i(a,o);if(u&&l.push([a,o]),m)h=a,f=o,d=s,m=!1,s&&(b.lineStart(),b.point(a,o));else if(s&&g)b.point(a,o);else{var c=[p=Math.max($l,Math.min(Hl,p)),y=Math.max($l,Math.min(Hl,y))],_=[a=Math.max($l,Math.min(Hl,a)),o=Math.max($l,Math.min(Hl,o))];!function(t,e,n,r,i,a){var o,s=t[0],c=t[1],u=0,l=1,h=e[0]-s,f=e[1]-c;if(o=n-s,h||!(o>0)){if(o/=h,h<0){if(o<u)return;o<l&&(l=o)}else if(h>0){if(o>l)return;o>u&&(u=o)}if(o=i-s,h||!(o<0)){if(o/=h,h<0){if(o>l)return;o>u&&(u=o)}else if(h>0){if(o<u)return;o<l&&(l=o)}if(o=r-c,f||!(o>0)){if(o/=f,f<0){if(o<u)return;o<l&&(l=o)}else if(f>0){if(o>l)return;o>u&&(u=o)}if(o=a-c,f||!(o<0)){if(o/=f,f<0){if(o>l)return;o>u&&(u=o)}else if(f>0){if(o<u)return;o<l&&(l=o)}return u>0&&(t[0]=s+u*h,t[1]=c+u*f),l<1&&(e[0]=s+l*h,e[1]=c+l*f),!0}}}}}(c,_,t,e,n,r)?s&&(b.lineStart(),b.point(a,o),v=!1):(g||(b.lineStart(),b.point(c[0],c[1])),b.point(_[0],_[1]),s||b.lineEnd(),v=!1)}p=a,y=o,g=s}return x}}function Vl(){var t,e,n,r=0,i=0,a=960,o=500;return n={stream:function(n){return t&&e===n?t:t=Wl(r,i,a,o)(e=n)},extent:function(s){return arguments.length?(r=+s[0][0],i=+s[0][1],a=+s[1][0],o=+s[1][1],t=e=null,n):[[r,i],[a,o]]}}}var Gl,Xl,Zl,Ql=kc(),Kl={sphere:Zc,point:Zc,lineStart:function(){Kl.point=th,Kl.lineEnd=Jl},lineEnd:Zc,polygonStart:Zc,polygonEnd:Zc};function Jl(){Kl.point=Kl.lineEnd=Zc}function th(t,e){Gl=t*=Lc,Xl=qc(e*=Lc),Zl=Pc(e),Kl.point=eh}function eh(t,e){t*=Lc;var n=qc(e*=Lc),r=Pc(e),i=Ic(t-Gl),a=Pc(i),o=r*qc(i),s=Zl*n-Xl*r*a,c=Xl*n+Zl*r*a;Ql.add(Fc($c(o*o+s*s),c)),Gl=t,Xl=n,Zl=r}function nh(t){return Ql.reset(),nu(t,Kl),+Ql}var rh=[null,null],ih={type:"LineString",coordinates:rh};function ah(t,e){return rh[0]=t,rh[1]=e,nh(ih)}var oh={Feature:function(t,e){return ch(t.geometry,e)},FeatureCollection:function(t,e){for(var n=t.features,r=-1,i=n.length;++r<i;)if(ch(n[r].geometry,e))return!0;return!1}},sh={Sphere:function(){return!0},Point:function(t,e){return uh(t.coordinates,e)},MultiPoint:function(t,e){for(var n=t.coordinates,r=-1,i=n.length;++r<i;)if(uh(n[r],e))return!0;return!1},LineString:function(t,e){return lh(t.coordinates,e)},MultiLineString:function(t,e){for(var n=t.coordinates,r=-1,i=n.length;++r<i;)if(lh(n[r],e))return!0;return!1},Polygon:function(t,e){return hh(t.coordinates,e)},MultiPolygon:function(t,e){for(var n=t.coordinates,r=-1,i=n.length;++r<i;)if(hh(n[r],e))return!0;return!1},GeometryCollection:function(t,e){for(var n=t.geometries,r=-1,i=n.length;++r<i;)if(ch(n[r],e))return!0;return!1}};function ch(t,e){return!(!t||!sh.hasOwnProperty(t.type))&&sh[t.type](t,e)}function uh(t,e){return 0===ah(t,e)}function lh(t,e){for(var n,r,i,a=0,o=t.length;a<o;a++){if(0===(r=ah(t[a],e)))return!0;if(a>0&&(i=ah(t[a],t[a-1]))>0&&n<=i&&r<=i&&(n+r-i)*(1-Math.pow((n-r)/i,2))<Ac*i)return!0;n=r}return!1}function hh(t,e){return!!Pl(t.map(fh),dh(e))}function fh(t){return(t=t.map(dh)).pop(),t}function dh(t){return[t[0]*Lc,t[1]*Lc]}function ph(t,e){return(t&&oh.hasOwnProperty(t.type)?oh[t.type]:ch)(t,e)}function yh(t,e,n){var r=k(t,e-Sc,n).concat(e);return function(t){return r.map((function(e){return[t,e]}))}}function gh(t,e,n){var r=k(t,e-Sc,n).concat(e);return function(t){return r.map((function(e){return[e,t]}))}}function mh(){var t,e,n,r,i,a,o,s,c,u,l,h,f=10,d=f,p=90,y=360,g=2.5;function m(){return{type:"MultiLineString",coordinates:v()}}function v(){return k(jc(r/p)*p,n,p).map(l).concat(k(jc(s/y)*y,o,y).map(h)).concat(k(jc(e/f)*f,t,f).filter((function(t){return Ic(t%p)>Sc})).map(c)).concat(k(jc(a/d)*d,i,d).filter((function(t){return Ic(t%y)>Sc})).map(u))}return m.lines=function(){return v().map((function(t){return{type:"LineString",coordinates:t}}))},m.outline=function(){return{type:"Polygon",coordinates:[l(r).concat(h(o).slice(1),l(n).reverse().slice(1),h(s).reverse().slice(1))]}},m.extent=function(t){return arguments.length?m.extentMajor(t).extentMinor(t):m.extentMinor()},m.extentMajor=function(t){return arguments.length?(r=+t[0][0],n=+t[1][0],s=+t[0][1],o=+t[1][1],r>n&&(t=r,r=n,n=t),s>o&&(t=s,s=o,o=t),m.precision(g)):[[r,s],[n,o]]},m.extentMinor=function(n){return arguments.length?(e=+n[0][0],t=+n[1][0],a=+n[0][1],i=+n[1][1],e>t&&(n=e,e=t,t=n),a>i&&(n=a,a=i,i=n),m.precision(g)):[[e,a],[t,i]]},m.step=function(t){return arguments.length?m.stepMajor(t).stepMinor(t):m.stepMinor()},m.stepMajor=function(t){return arguments.length?(p=+t[0],y=+t[1],m):[p,y]},m.stepMinor=function(t){return arguments.length?(f=+t[0],d=+t[1],m):[f,d]},m.precision=function(f){return arguments.length?(g=+f,c=yh(a,i,90),u=gh(e,t,g),l=yh(s,o,90),h=gh(r,n,g),m):g},m.extentMajor([[-180,-89.999999],[180,89.999999]]).extentMinor([[-180,-80.000001],[180,80.000001]])}function vh(){return mh()()}function bh(t,e){var n=t[0]*Lc,r=t[1]*Lc,i=e[0]*Lc,a=e[1]*Lc,o=Pc(r),s=qc(r),c=Pc(a),u=qc(a),l=o*Pc(n),h=o*qc(n),f=c*Pc(i),d=c*qc(i),p=2*Gc($c(Xc(a-r)+o*c*Xc(i-n))),y=qc(p),g=p?function(t){var e=qc(t*=p)/y,n=qc(p-t)/y,r=n*l+e*f,i=n*h+e*d,a=n*s+e*u;return[Fc(i,r)*Bc,Fc(a,$c(r*r+i*i))*Bc]}:function(){return[n*Bc,r*Bc]};return g.distance=p,g}function _h(t){return t}var xh,wh,kh,Th,Eh=kc(),Ch=kc(),Sh={point:Zc,lineStart:Zc,lineEnd:Zc,polygonStart:function(){Sh.lineStart=Ah,Sh.lineEnd=Dh},polygonEnd:function(){Sh.lineStart=Sh.lineEnd=Sh.point=Zc,Eh.add(Ic(Ch)),Ch.reset()},result:function(){var t=Eh/2;return Eh.reset(),t}};function Ah(){Sh.point=Mh}function Mh(t,e){Sh.point=Nh,xh=kh=t,wh=Th=e}function Nh(t,e){Ch.add(Th*t-kh*e),kh=t,Th=e}function Dh(){Nh(xh,wh)}const Oh=Sh;var Bh=1/0,Lh=Bh,Ih=-Bh,Rh=Ih,Fh={point:function(t,e){t<Bh&&(Bh=t),t>Ih&&(Ih=t),e<Lh&&(Lh=e),e>Rh&&(Rh=e)},lineStart:Zc,lineEnd:Zc,polygonStart:Zc,polygonEnd:Zc,result:function(){var t=[[Bh,Lh],[Ih,Rh]];return Ih=Rh=-(Lh=Bh=1/0),t}};const Ph=Fh;var jh,Yh,zh,Uh,qh=0,Hh=0,$h=0,Wh=0,Vh=0,Gh=0,Xh=0,Zh=0,Qh=0,Kh={point:Jh,lineStart:tf,lineEnd:rf,polygonStart:function(){Kh.lineStart=af,Kh.lineEnd=of},polygonEnd:function(){Kh.point=Jh,Kh.lineStart=tf,Kh.lineEnd=rf},result:function(){var t=Qh?[Xh/Qh,Zh/Qh]:Gh?[Wh/Gh,Vh/Gh]:$h?[qh/$h,Hh/$h]:[NaN,NaN];return qh=Hh=$h=Wh=Vh=Gh=Xh=Zh=Qh=0,t}};function Jh(t,e){qh+=t,Hh+=e,++$h}function tf(){Kh.point=ef}function ef(t,e){Kh.point=nf,Jh(zh=t,Uh=e)}function nf(t,e){var n=t-zh,r=e-Uh,i=$c(n*n+r*r);Wh+=i*(zh+t)/2,Vh+=i*(Uh+e)/2,Gh+=i,Jh(zh=t,Uh=e)}function rf(){Kh.point=Jh}function af(){Kh.point=sf}function of(){cf(jh,Yh)}function sf(t,e){Kh.point=cf,Jh(jh=zh=t,Yh=Uh=e)}function cf(t,e){var n=t-zh,r=e-Uh,i=$c(n*n+r*r);Wh+=i*(zh+t)/2,Vh+=i*(Uh+e)/2,Gh+=i,Xh+=(i=Uh*t-zh*e)*(zh+t),Zh+=i*(Uh+e),Qh+=3*i,Jh(zh=t,Uh=e)}const uf=Kh;function lf(t){this._context=t}lf.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,e){switch(this._point){case 0:this._context.moveTo(t,e),this._point=1;break;case 1:this._context.lineTo(t,e);break;default:this._context.moveTo(t+this._radius,e),this._context.arc(t,e,this._radius,0,Oc)}},result:Zc};var hf,ff,df,pf,yf,gf=kc(),mf={point:Zc,lineStart:function(){mf.point=vf},lineEnd:function(){hf&&bf(ff,df),mf.point=Zc},polygonStart:function(){hf=!0},polygonEnd:function(){hf=null},result:function(){var t=+gf;return gf.reset(),t}};function vf(t,e){mf.point=bf,ff=pf=t,df=yf=e}function bf(t,e){pf-=t,yf-=e,gf.add($c(pf*pf+yf*yf)),pf=t,yf=e}const _f=mf;function xf(){this._string=[]}function wf(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function kf(t,e){var n,r,i=4.5;function a(t){return t&&("function"==typeof i&&r.pointRadius(+i.apply(this,arguments)),nu(t,n(r))),r.result()}return a.area=function(t){return nu(t,n(Oh)),Oh.result()},a.measure=function(t){return nu(t,n(_f)),_f.result()},a.bounds=function(t){return nu(t,n(Ph)),Ph.result()},a.centroid=function(t){return nu(t,n(uf)),uf.result()},a.projection=function(e){return arguments.length?(n=null==e?(t=null,_h):(t=e).stream,a):t},a.context=function(t){return arguments.length?(r=null==t?(e=null,new xf):new lf(e=t),"function"!=typeof i&&r.pointRadius(i),a):e},a.pointRadius=function(t){return arguments.length?(i="function"==typeof t?t:(r.pointRadius(+t),+t),a):i},a.projection(t).context(e)}function Tf(t){return{stream:Ef(t)}}function Ef(t){return function(e){var n=new Cf;for(var r in t)n[r]=t[r];return n.stream=e,n}}function Cf(){}function Sf(t,e,n){var r=t.clipExtent&&t.clipExtent();return t.scale(150).translate([0,0]),null!=r&&t.clipExtent(null),nu(n,t.stream(Ph)),e(Ph.result()),null!=r&&t.clipExtent(r),t}function Af(t,e,n){return Sf(t,(function(n){var r=e[1][0]-e[0][0],i=e[1][1]-e[0][1],a=Math.min(r/(n[1][0]-n[0][0]),i/(n[1][1]-n[0][1])),o=+e[0][0]+(r-a*(n[1][0]+n[0][0]))/2,s=+e[0][1]+(i-a*(n[1][1]+n[0][1]))/2;t.scale(150*a).translate([o,s])}),n)}function Mf(t,e,n){return Af(t,[[0,0],e],n)}function Nf(t,e,n){return Sf(t,(function(n){var r=+e,i=r/(n[1][0]-n[0][0]),a=(r-i*(n[1][0]+n[0][0]))/2,o=-i*n[0][1];t.scale(150*i).translate([a,o])}),n)}function Df(t,e,n){return Sf(t,(function(n){var r=+e,i=r/(n[1][1]-n[0][1]),a=-i*n[0][0],o=(r-i*(n[1][1]+n[0][1]))/2;t.scale(150*i).translate([a,o])}),n)}xf.prototype={_radius:4.5,_circle:wf(4.5),pointRadius:function(t){return(t=+t)!==this._radius&&(this._radius=t,this._circle=null),this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._string.push("Z"),this._point=NaN},point:function(t,e){switch(this._point){case 0:this._string.push("M",t,",",e),this._point=1;break;case 1:this._string.push("L",t,",",e);break;default:null==this._circle&&(this._circle=wf(this._radius)),this._string.push("M",t,",",e,this._circle)}},result:function(){if(this._string.length){var t=this._string.join("");return this._string=[],t}return null}},Cf.prototype={constructor:Cf,point:function(t,e){this.stream.point(t,e)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var Of=Pc(30*Lc);function Bf(t,e){return+e?function(t,e){function n(r,i,a,o,s,c,u,l,h,f,d,p,y,g){var m=u-r,v=l-i,b=m*m+v*v;if(b>4*e&&y--){var _=o+f,x=s+d,w=c+p,k=$c(_*_+x*x+w*w),T=Gc(w/=k),E=Ic(Ic(w)-1)<Sc||Ic(a-h)<Sc?(a+h)/2:Fc(x,_),C=t(E,T),S=C[0],A=C[1],M=S-r,N=A-i,D=v*M-m*N;(D*D/b>e||Ic((m*M+v*N)/b-.5)>.3||o*f+s*d+c*p<Of)&&(n(r,i,a,o,s,c,S,A,E,_/=k,x/=k,w,y,g),g.point(S,A),n(S,A,E,_,x,w,u,l,h,f,d,p,y,g))}}return function(e){var r,i,a,o,s,c,u,l,h,f,d,p,y={point:g,lineStart:m,lineEnd:b,polygonStart:function(){e.polygonStart(),y.lineStart=_},polygonEnd:function(){e.polygonEnd(),y.lineStart=m}};function g(n,r){n=t(n,r),e.point(n[0],n[1])}function m(){l=NaN,y.point=v,e.lineStart()}function v(r,i){var a=mu([r,i]),o=t(r,i);n(l,h,u,f,d,p,l=o[0],h=o[1],u=r,f=a[0],d=a[1],p=a[2],16,e),e.point(l,h)}function b(){y.point=g,e.lineEnd()}function _(){m(),y.point=x,y.lineEnd=w}function x(t,e){v(r=t,e),i=l,a=h,o=f,s=d,c=p,y.point=v}function w(){n(l,h,u,f,d,p,i,a,r,o,s,c,16,e),y.lineEnd=b,b()}return y}}(t,e):function(t){return Ef({point:function(e,n){e=t(e,n),this.stream.point(e[0],e[1])}})}(t)}var Lf=Ef({point:function(t,e){this.stream.point(t*Lc,e*Lc)}});function If(t,e,n,r,i){function a(a,o){return[e+t*(a*=r),n-t*(o*=i)]}return a.invert=function(a,o){return[(a-e)/t*r,(n-o)/t*i]},a}function Rf(t,e,n,r,i,a){var o=Pc(a),s=qc(a),c=o*t,u=s*t,l=o/t,h=s/t,f=(s*n-o*e)/t,d=(s*e+o*n)/t;function p(t,a){return[c*(t*=r)-u*(a*=i)+e,n-u*t-c*a]}return p.invert=function(t,e){return[r*(l*t-h*e+f),i*(d-h*t-l*e)]},p}function Ff(t){return Pf((function(){return t}))()}function Pf(t){var e,n,r,i,a,o,s,c,u,l,h=150,f=480,d=250,p=0,y=0,g=0,m=0,v=0,b=0,_=1,x=1,w=null,k=Ul,T=null,E=_h,C=.5;function S(t){return c(t[0]*Lc,t[1]*Lc)}function A(t){return(t=c.invert(t[0],t[1]))&&[t[0]*Bc,t[1]*Bc]}function M(){var t=Rf(h,0,0,_,x,b).apply(null,e(p,y)),r=(b?Rf:If)(h,f-t[0],d-t[1],_,x,b);return n=kl(g,m,v),s=xl(e,r),c=xl(n,s),o=Bf(s,C),N()}function N(){return u=l=null,S}return S.stream=function(t){return u&&l===t?u:u=Lf(function(t){return Ef({point:function(e,n){var r=t(e,n);return this.stream.point(r[0],r[1])}})}(n)(k(o(E(l=t)))))},S.preclip=function(t){return arguments.length?(k=t,w=void 0,N()):k},S.postclip=function(t){return arguments.length?(E=t,T=r=i=a=null,N()):E},S.clipAngle=function(t){return arguments.length?(k=+t?ql(w=t*Lc):(w=null,Ul),N()):w*Bc},S.clipExtent=function(t){return arguments.length?(E=null==t?(T=r=i=a=null,_h):Wl(T=+t[0][0],r=+t[0][1],i=+t[1][0],a=+t[1][1]),N()):null==T?null:[[T,r],[i,a]]},S.scale=function(t){return arguments.length?(h=+t,M()):h},S.translate=function(t){return arguments.length?(f=+t[0],d=+t[1],M()):[f,d]},S.center=function(t){return arguments.length?(p=t[0]%360*Lc,y=t[1]%360*Lc,M()):[p*Bc,y*Bc]},S.rotate=function(t){return arguments.length?(g=t[0]%360*Lc,m=t[1]%360*Lc,v=t.length>2?t[2]%360*Lc:0,M()):[g*Bc,m*Bc,v*Bc]},S.angle=function(t){return arguments.length?(b=t%360*Lc,M()):b*Bc},S.reflectX=function(t){return arguments.length?(_=t?-1:1,M()):_<0},S.reflectY=function(t){return arguments.length?(x=t?-1:1,M()):x<0},S.precision=function(t){return arguments.length?(o=Bf(s,C=t*t),N()):$c(C)},S.fitExtent=function(t,e){return Af(S,t,e)},S.fitSize=function(t,e){return Mf(S,t,e)},S.fitWidth=function(t,e){return Nf(S,t,e)},S.fitHeight=function(t,e){return Df(S,t,e)},function(){return e=t.apply(this,arguments),S.invert=e.invert&&A,M()}}function jf(t){var e=0,n=Mc/3,r=Pf(t),i=r(e,n);return i.parallels=function(t){return arguments.length?r(e=t[0]*Lc,n=t[1]*Lc):[e*Bc,n*Bc]},i}function Yf(t,e){var n=qc(t),r=(n+qc(e))/2;if(Ic(r)<Sc)return function(t){var e=Pc(t);function n(t,n){return[t*e,qc(n)/e]}return n.invert=function(t,n){return[t/e,Gc(n*e)]},n}(t);var i=1+n*(2*r-n),a=$c(i)/r;function o(t,e){var n=$c(i-2*r*qc(e))/r;return[n*qc(t*=r),a-n*Pc(t)]}return o.invert=function(t,e){var n=a-e,o=Fc(t,Ic(n))*Hc(n);return n*r<0&&(o-=Mc*Hc(t)*Hc(n)),[o/r,Gc((i-(t*t+n*n)*r*r)/(2*r))]},o}function zf(){return jf(Yf).scale(155.424).center([0,33.6442])}function Uf(){return zf().parallels([29.5,45.5]).scale(1070).translate([480,250]).rotate([96,0]).center([-.6,38.7])}function qf(){var t,e,n,r,i,a,o=Uf(),s=zf().rotate([154,0]).center([-2,58.5]).parallels([55,65]),c=zf().rotate([157,0]).center([-3,19.9]).parallels([8,18]),u={point:function(t,e){a=[t,e]}};function l(t){var e=t[0],o=t[1];return a=null,n.point(e,o),a||(r.point(e,o),a)||(i.point(e,o),a)}function h(){return t=e=null,l}return l.invert=function(t){var e=o.scale(),n=o.translate(),r=(t[0]-n[0])/e,i=(t[1]-n[1])/e;return(i>=.12&&i<.234&&r>=-.425&&r<-.214?s:i>=.166&&i<.234&&r>=-.214&&r<-.115?c:o).invert(t)},l.stream=function(n){return t&&e===n?t:(r=[o.stream(e=n),s.stream(n),c.stream(n)],i=r.length,t={point:function(t,e){for(var n=-1;++n<i;)r[n].point(t,e)},sphere:function(){for(var t=-1;++t<i;)r[t].sphere()},lineStart:function(){for(var t=-1;++t<i;)r[t].lineStart()},lineEnd:function(){for(var t=-1;++t<i;)r[t].lineEnd()},polygonStart:function(){for(var t=-1;++t<i;)r[t].polygonStart()},polygonEnd:function(){for(var t=-1;++t<i;)r[t].polygonEnd()}});var r,i},l.precision=function(t){return arguments.length?(o.precision(t),s.precision(t),c.precision(t),h()):o.precision()},l.scale=function(t){return arguments.length?(o.scale(t),s.scale(.35*t),c.scale(t),l.translate(o.translate())):o.scale()},l.translate=function(t){if(!arguments.length)return o.translate();var e=o.scale(),a=+t[0],l=+t[1];return n=o.translate(t).clipExtent([[a-.455*e,l-.238*e],[a+.455*e,l+.238*e]]).stream(u),r=s.translate([a-.307*e,l+.201*e]).clipExtent([[a-.425*e+Sc,l+.12*e+Sc],[a-.214*e-Sc,l+.234*e-Sc]]).stream(u),i=c.translate([a-.205*e,l+.212*e]).clipExtent([[a-.214*e+Sc,l+.166*e+Sc],[a-.115*e-Sc,l+.234*e-Sc]]).stream(u),h()},l.fitExtent=function(t,e){return Af(l,t,e)},l.fitSize=function(t,e){return Mf(l,t,e)},l.fitWidth=function(t,e){return Nf(l,t,e)},l.fitHeight=function(t,e){return Df(l,t,e)},l.scale(1070)}function Hf(t){return function(e,n){var r=Pc(e),i=Pc(n),a=t(r*i);return[a*i*qc(e),a*qc(n)]}}function $f(t){return function(e,n){var r=$c(e*e+n*n),i=t(r),a=qc(i),o=Pc(i);return[Fc(e*a,r*o),Gc(r&&n*a/r)]}}var Wf=Hf((function(t){return $c(2/(1+t))}));function Vf(){return Ff(Wf).scale(124.75).clipAngle(179.999)}Wf.invert=$f((function(t){return 2*Gc(t/2)}));var Gf=Hf((function(t){return(t=Vc(t))&&t/qc(t)}));function Xf(){return Ff(Gf).scale(79.4188).clipAngle(179.999)}function Zf(t,e){return[t,zc(Wc((Nc+e)/2))]}function Qf(){return Kf(Zf).scale(961/Oc)}function Kf(t){var e,n,r,i=Ff(t),a=i.center,o=i.scale,s=i.translate,c=i.clipExtent,u=null;function l(){var a=Mc*o(),s=i(Sl(i.rotate()).invert([0,0]));return c(null==u?[[s[0]-a,s[1]-a],[s[0]+a,s[1]+a]]:t===Zf?[[Math.max(s[0]-a,u),e],[Math.min(s[0]+a,n),r]]:[[u,Math.max(s[1]-a,e)],[n,Math.min(s[1]+a,r)]])}return i.scale=function(t){return arguments.length?(o(t),l()):o()},i.translate=function(t){return arguments.length?(s(t),l()):s()},i.center=function(t){return arguments.length?(a(t),l()):a()},i.clipExtent=function(t){return arguments.length?(null==t?u=e=n=r=null:(u=+t[0][0],e=+t[0][1],n=+t[1][0],r=+t[1][1]),l()):null==u?null:[[u,e],[n,r]]},l()}function Jf(t){return Wc((Nc+t)/2)}function td(t,e){var n=Pc(t),r=t===e?qc(t):zc(n/Pc(e))/zc(Jf(e)/Jf(t)),i=n*Uc(Jf(t),r)/r;if(!r)return Zf;function a(t,e){i>0?e<-Nc+Sc&&(e=-Nc+Sc):e>Nc-Sc&&(e=Nc-Sc);var n=i/Uc(Jf(e),r);return[n*qc(r*t),i-n*Pc(r*t)]}return a.invert=function(t,e){var n=i-e,a=Hc(r)*$c(t*t+n*n),o=Fc(t,Ic(n))*Hc(n);return n*r<0&&(o-=Mc*Hc(t)*Hc(n)),[o/r,2*Rc(Uc(i/a,1/r))-Nc]},a}function ed(){return jf(td).scale(109.5).parallels([30,30])}function nd(t,e){return[t,e]}function rd(){return Ff(nd).scale(152.63)}function id(t,e){var n=Pc(t),r=t===e?qc(t):(n-Pc(e))/(e-t),i=n/r+t;if(Ic(r)<Sc)return nd;function a(t,e){var n=i-e,a=r*t;return[n*qc(a),i-n*Pc(a)]}return a.invert=function(t,e){var n=i-e,a=Fc(t,Ic(n))*Hc(n);return n*r<0&&(a-=Mc*Hc(t)*Hc(n)),[a/r,i-Hc(r)*$c(t*t+n*n)]},a}function ad(){return jf(id).scale(131.154).center([0,13.9389])}Gf.invert=$f((function(t){return t})),Zf.invert=function(t,e){return[t,2*Rc(Yc(e))-Nc]},nd.invert=nd;var od=1.340264,sd=-.081106,cd=893e-6,ud=.003796,ld=$c(3)/2;function hd(t,e){var n=Gc(ld*qc(e)),r=n*n,i=r*r*r;return[t*Pc(n)/(ld*(od+3*sd*r+i*(7*cd+9*ud*r))),n*(od+sd*r+i*(cd+ud*r))]}function fd(){return Ff(hd).scale(177.158)}function dd(t,e){var n=Pc(e),r=Pc(t)*n;return[n*qc(t)/r,qc(e)/r]}function pd(){return Ff(dd).scale(144.049).clipAngle(60)}function yd(){var t,e,n,r,i,a,o,s=1,c=0,u=0,l=1,h=1,f=0,d=null,p=1,y=1,g=Ef({point:function(t,e){var n=b([t,e]);this.stream.point(n[0],n[1])}}),m=_h;function v(){return p=s*l,y=s*h,a=o=null,b}function b(n){var r=n[0]*p,i=n[1]*y;if(f){var a=i*t-r*e;r=r*t+i*e,i=a}return[r+c,i+u]}return b.invert=function(n){var r=n[0]-c,i=n[1]-u;if(f){var a=i*t+r*e;r=r*t-i*e,i=a}return[r/p,i/y]},b.stream=function(t){return a&&o===t?a:a=g(m(o=t))},b.postclip=function(t){return arguments.length?(m=t,d=n=r=i=null,v()):m},b.clipExtent=function(t){return arguments.length?(m=null==t?(d=n=r=i=null,_h):Wl(d=+t[0][0],n=+t[0][1],r=+t[1][0],i=+t[1][1]),v()):null==d?null:[[d,n],[r,i]]},b.scale=function(t){return arguments.length?(s=+t,v()):s},b.translate=function(t){return arguments.length?(c=+t[0],u=+t[1],v()):[c,u]},b.angle=function(n){return arguments.length?(e=qc(f=n%360*Lc),t=Pc(f),v()):f*Bc},b.reflectX=function(t){return arguments.length?(l=t?-1:1,v()):l<0},b.reflectY=function(t){return arguments.length?(h=t?-1:1,v()):h<0},b.fitExtent=function(t,e){return Af(b,t,e)},b.fitSize=function(t,e){return Mf(b,t,e)},b.fitWidth=function(t,e){return Nf(b,t,e)},b.fitHeight=function(t,e){return Df(b,t,e)},b}function gd(t,e){var n=e*e,r=n*n;return[t*(.8707-.131979*n+r*(r*(.003971*n-.001529*r)-.013791)),e*(1.007226+n*(.015085+r*(.028874*n-.044475-.005916*r)))]}function md(){return Ff(gd).scale(175.295)}function vd(t,e){return[Pc(e)*qc(t),qc(e)]}function bd(){return Ff(vd).scale(249.5).clipAngle(90.000001)}function _d(t,e){var n=Pc(e),r=1+Pc(t)*n;return[n*qc(t)/r,qc(e)/r]}function xd(){return Ff(_d).scale(250).clipAngle(142)}function wd(t,e){return[zc(Wc((Nc+e)/2)),-t]}function kd(){var t=Kf(wd),e=t.center,n=t.rotate;return t.center=function(t){return arguments.length?e([-t[1],t[0]]):[(t=e())[1],-t[0]]},t.rotate=function(t){return arguments.length?n([t[0],t[1],t.length>2?t[2]+90:90]):[(t=n())[0],t[1],t[2]-90]},n([0,0,90]).scale(159.155)}function Td(t,e){return t.parent===e.parent?1:2}function Ed(t,e){return t+e.x}function Cd(t,e){return Math.max(t,e.y)}function Sd(){var t=Td,e=1,n=1,r=!1;function i(i){var a,o=0;i.eachAfter((function(e){var n=e.children;n?(e.x=function(t){return t.reduce(Ed,0)/t.length}(n),e.y=function(t){return 1+t.reduce(Cd,0)}(n)):(e.x=a?o+=t(e,a):0,e.y=0,a=e)}));var s=function(t){for(var e;e=t.children;)t=e[0];return t}(i),c=function(t){for(var e;e=t.children;)t=e[e.length-1];return t}(i),u=s.x-t(s,c)/2,l=c.x+t(c,s)/2;return i.eachAfter(r?function(t){t.x=(t.x-i.x)*e,t.y=(i.y-t.y)*n}:function(t){t.x=(t.x-u)/(l-u)*e,t.y=(1-(i.y?t.y/i.y:1))*n})}return i.separation=function(e){return arguments.length?(t=e,i):t},i.size=function(t){return arguments.length?(r=!1,e=+t[0],n=+t[1],i):r?null:[e,n]},i.nodeSize=function(t){return arguments.length?(r=!0,e=+t[0],n=+t[1],i):r?[e,n]:null},i}function Ad(t){var e=0,n=t.children,r=n&&n.length;if(r)for(;--r>=0;)e+=n[r].value;else e=1;t.value=e}function Md(t,e){var n,r,i,a,o,s=new Bd(t),c=+t.value&&(s.value=t.value),u=[s];for(null==e&&(e=Nd);n=u.pop();)if(c&&(n.value=+n.data.value),(i=e(n.data))&&(o=i.length))for(n.children=new Array(o),a=o-1;a>=0;--a)u.push(r=n.children[a]=new Bd(i[a])),r.parent=n,r.depth=n.depth+1;return s.eachBefore(Od)}function Nd(t){return t.children}function Dd(t){t.data=t.data.data}function Od(t){var e=0;do{t.height=e}while((t=t.parent)&&t.height<++e)}function Bd(t){this.data=t,this.depth=this.height=0,this.parent=null}hd.invert=function(t,e){for(var n,r=e,i=r*r,a=i*i*i,o=0;o<12&&(a=(i=(r-=n=(r*(od+sd*i+a*(cd+ud*i))-e)/(od+3*sd*i+a*(7*cd+9*ud*i)))*r)*i*i,!(Ic(n)<Ac));++o);return[ld*t*(od+3*sd*i+a*(7*cd+9*ud*i))/Pc(r),Gc(qc(r)/ld)]},dd.invert=$f(Rc),gd.invert=function(t,e){var n,r=e,i=25;do{var a=r*r,o=a*a;r-=n=(r*(1.007226+a*(.015085+o*(.028874*a-.044475-.005916*o)))-e)/(1.007226+a*(.045255+o*(.259866*a-.311325-.005916*11*o)))}while(Ic(n)>Sc&&--i>0);return[t/(.8707+(a=r*r)*(a*(a*a*a*(.003971-.001529*a)-.013791)-.131979)),r]},vd.invert=$f(Gc),_d.invert=$f((function(t){return 2*Rc(t)})),wd.invert=function(t,e){return[-e,2*Rc(Yc(t))-Nc]},Bd.prototype=Md.prototype={constructor:Bd,count:function(){return this.eachAfter(Ad)},each:function(t){var e,n,r,i,a=this,o=[a];do{for(e=o.reverse(),o=[];a=e.pop();)if(t(a),n=a.children)for(r=0,i=n.length;r<i;++r)o.push(n[r])}while(o.length);return this},eachAfter:function(t){for(var e,n,r,i=this,a=[i],o=[];i=a.pop();)if(o.push(i),e=i.children)for(n=0,r=e.length;n<r;++n)a.push(e[n]);for(;i=o.pop();)t(i);return this},eachBefore:function(t){for(var e,n,r=this,i=[r];r=i.pop();)if(t(r),e=r.children)for(n=e.length-1;n>=0;--n)i.push(e[n]);return this},sum:function(t){return this.eachAfter((function(e){for(var n=+t(e.data)||0,r=e.children,i=r&&r.length;--i>=0;)n+=r[i].value;e.value=n}))},sort:function(t){return this.eachBefore((function(e){e.children&&e.children.sort(t)}))},path:function(t){for(var e=this,n=function(t,e){if(t===e)return t;var n=t.ancestors(),r=e.ancestors(),i=null;for(t=n.pop(),e=r.pop();t===e;)i=t,t=n.pop(),e=r.pop();return i}(e,t),r=[e];e!==n;)e=e.parent,r.push(e);for(var i=r.length;t!==n;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,e=[t];t=t.parent;)e.push(t);return e},descendants:function(){var t=[];return this.each((function(e){t.push(e)})),t},leaves:function(){var t=[];return this.eachBefore((function(e){e.children||t.push(e)})),t},links:function(){var t=this,e=[];return t.each((function(n){n!==t&&e.push({source:n.parent,target:n})})),e},copy:function(){return Md(this).eachBefore(Dd)}};var Ld=Array.prototype.slice;function Id(t){for(var e,n,r=0,i=(t=function(t){for(var e,n,r=t.length;r;)n=Math.random()*r--|0,e=t[r],t[r]=t[n],t[n]=e;return t}(Ld.call(t))).length,a=[];r<i;)e=t[r],n&&Pd(n,e)?++r:(n=Yd(a=Rd(a,e)),r=0);return n}function Rd(t,e){var n,r;if(jd(e,t))return[e];for(n=0;n<t.length;++n)if(Fd(e,t[n])&&jd(zd(t[n],e),t))return[t[n],e];for(n=0;n<t.length-1;++n)for(r=n+1;r<t.length;++r)if(Fd(zd(t[n],t[r]),e)&&Fd(zd(t[n],e),t[r])&&Fd(zd(t[r],e),t[n])&&jd(Ud(t[n],t[r],e),t))return[t[n],t[r],e];throw new Error}function Fd(t,e){var n=t.r-e.r,r=e.x-t.x,i=e.y-t.y;return n<0||n*n<r*r+i*i}function Pd(t,e){var n=t.r-e.r+1e-6,r=e.x-t.x,i=e.y-t.y;return n>0&&n*n>r*r+i*i}function jd(t,e){for(var n=0;n<e.length;++n)if(!Pd(t,e[n]))return!1;return!0}function Yd(t){switch(t.length){case 1:return function(t){return{x:t.x,y:t.y,r:t.r}}(t[0]);case 2:return zd(t[0],t[1]);case 3:return Ud(t[0],t[1],t[2])}}function zd(t,e){var n=t.x,r=t.y,i=t.r,a=e.x,o=e.y,s=e.r,c=a-n,u=o-r,l=s-i,h=Math.sqrt(c*c+u*u);return{x:(n+a+c/h*l)/2,y:(r+o+u/h*l)/2,r:(h+i+s)/2}}function Ud(t,e,n){var r=t.x,i=t.y,a=t.r,o=e.x,s=e.y,c=e.r,u=n.x,l=n.y,h=n.r,f=r-o,d=r-u,p=i-s,y=i-l,g=c-a,m=h-a,v=r*r+i*i-a*a,b=v-o*o-s*s+c*c,_=v-u*u-l*l+h*h,x=d*p-f*y,w=(p*_-y*b)/(2*x)-r,k=(y*g-p*m)/x,T=(d*b-f*_)/(2*x)-i,E=(f*m-d*g)/x,C=k*k+E*E-1,S=2*(a+w*k+T*E),A=w*w+T*T-a*a,M=-(C?(S+Math.sqrt(S*S-4*C*A))/(2*C):A/S);return{x:r+w+k*M,y:i+T+E*M,r:M}}function qd(t,e,n){var r,i,a,o,s=t.x-e.x,c=t.y-e.y,u=s*s+c*c;u?(i=e.r+n.r,i*=i,o=t.r+n.r,i>(o*=o)?(r=(u+o-i)/(2*u),a=Math.sqrt(Math.max(0,o/u-r*r)),n.x=t.x-r*s-a*c,n.y=t.y-r*c+a*s):(r=(u+i-o)/(2*u),a=Math.sqrt(Math.max(0,i/u-r*r)),n.x=e.x+r*s-a*c,n.y=e.y+r*c+a*s)):(n.x=e.x+n.r,n.y=e.y)}function Hd(t,e){var n=t.r+e.r-1e-6,r=e.x-t.x,i=e.y-t.y;return n>0&&n*n>r*r+i*i}function $d(t){var e=t._,n=t.next._,r=e.r+n.r,i=(e.x*n.r+n.x*e.r)/r,a=(e.y*n.r+n.y*e.r)/r;return i*i+a*a}function Wd(t){this._=t,this.next=null,this.previous=null}function Vd(t){if(!(i=t.length))return 0;var e,n,r,i,a,o,s,c,u,l,h;if((e=t[0]).x=0,e.y=0,!(i>1))return e.r;if(n=t[1],e.x=-n.r,n.x=e.r,n.y=0,!(i>2))return e.r+n.r;qd(n,e,r=t[2]),e=new Wd(e),n=new Wd(n),r=new Wd(r),e.next=r.previous=n,n.next=e.previous=r,r.next=n.previous=e;t:for(s=3;s<i;++s){qd(e._,n._,r=t[s]),r=new Wd(r),c=n.next,u=e.previous,l=n._.r,h=e._.r;do{if(l<=h){if(Hd(c._,r._)){n=c,e.next=n,n.previous=e,--s;continue t}l+=c._.r,c=c.next}else{if(Hd(u._,r._)){(e=u).next=n,n.previous=e,--s;continue t}h+=u._.r,u=u.previous}}while(c!==u.next);for(r.previous=e,r.next=n,e.next=n.previous=n=r,a=$d(e);(r=r.next)!==n;)(o=$d(r))<a&&(e=r,a=o);n=e.next}for(e=[n._],r=n;(r=r.next)!==n;)e.push(r._);for(r=Id(e),s=0;s<i;++s)(e=t[s]).x-=r.x,e.y-=r.y;return r.r}function Gd(t){return Vd(t),t}function Xd(t){return null==t?null:Zd(t)}function Zd(t){if("function"!=typeof t)throw new Error;return t}function Qd(){return 0}function Kd(t){return function(){return t}}function Jd(t){return Math.sqrt(t.value)}function tp(){var t=null,e=1,n=1,r=Qd;function i(i){return i.x=e/2,i.y=n/2,t?i.eachBefore(ep(t)).eachAfter(np(r,.5)).eachBefore(rp(1)):i.eachBefore(ep(Jd)).eachAfter(np(Qd,1)).eachAfter(np(r,i.r/Math.min(e,n))).eachBefore(rp(Math.min(e,n)/(2*i.r))),i}return i.radius=function(e){return arguments.length?(t=Xd(e),i):t},i.size=function(t){return arguments.length?(e=+t[0],n=+t[1],i):[e,n]},i.padding=function(t){return arguments.length?(r="function"==typeof t?t:Kd(+t),i):r},i}function ep(t){return function(e){e.children||(e.r=Math.max(0,+t(e)||0))}}function np(t,e){return function(n){if(r=n.children){var r,i,a,o=r.length,s=t(n)*e||0;if(s)for(i=0;i<o;++i)r[i].r+=s;if(a=Vd(r),s)for(i=0;i<o;++i)r[i].r-=s;n.r=a+s}}}function rp(t){return function(e){var n=e.parent;e.r*=t,n&&(e.x=n.x+t*e.x,e.y=n.y+t*e.y)}}function ip(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)}function ap(t,e,n,r,i){for(var a,o=t.children,s=-1,c=o.length,u=t.value&&(r-e)/t.value;++s<c;)(a=o[s]).y0=n,a.y1=i,a.x0=e,a.x1=e+=a.value*u}function op(){var t=1,e=1,n=0,r=!1;function i(i){var a=i.height+1;return i.x0=i.y0=n,i.x1=t,i.y1=e/a,i.eachBefore(function(t,e){return function(r){r.children&&ap(r,r.x0,t*(r.depth+1)/e,r.x1,t*(r.depth+2)/e);var i=r.x0,a=r.y0,o=r.x1-n,s=r.y1-n;o<i&&(i=o=(i+o)/2),s<a&&(a=s=(a+s)/2),r.x0=i,r.y0=a,r.x1=o,r.y1=s}}(e,a)),r&&i.eachBefore(ip),i}return i.round=function(t){return arguments.length?(r=!!t,i):r},i.size=function(n){return arguments.length?(t=+n[0],e=+n[1],i):[t,e]},i.padding=function(t){return arguments.length?(n=+t,i):n},i}var sp={depth:-1},cp={};function up(t){return t.id}function lp(t){return t.parentId}function hp(){var t=up,e=lp;function n(n){var r,i,a,o,s,c,u,l=n.length,h=new Array(l),f={};for(i=0;i<l;++i)r=n[i],s=h[i]=new Bd(r),null!=(c=t(r,i,n))&&(c+="")&&(f[u="$"+(s.id=c)]=u in f?cp:s);for(i=0;i<l;++i)if(s=h[i],null!=(c=e(n[i],i,n))&&(c+="")){if(!(o=f["$"+c]))throw new Error("missing: "+c);if(o===cp)throw new Error("ambiguous: "+c);o.children?o.children.push(s):o.children=[s],s.parent=o}else{if(a)throw new Error("multiple roots");a=s}if(!a)throw new Error("no root");if(a.parent=sp,a.eachBefore((function(t){t.depth=t.parent.depth+1,--l})).eachBefore(Od),a.parent=null,l>0)throw new Error("cycle");return a}return n.id=function(e){return arguments.length?(t=Zd(e),n):t},n.parentId=function(t){return arguments.length?(e=Zd(t),n):e},n}function fp(t,e){return t.parent===e.parent?1:2}function dp(t){var e=t.children;return e?e[0]:t.t}function pp(t){var e=t.children;return e?e[e.length-1]:t.t}function yp(t,e,n){var r=n/(e.i-t.i);e.c-=r,e.s+=n,t.c+=r,e.z+=n,e.m+=n}function gp(t,e,n){return t.a.parent===e.parent?t.a:n}function mp(t,e){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=e}function vp(){var t=fp,e=1,n=1,r=null;function i(i){var c=function(t){for(var e,n,r,i,a,o=new mp(t,0),s=[o];e=s.pop();)if(r=e._.children)for(e.children=new Array(a=r.length),i=a-1;i>=0;--i)s.push(n=e.children[i]=new mp(r[i],i)),n.parent=e;return(o.parent=new mp(null,0)).children=[o],o}(i);if(c.eachAfter(a),c.parent.m=-c.z,c.eachBefore(o),r)i.eachBefore(s);else{var u=i,l=i,h=i;i.eachBefore((function(t){t.x<u.x&&(u=t),t.x>l.x&&(l=t),t.depth>h.depth&&(h=t)}));var f=u===l?1:t(u,l)/2,d=f-u.x,p=e/(l.x+f+d),y=n/(h.depth||1);i.eachBefore((function(t){t.x=(t.x+d)*p,t.y=t.depth*y}))}return i}function a(e){var n=e.children,r=e.parent.children,i=e.i?r[e.i-1]:null;if(n){!function(t){for(var e,n=0,r=0,i=t.children,a=i.length;--a>=0;)(e=i[a]).z+=n,e.m+=n,n+=e.s+(r+=e.c)}(e);var a=(n[0].z+n[n.length-1].z)/2;i?(e.z=i.z+t(e._,i._),e.m=e.z-a):e.z=a}else i&&(e.z=i.z+t(e._,i._));e.parent.A=function(e,n,r){if(n){for(var i,a=e,o=e,s=n,c=a.parent.children[0],u=a.m,l=o.m,h=s.m,f=c.m;s=pp(s),a=dp(a),s&&a;)c=dp(c),(o=pp(o)).a=e,(i=s.z+h-a.z-u+t(s._,a._))>0&&(yp(gp(s,e,r),e,i),u+=i,l+=i),h+=s.m,u+=a.m,f+=c.m,l+=o.m;s&&!pp(o)&&(o.t=s,o.m+=h-l),a&&!dp(c)&&(c.t=a,c.m+=u-f,r=e)}return r}(e,i,e.parent.A||r[0])}function o(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function s(t){t.x*=e,t.y=t.depth*n}return i.separation=function(e){return arguments.length?(t=e,i):t},i.size=function(t){return arguments.length?(r=!1,e=+t[0],n=+t[1],i):r?null:[e,n]},i.nodeSize=function(t){return arguments.length?(r=!0,e=+t[0],n=+t[1],i):r?[e,n]:null},i}function bp(t,e,n,r,i){for(var a,o=t.children,s=-1,c=o.length,u=t.value&&(i-n)/t.value;++s<c;)(a=o[s]).x0=e,a.x1=r,a.y0=n,a.y1=n+=a.value*u}mp.prototype=Object.create(Bd.prototype);var _p=(1+Math.sqrt(5))/2;function xp(t,e,n,r,i,a){for(var o,s,c,u,l,h,f,d,p,y,g,m=[],v=e.children,b=0,_=0,x=v.length,w=e.value;b<x;){c=i-n,u=a-r;do{l=v[_++].value}while(!l&&_<x);for(h=f=l,g=l*l*(y=Math.max(u/c,c/u)/(w*t)),p=Math.max(f/g,g/h);_<x;++_){if(l+=s=v[_].value,s<h&&(h=s),s>f&&(f=s),g=l*l*y,(d=Math.max(f/g,g/h))>p){l-=s;break}p=d}m.push(o={value:l,dice:c<u,children:v.slice(b,_)}),o.dice?ap(o,n,r,i,w?r+=u*l/w:a):bp(o,n,r,w?n+=c*l/w:i,a),w-=l,b=_}return m}const wp=function t(e){function n(t,n,r,i,a){xp(e,t,n,r,i,a)}return n.ratio=function(e){return t((e=+e)>1?e:1)},n}(_p);function kp(){var t=wp,e=!1,n=1,r=1,i=[0],a=Qd,o=Qd,s=Qd,c=Qd,u=Qd;function l(t){return t.x0=t.y0=0,t.x1=n,t.y1=r,t.eachBefore(h),i=[0],e&&t.eachBefore(ip),t}function h(e){var n=i[e.depth],r=e.x0+n,l=e.y0+n,h=e.x1-n,f=e.y1-n;h<r&&(r=h=(r+h)/2),f<l&&(l=f=(l+f)/2),e.x0=r,e.y0=l,e.x1=h,e.y1=f,e.children&&(n=i[e.depth+1]=a(e)/2,r+=u(e)-n,l+=o(e)-n,(h-=s(e)-n)<r&&(r=h=(r+h)/2),(f-=c(e)-n)<l&&(l=f=(l+f)/2),t(e,r,l,h,f))}return l.round=function(t){return arguments.length?(e=!!t,l):e},l.size=function(t){return arguments.length?(n=+t[0],r=+t[1],l):[n,r]},l.tile=function(e){return arguments.length?(t=Zd(e),l):t},l.padding=function(t){return arguments.length?l.paddingInner(t).paddingOuter(t):l.paddingInner()},l.paddingInner=function(t){return arguments.length?(a="function"==typeof t?t:Kd(+t),l):a},l.paddingOuter=function(t){return arguments.length?l.paddingTop(t).paddingRight(t).paddingBottom(t).paddingLeft(t):l.paddingTop()},l.paddingTop=function(t){return arguments.length?(o="function"==typeof t?t:Kd(+t),l):o},l.paddingRight=function(t){return arguments.length?(s="function"==typeof t?t:Kd(+t),l):s},l.paddingBottom=function(t){return arguments.length?(c="function"==typeof t?t:Kd(+t),l):c},l.paddingLeft=function(t){return arguments.length?(u="function"==typeof t?t:Kd(+t),l):u},l}function Tp(t,e,n,r,i){var a,o,s=t.children,c=s.length,u=new Array(c+1);for(u[0]=o=a=0;a<c;++a)u[a+1]=o+=s[a].value;!function t(e,n,r,i,a,o,c){if(e>=n-1){var l=s[e];return l.x0=i,l.y0=a,l.x1=o,void(l.y1=c)}for(var h=u[e],f=r/2+h,d=e+1,p=n-1;d<p;){var y=d+p>>>1;u[y]<f?d=y+1:p=y}f-u[d-1]<u[d]-f&&e+1<d&&--d;var g=u[d]-h,m=r-g;if(o-i>c-a){var v=(i*m+o*g)/r;t(e,d,g,i,a,v,c),t(d,n,m,v,a,o,c)}else{var b=(a*m+c*g)/r;t(e,d,g,i,a,o,b),t(d,n,m,i,b,o,c)}}(0,c,t.value,e,n,r,i)}function Ep(t,e,n,r,i){(1&t.depth?bp:ap)(t,e,n,r,i)}const Cp=function t(e){function n(t,n,r,i,a){if((o=t._squarify)&&o.ratio===e)for(var o,s,c,u,l,h=-1,f=o.length,d=t.value;++h<f;){for(c=(s=o[h]).children,u=s.value=0,l=c.length;u<l;++u)s.value+=c[u].value;s.dice?ap(s,n,r,i,r+=(a-r)*s.value/d):bp(s,n,r,n+=(i-n)*s.value/d,a),d-=s.value}else t._squarify=o=xp(e,t,n,r,i,a),o.ratio=e}return n.ratio=function(e){return t((e=+e)>1?e:1)},n}(_p);function Sp(t){var e=t.length;return function(n){return t[Math.max(0,Math.min(e-1,Math.floor(n*e)))]}}function Ap(t,e){var n=dn(+t,+e);return function(t){var e=n(t);return e-360*Math.floor(e/360)}}function Mp(t,e){return t=+t,e=+e,function(n){return Math.round(t*(1-n)+e*n)}}var Np=Math.SQRT2;function Dp(t){return((t=Math.exp(t))+1/t)/2}function Op(t,e){var n,r,i=t[0],a=t[1],o=t[2],s=e[0],c=e[1],u=e[2],l=s-i,h=c-a,f=l*l+h*h;if(f<1e-12)r=Math.log(u/o)/Np,n=function(t){return[i+t*l,a+t*h,o*Math.exp(Np*t*r)]};else{var d=Math.sqrt(f),p=(u*u-o*o+4*f)/(2*o*2*d),y=(u*u-o*o-4*f)/(2*u*2*d),g=Math.log(Math.sqrt(p*p+1)-p),m=Math.log(Math.sqrt(y*y+1)-y);r=(m-g)/Np,n=function(t){var e,n=t*r,s=Dp(g),c=o/(2*d)*(s*(e=Np*n+g,((e=Math.exp(2*e))-1)/(e+1))-function(t){return((t=Math.exp(t))-1/t)/2}(g));return[i+c*l,a+c*h,o*s/Dp(Np*n+g)]}}return n.duration=1e3*r,n}function Bp(t){return function(e,n){var r=t((e=an(e)).h,(n=an(n)).h),i=pn(e.s,n.s),a=pn(e.l,n.l),o=pn(e.opacity,n.opacity);return function(t){return e.h=r(t),e.s=i(t),e.l=a(t),e.opacity=o(t),e+""}}}const Lp=Bp(dn);var Ip=Bp(pn);function Rp(t,e){var n=pn((t=Ta(t)).l,(e=Ta(e)).l),r=pn(t.a,e.a),i=pn(t.b,e.b),a=pn(t.opacity,e.opacity);return function(e){return t.l=n(e),t.a=r(e),t.b=i(e),t.opacity=a(e),t+""}}function Fp(t){return function(e,n){var r=t((e=Oa(e)).h,(n=Oa(n)).h),i=pn(e.c,n.c),a=pn(e.l,n.l),o=pn(e.opacity,n.opacity);return function(t){return e.h=r(t),e.c=i(t),e.l=a(t),e.opacity=o(t),e+""}}}const Pp=Fp(dn);var jp=Fp(pn);function Yp(t){return function e(n){function r(e,r){var i=t((e=Ha(e)).h,(r=Ha(r)).h),a=pn(e.s,r.s),o=pn(e.l,r.l),s=pn(e.opacity,r.opacity);return function(t){return e.h=i(t),e.s=a(t),e.l=o(Math.pow(t,n)),e.opacity=s(t),e+""}}return n=+n,r.gamma=e,r}(1)}const zp=Yp(dn);var Up=Yp(pn);function qp(t,e){for(var n=0,r=e.length-1,i=e[0],a=new Array(r<0?0:r);n<r;)a[n]=t(i,i=e[++n]);return function(t){var e=Math.max(0,Math.min(r-1,Math.floor(t*=r)));return a[e](t-e)}}function Hp(t,e){for(var n=new Array(e),r=0;r<e;++r)n[r]=t(r/(e-1));return n}function $p(t){for(var e,n=-1,r=t.length,i=t[r-1],a=0;++n<r;)e=i,i=t[n],a+=e[1]*i[0]-e[0]*i[1];return a/2}function Wp(t){for(var e,n,r=-1,i=t.length,a=0,o=0,s=t[i-1],c=0;++r<i;)e=s,s=t[r],c+=n=e[0]*s[1]-s[0]*e[1],a+=(e[0]+s[0])*n,o+=(e[1]+s[1])*n;return[a/(c*=3),o/c]}function Vp(t,e,n){return(e[0]-t[0])*(n[1]-t[1])-(e[1]-t[1])*(n[0]-t[0])}function Gp(t,e){return t[0]-e[0]||t[1]-e[1]}function Xp(t){for(var e=t.length,n=[0,1],r=2,i=2;i<e;++i){for(;r>1&&Vp(t[n[r-2]],t[n[r-1]],t[i])<=0;)--r;n[r++]=i}return n.slice(0,r)}function Zp(t){if((n=t.length)<3)return null;var e,n,r=new Array(n),i=new Array(n);for(e=0;e<n;++e)r[e]=[+t[e][0],+t[e][1],e];for(r.sort(Gp),e=0;e<n;++e)i[e]=[r[e][0],-r[e][1]];var a=Xp(r),o=Xp(i),s=o[0]===a[0],c=o[o.length-1]===a[a.length-1],u=[];for(e=a.length-1;e>=0;--e)u.push(t[r[a[e]][2]]);for(e=+s;e<o.length-c;++e)u.push(t[r[o[e]][2]]);return u}function Qp(t,e){for(var n,r,i=t.length,a=t[i-1],o=e[0],s=e[1],c=a[0],u=a[1],l=!1,h=0;h<i;++h)n=(a=t[h])[0],(r=a[1])>s!=u>s&&o<(c-n)*(s-r)/(u-r)+n&&(l=!l),c=n,u=r;return l}function Kp(t){for(var e,n,r=-1,i=t.length,a=t[i-1],o=a[0],s=a[1],c=0;++r<i;)e=o,n=s,e-=o=(a=t[r])[0],n-=s=a[1],c+=Math.sqrt(e*e+n*n);return c}function Jp(){return Math.random()}const ty=function t(e){function n(t,n){return t=null==t?0:+t,n=null==n?1:+n,1===arguments.length?(n=t,t=0):n-=t,function(){return e()*n+t}}return n.source=t,n}(Jp),ey=function t(e){function n(t,n){var r,i;return t=null==t?0:+t,n=null==n?1:+n,function(){var a;if(null!=r)a=r,r=null;else do{r=2*e()-1,a=2*e()-1,i=r*r+a*a}while(!i||i>1);return t+n*a*Math.sqrt(-2*Math.log(i)/i)}}return n.source=t,n}(Jp),ny=function t(e){function n(){var t=ey.source(e).apply(this,arguments);return function(){return Math.exp(t())}}return n.source=t,n}(Jp),ry=function t(e){function n(t){return function(){for(var n=0,r=0;r<t;++r)n+=e();return n}}return n.source=t,n}(Jp),iy=function t(e){function n(t){var n=ry.source(e)(t);return function(){return n()/t}}return n.source=t,n}(Jp),ay=function t(e){function n(t){return function(){return-Math.log(1-e())/t}}return n.source=t,n}(Jp);function oy(t,e){switch(arguments.length){case 0:break;case 1:this.range(t);break;default:this.range(e).domain(t)}return this}function sy(t,e){switch(arguments.length){case 0:break;case 1:this.interpolator(t);break;default:this.interpolator(e).domain(t)}return this}var cy=Array.prototype,uy=cy.map,ly=cy.slice,hy={name:"implicit"};function fy(){var t=na(),e=[],n=[],r=hy;function i(i){var a=i+"",o=t.get(a);if(!o){if(r!==hy)return r;t.set(a,o=e.push(i))}return n[(o-1)%n.length]}return i.domain=function(n){if(!arguments.length)return e.slice();e=[],t=na();for(var r,a,o=-1,s=n.length;++o<s;)t.has(a=(r=n[o])+"")||t.set(a,e.push(r));return i},i.range=function(t){return arguments.length?(n=ly.call(t),i):n.slice()},i.unknown=function(t){return arguments.length?(r=t,i):r},i.copy=function(){return fy(e,n).unknown(r)},oy.apply(i,arguments),i}function dy(){var t,e,n=fy().unknown(void 0),r=n.domain,i=n.range,a=[0,1],o=!1,s=0,c=0,u=.5;function l(){var n=r().length,l=a[1]<a[0],h=a[l-0],f=a[1-l];t=(f-h)/Math.max(1,n-s+2*c),o&&(t=Math.floor(t)),h+=(f-h-t*(n-s))*u,e=t*(1-s),o&&(h=Math.round(h),e=Math.round(e));var d=k(n).map((function(e){return h+t*e}));return i(l?d.reverse():d)}return delete n.unknown,n.domain=function(t){return arguments.length?(r(t),l()):r()},n.range=function(t){return arguments.length?(a=[+t[0],+t[1]],l()):a.slice()},n.rangeRound=function(t){return a=[+t[0],+t[1]],o=!0,l()},n.bandwidth=function(){return e},n.step=function(){return t},n.round=function(t){return arguments.length?(o=!!t,l()):o},n.padding=function(t){return arguments.length?(s=Math.min(1,c=+t),l()):s},n.paddingInner=function(t){return arguments.length?(s=Math.min(1,t),l()):s},n.paddingOuter=function(t){return arguments.length?(c=+t,l()):c},n.align=function(t){return arguments.length?(u=Math.max(0,Math.min(1,t)),l()):u},n.copy=function(){return dy(r(),a).round(o).paddingInner(s).paddingOuter(c).align(u)},oy.apply(l(),arguments)}function py(t){var e=t.copy;return t.padding=t.paddingOuter,delete t.paddingInner,delete t.paddingOuter,t.copy=function(){return py(e())},t}function yy(){return py(dy.apply(null,arguments).paddingInner(1))}function gy(t){return+t}var my=[0,1];function vy(t){return t}function by(t,e){return(e-=t=+t)?function(n){return(n-t)/e}:(n=isNaN(e)?NaN:.5,function(){return n});var n}function _y(t){var e,n=t[0],r=t[t.length-1];return n>r&&(e=n,n=r,r=e),function(t){return Math.max(n,Math.min(r,t))}}function xy(t,e,n){var r=t[0],i=t[1],a=e[0],o=e[1];return i<r?(r=by(i,r),a=n(o,a)):(r=by(r,i),a=n(a,o)),function(t){return a(r(t))}}function wy(t,e,n){var r=Math.min(t.length,e.length)-1,i=new Array(r),a=new Array(r),o=-1;for(t[r]<t[0]&&(t=t.slice().reverse(),e=e.slice().reverse());++o<r;)i[o]=by(t[o],t[o+1]),a[o]=n(e[o],e[o+1]);return function(e){var n=u(t,e,1,r)-1;return a[n](i[n](e))}}function ky(t,e){return e.domain(t.domain()).range(t.range()).interpolate(t.interpolate()).clamp(t.clamp()).unknown(t.unknown())}function Ty(){var t,e,n,r,i,a,o=my,s=my,c=Mn,u=vy;function l(){return r=Math.min(o.length,s.length)>2?wy:xy,i=a=null,h}function h(e){return isNaN(e=+e)?n:(i||(i=r(o.map(t),s,c)))(t(u(e)))}return h.invert=function(n){return u(e((a||(a=r(s,o.map(t),Tn)))(n)))},h.domain=function(t){return arguments.length?(o=uy.call(t,gy),u===vy||(u=_y(o)),l()):o.slice()},h.range=function(t){return arguments.length?(s=ly.call(t),l()):s.slice()},h.rangeRound=function(t){return s=ly.call(t),c=Mp,l()},h.clamp=function(t){return arguments.length?(u=t?_y(o):vy,h):u!==vy},h.interpolate=function(t){return arguments.length?(c=t,l()):c},h.unknown=function(t){return arguments.length?(n=t,h):n},function(n,r){return t=n,e=r,l()}}function Ey(t,e){return Ty()(t,e)}function Cy(t,e,n,r){var i,a=M(t,e,n);switch((r=cc(null==r?",f":r)).type){case"s":var o=Math.max(Math.abs(t),Math.abs(e));return null!=r.precision||isNaN(i=xc(a,o))||(r.precision=i),yc(r,o);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(i=wc(a,Math.max(Math.abs(t),Math.abs(e))))||(r.precision=i-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(i=_c(a))||(r.precision=i-2*("%"===r.type))}return pc(r)}function Sy(t){var e=t.domain;return t.ticks=function(t){var n=e();return S(n[0],n[n.length-1],null==t?10:t)},t.tickFormat=function(t,n){var r=e();return Cy(r[0],r[r.length-1],null==t?10:t,n)},t.nice=function(n){null==n&&(n=10);var r,i=e(),a=0,o=i.length-1,s=i[a],c=i[o];return c<s&&(r=s,s=c,c=r,r=a,a=o,o=r),(r=A(s,c,n))>0?r=A(s=Math.floor(s/r)*r,c=Math.ceil(c/r)*r,n):r<0&&(r=A(s=Math.ceil(s*r)/r,c=Math.floor(c*r)/r,n)),r>0?(i[a]=Math.floor(s/r)*r,i[o]=Math.ceil(c/r)*r,e(i)):r<0&&(i[a]=Math.ceil(s*r)/r,i[o]=Math.floor(c*r)/r,e(i)),t},t}function Ay(){var t=Ey(vy,vy);return t.copy=function(){return ky(t,Ay())},oy.apply(t,arguments),Sy(t)}function My(t){var e;function n(t){return isNaN(t=+t)?e:t}return n.invert=n,n.domain=n.range=function(e){return arguments.length?(t=uy.call(e,gy),n):t.slice()},n.unknown=function(t){return arguments.length?(e=t,n):e},n.copy=function(){return My(t).unknown(e)},t=arguments.length?uy.call(t,gy):[0,1],Sy(n)}function Ny(t,e){var n,r=0,i=(t=t.slice()).length-1,a=t[r],o=t[i];return o<a&&(n=r,r=i,i=n,n=a,a=o,o=n),t[r]=e.floor(a),t[i]=e.ceil(o),t}function Dy(t){return Math.log(t)}function Oy(t){return Math.exp(t)}function By(t){return-Math.log(-t)}function Ly(t){return-Math.exp(-t)}function Iy(t){return isFinite(t)?+("1e"+t):t<0?0:t}function Ry(t){return function(e){return-t(-e)}}function Fy(t){var e,n,r=t(Dy,Oy),i=r.domain,a=10;function o(){return e=function(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Math.log2||(t=Math.log(t),function(e){return Math.log(e)/t})}(a),n=function(t){return 10===t?Iy:t===Math.E?Math.exp:function(e){return Math.pow(t,e)}}(a),i()[0]<0?(e=Ry(e),n=Ry(n),t(By,Ly)):t(Dy,Oy),r}return r.base=function(t){return arguments.length?(a=+t,o()):a},r.domain=function(t){return arguments.length?(i(t),o()):i()},r.ticks=function(t){var r,o=i(),s=o[0],c=o[o.length-1];(r=c<s)&&(f=s,s=c,c=f);var u,l,h,f=e(s),d=e(c),p=null==t?10:+t,y=[];if(!(a%1)&&d-f<p){if(f=Math.round(f)-1,d=Math.round(d)+1,s>0){for(;f<d;++f)for(l=1,u=n(f);l<a;++l)if(!((h=u*l)<s)){if(h>c)break;y.push(h)}}else for(;f<d;++f)for(l=a-1,u=n(f);l>=1;--l)if(!((h=u*l)<s)){if(h>c)break;y.push(h)}}else y=S(f,d,Math.min(d-f,p)).map(n);return r?y.reverse():y},r.tickFormat=function(t,i){if(null==i&&(i=10===a?".0e":","),"function"!=typeof i&&(i=pc(i)),t===1/0)return i;null==t&&(t=10);var o=Math.max(1,a*t/r.ticks().length);return function(t){var r=t/n(Math.round(e(t)));return r*a<a-.5&&(r*=a),r<=o?i(t):""}},r.nice=function(){return i(Ny(i(),{floor:function(t){return n(Math.floor(e(t)))},ceil:function(t){return n(Math.ceil(e(t)))}}))},r}function Py(){var t=Fy(Ty()).domain([1,10]);return t.copy=function(){return ky(t,Py()).base(t.base())},oy.apply(t,arguments),t}function jy(t){return function(e){return Math.sign(e)*Math.log1p(Math.abs(e/t))}}function Yy(t){return function(e){return Math.sign(e)*Math.expm1(Math.abs(e))*t}}function zy(t){var e=1,n=t(jy(e),Yy(e));return n.constant=function(n){return arguments.length?t(jy(e=+n),Yy(e)):e},Sy(n)}function Uy(){var t=zy(Ty());return t.copy=function(){return ky(t,Uy()).constant(t.constant())},oy.apply(t,arguments)}function qy(t){return function(e){return e<0?-Math.pow(-e,t):Math.pow(e,t)}}function Hy(t){return t<0?-Math.sqrt(-t):Math.sqrt(t)}function $y(t){return t<0?-t*t:t*t}function Wy(t){var e=t(vy,vy),n=1;function r(){return 1===n?t(vy,vy):.5===n?t(Hy,$y):t(qy(n),qy(1/n))}return e.exponent=function(t){return arguments.length?(n=+t,r()):n},Sy(e)}function Vy(){var t=Wy(Ty());return t.copy=function(){return ky(t,Vy()).exponent(t.exponent())},oy.apply(t,arguments),t}function Gy(){return Vy.apply(null,arguments).exponent(.5)}function Xy(){var t,e=[],n=[],r=[];function a(){var t=0,i=Math.max(1,n.length);for(r=new Array(i-1);++t<i;)r[t-1]=O(e,t/i);return o}function o(e){return isNaN(e=+e)?t:n[u(r,e)]}return o.invertExtent=function(t){var i=n.indexOf(t);return i<0?[NaN,NaN]:[i>0?r[i-1]:e[0],i<r.length?r[i]:e[e.length-1]]},o.domain=function(t){if(!arguments.length)return e.slice();e=[];for(var n,r=0,o=t.length;r<o;++r)null==(n=t[r])||isNaN(n=+n)||e.push(n);return e.sort(i),a()},o.range=function(t){return arguments.length?(n=ly.call(t),a()):n.slice()},o.unknown=function(e){return arguments.length?(t=e,o):t},o.quantiles=function(){return r.slice()},o.copy=function(){return Xy().domain(e).range(n).unknown(t)},oy.apply(o,arguments)}function Zy(){var t,e=0,n=1,r=1,i=[.5],a=[0,1];function o(e){return e<=e?a[u(i,e,0,r)]:t}function s(){var t=-1;for(i=new Array(r);++t<r;)i[t]=((t+1)*n-(t-r)*e)/(r+1);return o}return o.domain=function(t){return arguments.length?(e=+t[0],n=+t[1],s()):[e,n]},o.range=function(t){return arguments.length?(r=(a=ly.call(t)).length-1,s()):a.slice()},o.invertExtent=function(t){var o=a.indexOf(t);return o<0?[NaN,NaN]:o<1?[e,i[0]]:o>=r?[i[r-1],n]:[i[o-1],i[o]]},o.unknown=function(e){return arguments.length?(t=e,o):o},o.thresholds=function(){return i.slice()},o.copy=function(){return Zy().domain([e,n]).range(a).unknown(t)},oy.apply(Sy(o),arguments)}function Qy(){var t,e=[.5],n=[0,1],r=1;function i(i){return i<=i?n[u(e,i,0,r)]:t}return i.domain=function(t){return arguments.length?(e=ly.call(t),r=Math.min(e.length,n.length-1),i):e.slice()},i.range=function(t){return arguments.length?(n=ly.call(t),r=Math.min(e.length,n.length-1),i):n.slice()},i.invertExtent=function(t){var r=n.indexOf(t);return[e[r-1],e[r]]},i.unknown=function(e){return arguments.length?(t=e,i):t},i.copy=function(){return Qy().domain(e).range(n).unknown(t)},oy.apply(i,arguments)}var Ky=new Date,Jy=new Date;function tg(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=function(e){return t(e=new Date(+e)),e},i.ceil=function(n){return t(n=new Date(n-1)),e(n,1),t(n),n},i.round=function(t){var e=i(t),n=i.ceil(t);return t-e<n-t?e:n},i.offset=function(t,n){return e(t=new Date(+t),null==n?1:Math.floor(n)),t},i.range=function(n,r,a){var o,s=[];if(n=i.ceil(n),a=null==a?1:Math.floor(a),!(n<r&&a>0))return s;do{s.push(o=new Date(+n)),e(n,a),t(n)}while(o<n&&n<r);return s},i.filter=function(n){return tg((function(e){if(e>=e)for(;t(e),!n(e);)e.setTime(e-1)}),(function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););}))},n&&(i.count=function(e,r){return Ky.setTime(+e),Jy.setTime(+r),t(Ky),t(Jy),Math.floor(n(Ky,Jy))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(e){return r(e)%t==0}:function(e){return i.count(0,e)%t==0}):i:null}),i}var eg=tg((function(t){t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,e){t.setFullYear(t.getFullYear()+e)}),(function(t,e){return e.getFullYear()-t.getFullYear()}),(function(t){return t.getFullYear()}));eg.every=function(t){return isFinite(t=Math.floor(t))&&t>0?tg((function(e){e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,n){e.setFullYear(e.getFullYear()+n*t)})):null};const ng=eg;var rg=eg.range,ig=tg((function(t){t.setDate(1),t.setHours(0,0,0,0)}),(function(t,e){t.setMonth(t.getMonth()+e)}),(function(t,e){return e.getMonth()-t.getMonth()+12*(e.getFullYear()-t.getFullYear())}),(function(t){return t.getMonth()}));const ag=ig;var og=ig.range,sg=1e3,cg=6e4,ug=36e5,lg=864e5,hg=6048e5;function fg(t){return tg((function(e){e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+7*e)}),(function(t,e){return(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*cg)/hg}))}var dg=fg(0),pg=fg(1),yg=fg(2),gg=fg(3),mg=fg(4),vg=fg(5),bg=fg(6),_g=dg.range,xg=pg.range,wg=yg.range,kg=gg.range,Tg=mg.range,Eg=vg.range,Cg=bg.range,Sg=tg((function(t){t.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+e)}),(function(t,e){return(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*cg)/lg}),(function(t){return t.getDate()-1}));const Ag=Sg;var Mg=Sg.range,Ng=tg((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*sg-t.getMinutes()*cg)}),(function(t,e){t.setTime(+t+e*ug)}),(function(t,e){return(e-t)/ug}),(function(t){return t.getHours()}));const Dg=Ng;var Og=Ng.range,Bg=tg((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*sg)}),(function(t,e){t.setTime(+t+e*cg)}),(function(t,e){return(e-t)/cg}),(function(t){return t.getMinutes()}));const Lg=Bg;var Ig=Bg.range,Rg=tg((function(t){t.setTime(t-t.getMilliseconds())}),(function(t,e){t.setTime(+t+e*sg)}),(function(t,e){return(e-t)/sg}),(function(t){return t.getUTCSeconds()}));const Fg=Rg;var Pg=Rg.range,jg=tg((function(){}),(function(t,e){t.setTime(+t+e)}),(function(t,e){return e-t}));jg.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?tg((function(e){e.setTime(Math.floor(e/t)*t)}),(function(e,n){e.setTime(+e+n*t)}),(function(e,n){return(n-e)/t})):jg:null};const Yg=jg;var zg=jg.range;function Ug(t){return tg((function(e){e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+7*e)}),(function(t,e){return(e-t)/hg}))}var qg=Ug(0),Hg=Ug(1),$g=Ug(2),Wg=Ug(3),Vg=Ug(4),Gg=Ug(5),Xg=Ug(6),Zg=qg.range,Qg=Hg.range,Kg=$g.range,Jg=Wg.range,tm=Vg.range,em=Gg.range,nm=Xg.range,rm=tg((function(t){t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+e)}),(function(t,e){return(e-t)/lg}),(function(t){return t.getUTCDate()-1}));const im=rm;var am=rm.range,om=tg((function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCFullYear(t.getUTCFullYear()+e)}),(function(t,e){return e.getUTCFullYear()-t.getUTCFullYear()}),(function(t){return t.getUTCFullYear()}));om.every=function(t){return isFinite(t=Math.floor(t))&&t>0?tg((function(e){e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,n){e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null};const sm=om;var cm=om.range;function um(t){if(0<=t.y&&t.y<100){var e=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return e.setFullYear(t.y),e}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function lm(t){if(0<=t.y&&t.y<100){var e=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return e.setUTCFullYear(t.y),e}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function hm(t,e,n){return{y:t,m:e,d:n,H:0,M:0,S:0,L:0}}function fm(t){var e=t.dateTime,n=t.date,r=t.time,i=t.periods,a=t.days,o=t.shortDays,s=t.months,c=t.shortMonths,u=Tm(i),l=Em(i),h=Tm(a),f=Em(a),d=Tm(o),p=Em(o),y=Tm(s),g=Em(s),m=Tm(c),v=Em(c),b={a:function(t){return o[t.getDay()]},A:function(t){return a[t.getDay()]},b:function(t){return c[t.getMonth()]},B:function(t){return s[t.getMonth()]},c:null,d:Wm,e:Wm,f:Qm,g:cv,G:lv,H:Vm,I:Gm,j:Xm,L:Zm,m:Km,M:Jm,p:function(t){return i[+(t.getHours()>=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:Bv,s:Lv,S:tv,u:ev,U:nv,V:iv,w:av,W:ov,x:null,X:null,y:sv,Y:uv,Z:hv,"%":Ov},_={a:function(t){return o[t.getUTCDay()]},A:function(t){return a[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:fv,e:fv,f:mv,g:Av,G:Nv,H:dv,I:pv,j:yv,L:gv,m:vv,M:bv,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:Bv,s:Lv,S:_v,u:xv,U:wv,V:Tv,w:Ev,W:Cv,x:null,X:null,y:Sv,Y:Mv,Z:Dv,"%":Ov},x={a:function(t,e,n){var r=d.exec(e.slice(n));return r?(t.w=p[r[0].toLowerCase()],n+r[0].length):-1},A:function(t,e,n){var r=h.exec(e.slice(n));return r?(t.w=f[r[0].toLowerCase()],n+r[0].length):-1},b:function(t,e,n){var r=m.exec(e.slice(n));return r?(t.m=v[r[0].toLowerCase()],n+r[0].length):-1},B:function(t,e,n){var r=y.exec(e.slice(n));return r?(t.m=g[r[0].toLowerCase()],n+r[0].length):-1},c:function(t,n,r){return T(t,e,n,r)},d:Rm,e:Rm,f:Um,g:Om,G:Dm,H:Pm,I:Pm,j:Fm,L:zm,m:Im,M:jm,p:function(t,e,n){var r=u.exec(e.slice(n));return r?(t.p=l[r[0].toLowerCase()],n+r[0].length):-1},q:Lm,Q:Hm,s:$m,S:Ym,u:Sm,U:Am,V:Mm,w:Cm,W:Nm,x:function(t,e,r){return T(t,n,e,r)},X:function(t,e,n){return T(t,r,e,n)},y:Om,Y:Dm,Z:Bm,"%":qm};function w(t,e){return function(n){var r,i,a,o=[],s=-1,c=0,u=t.length;for(n instanceof Date||(n=new Date(+n));++s<u;)37===t.charCodeAt(s)&&(o.push(t.slice(c,s)),null!=(i=vm[r=t.charAt(++s)])?r=t.charAt(++s):i="e"===r?" ":"0",(a=e[r])&&(r=a(n,i)),o.push(r),c=s+1);return o.push(t.slice(c,s)),o.join("")}}function k(t,e){return function(n){var r,i,a=hm(1900,void 0,1);if(T(a,t,n+="",0)!=n.length)return null;if("Q"in a)return new Date(a.Q);if("s"in a)return new Date(1e3*a.s+("L"in a?a.L:0));if(e&&!("Z"in a)&&(a.Z=0),"p"in a&&(a.H=a.H%12+12*a.p),void 0===a.m&&(a.m="q"in a?a.q:0),"V"in a){if(a.V<1||a.V>53)return null;"w"in a||(a.w=1),"Z"in a?(i=(r=lm(hm(a.y,0,1))).getUTCDay(),r=i>4||0===i?Hg.ceil(r):Hg(r),r=im.offset(r,7*(a.V-1)),a.y=r.getUTCFullYear(),a.m=r.getUTCMonth(),a.d=r.getUTCDate()+(a.w+6)%7):(i=(r=um(hm(a.y,0,1))).getDay(),r=i>4||0===i?pg.ceil(r):pg(r),r=Ag.offset(r,7*(a.V-1)),a.y=r.getFullYear(),a.m=r.getMonth(),a.d=r.getDate()+(a.w+6)%7)}else("W"in a||"U"in a)&&("w"in a||(a.w="u"in a?a.u%7:"W"in a?1:0),i="Z"in a?lm(hm(a.y,0,1)).getUTCDay():um(hm(a.y,0,1)).getDay(),a.m=0,a.d="W"in a?(a.w+6)%7+7*a.W-(i+5)%7:a.w+7*a.U-(i+6)%7);return"Z"in a?(a.H+=a.Z/100|0,a.M+=a.Z%100,lm(a)):um(a)}}function T(t,e,n,r){for(var i,a,o=0,s=e.length,c=n.length;o<s;){if(r>=c)return-1;if(37===(i=e.charCodeAt(o++))){if(i=e.charAt(o++),!(a=x[i in vm?e.charAt(o++):i])||(r=a(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return b.x=w(n,b),b.X=w(r,b),b.c=w(e,b),_.x=w(n,_),_.X=w(r,_),_.c=w(e,_),{format:function(t){var e=w(t+="",b);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}var dm,pm,ym,gm,mm,vm={"-":"",_:" ",0:"0"},bm=/^\s*\d+/,_m=/^%/,xm=/[\\^$*+?|[\]().{}]/g;function wm(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",a=i.length;return r+(a<n?new Array(n-a+1).join(e)+i:i)}function km(t){return t.replace(xm,"\\$&")}function Tm(t){return new RegExp("^(?:"+t.map(km).join("|")+")","i")}function Em(t){for(var e={},n=-1,r=t.length;++n<r;)e[t[n].toLowerCase()]=n;return e}function Cm(t,e,n){var r=bm.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function Sm(t,e,n){var r=bm.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function Am(t,e,n){var r=bm.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function Mm(t,e,n){var r=bm.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function Nm(t,e,n){var r=bm.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function Dm(t,e,n){var r=bm.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function Om(t,e,n){var r=bm.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function Bm(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function Lm(t,e,n){var r=bm.exec(e.slice(n,n+1));return r?(t.q=3*r[0]-3,n+r[0].length):-1}function Im(t,e,n){var r=bm.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function Rm(t,e,n){var r=bm.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function Fm(t,e,n){var r=bm.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function Pm(t,e,n){var r=bm.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function jm(t,e,n){var r=bm.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Ym(t,e,n){var r=bm.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function zm(t,e,n){var r=bm.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function Um(t,e,n){var r=bm.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function qm(t,e,n){var r=_m.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function Hm(t,e,n){var r=bm.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function $m(t,e,n){var r=bm.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function Wm(t,e){return wm(t.getDate(),e,2)}function Vm(t,e){return wm(t.getHours(),e,2)}function Gm(t,e){return wm(t.getHours()%12||12,e,2)}function Xm(t,e){return wm(1+Ag.count(ng(t),t),e,3)}function Zm(t,e){return wm(t.getMilliseconds(),e,3)}function Qm(t,e){return Zm(t,e)+"000"}function Km(t,e){return wm(t.getMonth()+1,e,2)}function Jm(t,e){return wm(t.getMinutes(),e,2)}function tv(t,e){return wm(t.getSeconds(),e,2)}function ev(t){var e=t.getDay();return 0===e?7:e}function nv(t,e){return wm(dg.count(ng(t)-1,t),e,2)}function rv(t){var e=t.getDay();return e>=4||0===e?mg(t):mg.ceil(t)}function iv(t,e){return t=rv(t),wm(mg.count(ng(t),t)+(4===ng(t).getDay()),e,2)}function av(t){return t.getDay()}function ov(t,e){return wm(pg.count(ng(t)-1,t),e,2)}function sv(t,e){return wm(t.getFullYear()%100,e,2)}function cv(t,e){return wm((t=rv(t)).getFullYear()%100,e,2)}function uv(t,e){return wm(t.getFullYear()%1e4,e,4)}function lv(t,e){var n=t.getDay();return wm((t=n>=4||0===n?mg(t):mg.ceil(t)).getFullYear()%1e4,e,4)}function hv(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+wm(e/60|0,"0",2)+wm(e%60,"0",2)}function fv(t,e){return wm(t.getUTCDate(),e,2)}function dv(t,e){return wm(t.getUTCHours(),e,2)}function pv(t,e){return wm(t.getUTCHours()%12||12,e,2)}function yv(t,e){return wm(1+im.count(sm(t),t),e,3)}function gv(t,e){return wm(t.getUTCMilliseconds(),e,3)}function mv(t,e){return gv(t,e)+"000"}function vv(t,e){return wm(t.getUTCMonth()+1,e,2)}function bv(t,e){return wm(t.getUTCMinutes(),e,2)}function _v(t,e){return wm(t.getUTCSeconds(),e,2)}function xv(t){var e=t.getUTCDay();return 0===e?7:e}function wv(t,e){return wm(qg.count(sm(t)-1,t),e,2)}function kv(t){var e=t.getUTCDay();return e>=4||0===e?Vg(t):Vg.ceil(t)}function Tv(t,e){return t=kv(t),wm(Vg.count(sm(t),t)+(4===sm(t).getUTCDay()),e,2)}function Ev(t){return t.getUTCDay()}function Cv(t,e){return wm(Hg.count(sm(t)-1,t),e,2)}function Sv(t,e){return wm(t.getUTCFullYear()%100,e,2)}function Av(t,e){return wm((t=kv(t)).getUTCFullYear()%100,e,2)}function Mv(t,e){return wm(t.getUTCFullYear()%1e4,e,4)}function Nv(t,e){var n=t.getUTCDay();return wm((t=n>=4||0===n?Vg(t):Vg.ceil(t)).getUTCFullYear()%1e4,e,4)}function Dv(){return"+0000"}function Ov(){return"%"}function Bv(t){return+t}function Lv(t){return Math.floor(+t/1e3)}function Iv(t){return dm=fm(t),pm=dm.format,ym=dm.parse,gm=dm.utcFormat,mm=dm.utcParse,dm}Iv({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var Rv=31536e6;function Fv(t){return new Date(t)}function Pv(t){return t instanceof Date?+t:+new Date(+t)}function jv(t,e,n,r,i,o,s,c,u){var l=Ey(vy,vy),h=l.invert,f=l.domain,d=u(".%L"),p=u(":%S"),y=u("%I:%M"),g=u("%I %p"),m=u("%a %d"),v=u("%b %d"),b=u("%B"),_=u("%Y"),x=[[s,1,1e3],[s,5,5e3],[s,15,15e3],[s,30,3e4],[o,1,6e4],[o,5,3e5],[o,15,9e5],[o,30,18e5],[i,1,36e5],[i,3,108e5],[i,6,216e5],[i,12,432e5],[r,1,864e5],[r,2,1728e5],[n,1,6048e5],[e,1,2592e6],[e,3,7776e6],[t,1,Rv]];function w(a){return(s(a)<a?d:o(a)<a?p:i(a)<a?y:r(a)<a?g:e(a)<a?n(a)<a?m:v:t(a)<a?b:_)(a)}function k(e,n,r,i){if(null==e&&(e=10),"number"==typeof e){var o=Math.abs(r-n)/e,s=a((function(t){return t[2]})).right(x,o);s===x.length?(i=M(n/Rv,r/Rv,e),e=t):s?(i=(s=x[o/x[s-1][2]<x[s][2]/o?s-1:s])[1],e=s[0]):(i=Math.max(M(n,r,e),1),e=c)}return null==i?e:e.every(i)}return l.invert=function(t){return new Date(h(t))},l.domain=function(t){return arguments.length?f(uy.call(t,Pv)):f().map(Fv)},l.ticks=function(t,e){var n,r=f(),i=r[0],a=r[r.length-1],o=a<i;return o&&(n=i,i=a,a=n),n=(n=k(t,i,a,e))?n.range(i,a+1):[],o?n.reverse():n},l.tickFormat=function(t,e){return null==e?w:u(e)},l.nice=function(t,e){var n=f();return(t=k(t,n[0],n[n.length-1],e))?f(Ny(n,t)):l},l.copy=function(){return ky(l,jv(t,e,n,r,i,o,s,c,u))},l}function Yv(){return oy.apply(jv(ng,ag,dg,Ag,Dg,Lg,Fg,Yg,pm).domain([new Date(2e3,0,1),new Date(2e3,0,2)]),arguments)}var zv=tg((function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCMonth(t.getUTCMonth()+e)}),(function(t,e){return e.getUTCMonth()-t.getUTCMonth()+12*(e.getUTCFullYear()-t.getUTCFullYear())}),(function(t){return t.getUTCMonth()}));const Uv=zv;var qv=zv.range,Hv=tg((function(t){t.setUTCMinutes(0,0,0)}),(function(t,e){t.setTime(+t+e*ug)}),(function(t,e){return(e-t)/ug}),(function(t){return t.getUTCHours()}));const $v=Hv;var Wv=Hv.range,Vv=tg((function(t){t.setUTCSeconds(0,0)}),(function(t,e){t.setTime(+t+e*cg)}),(function(t,e){return(e-t)/cg}),(function(t){return t.getUTCMinutes()}));const Gv=Vv;var Xv=Vv.range;function Zv(){return oy.apply(jv(sm,Uv,qg,im,$v,Gv,Fg,Yg,gm).domain([Date.UTC(2e3,0,1),Date.UTC(2e3,0,2)]),arguments)}function Qv(){var t,e,n,r,i,a=0,o=1,s=vy,c=!1;function u(e){return isNaN(e=+e)?i:s(0===n?.5:(e=(r(e)-t)*n,c?Math.max(0,Math.min(1,e)):e))}return u.domain=function(i){return arguments.length?(t=r(a=+i[0]),e=r(o=+i[1]),n=t===e?0:1/(e-t),u):[a,o]},u.clamp=function(t){return arguments.length?(c=!!t,u):c},u.interpolator=function(t){return arguments.length?(s=t,u):s},u.unknown=function(t){return arguments.length?(i=t,u):i},function(i){return r=i,t=i(a),e=i(o),n=t===e?0:1/(e-t),u}}function Kv(t,e){return e.domain(t.domain()).interpolator(t.interpolator()).clamp(t.clamp()).unknown(t.unknown())}function Jv(){var t=Sy(Qv()(vy));return t.copy=function(){return Kv(t,Jv())},sy.apply(t,arguments)}function tb(){var t=Fy(Qv()).domain([1,10]);return t.copy=function(){return Kv(t,tb()).base(t.base())},sy.apply(t,arguments)}function eb(){var t=zy(Qv());return t.copy=function(){return Kv(t,eb()).constant(t.constant())},sy.apply(t,arguments)}function nb(){var t=Wy(Qv());return t.copy=function(){return Kv(t,nb()).exponent(t.exponent())},sy.apply(t,arguments)}function rb(){return nb.apply(null,arguments).exponent(.5)}function ib(){var t=[],e=vy;function n(n){if(!isNaN(n=+n))return e((u(t,n)-1)/(t.length-1))}return n.domain=function(e){if(!arguments.length)return t.slice();t=[];for(var r,a=0,o=e.length;a<o;++a)null==(r=e[a])||isNaN(r=+r)||t.push(r);return t.sort(i),n},n.interpolator=function(t){return arguments.length?(e=t,n):e},n.copy=function(){return ib(e).domain(t)},sy.apply(n,arguments)}function ab(){var t,e,n,r,i,a,o,s=0,c=.5,u=1,l=vy,h=!1;function f(t){return isNaN(t=+t)?o:(t=.5+((t=+a(t))-e)*(t<e?r:i),l(h?Math.max(0,Math.min(1,t)):t))}return f.domain=function(o){return arguments.length?(t=a(s=+o[0]),e=a(c=+o[1]),n=a(u=+o[2]),r=t===e?0:.5/(e-t),i=e===n?0:.5/(n-e),f):[s,c,u]},f.clamp=function(t){return arguments.length?(h=!!t,f):h},f.interpolator=function(t){return arguments.length?(l=t,f):l},f.unknown=function(t){return arguments.length?(o=t,f):o},function(o){return a=o,t=o(s),e=o(c),n=o(u),r=t===e?0:.5/(e-t),i=e===n?0:.5/(n-e),f}}function ob(){var t=Sy(ab()(vy));return t.copy=function(){return Kv(t,ob())},sy.apply(t,arguments)}function sb(){var t=Fy(ab()).domain([.1,1,10]);return t.copy=function(){return Kv(t,sb()).base(t.base())},sy.apply(t,arguments)}function cb(){var t=zy(ab());return t.copy=function(){return Kv(t,cb()).constant(t.constant())},sy.apply(t,arguments)}function ub(){var t=Wy(ab());return t.copy=function(){return Kv(t,ub()).exponent(t.exponent())},sy.apply(t,arguments)}function lb(){return ub.apply(null,arguments).exponent(.5)}function hb(t){for(var e=t.length/6|0,n=new Array(e),r=0;r<e;)n[r]="#"+t.slice(6*r,6*++r);return n}const fb=hb("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"),db=hb("7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666"),pb=hb("1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666"),yb=hb("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928"),gb=hb("fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2"),mb=hb("b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc"),vb=hb("e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999"),bb=hb("66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3"),_b=hb("8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f"),xb=hb("4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab");function wb(t){return mn(t[t.length-1])}var kb=new Array(3).concat("d8b365f5f5f55ab4ac","a6611adfc27d80cdc1018571","a6611adfc27df5f5f580cdc1018571","8c510ad8b365f6e8c3c7eae55ab4ac01665e","8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e","8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e","8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e","5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30","5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30").map(hb);const Tb=wb(kb);var Eb=new Array(3).concat("af8dc3f7f7f77fbf7b","7b3294c2a5cfa6dba0008837","7b3294c2a5cff7f7f7a6dba0008837","762a83af8dc3e7d4e8d9f0d37fbf7b1b7837","762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837","762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837","762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837","40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b","40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b").map(hb);const Cb=wb(Eb);var Sb=new Array(3).concat("e9a3c9f7f7f7a1d76a","d01c8bf1b6dab8e1864dac26","d01c8bf1b6daf7f7f7b8e1864dac26","c51b7de9a3c9fde0efe6f5d0a1d76a4d9221","c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221","c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221","c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221","8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419","8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419").map(hb);const Ab=wb(Sb);var Mb=new Array(3).concat("998ec3f7f7f7f1a340","5e3c99b2abd2fdb863e66101","5e3c99b2abd2f7f7f7fdb863e66101","542788998ec3d8daebfee0b6f1a340b35806","542788998ec3d8daebf7f7f7fee0b6f1a340b35806","5427888073acb2abd2d8daebfee0b6fdb863e08214b35806","5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806","2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08","2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08").map(hb);const Nb=wb(Mb);var Db=new Array(3).concat("ef8a62f7f7f767a9cf","ca0020f4a58292c5de0571b0","ca0020f4a582f7f7f792c5de0571b0","b2182bef8a62fddbc7d1e5f067a9cf2166ac","b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac","b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac","b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac","67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061","67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061").map(hb);const Ob=wb(Db);var Bb=new Array(3).concat("ef8a62ffffff999999","ca0020f4a582bababa404040","ca0020f4a582ffffffbababa404040","b2182bef8a62fddbc7e0e0e09999994d4d4d","b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d","b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d","b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d","67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a","67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a").map(hb);const Lb=wb(Bb);var Ib=new Array(3).concat("fc8d59ffffbf91bfdb","d7191cfdae61abd9e92c7bb6","d7191cfdae61ffffbfabd9e92c7bb6","d73027fc8d59fee090e0f3f891bfdb4575b4","d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4","d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4","d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4","a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695","a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695").map(hb);const Rb=wb(Ib);var Fb=new Array(3).concat("fc8d59ffffbf91cf60","d7191cfdae61a6d96a1a9641","d7191cfdae61ffffbfa6d96a1a9641","d73027fc8d59fee08bd9ef8b91cf601a9850","d73027fc8d59fee08bffffbfd9ef8b91cf601a9850","d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850","d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850","a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837","a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837").map(hb);const Pb=wb(Fb);var jb=new Array(3).concat("fc8d59ffffbf99d594","d7191cfdae61abdda42b83ba","d7191cfdae61ffffbfabdda42b83ba","d53e4ffc8d59fee08be6f59899d5943288bd","d53e4ffc8d59fee08bffffbfe6f59899d5943288bd","d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd","d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd","9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2","9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2").map(hb);const Yb=wb(jb);var zb=new Array(3).concat("e5f5f999d8c92ca25f","edf8fbb2e2e266c2a4238b45","edf8fbb2e2e266c2a42ca25f006d2c","edf8fbccece699d8c966c2a42ca25f006d2c","edf8fbccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b").map(hb);const Ub=wb(zb);var qb=new Array(3).concat("e0ecf49ebcda8856a7","edf8fbb3cde38c96c688419d","edf8fbb3cde38c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b").map(hb);const Hb=wb(qb);var $b=new Array(3).concat("e0f3dba8ddb543a2ca","f0f9e8bae4bc7bccc42b8cbe","f0f9e8bae4bc7bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081").map(hb);const Wb=wb($b);var Vb=new Array(3).concat("fee8c8fdbb84e34a33","fef0d9fdcc8afc8d59d7301f","fef0d9fdcc8afc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000").map(hb);const Gb=wb(Vb);var Xb=new Array(3).concat("ece2f0a6bddb1c9099","f6eff7bdc9e167a9cf02818a","f6eff7bdc9e167a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636").map(hb);const Zb=wb(Xb);var Qb=new Array(3).concat("ece7f2a6bddb2b8cbe","f1eef6bdc9e174a9cf0570b0","f1eef6bdc9e174a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858").map(hb);const Kb=wb(Qb);var Jb=new Array(3).concat("e7e1efc994c7dd1c77","f1eef6d7b5d8df65b0ce1256","f1eef6d7b5d8df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f").map(hb);const t_=wb(Jb);var e_=new Array(3).concat("fde0ddfa9fb5c51b8a","feebe2fbb4b9f768a1ae017e","feebe2fbb4b9f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a").map(hb);const n_=wb(e_);var r_=new Array(3).concat("edf8b17fcdbb2c7fb8","ffffcca1dab441b6c4225ea8","ffffcca1dab441b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58").map(hb);const i_=wb(r_);var a_=new Array(3).concat("f7fcb9addd8e31a354","ffffccc2e69978c679238443","ffffccc2e69978c67931a354006837","ffffccd9f0a3addd8e78c67931a354006837","ffffccd9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529").map(hb);const o_=wb(a_);var s_=new Array(3).concat("fff7bcfec44fd95f0e","ffffd4fed98efe9929cc4c02","ffffd4fed98efe9929d95f0e993404","ffffd4fee391fec44ffe9929d95f0e993404","ffffd4fee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506").map(hb);const c_=wb(s_);var u_=new Array(3).concat("ffeda0feb24cf03b20","ffffb2fecc5cfd8d3ce31a1c","ffffb2fecc5cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026").map(hb);const l_=wb(u_);var h_=new Array(3).concat("deebf79ecae13182bd","eff3ffbdd7e76baed62171b5","eff3ffbdd7e76baed63182bd08519c","eff3ffc6dbef9ecae16baed63182bd08519c","eff3ffc6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b").map(hb);const f_=wb(h_);var d_=new Array(3).concat("e5f5e0a1d99b31a354","edf8e9bae4b374c476238b45","edf8e9bae4b374c47631a354006d2c","edf8e9c7e9c0a1d99b74c47631a354006d2c","edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b").map(hb);const p_=wb(d_);var y_=new Array(3).concat("f0f0f0bdbdbd636363","f7f7f7cccccc969696525252","f7f7f7cccccc969696636363252525","f7f7f7d9d9d9bdbdbd969696636363252525","f7f7f7d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000").map(hb);const g_=wb(y_);var m_=new Array(3).concat("efedf5bcbddc756bb1","f2f0f7cbc9e29e9ac86a51a3","f2f0f7cbc9e29e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d").map(hb);const v_=wb(m_);var b_=new Array(3).concat("fee0d2fc9272de2d26","fee5d9fcae91fb6a4acb181d","fee5d9fcae91fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d").map(hb);const __=wb(b_);var x_=new Array(3).concat("fee6cefdae6be6550d","feeddefdbe85fd8d3cd94701","feeddefdbe85fd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704").map(hb);const w_=wb(x_);function k_(t){return t=Math.max(0,Math.min(1,t)),"rgb("+Math.max(0,Math.min(255,Math.round(-4.54-t*(35.34-t*(2381.73-t*(6402.7-t*(7024.72-2710.57*t)))))))+", "+Math.max(0,Math.min(255,Math.round(32.49+t*(170.73+t*(52.82-t*(131.46-t*(176.58-67.37*t)))))))+", "+Math.max(0,Math.min(255,Math.round(81.24+t*(442.36-t*(2482.43-t*(6167.24-t*(6614.94-2475.67*t)))))))+")"}const T_=Up(Ha(300,.5,0),Ha(-240,.5,1));var E_=Up(Ha(-100,.75,.35),Ha(80,1.5,.8)),C_=Up(Ha(260,.75,.35),Ha(80,1.5,.8)),S_=Ha();function A_(t){(t<0||t>1)&&(t-=Math.floor(t));var e=Math.abs(t-.5);return S_.h=360*t-100,S_.s=1.5-1.5*e,S_.l=.8-.9*e,S_+""}var M_=Qe(),N_=Math.PI/3,D_=2*Math.PI/3;function O_(t){var e;return t=(.5-t)*Math.PI,M_.r=255*(e=Math.sin(t))*e,M_.g=255*(e=Math.sin(t+N_))*e,M_.b=255*(e=Math.sin(t+D_))*e,M_+""}function B_(t){return t=Math.max(0,Math.min(1,t)),"rgb("+Math.max(0,Math.min(255,Math.round(34.61+t*(1172.33-t*(10793.56-t*(33300.12-t*(38394.49-14825.05*t)))))))+", "+Math.max(0,Math.min(255,Math.round(23.31+t*(557.33+t*(1225.33-t*(3574.96-t*(1073.77+707.56*t)))))))+", "+Math.max(0,Math.min(255,Math.round(27.2+t*(3211.1-t*(15327.97-t*(27814-t*(22569.18-6838.66*t)))))))+")"}function L_(t){var e=t.length;return function(n){return t[Math.max(0,Math.min(e-1,Math.floor(n*e)))]}}const I_=L_(hb("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));var R_=L_(hb("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),F_=L_(hb("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),P_=L_(hb("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));function j_(t){return Te(ie(t).call(document.documentElement))}var Y_=0;function z_(){return new U_}function U_(){this._="@"+(++Y_).toString(36)}function q_(t){return"string"==typeof t?new xe([document.querySelectorAll(t)],[document.documentElement]):new xe([null==t?[]:t],_e)}function H_(t,e){null==e&&(e=Nn().touches);for(var n=0,r=e?e.length:0,i=new Array(r);n<r;++n)i[n]=Dn(t,e[n]);return i}function $_(t){return function(){return t}}U_.prototype=z_.prototype={constructor:U_,get:function(t){for(var e=this._;!(e in t);)if(!(t=t.parentNode))return;return t[e]},set:function(t,e){return t[this._]=e},remove:function(t){return this._ in t&&delete t[this._]},toString:function(){return this._}};var W_=Math.abs,V_=Math.atan2,G_=Math.cos,X_=Math.max,Z_=Math.min,Q_=Math.sin,K_=Math.sqrt,J_=1e-12,tx=Math.PI,ex=tx/2,nx=2*tx;function rx(t){return t>1?0:t<-1?tx:Math.acos(t)}function ix(t){return t>=1?ex:t<=-1?-ex:Math.asin(t)}function ax(t){return t.innerRadius}function ox(t){return t.outerRadius}function sx(t){return t.startAngle}function cx(t){return t.endAngle}function ux(t){return t&&t.padAngle}function lx(t,e,n,r,i,a,o,s){var c=n-t,u=r-e,l=o-i,h=s-a,f=h*c-l*u;if(!(f*f<J_))return[t+(f=(l*(e-a)-h*(t-i))/f)*c,e+f*u]}function hx(t,e,n,r,i,a,o){var s=t-n,c=e-r,u=(o?a:-a)/K_(s*s+c*c),l=u*c,h=-u*s,f=t+l,d=e+h,p=n+l,y=r+h,g=(f+p)/2,m=(d+y)/2,v=p-f,b=y-d,_=v*v+b*b,x=i-a,w=f*y-p*d,k=(b<0?-1:1)*K_(X_(0,x*x*_-w*w)),T=(w*b-v*k)/_,E=(-w*v-b*k)/_,C=(w*b+v*k)/_,S=(-w*v+b*k)/_,A=T-g,M=E-m,N=C-g,D=S-m;return A*A+M*M>N*N+D*D&&(T=C,E=S),{cx:T,cy:E,x01:-l,y01:-h,x11:T*(i/x-1),y11:E*(i/x-1)}}function fx(){var t=ax,e=ox,n=$_(0),r=null,i=sx,a=cx,o=ux,s=null;function c(){var c,u,l=+t.apply(this,arguments),h=+e.apply(this,arguments),f=i.apply(this,arguments)-ex,d=a.apply(this,arguments)-ex,p=W_(d-f),y=d>f;if(s||(s=c=Wi()),h<l&&(u=h,h=l,l=u),h>J_)if(p>nx-J_)s.moveTo(h*G_(f),h*Q_(f)),s.arc(0,0,h,f,d,!y),l>J_&&(s.moveTo(l*G_(d),l*Q_(d)),s.arc(0,0,l,d,f,y));else{var g,m,v=f,b=d,_=f,x=d,w=p,k=p,T=o.apply(this,arguments)/2,E=T>J_&&(r?+r.apply(this,arguments):K_(l*l+h*h)),C=Z_(W_(h-l)/2,+n.apply(this,arguments)),S=C,A=C;if(E>J_){var M=ix(E/l*Q_(T)),N=ix(E/h*Q_(T));(w-=2*M)>J_?(_+=M*=y?1:-1,x-=M):(w=0,_=x=(f+d)/2),(k-=2*N)>J_?(v+=N*=y?1:-1,b-=N):(k=0,v=b=(f+d)/2)}var D=h*G_(v),O=h*Q_(v),B=l*G_(x),L=l*Q_(x);if(C>J_){var I,R=h*G_(b),F=h*Q_(b),P=l*G_(_),j=l*Q_(_);if(p<tx&&(I=lx(D,O,P,j,R,F,B,L))){var Y=D-I[0],z=O-I[1],U=R-I[0],q=F-I[1],H=1/Q_(rx((Y*U+z*q)/(K_(Y*Y+z*z)*K_(U*U+q*q)))/2),$=K_(I[0]*I[0]+I[1]*I[1]);S=Z_(C,(l-$)/(H-1)),A=Z_(C,(h-$)/(H+1))}}k>J_?A>J_?(g=hx(P,j,D,O,h,A,y),m=hx(R,F,B,L,h,A,y),s.moveTo(g.cx+g.x01,g.cy+g.y01),A<C?s.arc(g.cx,g.cy,A,V_(g.y01,g.x01),V_(m.y01,m.x01),!y):(s.arc(g.cx,g.cy,A,V_(g.y01,g.x01),V_(g.y11,g.x11),!y),s.arc(0,0,h,V_(g.cy+g.y11,g.cx+g.x11),V_(m.cy+m.y11,m.cx+m.x11),!y),s.arc(m.cx,m.cy,A,V_(m.y11,m.x11),V_(m.y01,m.x01),!y))):(s.moveTo(D,O),s.arc(0,0,h,v,b,!y)):s.moveTo(D,O),l>J_&&w>J_?S>J_?(g=hx(B,L,R,F,l,-S,y),m=hx(D,O,P,j,l,-S,y),s.lineTo(g.cx+g.x01,g.cy+g.y01),S<C?s.arc(g.cx,g.cy,S,V_(g.y01,g.x01),V_(m.y01,m.x01),!y):(s.arc(g.cx,g.cy,S,V_(g.y01,g.x01),V_(g.y11,g.x11),!y),s.arc(0,0,l,V_(g.cy+g.y11,g.cx+g.x11),V_(m.cy+m.y11,m.cx+m.x11),y),s.arc(m.cx,m.cy,S,V_(m.y11,m.x11),V_(m.y01,m.x01),!y))):s.arc(0,0,l,x,_,y):s.lineTo(B,L)}else s.moveTo(0,0);if(s.closePath(),c)return s=null,c+""||null}return c.centroid=function(){var n=(+t.apply(this,arguments)+ +e.apply(this,arguments))/2,r=(+i.apply(this,arguments)+ +a.apply(this,arguments))/2-tx/2;return[G_(r)*n,Q_(r)*n]},c.innerRadius=function(e){return arguments.length?(t="function"==typeof e?e:$_(+e),c):t},c.outerRadius=function(t){return arguments.length?(e="function"==typeof t?t:$_(+t),c):e},c.cornerRadius=function(t){return arguments.length?(n="function"==typeof t?t:$_(+t),c):n},c.padRadius=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:$_(+t),c):r},c.startAngle=function(t){return arguments.length?(i="function"==typeof t?t:$_(+t),c):i},c.endAngle=function(t){return arguments.length?(a="function"==typeof t?t:$_(+t),c):a},c.padAngle=function(t){return arguments.length?(o="function"==typeof t?t:$_(+t),c):o},c.context=function(t){return arguments.length?(s=null==t?null:t,c):s},c}function dx(t){this._context=t}function px(t){return new dx(t)}function yx(t){return t[0]}function gx(t){return t[1]}function mx(){var t=yx,e=gx,n=$_(!0),r=null,i=px,a=null;function o(o){var s,c,u,l=o.length,h=!1;for(null==r&&(a=i(u=Wi())),s=0;s<=l;++s)!(s<l&&n(c=o[s],s,o))===h&&((h=!h)?a.lineStart():a.lineEnd()),h&&a.point(+t(c,s,o),+e(c,s,o));if(u)return a=null,u+""||null}return o.x=function(e){return arguments.length?(t="function"==typeof e?e:$_(+e),o):t},o.y=function(t){return arguments.length?(e="function"==typeof t?t:$_(+t),o):e},o.defined=function(t){return arguments.length?(n="function"==typeof t?t:$_(!!t),o):n},o.curve=function(t){return arguments.length?(i=t,null!=r&&(a=i(r)),o):i},o.context=function(t){return arguments.length?(null==t?r=a=null:a=i(r=t),o):r},o}function vx(){var t=yx,e=null,n=$_(0),r=gx,i=$_(!0),a=null,o=px,s=null;function c(c){var u,l,h,f,d,p=c.length,y=!1,g=new Array(p),m=new Array(p);for(null==a&&(s=o(d=Wi())),u=0;u<=p;++u){if(!(u<p&&i(f=c[u],u,c))===y)if(y=!y)l=u,s.areaStart(),s.lineStart();else{for(s.lineEnd(),s.lineStart(),h=u-1;h>=l;--h)s.point(g[h],m[h]);s.lineEnd(),s.areaEnd()}y&&(g[u]=+t(f,u,c),m[u]=+n(f,u,c),s.point(e?+e(f,u,c):g[u],r?+r(f,u,c):m[u]))}if(d)return s=null,d+""||null}function u(){return mx().defined(i).curve(o).context(a)}return c.x=function(n){return arguments.length?(t="function"==typeof n?n:$_(+n),e=null,c):t},c.x0=function(e){return arguments.length?(t="function"==typeof e?e:$_(+e),c):t},c.x1=function(t){return arguments.length?(e=null==t?null:"function"==typeof t?t:$_(+t),c):e},c.y=function(t){return arguments.length?(n="function"==typeof t?t:$_(+t),r=null,c):n},c.y0=function(t){return arguments.length?(n="function"==typeof t?t:$_(+t),c):n},c.y1=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:$_(+t),c):r},c.lineX0=c.lineY0=function(){return u().x(t).y(n)},c.lineY1=function(){return u().x(t).y(r)},c.lineX1=function(){return u().x(e).y(n)},c.defined=function(t){return arguments.length?(i="function"==typeof t?t:$_(!!t),c):i},c.curve=function(t){return arguments.length?(o=t,null!=a&&(s=o(a)),c):o},c.context=function(t){return arguments.length?(null==t?a=s=null:s=o(a=t),c):a},c}function bx(t,e){return e<t?-1:e>t?1:e>=t?0:NaN}function _x(t){return t}function xx(){var t=_x,e=bx,n=null,r=$_(0),i=$_(nx),a=$_(0);function o(o){var s,c,u,l,h,f=o.length,d=0,p=new Array(f),y=new Array(f),g=+r.apply(this,arguments),m=Math.min(nx,Math.max(-nx,i.apply(this,arguments)-g)),v=Math.min(Math.abs(m)/f,a.apply(this,arguments)),b=v*(m<0?-1:1);for(s=0;s<f;++s)(h=y[p[s]=s]=+t(o[s],s,o))>0&&(d+=h);for(null!=e?p.sort((function(t,n){return e(y[t],y[n])})):null!=n&&p.sort((function(t,e){return n(o[t],o[e])})),s=0,u=d?(m-f*b)/d:0;s<f;++s,g=l)c=p[s],l=g+((h=y[c])>0?h*u:0)+b,y[c]={data:o[c],index:s,value:h,startAngle:g,endAngle:l,padAngle:v};return y}return o.value=function(e){return arguments.length?(t="function"==typeof e?e:$_(+e),o):t},o.sortValues=function(t){return arguments.length?(e=t,n=null,o):e},o.sort=function(t){return arguments.length?(n=t,e=null,o):n},o.startAngle=function(t){return arguments.length?(r="function"==typeof t?t:$_(+t),o):r},o.endAngle=function(t){return arguments.length?(i="function"==typeof t?t:$_(+t),o):i},o.padAngle=function(t){return arguments.length?(a="function"==typeof t?t:$_(+t),o):a},o}dx.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:this._context.lineTo(t,e)}}};var wx=Tx(px);function kx(t){this._curve=t}function Tx(t){function e(e){return new kx(t(e))}return e._curve=t,e}function Ex(t){var e=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?e(Tx(t)):e()._curve},t}function Cx(){return Ex(mx().curve(wx))}function Sx(){var t=vx().curve(wx),e=t.curve,n=t.lineX0,r=t.lineX1,i=t.lineY0,a=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return Ex(n())},delete t.lineX0,t.lineEndAngle=function(){return Ex(r())},delete t.lineX1,t.lineInnerRadius=function(){return Ex(i())},delete t.lineY0,t.lineOuterRadius=function(){return Ex(a())},delete t.lineY1,t.curve=function(t){return arguments.length?e(Tx(t)):e()._curve},t}function Ax(t,e){return[(e=+e)*Math.cos(t-=Math.PI/2),e*Math.sin(t)]}kx.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,e){this._curve.point(e*Math.sin(t),e*-Math.cos(t))}};var Mx=Array.prototype.slice;function Nx(t){return t.source}function Dx(t){return t.target}function Ox(t){var e=Nx,n=Dx,r=yx,i=gx,a=null;function o(){var o,s=Mx.call(arguments),c=e.apply(this,s),u=n.apply(this,s);if(a||(a=o=Wi()),t(a,+r.apply(this,(s[0]=c,s)),+i.apply(this,s),+r.apply(this,(s[0]=u,s)),+i.apply(this,s)),o)return a=null,o+""||null}return o.source=function(t){return arguments.length?(e=t,o):e},o.target=function(t){return arguments.length?(n=t,o):n},o.x=function(t){return arguments.length?(r="function"==typeof t?t:$_(+t),o):r},o.y=function(t){return arguments.length?(i="function"==typeof t?t:$_(+t),o):i},o.context=function(t){return arguments.length?(a=null==t?null:t,o):a},o}function Bx(t,e,n,r,i){t.moveTo(e,n),t.bezierCurveTo(e=(e+r)/2,n,e,i,r,i)}function Lx(t,e,n,r,i){t.moveTo(e,n),t.bezierCurveTo(e,n=(n+i)/2,r,n,r,i)}function Ix(t,e,n,r,i){var a=Ax(e,n),o=Ax(e,n=(n+i)/2),s=Ax(r,n),c=Ax(r,i);t.moveTo(a[0],a[1]),t.bezierCurveTo(o[0],o[1],s[0],s[1],c[0],c[1])}function Rx(){return Ox(Bx)}function Fx(){return Ox(Lx)}function Px(){var t=Ox(Ix);return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t}const jx={draw:function(t,e){var n=Math.sqrt(e/tx);t.moveTo(n,0),t.arc(0,0,n,0,nx)}},Yx={draw:function(t,e){var n=Math.sqrt(e/5)/2;t.moveTo(-3*n,-n),t.lineTo(-n,-n),t.lineTo(-n,-3*n),t.lineTo(n,-3*n),t.lineTo(n,-n),t.lineTo(3*n,-n),t.lineTo(3*n,n),t.lineTo(n,n),t.lineTo(n,3*n),t.lineTo(-n,3*n),t.lineTo(-n,n),t.lineTo(-3*n,n),t.closePath()}};var zx=Math.sqrt(1/3),Ux=2*zx;const qx={draw:function(t,e){var n=Math.sqrt(e/Ux),r=n*zx;t.moveTo(0,-n),t.lineTo(r,0),t.lineTo(0,n),t.lineTo(-r,0),t.closePath()}};var Hx=Math.sin(tx/10)/Math.sin(7*tx/10),$x=Math.sin(nx/10)*Hx,Wx=-Math.cos(nx/10)*Hx;const Vx={draw:function(t,e){var n=Math.sqrt(.8908130915292852*e),r=$x*n,i=Wx*n;t.moveTo(0,-n),t.lineTo(r,i);for(var a=1;a<5;++a){var o=nx*a/5,s=Math.cos(o),c=Math.sin(o);t.lineTo(c*n,-s*n),t.lineTo(s*r-c*i,c*r+s*i)}t.closePath()}},Gx={draw:function(t,e){var n=Math.sqrt(e),r=-n/2;t.rect(r,r,n,n)}};var Xx=Math.sqrt(3);const Zx={draw:function(t,e){var n=-Math.sqrt(e/(3*Xx));t.moveTo(0,2*n),t.lineTo(-Xx*n,-n),t.lineTo(Xx*n,-n),t.closePath()}};var Qx=-.5,Kx=Math.sqrt(3)/2,Jx=1/Math.sqrt(12),tw=3*(Jx/2+1);const ew={draw:function(t,e){var n=Math.sqrt(e/tw),r=n/2,i=n*Jx,a=r,o=n*Jx+n,s=-a,c=o;t.moveTo(r,i),t.lineTo(a,o),t.lineTo(s,c),t.lineTo(Qx*r-Kx*i,Kx*r+Qx*i),t.lineTo(Qx*a-Kx*o,Kx*a+Qx*o),t.lineTo(Qx*s-Kx*c,Kx*s+Qx*c),t.lineTo(Qx*r+Kx*i,Qx*i-Kx*r),t.lineTo(Qx*a+Kx*o,Qx*o-Kx*a),t.lineTo(Qx*s+Kx*c,Qx*c-Kx*s),t.closePath()}};var nw=[jx,Yx,qx,Gx,Vx,Zx,ew];function rw(){var t=$_(jx),e=$_(64),n=null;function r(){var r;if(n||(n=r=Wi()),t.apply(this,arguments).draw(n,+e.apply(this,arguments)),r)return n=null,r+""||null}return r.type=function(e){return arguments.length?(t="function"==typeof e?e:$_(e),r):t},r.size=function(t){return arguments.length?(e="function"==typeof t?t:$_(+t),r):e},r.context=function(t){return arguments.length?(n=null==t?null:t,r):n},r}function iw(){}function aw(t,e,n){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+e)/6,(t._y0+4*t._y1+n)/6)}function ow(t){this._context=t}function sw(t){return new ow(t)}function cw(t){this._context=t}function uw(t){return new cw(t)}function lw(t){this._context=t}function hw(t){return new lw(t)}function fw(t,e){this._basis=new ow(t),this._beta=e}ow.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:aw(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:aw(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},cw.prototype={areaStart:iw,areaEnd:iw,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x2=t,this._y2=e;break;case 1:this._point=2,this._x3=t,this._y3=e;break;case 2:this._point=3,this._x4=t,this._y4=e,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+e)/6);break;default:aw(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},lw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var n=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+e)/6;this._line?this._context.lineTo(n,r):this._context.moveTo(n,r);break;case 3:this._point=4;default:aw(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},fw.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,e=this._y,n=t.length-1;if(n>0)for(var r,i=t[0],a=e[0],o=t[n]-i,s=e[n]-a,c=-1;++c<=n;)r=c/n,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*o),this._beta*e[c]+(1-this._beta)*(a+r*s));this._x=this._y=null,this._basis.lineEnd()},point:function(t,e){this._x.push(+t),this._y.push(+e)}};const dw=function t(e){function n(t){return 1===e?new ow(t):new fw(t,e)}return n.beta=function(e){return t(+e)},n}(.85);function pw(t,e,n){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-e),t._y2+t._k*(t._y1-n),t._x2,t._y2)}function yw(t,e){this._context=t,this._k=(1-e)/6}yw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:pw(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2,this._x1=t,this._y1=e;break;case 2:this._point=3;default:pw(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const gw=function t(e){function n(t){return new yw(t,e)}return n.tension=function(e){return t(+e)},n}(0);function mw(t,e){this._context=t,this._k=(1-e)/6}mw.prototype={areaStart:iw,areaEnd:iw,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x3=t,this._y3=e;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=e);break;case 2:this._point=3,this._x5=t,this._y5=e;break;default:pw(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const vw=function t(e){function n(t){return new mw(t,e)}return n.tension=function(e){return t(+e)},n}(0);function bw(t,e){this._context=t,this._k=(1-e)/6}bw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:pw(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const _w=function t(e){function n(t){return new bw(t,e)}return n.tension=function(e){return t(+e)},n}(0);function xw(t,e,n){var r=t._x1,i=t._y1,a=t._x2,o=t._y2;if(t._l01_a>J_){var s=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*s-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*s-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>J_){var u=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,l=3*t._l23_a*(t._l23_a+t._l12_a);a=(a*u+t._x1*t._l23_2a-e*t._l12_2a)/l,o=(o*u+t._y1*t._l23_2a-n*t._l12_2a)/l}t._context.bezierCurveTo(r,i,a,o,t._x2,t._y2)}function ww(t,e){this._context=t,this._alpha=e}ww.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3;default:xw(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const kw=function t(e){function n(t){return e?new ww(t,e):new yw(t,0)}return n.alpha=function(e){return t(+e)},n}(.5);function Tw(t,e){this._context=t,this._alpha=e}Tw.prototype={areaStart:iw,areaEnd:iw,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=e;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=e);break;case 2:this._point=3,this._x5=t,this._y5=e;break;default:xw(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const Ew=function t(e){function n(t){return e?new Tw(t,e):new mw(t,0)}return n.alpha=function(e){return t(+e)},n}(.5);function Cw(t,e){this._context=t,this._alpha=e}Cw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:xw(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};const Sw=function t(e){function n(t){return e?new Cw(t,e):new bw(t,0)}return n.alpha=function(e){return t(+e)},n}(.5);function Aw(t){this._context=t}function Mw(t){return new Aw(t)}function Nw(t){return t<0?-1:1}function Dw(t,e,n){var r=t._x1-t._x0,i=e-t._x1,a=(t._y1-t._y0)/(r||i<0&&-0),o=(n-t._y1)/(i||r<0&&-0),s=(a*i+o*r)/(r+i);return(Nw(a)+Nw(o))*Math.min(Math.abs(a),Math.abs(o),.5*Math.abs(s))||0}function Ow(t,e){var n=t._x1-t._x0;return n?(3*(t._y1-t._y0)/n-e)/2:e}function Bw(t,e,n){var r=t._x0,i=t._y0,a=t._x1,o=t._y1,s=(a-r)/3;t._context.bezierCurveTo(r+s,i+s*e,a-s,o-s*n,a,o)}function Lw(t){this._context=t}function Iw(t){this._context=new Rw(t)}function Rw(t){this._context=t}function Fw(t){return new Lw(t)}function Pw(t){return new Iw(t)}function jw(t){this._context=t}function Yw(t){var e,n,r=t.length-1,i=new Array(r),a=new Array(r),o=new Array(r);for(i[0]=0,a[0]=2,o[0]=t[0]+2*t[1],e=1;e<r-1;++e)i[e]=1,a[e]=4,o[e]=4*t[e]+2*t[e+1];for(i[r-1]=2,a[r-1]=7,o[r-1]=8*t[r-1]+t[r],e=1;e<r;++e)n=i[e]/a[e-1],a[e]-=n,o[e]-=n*o[e-1];for(i[r-1]=o[r-1]/a[r-1],e=r-2;e>=0;--e)i[e]=(o[e]-i[e+1])/a[e];for(a[r-1]=(t[r]+i[r-1])/2,e=0;e<r-1;++e)a[e]=2*t[e+1]-i[e+1];return[i,a]}function zw(t){return new jw(t)}function Uw(t,e){this._context=t,this._t=e}function qw(t){return new Uw(t,.5)}function Hw(t){return new Uw(t,0)}function $w(t){return new Uw(t,1)}function Ww(t,e){if((i=t.length)>1)for(var n,r,i,a=1,o=t[e[0]],s=o.length;a<i;++a)for(r=o,o=t[e[a]],n=0;n<s;++n)o[n][1]+=o[n][0]=isNaN(r[n][1])?r[n][0]:r[n][1]}function Vw(t){for(var e=t.length,n=new Array(e);--e>=0;)n[e]=e;return n}function Gw(t,e){return t[e]}function Xw(){var t=$_([]),e=Vw,n=Ww,r=Gw;function i(i){var a,o,s=t.apply(this,arguments),c=i.length,u=s.length,l=new Array(u);for(a=0;a<u;++a){for(var h,f=s[a],d=l[a]=new Array(c),p=0;p<c;++p)d[p]=h=[0,+r(i[p],f,p,i)],h.data=i[p];d.key=f}for(a=0,o=e(l);a<u;++a)l[o[a]].index=a;return n(l,o),l}return i.keys=function(e){return arguments.length?(t="function"==typeof e?e:$_(Mx.call(e)),i):t},i.value=function(t){return arguments.length?(r="function"==typeof t?t:$_(+t),i):r},i.order=function(t){return arguments.length?(e=null==t?Vw:"function"==typeof t?t:$_(Mx.call(t)),i):e},i.offset=function(t){return arguments.length?(n=null==t?Ww:t,i):n},i}function Zw(t,e){if((r=t.length)>0){for(var n,r,i,a=0,o=t[0].length;a<o;++a){for(i=n=0;n<r;++n)i+=t[n][a][1]||0;if(i)for(n=0;n<r;++n)t[n][a][1]/=i}Ww(t,e)}}function Qw(t,e){if((s=t.length)>0)for(var n,r,i,a,o,s,c=0,u=t[e[0]].length;c<u;++c)for(a=o=0,n=0;n<s;++n)(i=(r=t[e[n]][c])[1]-r[0])>0?(r[0]=a,r[1]=a+=i):i<0?(r[1]=o,r[0]=o+=i):(r[0]=0,r[1]=i)}function Kw(t,e){if((n=t.length)>0){for(var n,r=0,i=t[e[0]],a=i.length;r<a;++r){for(var o=0,s=0;o<n;++o)s+=t[o][r][1]||0;i[r][1]+=i[r][0]=-s/2}Ww(t,e)}}function Jw(t,e){if((i=t.length)>0&&(r=(n=t[e[0]]).length)>0){for(var n,r,i,a=0,o=1;o<r;++o){for(var s=0,c=0,u=0;s<i;++s){for(var l=t[e[s]],h=l[o][1]||0,f=(h-(l[o-1][1]||0))/2,d=0;d<s;++d){var p=t[e[d]];f+=(p[o][1]||0)-(p[o-1][1]||0)}c+=h,u+=f*h}n[o-1][1]+=n[o-1][0]=a,c&&(a-=u/c)}n[o-1][1]+=n[o-1][0]=a,Ww(t,e)}}function tk(t){var e=t.map(ek);return Vw(t).sort((function(t,n){return e[t]-e[n]}))}function ek(t){for(var e,n=-1,r=0,i=t.length,a=-1/0;++n<i;)(e=+t[n][1])>a&&(a=e,r=n);return r}function nk(t){var e=t.map(rk);return Vw(t).sort((function(t,n){return e[t]-e[n]}))}function rk(t){for(var e,n=0,r=-1,i=t.length;++r<i;)(e=+t[r][1])&&(n+=e);return n}function ik(t){return nk(t).reverse()}function ak(t){var e,n,r=t.length,i=t.map(rk),a=tk(t),o=0,s=0,c=[],u=[];for(e=0;e<r;++e)n=a[e],o<s?(o+=i[n],c.push(n)):(s+=i[n],u.push(n));return u.reverse().concat(c)}function ok(t){return Vw(t).reverse()}Aw.prototype={areaStart:iw,areaEnd:iw,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(t,e){t=+t,e=+e,this._point?this._context.lineTo(t,e):(this._point=1,this._context.moveTo(t,e))}},Lw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:Bw(this,this._t0,Ow(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){var n=NaN;if(e=+e,(t=+t)!==this._x1||e!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,Bw(this,Ow(this,n=Dw(this,t,e)),n);break;default:Bw(this,this._t0,n=Dw(this,t,e))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e,this._t0=n}}},(Iw.prototype=Object.create(Lw.prototype)).point=function(t,e){Lw.prototype.point.call(this,e,t)},Rw.prototype={moveTo:function(t,e){this._context.moveTo(e,t)},closePath:function(){this._context.closePath()},lineTo:function(t,e){this._context.lineTo(e,t)},bezierCurveTo:function(t,e,n,r,i,a){this._context.bezierCurveTo(e,t,r,n,a,i)}},jw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var t=this._x,e=this._y,n=t.length;if(n)if(this._line?this._context.lineTo(t[0],e[0]):this._context.moveTo(t[0],e[0]),2===n)this._context.lineTo(t[1],e[1]);else for(var r=Yw(t),i=Yw(e),a=0,o=1;o<n;++a,++o)this._context.bezierCurveTo(r[0][a],i[0][a],r[1][a],i[1][a],t[o],e[o]);(this._line||0!==this._line&&1===n)&&this._context.closePath(),this._line=1-this._line,this._x=this._y=null},point:function(t,e){this._x.push(+t),this._y.push(+e)}},Uw.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=this._y=NaN,this._point=0},lineEnd:function(){0<this._t&&this._t<1&&2===this._point&&this._context.lineTo(this._x,this._y),(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line>=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,e),this._context.lineTo(t,e);else{var n=this._x*(1-this._t)+t*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,e)}}this._x=t,this._y=e}};var sk="%Y-%m-%dT%H:%M:%S.%LZ",ck=Date.prototype.toISOString?function(t){return t.toISOString()}:gm(sk);const uk=ck;var lk=+new Date("2000-01-01T00:00:00.000Z")?function(t){var e=new Date(t);return isNaN(e)?null:e}:mm(sk);const hk=lk;function fk(t,e,n){var r=new Wn,i=e;return null==e?(r.restart(t,e,n),r):(e=+e,n=null==n?Hn():+n,r.restart((function a(o){o+=i,r.restart(a,i+=e,n),t(o)}),e,n),r)}function dk(t){return function(){return t}}function pk(t){return t[0]}function yk(t){return t[1]}function gk(){this._=null}function mk(t){t.U=t.C=t.L=t.R=t.P=t.N=null}function vk(t,e){var n=e,r=e.R,i=n.U;i?i.L===n?i.L=r:i.R=r:t._=r,r.U=i,n.U=r,n.R=r.L,n.R&&(n.R.U=n),r.L=n}function bk(t,e){var n=e,r=e.L,i=n.U;i?i.L===n?i.L=r:i.R=r:t._=r,r.U=i,n.U=r,n.L=r.R,n.L&&(n.L.U=n),r.R=n}function _k(t){for(;t.L;)t=t.L;return t}gk.prototype={constructor:gk,insert:function(t,e){var n,r,i;if(t){if(e.P=t,e.N=t.N,t.N&&(t.N.P=e),t.N=e,t.R){for(t=t.R;t.L;)t=t.L;t.L=e}else t.R=e;n=t}else this._?(t=_k(this._),e.P=null,e.N=t,t.P=t.L=e,n=t):(e.P=e.N=null,this._=e,n=null);for(e.L=e.R=null,e.U=n,e.C=!0,t=e;n&&n.C;)n===(r=n.U).L?(i=r.R)&&i.C?(n.C=i.C=!1,r.C=!0,t=r):(t===n.R&&(vk(this,n),n=(t=n).U),n.C=!1,r.C=!0,bk(this,r)):(i=r.L)&&i.C?(n.C=i.C=!1,r.C=!0,t=r):(t===n.L&&(bk(this,n),n=(t=n).U),n.C=!1,r.C=!0,vk(this,r)),n=t.U;this._.C=!1},remove:function(t){t.N&&(t.N.P=t.P),t.P&&(t.P.N=t.N),t.N=t.P=null;var e,n,r,i=t.U,a=t.L,o=t.R;if(n=a?o?_k(o):a:o,i?i.L===t?i.L=n:i.R=n:this._=n,a&&o?(r=n.C,n.C=t.C,n.L=a,a.U=n,n!==o?(i=n.U,n.U=t.U,t=n.R,i.L=t,n.R=o,o.U=n):(n.U=i,i=n,t=n.R)):(r=t.C,t=n),t&&(t.U=i),!r)if(t&&t.C)t.C=!1;else{do{if(t===this._)break;if(t===i.L){if((e=i.R).C&&(e.C=!1,i.C=!0,vk(this,i),e=i.R),e.L&&e.L.C||e.R&&e.R.C){e.R&&e.R.C||(e.L.C=!1,e.C=!0,bk(this,e),e=i.R),e.C=i.C,i.C=e.R.C=!1,vk(this,i),t=this._;break}}else if((e=i.L).C&&(e.C=!1,i.C=!0,bk(this,i),e=i.L),e.L&&e.L.C||e.R&&e.R.C){e.L&&e.L.C||(e.R.C=!1,e.C=!0,vk(this,e),e=i.L),e.C=i.C,i.C=e.L.C=!1,bk(this,i),t=this._;break}e.C=!0,t=i,i=i.U}while(!t.C);t&&(t.C=!1)}}};const xk=gk;function wk(t,e,n,r){var i=[null,null],a=Wk.push(i)-1;return i.left=t,i.right=e,n&&Tk(i,t,e,n),r&&Tk(i,e,t,r),Hk[t.index].halfedges.push(a),Hk[e.index].halfedges.push(a),i}function kk(t,e,n){var r=[e,n];return r.left=t,r}function Tk(t,e,n,r){t[0]||t[1]?t.left===n?t[1]=r:t[0]=r:(t[0]=r,t.left=e,t.right=n)}function Ek(t,e,n,r,i){var a,o=t[0],s=t[1],c=o[0],u=o[1],l=0,h=1,f=s[0]-c,d=s[1]-u;if(a=e-c,f||!(a>0)){if(a/=f,f<0){if(a<l)return;a<h&&(h=a)}else if(f>0){if(a>h)return;a>l&&(l=a)}if(a=r-c,f||!(a<0)){if(a/=f,f<0){if(a>h)return;a>l&&(l=a)}else if(f>0){if(a<l)return;a<h&&(h=a)}if(a=n-u,d||!(a>0)){if(a/=d,d<0){if(a<l)return;a<h&&(h=a)}else if(d>0){if(a>h)return;a>l&&(l=a)}if(a=i-u,d||!(a<0)){if(a/=d,d<0){if(a>h)return;a>l&&(l=a)}else if(d>0){if(a<l)return;a<h&&(h=a)}return!(l>0||h<1)||(l>0&&(t[0]=[c+l*f,u+l*d]),h<1&&(t[1]=[c+h*f,u+h*d]),!0)}}}}}function Ck(t,e,n,r,i){var a=t[1];if(a)return!0;var o,s,c=t[0],u=t.left,l=t.right,h=u[0],f=u[1],d=l[0],p=l[1],y=(h+d)/2,g=(f+p)/2;if(p===f){if(y<e||y>=r)return;if(h>d){if(c){if(c[1]>=i)return}else c=[y,n];a=[y,i]}else{if(c){if(c[1]<n)return}else c=[y,i];a=[y,n]}}else if(s=g-(o=(h-d)/(p-f))*y,o<-1||o>1)if(h>d){if(c){if(c[1]>=i)return}else c=[(n-s)/o,n];a=[(i-s)/o,i]}else{if(c){if(c[1]<n)return}else c=[(i-s)/o,i];a=[(n-s)/o,n]}else if(f<p){if(c){if(c[0]>=r)return}else c=[e,o*e+s];a=[r,o*r+s]}else{if(c){if(c[0]<e)return}else c=[r,o*r+s];a=[e,o*e+s]}return t[0]=c,t[1]=a,!0}function Sk(t,e){var n=t.site,r=e.left,i=e.right;return n===i&&(i=r,r=n),i?Math.atan2(i[1]-r[1],i[0]-r[0]):(n===r?(r=e[1],i=e[0]):(r=e[0],i=e[1]),Math.atan2(r[0]-i[0],i[1]-r[1]))}function Ak(t,e){return e[+(e.left!==t.site)]}function Mk(t,e){return e[+(e.left===t.site)]}var Nk,Dk=[];function Ok(){mk(this),this.x=this.y=this.arc=this.site=this.cy=null}function Bk(t){var e=t.P,n=t.N;if(e&&n){var r=e.site,i=t.site,a=n.site;if(r!==a){var o=i[0],s=i[1],c=r[0]-o,u=r[1]-s,l=a[0]-o,h=a[1]-s,f=2*(c*h-u*l);if(!(f>=-Gk)){var d=c*c+u*u,p=l*l+h*h,y=(h*d-u*p)/f,g=(c*p-l*d)/f,m=Dk.pop()||new Ok;m.arc=t,m.site=i,m.x=y+o,m.y=(m.cy=g+s)+Math.sqrt(y*y+g*g),t.circle=m;for(var v=null,b=$k._;b;)if(m.y<b.y||m.y===b.y&&m.x<=b.x){if(!b.L){v=b.P;break}b=b.L}else{if(!b.R){v=b;break}b=b.R}$k.insert(v,m),v||(Nk=m)}}}}function Lk(t){var e=t.circle;e&&(e.P||(Nk=e.N),$k.remove(e),Dk.push(e),mk(e),t.circle=null)}var Ik=[];function Rk(){mk(this),this.edge=this.site=this.circle=null}function Fk(t){var e=Ik.pop()||new Rk;return e.site=t,e}function Pk(t){Lk(t),qk.remove(t),Ik.push(t),mk(t)}function jk(t){var e=t.circle,n=e.x,r=e.cy,i=[n,r],a=t.P,o=t.N,s=[t];Pk(t);for(var c=a;c.circle&&Math.abs(n-c.circle.x)<Vk&&Math.abs(r-c.circle.cy)<Vk;)a=c.P,s.unshift(c),Pk(c),c=a;s.unshift(c),Lk(c);for(var u=o;u.circle&&Math.abs(n-u.circle.x)<Vk&&Math.abs(r-u.circle.cy)<Vk;)o=u.N,s.push(u),Pk(u),u=o;s.push(u),Lk(u);var l,h=s.length;for(l=1;l<h;++l)u=s[l],c=s[l-1],Tk(u.edge,c.site,u.site,i);c=s[0],(u=s[h-1]).edge=wk(c.site,u.site,null,i),Bk(c),Bk(u)}function Yk(t){for(var e,n,r,i,a=t[0],o=t[1],s=qk._;s;)if((r=zk(s,o)-a)>Vk)s=s.L;else{if(!((i=a-Uk(s,o))>Vk)){r>-Vk?(e=s.P,n=s):i>-Vk?(e=s,n=s.N):e=n=s;break}if(!s.R){e=s;break}s=s.R}!function(t){Hk[t.index]={site:t,halfedges:[]}}(t);var c=Fk(t);if(qk.insert(e,c),e||n){if(e===n)return Lk(e),n=Fk(e.site),qk.insert(c,n),c.edge=n.edge=wk(e.site,c.site),Bk(e),void Bk(n);if(n){Lk(e),Lk(n);var u=e.site,l=u[0],h=u[1],f=t[0]-l,d=t[1]-h,p=n.site,y=p[0]-l,g=p[1]-h,m=2*(f*g-d*y),v=f*f+d*d,b=y*y+g*g,_=[(g*v-d*b)/m+l,(f*b-y*v)/m+h];Tk(n.edge,u,p,_),c.edge=wk(u,t,null,_),n.edge=wk(t,p,null,_),Bk(e),Bk(n)}else c.edge=wk(e.site,c.site)}}function zk(t,e){var n=t.site,r=n[0],i=n[1],a=i-e;if(!a)return r;var o=t.P;if(!o)return-1/0;var s=(n=o.site)[0],c=n[1],u=c-e;if(!u)return s;var l=s-r,h=1/a-1/u,f=l/u;return h?(-f+Math.sqrt(f*f-2*h*(l*l/(-2*u)-c+u/2+i-a/2)))/h+r:(r+s)/2}function Uk(t,e){var n=t.N;if(n)return zk(n,e);var r=t.site;return r[1]===e?r[0]:1/0}var qk,Hk,$k,Wk,Vk=1e-6,Gk=1e-12;function Xk(t,e,n){return(t[0]-n[0])*(e[1]-t[1])-(t[0]-e[0])*(n[1]-t[1])}function Zk(t,e){return e[1]-t[1]||e[0]-t[0]}function Qk(t,e){var n,r,i,a=t.sort(Zk).pop();for(Wk=[],Hk=new Array(t.length),qk=new xk,$k=new xk;;)if(i=Nk,a&&(!i||a[1]<i.y||a[1]===i.y&&a[0]<i.x))a[0]===n&&a[1]===r||(Yk(a),n=a[0],r=a[1]),a=t.pop();else{if(!i)break;jk(i.arc)}if(function(){for(var t,e,n,r,i=0,a=Hk.length;i<a;++i)if((t=Hk[i])&&(r=(e=t.halfedges).length)){var o=new Array(r),s=new Array(r);for(n=0;n<r;++n)o[n]=n,s[n]=Sk(t,Wk[e[n]]);for(o.sort((function(t,e){return s[e]-s[t]})),n=0;n<r;++n)s[n]=e[o[n]];for(n=0;n<r;++n)e[n]=s[n]}}(),e){var o=+e[0][0],s=+e[0][1],c=+e[1][0],u=+e[1][1];!function(t,e,n,r){for(var i,a=Wk.length;a--;)Ck(i=Wk[a],t,e,n,r)&&Ek(i,t,e,n,r)&&(Math.abs(i[0][0]-i[1][0])>Vk||Math.abs(i[0][1]-i[1][1])>Vk)||delete Wk[a]}(o,s,c,u),function(t,e,n,r){var i,a,o,s,c,u,l,h,f,d,p,y,g=Hk.length,m=!0;for(i=0;i<g;++i)if(a=Hk[i]){for(o=a.site,s=(c=a.halfedges).length;s--;)Wk[c[s]]||c.splice(s,1);for(s=0,u=c.length;s<u;)p=(d=Mk(a,Wk[c[s]]))[0],y=d[1],h=(l=Ak(a,Wk[c[++s%u]]))[0],f=l[1],(Math.abs(p-h)>Vk||Math.abs(y-f)>Vk)&&(c.splice(s,0,Wk.push(kk(o,d,Math.abs(p-t)<Vk&&r-y>Vk?[t,Math.abs(h-t)<Vk?f:r]:Math.abs(y-r)<Vk&&n-p>Vk?[Math.abs(f-r)<Vk?h:n,r]:Math.abs(p-n)<Vk&&y-e>Vk?[n,Math.abs(h-n)<Vk?f:e]:Math.abs(y-e)<Vk&&p-t>Vk?[Math.abs(f-e)<Vk?h:t,e]:null))-1),++u);u&&(m=!1)}if(m){var v,b,_,x=1/0;for(i=0,m=null;i<g;++i)(a=Hk[i])&&(_=(v=(o=a.site)[0]-t)*v+(b=o[1]-e)*b)<x&&(x=_,m=a);if(m){var w=[t,e],k=[t,r],T=[n,r],E=[n,e];m.halfedges.push(Wk.push(kk(o=m.site,w,k))-1,Wk.push(kk(o,k,T))-1,Wk.push(kk(o,T,E))-1,Wk.push(kk(o,E,w))-1)}}for(i=0;i<g;++i)(a=Hk[i])&&(a.halfedges.length||delete Hk[i])}(o,s,c,u)}this.edges=Wk,this.cells=Hk,qk=$k=Wk=Hk=null}function Kk(){var t=pk,e=yk,n=null;function r(r){return new Qk(r.map((function(n,i){var a=[Math.round(t(n,i,r)/Vk)*Vk,Math.round(e(n,i,r)/Vk)*Vk];return a.index=i,a.data=n,a})),n)}return r.polygons=function(t){return r(t).polygons()},r.links=function(t){return r(t).links()},r.triangles=function(t){return r(t).triangles()},r.x=function(e){return arguments.length?(t="function"==typeof e?e:dk(+e),r):t},r.y=function(t){return arguments.length?(e="function"==typeof t?t:dk(+t),r):e},r.extent=function(t){return arguments.length?(n=null==t?null:[[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]],r):n&&[[n[0][0],n[0][1]],[n[1][0],n[1][1]]]},r.size=function(t){return arguments.length?(n=null==t?null:[[0,0],[+t[0],+t[1]]],r):n&&[n[1][0]-n[0][0],n[1][1]-n[0][1]]},r}function Jk(t){return function(){return t}}function tT(t,e,n){this.target=t,this.type=e,this.transform=n}function eT(t,e,n){this.k=t,this.x=e,this.y=n}Qk.prototype={constructor:Qk,polygons:function(){var t=this.edges;return this.cells.map((function(e){var n=e.halfedges.map((function(n){return Ak(e,t[n])}));return n.data=e.site.data,n}))},triangles:function(){var t=[],e=this.edges;return this.cells.forEach((function(n,r){if(a=(i=n.halfedges).length)for(var i,a,o,s=n.site,c=-1,u=e[i[a-1]],l=u.left===s?u.right:u.left;++c<a;)o=l,l=(u=e[i[c]]).left===s?u.right:u.left,o&&l&&r<o.index&&r<l.index&&Xk(s,o,l)<0&&t.push([s.data,o.data,l.data])})),t},links:function(){return this.edges.filter((function(t){return t.right})).map((function(t){return{source:t.left.data,target:t.right.data}}))},find:function(t,e,n){for(var r,i,a=this,o=a._found||0,s=a.cells.length;!(i=a.cells[o]);)if(++o>=s)return null;var c=t-i.site[0],u=e-i.site[1],l=c*c+u*u;do{i=a.cells[r=o],o=null,i.halfedges.forEach((function(n){var r=a.edges[n],s=r.left;if(s!==i.site&&s||(s=r.right)){var c=t-s[0],u=e-s[1],h=c*c+u*u;h<l&&(l=h,o=s.index)}}))}while(null!==o);return a._found=r,null==n||l<=n*n?i.site:null}},eT.prototype={constructor:eT,scale:function(t){return 1===t?this:new eT(this.k*t,this.x,this.y)},translate:function(t,e){return 0===t&0===e?this:new eT(this.k,this.x+this.k*t,this.y+this.k*e)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var nT=new eT(1,0,0);function rT(t){for(;!t.__zoom;)if(!(t=t.parentNode))return nT;return t.__zoom}function iT(){le.stopImmediatePropagation()}function aT(){le.preventDefault(),le.stopImmediatePropagation()}function oT(){return!le.ctrlKey&&!le.button}function sT(){var t=this;return t instanceof SVGElement?(t=t.ownerSVGElement||t).hasAttribute("viewBox")?[[(t=t.viewBox.baseVal).x,t.y],[t.x+t.width,t.y+t.height]]:[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]:[[0,0],[t.clientWidth,t.clientHeight]]}function cT(){return this.__zoom||nT}function uT(){return-le.deltaY*(1===le.deltaMode?.05:le.deltaMode?1:.002)}function lT(){return navigator.maxTouchPoints||"ontouchstart"in this}function hT(t,e,n){var r=t.invertX(e[0][0])-n[0][0],i=t.invertX(e[1][0])-n[1][0],a=t.invertY(e[0][1])-n[0][1],o=t.invertY(e[1][1])-n[1][1];return t.translate(i>r?(r+i)/2:Math.min(0,r)||Math.max(0,i),o>a?(a+o)/2:Math.min(0,a)||Math.max(0,o))}function fT(){var t,e,n=oT,r=sT,i=hT,a=uT,o=lT,s=[0,1/0],c=[[-1/0,-1/0],[1/0,1/0]],u=250,l=Op,h=ft("start","zoom","end"),f=500,d=0;function p(t){t.property("__zoom",cT).on("wheel.zoom",x).on("mousedown.zoom",w).on("dblclick.zoom",k).filter(o).on("touchstart.zoom",T).on("touchmove.zoom",E).on("touchend.zoom touchcancel.zoom",C).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function y(t,e){return(e=Math.max(s[0],Math.min(s[1],e)))===t.k?t:new eT(e,t.x,t.y)}function g(t,e,n){var r=e[0]-n[0]*t.k,i=e[1]-n[1]*t.k;return r===t.x&&i===t.y?t:new eT(t.k,r,i)}function m(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function v(t,e,n){t.on("start.zoom",(function(){b(this,arguments).start()})).on("interrupt.zoom end.zoom",(function(){b(this,arguments).end()})).tween("zoom",(function(){var t=this,i=arguments,a=b(t,i),o=r.apply(t,i),s=null==n?m(o):"function"==typeof n?n.apply(t,i):n,c=Math.max(o[1][0]-o[0][0],o[1][1]-o[0][1]),u=t.__zoom,h="function"==typeof e?e.apply(t,i):e,f=l(u.invert(s).concat(c/u.k),h.invert(s).concat(c/h.k));return function(t){if(1===t)t=h;else{var e=f(t),n=c/e[2];t=new eT(n,s[0]-e[0]*n,s[1]-e[1]*n)}a.zoom(null,t)}}))}function b(t,e,n){return!n&&t.__zooming||new _(t,e)}function _(t,e){this.that=t,this.args=e,this.active=0,this.extent=r.apply(t,e),this.taps=0}function x(){if(n.apply(this,arguments)){var t=b(this,arguments),e=this.__zoom,r=Math.max(s[0],Math.min(s[1],e.k*Math.pow(2,a.apply(this,arguments)))),o=Bn(this);if(t.wheel)t.mouse[0][0]===o[0]&&t.mouse[0][1]===o[1]||(t.mouse[1]=e.invert(t.mouse[0]=o)),clearTimeout(t.wheel);else{if(e.k===r)return;t.mouse=[o,e.invert(o)],ar(this),t.start()}aT(),t.wheel=setTimeout(u,150),t.zoom("mouse",i(g(y(e,r),t.mouse[0],t.mouse[1]),t.extent,c))}function u(){t.wheel=null,t.end()}}function w(){if(!e&&n.apply(this,arguments)){var t=b(this,arguments,!0),r=Te(le.view).on("mousemove.zoom",u,!0).on("mouseup.zoom",l,!0),a=Bn(this),o=le.clientX,s=le.clientY;Se(le.view),iT(),t.mouse=[a,this.__zoom.invert(a)],ar(this),t.start()}function u(){if(aT(),!t.moved){var e=le.clientX-o,n=le.clientY-s;t.moved=e*e+n*n>d}t.zoom("mouse",i(g(t.that.__zoom,t.mouse[0]=Bn(t.that),t.mouse[1]),t.extent,c))}function l(){r.on("mousemove.zoom mouseup.zoom",null),Ae(le.view,t.moved),aT(),t.end()}}function k(){if(n.apply(this,arguments)){var t=this.__zoom,e=Bn(this),a=t.invert(e),o=t.k*(le.shiftKey?.5:2),s=i(g(y(t,o),e,a),r.apply(this,arguments),c);aT(),u>0?Te(this).transition().duration(u).call(v,s,e):Te(this).call(p.transform,s)}}function T(){if(n.apply(this,arguments)){var e,r,i,a,o=le.touches,s=o.length,c=b(this,arguments,le.changedTouches.length===s);for(iT(),r=0;r<s;++r)a=[a=On(this,o,(i=o[r]).identifier),this.__zoom.invert(a),i.identifier],c.touch0?c.touch1||c.touch0[2]===a[2]||(c.touch1=a,c.taps=0):(c.touch0=a,e=!0,c.taps=1+!!t);t&&(t=clearTimeout(t)),e&&(c.taps<2&&(t=setTimeout((function(){t=null}),f)),ar(this),c.start())}}function E(){if(this.__zooming){var e,n,r,a,o=b(this,arguments),s=le.changedTouches,u=s.length;for(aT(),t&&(t=clearTimeout(t)),o.taps=0,e=0;e<u;++e)r=On(this,s,(n=s[e]).identifier),o.touch0&&o.touch0[2]===n.identifier?o.touch0[0]=r:o.touch1&&o.touch1[2]===n.identifier&&(o.touch1[0]=r);if(n=o.that.__zoom,o.touch1){var l=o.touch0[0],h=o.touch0[1],f=o.touch1[0],d=o.touch1[1],p=(p=f[0]-l[0])*p+(p=f[1]-l[1])*p,m=(m=d[0]-h[0])*m+(m=d[1]-h[1])*m;n=y(n,Math.sqrt(p/m)),r=[(l[0]+f[0])/2,(l[1]+f[1])/2],a=[(h[0]+d[0])/2,(h[1]+d[1])/2]}else{if(!o.touch0)return;r=o.touch0[0],a=o.touch0[1]}o.zoom("touch",i(g(n,r,a),o.extent,c))}}function C(){if(this.__zooming){var t,n,r=b(this,arguments),i=le.changedTouches,a=i.length;for(iT(),e&&clearTimeout(e),e=setTimeout((function(){e=null}),f),t=0;t<a;++t)n=i[t],r.touch0&&r.touch0[2]===n.identifier?delete r.touch0:r.touch1&&r.touch1[2]===n.identifier&&delete r.touch1;if(r.touch1&&!r.touch0&&(r.touch0=r.touch1,delete r.touch1),r.touch0)r.touch0[1]=this.__zoom.invert(r.touch0[0]);else if(r.end(),2===r.taps){var o=Te(this).on("dblclick.zoom");o&&o.apply(this,arguments)}}}return p.transform=function(t,e,n){var r=t.selection?t.selection():t;r.property("__zoom",cT),t!==r?v(t,e,n):r.interrupt().each((function(){b(this,arguments).start().zoom(null,"function"==typeof e?e.apply(this,arguments):e).end()}))},p.scaleBy=function(t,e,n){p.scaleTo(t,(function(){var t=this.__zoom.k,n="function"==typeof e?e.apply(this,arguments):e;return t*n}),n)},p.scaleTo=function(t,e,n){p.transform(t,(function(){var t=r.apply(this,arguments),a=this.__zoom,o=null==n?m(t):"function"==typeof n?n.apply(this,arguments):n,s=a.invert(o),u="function"==typeof e?e.apply(this,arguments):e;return i(g(y(a,u),o,s),t,c)}),n)},p.translateBy=function(t,e,n){p.transform(t,(function(){return i(this.__zoom.translate("function"==typeof e?e.apply(this,arguments):e,"function"==typeof n?n.apply(this,arguments):n),r.apply(this,arguments),c)}))},p.translateTo=function(t,e,n,a){p.transform(t,(function(){var t=r.apply(this,arguments),o=this.__zoom,s=null==a?m(t):"function"==typeof a?a.apply(this,arguments):a;return i(nT.translate(s[0],s[1]).scale(o.k).translate("function"==typeof e?-e.apply(this,arguments):-e,"function"==typeof n?-n.apply(this,arguments):-n),t,c)}),a)},_.prototype={start:function(){return 1==++this.active&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(t,e){return this.mouse&&"mouse"!==t&&(this.mouse[1]=e.invert(this.mouse[0])),this.touch0&&"touch"!==t&&(this.touch0[1]=e.invert(this.touch0[0])),this.touch1&&"touch"!==t&&(this.touch1[1]=e.invert(this.touch1[0])),this.that.__zoom=e,this.emit("zoom"),this},end:function(){return 0==--this.active&&(delete this.that.__zooming,this.emit("end")),this},emit:function(t){ge(new tT(p,t,this.that.__zoom),h.apply,h,[t,this.that,this.args])}},p.wheelDelta=function(t){return arguments.length?(a="function"==typeof t?t:Jk(+t),p):a},p.filter=function(t){return arguments.length?(n="function"==typeof t?t:Jk(!!t),p):n},p.touchable=function(t){return arguments.length?(o="function"==typeof t?t:Jk(!!t),p):o},p.extent=function(t){return arguments.length?(r="function"==typeof t?t:Jk([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),p):r},p.scaleExtent=function(t){return arguments.length?(s[0]=+t[0],s[1]=+t[1],p):[s[0],s[1]]},p.translateExtent=function(t){return arguments.length?(c[0][0]=+t[0][0],c[1][0]=+t[1][0],c[0][1]=+t[0][1],c[1][1]=+t[1][1],p):[[c[0][0],c[0][1]],[c[1][0],c[1][1]]]},p.constrain=function(t){return arguments.length?(i=t,p):i},p.duration=function(t){return arguments.length?(u=+t,p):u},p.interpolate=function(t){return arguments.length?(l=t,p):l},p.on=function(){var t=h.on.apply(h,arguments);return t===h?p:t},p.clickDistance=function(t){return arguments.length?(d=(t=+t)*t,p):Math.sqrt(d)},p}rT.prototype=eT.prototype},681:(t,e,n)=>{t.exports={graphlib:n(574),layout:n(8123),debug:n(7570),util:{time:n(1138).time,notime:n(1138).notime},version:n(8177)}},1207:(t,e,n)=>{"use strict";var r=n(8436),i=n(4079);t.exports={run:function(t){var e="greedy"===t.graph().acyclicer?i(t,function(t){return function(e){return t.edge(e).weight}}(t)):function(t){var e=[],n={},i={};return r.forEach(t.nodes(),(function a(o){r.has(i,o)||(i[o]=!0,n[o]=!0,r.forEach(t.outEdges(o),(function(t){r.has(n,t.w)?e.push(t):a(t.w)})),delete n[o])})),e}(t);r.forEach(e,(function(e){var n=t.edge(e);t.removeEdge(e),n.forwardName=e.name,n.reversed=!0,t.setEdge(e.w,e.v,n,r.uniqueId("rev"))}))},undo:function(t){r.forEach(t.edges(),(function(e){var n=t.edge(e);if(n.reversed){t.removeEdge(e);var r=n.forwardName;delete n.reversed,delete n.forwardName,t.setEdge(e.w,e.v,n,r)}}))}}},1133:(t,e,n)=>{var r=n(8436),i=n(1138);function a(t,e,n,r,a,o){var s={width:0,height:0,rank:o,borderType:e},c=a[e][o-1],u=i.addDummyNode(t,"border",s,n);a[e][o]=u,t.setParent(u,r),c&&t.setEdge(c,u,{weight:1})}t.exports=function(t){r.forEach(t.children(),(function e(n){var i=t.children(n),o=t.node(n);if(i.length&&r.forEach(i,e),r.has(o,"minRank")){o.borderLeft=[],o.borderRight=[];for(var s=o.minRank,c=o.maxRank+1;s<c;++s)a(t,"borderLeft","_bl",n,o,s),a(t,"borderRight","_br",n,o,s)}}))}},3258:(t,e,n)=>{"use strict";var r=n(8436);function i(t){r.forEach(t.nodes(),(function(e){a(t.node(e))})),r.forEach(t.edges(),(function(e){a(t.edge(e))}))}function a(t){var e=t.width;t.width=t.height,t.height=e}function o(t){t.y=-t.y}function s(t){var e=t.x;t.x=t.y,t.y=e}t.exports={adjust:function(t){var e=t.graph().rankdir.toLowerCase();"lr"!==e&&"rl"!==e||i(t)},undo:function(t){var e=t.graph().rankdir.toLowerCase();"bt"!==e&&"rl"!==e||function(t){r.forEach(t.nodes(),(function(e){o(t.node(e))})),r.forEach(t.edges(),(function(e){var n=t.edge(e);r.forEach(n.points,o),r.has(n,"y")&&o(n)}))}(t),"lr"!==e&&"rl"!==e||(function(t){r.forEach(t.nodes(),(function(e){s(t.node(e))})),r.forEach(t.edges(),(function(e){var n=t.edge(e);r.forEach(n.points,s),r.has(n,"x")&&s(n)}))}(t),i(t))}}},7822:t=>{function e(){var t={};t._next=t._prev=t,this._sentinel=t}function n(t){t._prev._next=t._next,t._next._prev=t._prev,delete t._next,delete t._prev}function r(t,e){if("_next"!==t&&"_prev"!==t)return e}t.exports=e,e.prototype.dequeue=function(){var t=this._sentinel,e=t._prev;if(e!==t)return n(e),e},e.prototype.enqueue=function(t){var e=this._sentinel;t._prev&&t._next&&n(t),t._next=e._next,e._next._prev=t,e._next=t,t._prev=e},e.prototype.toString=function(){for(var t=[],e=this._sentinel,n=e._prev;n!==e;)t.push(JSON.stringify(n,r)),n=n._prev;return"["+t.join(", ")+"]"}},7570:(t,e,n)=>{var r=n(8436),i=n(1138),a=n(574).Graph;t.exports={debugOrdering:function(t){var e=i.buildLayerMatrix(t),n=new a({compound:!0,multigraph:!0}).setGraph({});return r.forEach(t.nodes(),(function(e){n.setNode(e,{label:e}),n.setParent(e,"layer"+t.node(e).rank)})),r.forEach(t.edges(),(function(t){n.setEdge(t.v,t.w,{},t.name)})),r.forEach(e,(function(t,e){var i="layer"+e;n.setNode(i,{rank:"same"}),r.reduce(t,(function(t,e){return n.setEdge(t,e,{style:"invis"}),e}))})),n}}},574:(t,e,n)=>{var r;try{r=n(8282)}catch(t){}r||(r=window.graphlib),t.exports=r},4079:(t,e,n)=>{var r=n(8436),i=n(574).Graph,a=n(7822);t.exports=function(t,e){if(t.nodeCount()<=1)return[];var n=function(t,e){var n=new i,o=0,s=0;r.forEach(t.nodes(),(function(t){n.setNode(t,{v:t,in:0,out:0})})),r.forEach(t.edges(),(function(t){var r=n.edge(t.v,t.w)||0,i=e(t),a=r+i;n.setEdge(t.v,t.w,a),s=Math.max(s,n.node(t.v).out+=i),o=Math.max(o,n.node(t.w).in+=i)}));var u=r.range(s+o+3).map((function(){return new a})),l=o+1;return r.forEach(n.nodes(),(function(t){c(u,l,n.node(t))})),{graph:n,buckets:u,zeroIdx:l}}(t,e||o),u=function(t,e,n){for(var r,i=[],a=e[e.length-1],o=e[0];t.nodeCount();){for(;r=o.dequeue();)s(t,e,n,r);for(;r=a.dequeue();)s(t,e,n,r);if(t.nodeCount())for(var c=e.length-2;c>0;--c)if(r=e[c].dequeue()){i=i.concat(s(t,e,n,r,!0));break}}return i}(n.graph,n.buckets,n.zeroIdx);return r.flatten(r.map(u,(function(e){return t.outEdges(e.v,e.w)})),!0)};var o=r.constant(1);function s(t,e,n,i,a){var o=a?[]:void 0;return r.forEach(t.inEdges(i.v),(function(r){var i=t.edge(r),s=t.node(r.v);a&&o.push({v:r.v,w:r.w}),s.out-=i,c(e,n,s)})),r.forEach(t.outEdges(i.v),(function(r){var i=t.edge(r),a=r.w,o=t.node(a);o.in-=i,c(e,n,o)})),t.removeNode(i.v),o}function c(t,e,n){n.out?n.in?t[n.out-n.in+e].enqueue(n):t[t.length-1].enqueue(n):t[0].enqueue(n)}},8123:(t,e,n)=>{"use strict";var r=n(8436),i=n(1207),a=n(5995),o=n(8093),s=n(1138).normalizeRanks,c=n(4219),u=n(1138).removeEmptyRanks,l=n(2981),h=n(1133),f=n(3258),d=n(3408),p=n(7873),y=n(1138),g=n(574).Graph;t.exports=function(t,e){var n=e&&e.debugTiming?y.time:y.notime;n("layout",(function(){var e=n("  buildLayoutGraph",(function(){return function(t){var e=new g({multigraph:!0,compound:!0}),n=C(t.graph());return e.setGraph(r.merge({},v,E(n,m),r.pick(n,b))),r.forEach(t.nodes(),(function(n){var i=C(t.node(n));e.setNode(n,r.defaults(E(i,_),x)),e.setParent(n,t.parent(n))})),r.forEach(t.edges(),(function(n){var i=C(t.edge(n));e.setEdge(n,r.merge({},k,E(i,w),r.pick(i,T)))})),e}(t)}));n("  runLayout",(function(){!function(t,e){e("    makeSpaceForEdgeLabels",(function(){!function(t){var e=t.graph();e.ranksep/=2,r.forEach(t.edges(),(function(n){var r=t.edge(n);r.minlen*=2,"c"!==r.labelpos.toLowerCase()&&("TB"===e.rankdir||"BT"===e.rankdir?r.width+=r.labeloffset:r.height+=r.labeloffset)}))}(t)})),e("    removeSelfEdges",(function(){!function(t){r.forEach(t.edges(),(function(e){if(e.v===e.w){var n=t.node(e.v);n.selfEdges||(n.selfEdges=[]),n.selfEdges.push({e,label:t.edge(e)}),t.removeEdge(e)}}))}(t)})),e("    acyclic",(function(){i.run(t)})),e("    nestingGraph.run",(function(){l.run(t)})),e("    rank",(function(){o(y.asNonCompoundGraph(t))})),e("    injectEdgeLabelProxies",(function(){!function(t){r.forEach(t.edges(),(function(e){var n=t.edge(e);if(n.width&&n.height){var r=t.node(e.v),i={rank:(t.node(e.w).rank-r.rank)/2+r.rank,e};y.addDummyNode(t,"edge-proxy",i,"_ep")}}))}(t)})),e("    removeEmptyRanks",(function(){u(t)})),e("    nestingGraph.cleanup",(function(){l.cleanup(t)})),e("    normalizeRanks",(function(){s(t)})),e("    assignRankMinMax",(function(){!function(t){var e=0;r.forEach(t.nodes(),(function(n){var i=t.node(n);i.borderTop&&(i.minRank=t.node(i.borderTop).rank,i.maxRank=t.node(i.borderBottom).rank,e=r.max(e,i.maxRank))})),t.graph().maxRank=e}(t)})),e("    removeEdgeLabelProxies",(function(){!function(t){r.forEach(t.nodes(),(function(e){var n=t.node(e);"edge-proxy"===n.dummy&&(t.edge(n.e).labelRank=n.rank,t.removeNode(e))}))}(t)})),e("    normalize.run",(function(){a.run(t)})),e("    parentDummyChains",(function(){c(t)})),e("    addBorderSegments",(function(){h(t)})),e("    order",(function(){d(t)})),e("    insertSelfEdges",(function(){!function(t){var e=y.buildLayerMatrix(t);r.forEach(e,(function(e){var n=0;r.forEach(e,(function(e,i){var a=t.node(e);a.order=i+n,r.forEach(a.selfEdges,(function(e){y.addDummyNode(t,"selfedge",{width:e.label.width,height:e.label.height,rank:a.rank,order:i+ ++n,e:e.e,label:e.label},"_se")})),delete a.selfEdges}))}))}(t)})),e("    adjustCoordinateSystem",(function(){f.adjust(t)})),e("    position",(function(){p(t)})),e("    positionSelfEdges",(function(){!function(t){r.forEach(t.nodes(),(function(e){var n=t.node(e);if("selfedge"===n.dummy){var r=t.node(n.e.v),i=r.x+r.width/2,a=r.y,o=n.x-i,s=r.height/2;t.setEdge(n.e,n.label),t.removeNode(e),n.label.points=[{x:i+2*o/3,y:a-s},{x:i+5*o/6,y:a-s},{x:i+o,y:a},{x:i+5*o/6,y:a+s},{x:i+2*o/3,y:a+s}],n.label.x=n.x,n.label.y=n.y}}))}(t)})),e("    removeBorderNodes",(function(){!function(t){r.forEach(t.nodes(),(function(e){if(t.children(e).length){var n=t.node(e),i=t.node(n.borderTop),a=t.node(n.borderBottom),o=t.node(r.last(n.borderLeft)),s=t.node(r.last(n.borderRight));n.width=Math.abs(s.x-o.x),n.height=Math.abs(a.y-i.y),n.x=o.x+n.width/2,n.y=i.y+n.height/2}})),r.forEach(t.nodes(),(function(e){"border"===t.node(e).dummy&&t.removeNode(e)}))}(t)})),e("    normalize.undo",(function(){a.undo(t)})),e("    fixupEdgeLabelCoords",(function(){!function(t){r.forEach(t.edges(),(function(e){var n=t.edge(e);if(r.has(n,"x"))switch("l"!==n.labelpos&&"r"!==n.labelpos||(n.width-=n.labeloffset),n.labelpos){case"l":n.x-=n.width/2+n.labeloffset;break;case"r":n.x+=n.width/2+n.labeloffset}}))}(t)})),e("    undoCoordinateSystem",(function(){f.undo(t)})),e("    translateGraph",(function(){!function(t){var e=Number.POSITIVE_INFINITY,n=0,i=Number.POSITIVE_INFINITY,a=0,o=t.graph(),s=o.marginx||0,c=o.marginy||0;function u(t){var r=t.x,o=t.y,s=t.width,c=t.height;e=Math.min(e,r-s/2),n=Math.max(n,r+s/2),i=Math.min(i,o-c/2),a=Math.max(a,o+c/2)}r.forEach(t.nodes(),(function(e){u(t.node(e))})),r.forEach(t.edges(),(function(e){var n=t.edge(e);r.has(n,"x")&&u(n)})),e-=s,i-=c,r.forEach(t.nodes(),(function(n){var r=t.node(n);r.x-=e,r.y-=i})),r.forEach(t.edges(),(function(n){var a=t.edge(n);r.forEach(a.points,(function(t){t.x-=e,t.y-=i})),r.has(a,"x")&&(a.x-=e),r.has(a,"y")&&(a.y-=i)})),o.width=n-e+s,o.height=a-i+c}(t)})),e("    assignNodeIntersects",(function(){!function(t){r.forEach(t.edges(),(function(e){var n,r,i=t.edge(e),a=t.node(e.v),o=t.node(e.w);i.points?(n=i.points[0],r=i.points[i.points.length-1]):(i.points=[],n=o,r=a),i.points.unshift(y.intersectRect(a,n)),i.points.push(y.intersectRect(o,r))}))}(t)})),e("    reversePoints",(function(){!function(t){r.forEach(t.edges(),(function(e){var n=t.edge(e);n.reversed&&n.points.reverse()}))}(t)})),e("    acyclic.undo",(function(){i.undo(t)}))}(e,n)})),n("  updateInputGraph",(function(){!function(t,e){r.forEach(t.nodes(),(function(n){var r=t.node(n),i=e.node(n);r&&(r.x=i.x,r.y=i.y,e.children(n).length&&(r.width=i.width,r.height=i.height))})),r.forEach(t.edges(),(function(n){var i=t.edge(n),a=e.edge(n);i.points=a.points,r.has(a,"x")&&(i.x=a.x,i.y=a.y)})),t.graph().width=e.graph().width,t.graph().height=e.graph().height}(t,e)}))}))};var m=["nodesep","edgesep","ranksep","marginx","marginy"],v={ranksep:50,edgesep:20,nodesep:50,rankdir:"tb"},b=["acyclicer","ranker","rankdir","align"],_=["width","height"],x={width:0,height:0},w=["minlen","weight","width","height","labeloffset"],k={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"},T=["labelpos"];function E(t,e){return r.mapValues(r.pick(t,e),Number)}function C(t){var e={};return r.forEach(t,(function(t,n){e[n.toLowerCase()]=t})),e}},8436:(t,e,n)=>{var r;try{r={cloneDeep:n(361),constant:n(5703),defaults:n(1747),each:n(6073),filter:n(3105),find:n(3311),flatten:n(5564),forEach:n(4486),forIn:n(2620),has:n(8721),isUndefined:n(2353),last:n(928),map:n(5161),mapValues:n(6604),max:n(6162),merge:n(3857),min:n(3632),minBy:n(2762),now:n(7771),pick:n(9722),range:n(6026),reduce:n(4061),sortBy:n(9734),uniqueId:n(3955),values:n(2628),zipObject:n(7287)}}catch(t){}r||(r=window._),t.exports=r},2981:(t,e,n)=>{var r=n(8436),i=n(1138);function a(t,e,n,o,s,c,u){var l=t.children(u);if(l.length){var h=i.addBorderNode(t,"_bt"),f=i.addBorderNode(t,"_bb"),d=t.node(u);t.setParent(h,u),d.borderTop=h,t.setParent(f,u),d.borderBottom=f,r.forEach(l,(function(r){a(t,e,n,o,s,c,r);var i=t.node(r),l=i.borderTop?i.borderTop:r,d=i.borderBottom?i.borderBottom:r,p=i.borderTop?o:2*o,y=l!==d?1:s-c[u]+1;t.setEdge(h,l,{weight:p,minlen:y,nestingEdge:!0}),t.setEdge(d,f,{weight:p,minlen:y,nestingEdge:!0})})),t.parent(u)||t.setEdge(e,h,{weight:0,minlen:s+c[u]})}else u!==e&&t.setEdge(e,u,{weight:0,minlen:n})}t.exports={run:function(t){var e=i.addDummyNode(t,"root",{},"_root"),n=function(t){var e={};function n(i,a){var o=t.children(i);o&&o.length&&r.forEach(o,(function(t){n(t,a+1)})),e[i]=a}return r.forEach(t.children(),(function(t){n(t,1)})),e}(t),o=r.max(r.values(n))-1,s=2*o+1;t.graph().nestingRoot=e,r.forEach(t.edges(),(function(e){t.edge(e).minlen*=s}));var c=function(t){return r.reduce(t.edges(),(function(e,n){return e+t.edge(n).weight}),0)}(t)+1;r.forEach(t.children(),(function(r){a(t,e,s,c,o,n,r)})),t.graph().nodeRankFactor=s},cleanup:function(t){var e=t.graph();t.removeNode(e.nestingRoot),delete e.nestingRoot,r.forEach(t.edges(),(function(e){t.edge(e).nestingEdge&&t.removeEdge(e)}))}}},5995:(t,e,n)=>{"use strict";var r=n(8436),i=n(1138);t.exports={run:function(t){t.graph().dummyChains=[],r.forEach(t.edges(),(function(e){!function(t,e){var n,r,a,o=e.v,s=t.node(o).rank,c=e.w,u=t.node(c).rank,l=e.name,h=t.edge(e),f=h.labelRank;if(u!==s+1){for(t.removeEdge(e),a=0,++s;s<u;++a,++s)h.points=[],r={width:0,height:0,edgeLabel:h,edgeObj:e,rank:s},n=i.addDummyNode(t,"edge",r,"_d"),s===f&&(r.width=h.width,r.height=h.height,r.dummy="edge-label",r.labelpos=h.labelpos),t.setEdge(o,n,{weight:h.weight},l),0===a&&t.graph().dummyChains.push(n),o=n;t.setEdge(o,c,{weight:h.weight},l)}}(t,e)}))},undo:function(t){r.forEach(t.graph().dummyChains,(function(e){var n,r=t.node(e),i=r.edgeLabel;for(t.setEdge(r.edgeObj,i);r.dummy;)n=t.successors(e)[0],t.removeNode(e),i.points.push({x:r.x,y:r.y}),"edge-label"===r.dummy&&(i.x=r.x,i.y=r.y,i.width=r.width,i.height=r.height),e=n,r=t.node(e)}))}}},5093:(t,e,n)=>{var r=n(8436);t.exports=function(t,e,n){var i,a={};r.forEach(n,(function(n){for(var r,o,s=t.parent(n);s;){if((r=t.parent(s))?(o=a[r],a[r]=s):(o=i,i=s),o&&o!==s)return void e.setEdge(o,s);s=r}}))}},5439:(t,e,n)=>{var r=n(8436);t.exports=function(t,e){return r.map(e,(function(e){var n=t.inEdges(e);if(n.length){var i=r.reduce(n,(function(e,n){var r=t.edge(n),i=t.node(n.v);return{sum:e.sum+r.weight*i.order,weight:e.weight+r.weight}}),{sum:0,weight:0});return{v:e,barycenter:i.sum/i.weight,weight:i.weight}}return{v:e}}))}},3128:(t,e,n)=>{var r=n(8436),i=n(574).Graph;t.exports=function(t,e,n){var a=function(t){for(var e;t.hasNode(e=r.uniqueId("_root")););return e}(t),o=new i({compound:!0}).setGraph({root:a}).setDefaultNodeLabel((function(e){return t.node(e)}));return r.forEach(t.nodes(),(function(i){var s=t.node(i),c=t.parent(i);(s.rank===e||s.minRank<=e&&e<=s.maxRank)&&(o.setNode(i),o.setParent(i,c||a),r.forEach(t[n](i),(function(e){var n=e.v===i?e.w:e.v,a=o.edge(n,i),s=r.isUndefined(a)?0:a.weight;o.setEdge(n,i,{weight:t.edge(e).weight+s})})),r.has(s,"minRank")&&o.setNode(i,{borderLeft:s.borderLeft[e],borderRight:s.borderRight[e]}))})),o}},6630:(t,e,n)=>{"use strict";var r=n(8436);function i(t,e,n){for(var i=r.zipObject(n,r.map(n,(function(t,e){return e}))),a=r.flatten(r.map(e,(function(e){return r.sortBy(r.map(t.outEdges(e),(function(e){return{pos:i[e.w],weight:t.edge(e).weight}})),"pos")})),!0),o=1;o<n.length;)o<<=1;var s=2*o-1;o-=1;var c=r.map(new Array(s),(function(){return 0})),u=0;return r.forEach(a.forEach((function(t){var e=t.pos+o;c[e]+=t.weight;for(var n=0;e>0;)e%2&&(n+=c[e+1]),c[e=e-1>>1]+=t.weight;u+=t.weight*n}))),u}t.exports=function(t,e){for(var n=0,r=1;r<e.length;++r)n+=i(t,e[r-1],e[r]);return n}},3408:(t,e,n)=>{"use strict";var r=n(8436),i=n(2588),a=n(6630),o=n(1026),s=n(3128),c=n(5093),u=n(574).Graph,l=n(1138);function h(t,e,n){return r.map(e,(function(e){return s(t,e,n)}))}function f(t,e){var n=new u;r.forEach(t,(function(t){var i=t.graph().root,a=o(t,i,n,e);r.forEach(a.vs,(function(e,n){t.node(e).order=n})),c(t,n,a.vs)}))}function d(t,e){r.forEach(e,(function(e){r.forEach(e,(function(e,n){t.node(e).order=n}))}))}t.exports=function(t){var e=l.maxRank(t),n=h(t,r.range(1,e+1),"inEdges"),o=h(t,r.range(e-1,-1,-1),"outEdges"),s=i(t);d(t,s);for(var c,u=Number.POSITIVE_INFINITY,p=0,y=0;y<4;++p,++y){f(p%2?n:o,p%4>=2),s=l.buildLayerMatrix(t);var g=a(t,s);g<u&&(y=0,c=r.cloneDeep(s),u=g)}d(t,c)}},2588:(t,e,n)=>{"use strict";var r=n(8436);t.exports=function(t){var e={},n=r.filter(t.nodes(),(function(e){return!t.children(e).length})),i=r.max(r.map(n,(function(e){return t.node(e).rank}))),a=r.map(r.range(i+1),(function(){return[]})),o=r.sortBy(n,(function(e){return t.node(e).rank}));return r.forEach(o,(function n(i){if(!r.has(e,i)){e[i]=!0;var o=t.node(i);a[o.rank].push(i),r.forEach(t.successors(i),n)}})),a}},9567:(t,e,n)=>{"use strict";var r=n(8436);t.exports=function(t,e){var n={};return r.forEach(t,(function(t,e){var i=n[t.v]={indegree:0,in:[],out:[],vs:[t.v],i:e};r.isUndefined(t.barycenter)||(i.barycenter=t.barycenter,i.weight=t.weight)})),r.forEach(e.edges(),(function(t){var e=n[t.v],i=n[t.w];r.isUndefined(e)||r.isUndefined(i)||(i.indegree++,e.out.push(n[t.w]))})),function(t){var e=[];function n(t){return function(e){var n,i,a,o;e.merged||(r.isUndefined(e.barycenter)||r.isUndefined(t.barycenter)||e.barycenter>=t.barycenter)&&(i=e,a=0,o=0,(n=t).weight&&(a+=n.barycenter*n.weight,o+=n.weight),i.weight&&(a+=i.barycenter*i.weight,o+=i.weight),n.vs=i.vs.concat(n.vs),n.barycenter=a/o,n.weight=o,n.i=Math.min(i.i,n.i),i.merged=!0)}}function i(e){return function(n){n.in.push(e),0==--n.indegree&&t.push(n)}}for(;t.length;){var a=t.pop();e.push(a),r.forEach(a.in.reverse(),n(a)),r.forEach(a.out,i(a))}return r.map(r.filter(e,(function(t){return!t.merged})),(function(t){return r.pick(t,["vs","i","barycenter","weight"])}))}(r.filter(n,(function(t){return!t.indegree})))}},1026:(t,e,n)=>{var r=n(8436),i=n(5439),a=n(9567),o=n(7304);t.exports=function t(e,n,s,c){var u=e.children(n),l=e.node(n),h=l?l.borderLeft:void 0,f=l?l.borderRight:void 0,d={};h&&(u=r.filter(u,(function(t){return t!==h&&t!==f})));var p=i(e,u);r.forEach(p,(function(n){if(e.children(n.v).length){var i=t(e,n.v,s,c);d[n.v]=i,r.has(i,"barycenter")&&(a=n,o=i,r.isUndefined(a.barycenter)?(a.barycenter=o.barycenter,a.weight=o.weight):(a.barycenter=(a.barycenter*a.weight+o.barycenter*o.weight)/(a.weight+o.weight),a.weight+=o.weight))}var a,o}));var y=a(p,s);!function(t,e){r.forEach(t,(function(t){t.vs=r.flatten(t.vs.map((function(t){return e[t]?e[t].vs:t})),!0)}))}(y,d);var g=o(y,c);if(h&&(g.vs=r.flatten([h,g.vs,f],!0),e.predecessors(h).length)){var m=e.node(e.predecessors(h)[0]),v=e.node(e.predecessors(f)[0]);r.has(g,"barycenter")||(g.barycenter=0,g.weight=0),g.barycenter=(g.barycenter*g.weight+m.order+v.order)/(g.weight+2),g.weight+=2}return g}},7304:(t,e,n)=>{var r=n(8436),i=n(1138);function a(t,e,n){for(var i;e.length&&(i=r.last(e)).i<=n;)e.pop(),t.push(i.vs),n++;return n}t.exports=function(t,e){var n,o=i.partition(t,(function(t){return r.has(t,"barycenter")})),s=o.lhs,c=r.sortBy(o.rhs,(function(t){return-t.i})),u=[],l=0,h=0,f=0;s.sort((n=!!e,function(t,e){return t.barycenter<e.barycenter?-1:t.barycenter>e.barycenter?1:n?e.i-t.i:t.i-e.i})),f=a(u,c,f),r.forEach(s,(function(t){f+=t.vs.length,u.push(t.vs),l+=t.barycenter*t.weight,h+=t.weight,f=a(u,c,f)}));var d={vs:r.flatten(u,!0)};return h&&(d.barycenter=l/h,d.weight=h),d}},4219:(t,e,n)=>{var r=n(8436);t.exports=function(t){var e=function(t){var e={},n=0;return r.forEach(t.children(),(function i(a){var o=n;r.forEach(t.children(a),i),e[a]={low:o,lim:n++}})),e}(t);r.forEach(t.graph().dummyChains,(function(n){for(var r=t.node(n),i=r.edgeObj,a=function(t,e,n,r){var i,a,o=[],s=[],c=Math.min(e[n].low,e[r].low),u=Math.max(e[n].lim,e[r].lim);i=n;do{i=t.parent(i),o.push(i)}while(i&&(e[i].low>c||u>e[i].lim));for(a=i,i=r;(i=t.parent(i))!==a;)s.push(i);return{path:o.concat(s.reverse()),lca:a}}(t,e,i.v,i.w),o=a.path,s=a.lca,c=0,u=o[c],l=!0;n!==i.w;){if(r=t.node(n),l){for(;(u=o[c])!==s&&t.node(u).maxRank<r.rank;)c++;u===s&&(l=!1)}if(!l){for(;c<o.length-1&&t.node(u=o[c+1]).minRank<=r.rank;)c++;u=o[c]}t.setParent(n,u),n=t.successors(n)[0]}}))}},3573:(t,e,n)=>{"use strict";var r=n(8436),i=n(574).Graph,a=n(1138);function o(t,e){var n={};return r.reduce(e,(function(e,i){var a=0,o=0,s=e.length,u=r.last(i);return r.forEach(i,(function(e,l){var h=function(t,e){if(t.node(e).dummy)return r.find(t.predecessors(e),(function(e){return t.node(e).dummy}))}(t,e),f=h?t.node(h).order:s;(h||e===u)&&(r.forEach(i.slice(o,l+1),(function(e){r.forEach(t.predecessors(e),(function(r){var i=t.node(r),o=i.order;!(o<a||f<o)||i.dummy&&t.node(e).dummy||c(n,r,e)}))})),o=l+1,a=f)})),i})),n}function s(t,e){var n={};function i(e,i,a,o,s){var u;r.forEach(r.range(i,a),(function(i){u=e[i],t.node(u).dummy&&r.forEach(t.predecessors(u),(function(e){var r=t.node(e);r.dummy&&(r.order<o||r.order>s)&&c(n,e,u)}))}))}return r.reduce(e,(function(e,n){var a,o=-1,s=0;return r.forEach(n,(function(r,c){if("border"===t.node(r).dummy){var u=t.predecessors(r);u.length&&(a=t.node(u[0]).order,i(n,s,c,o,a),s=c,o=a)}i(n,s,n.length,a,e.length)})),n})),n}function c(t,e,n){if(e>n){var r=e;e=n,n=r}var i=t[e];i||(t[e]=i={}),i[n]=!0}function u(t,e,n){if(e>n){var i=e;e=n,n=i}return r.has(t[e],n)}function l(t,e,n,i){var a={},o={},s={};return r.forEach(e,(function(t){r.forEach(t,(function(t,e){a[t]=t,o[t]=t,s[t]=e}))})),r.forEach(e,(function(t){var e=-1;r.forEach(t,(function(t){var c=i(t);if(c.length){c=r.sortBy(c,(function(t){return s[t]}));for(var l=(c.length-1)/2,h=Math.floor(l),f=Math.ceil(l);h<=f;++h){var d=c[h];o[t]===t&&e<s[d]&&!u(n,t,d)&&(o[d]=t,o[t]=a[t]=a[d],e=s[d])}}}))})),{root:a,align:o}}function h(t,e,n,a,o){var s={},c=function(t,e,n,a){var o=new i,s=t.graph(),c=function(t,e,n){return function(i,a,o){var s,c=i.node(a),u=i.node(o),l=0;if(l+=c.width/2,r.has(c,"labelpos"))switch(c.labelpos.toLowerCase()){case"l":s=-c.width/2;break;case"r":s=c.width/2}if(s&&(l+=n?s:-s),s=0,l+=(c.dummy?e:t)/2,l+=(u.dummy?e:t)/2,l+=u.width/2,r.has(u,"labelpos"))switch(u.labelpos.toLowerCase()){case"l":s=u.width/2;break;case"r":s=-u.width/2}return s&&(l+=n?s:-s),s=0,l}}(s.nodesep,s.edgesep,a);return r.forEach(e,(function(e){var i;r.forEach(e,(function(e){var r=n[e];if(o.setNode(r),i){var a=n[i],s=o.edge(a,r);o.setEdge(a,r,Math.max(c(t,e,i),s||0))}i=e}))})),o}(t,e,n,o),u=o?"borderLeft":"borderRight";function l(t,e){for(var n=c.nodes(),r=n.pop(),i={};r;)i[r]?t(r):(i[r]=!0,n.push(r),n=n.concat(e(r))),r=n.pop()}return l((function(t){s[t]=c.inEdges(t).reduce((function(t,e){return Math.max(t,s[e.v]+c.edge(e))}),0)}),c.predecessors.bind(c)),l((function(e){var n=c.outEdges(e).reduce((function(t,e){return Math.min(t,s[e.w]-c.edge(e))}),Number.POSITIVE_INFINITY),r=t.node(e);n!==Number.POSITIVE_INFINITY&&r.borderType!==u&&(s[e]=Math.max(s[e],n))}),c.successors.bind(c)),r.forEach(a,(function(t){s[t]=s[n[t]]})),s}function f(t,e){return r.minBy(r.values(e),(function(e){var n=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY;return r.forIn(e,(function(e,r){var a=function(t,e){return t.node(e).width}(t,r)/2;n=Math.max(e+a,n),i=Math.min(e-a,i)})),n-i}))}function d(t,e){var n=r.values(e),i=r.min(n),a=r.max(n);r.forEach(["u","d"],(function(n){r.forEach(["l","r"],(function(o){var s,c=n+o,u=t[c];if(u!==e){var l=r.values(u);(s="l"===o?i-r.min(l):a-r.max(l))&&(t[c]=r.mapValues(u,(function(t){return t+s})))}}))}))}function p(t,e){return r.mapValues(t.ul,(function(n,i){if(e)return t[e.toLowerCase()][i];var a=r.sortBy(r.map(t,i));return(a[1]+a[2])/2}))}t.exports={positionX:function(t){var e,n=a.buildLayerMatrix(t),i=r.merge(o(t,n),s(t,n)),c={};r.forEach(["u","d"],(function(a){e="u"===a?n:r.values(n).reverse(),r.forEach(["l","r"],(function(n){"r"===n&&(e=r.map(e,(function(t){return r.values(t).reverse()})));var o=("u"===a?t.predecessors:t.successors).bind(t),s=l(0,e,i,o),u=h(t,e,s.root,s.align,"r"===n);"r"===n&&(u=r.mapValues(u,(function(t){return-t}))),c[a+n]=u}))}));var u=f(t,c);return d(c,u),p(c,t.graph().align)},findType1Conflicts:o,findType2Conflicts:s,addConflict:c,hasConflict:u,verticalAlignment:l,horizontalCompaction:h,alignCoordinates:d,findSmallestWidthAlignment:f,balance:p}},7873:(t,e,n)=>{"use strict";var r=n(8436),i=n(1138),a=n(3573).positionX;t.exports=function(t){(function(t){var e=i.buildLayerMatrix(t),n=t.graph().ranksep,a=0;r.forEach(e,(function(e){var i=r.max(r.map(e,(function(e){return t.node(e).height})));r.forEach(e,(function(e){t.node(e).y=a+i/2})),a+=i+n}))})(t=i.asNonCompoundGraph(t)),r.forEach(a(t),(function(e,n){t.node(n).x=e}))}},300:(t,e,n)=>{"use strict";var r=n(8436),i=n(574).Graph,a=n(6681).slack;function o(t,e){return r.forEach(t.nodes(),(function n(i){r.forEach(e.nodeEdges(i),(function(r){var o=r.v,s=i===o?r.w:o;t.hasNode(s)||a(e,r)||(t.setNode(s,{}),t.setEdge(i,s,{}),n(s))}))})),t.nodeCount()}function s(t,e){return r.minBy(e.edges(),(function(n){if(t.hasNode(n.v)!==t.hasNode(n.w))return a(e,n)}))}function c(t,e,n){r.forEach(t.nodes(),(function(t){e.node(t).rank+=n}))}t.exports=function(t){var e,n,r=new i({directed:!1}),u=t.nodes()[0],l=t.nodeCount();for(r.setNode(u,{});o(r,t)<l;)e=s(r,t),n=r.hasNode(e.v)?a(t,e):-a(t,e),c(r,t,n);return r}},8093:(t,e,n)=>{"use strict";var r=n(6681).longestPath,i=n(300),a=n(2472);t.exports=function(t){switch(t.graph().ranker){case"network-simplex":default:!function(t){a(t)}(t);break;case"tight-tree":!function(t){r(t),i(t)}(t);break;case"longest-path":o(t)}};var o=r},2472:(t,e,n)=>{"use strict";var r=n(8436),i=n(300),a=n(6681).slack,o=n(6681).longestPath,s=n(574).alg.preorder,c=n(574).alg.postorder,u=n(1138).simplify;function l(t){t=u(t),o(t);var e,n=i(t);for(d(n),h(n,t);e=y(n);)m(n,t,e,g(n,t,e))}function h(t,e){var n=c(t,t.nodes());n=n.slice(0,n.length-1),r.forEach(n,(function(n){!function(t,e,n){var r=t.node(n).parent;t.edge(n,r).cutvalue=f(t,e,n)}(t,e,n)}))}function f(t,e,n){var i=t.node(n).parent,a=!0,o=e.edge(n,i),s=0;return o||(a=!1,o=e.edge(i,n)),s=o.weight,r.forEach(e.nodeEdges(n),(function(r){var o,c,u=r.v===n,l=u?r.w:r.v;if(l!==i){var h=u===a,f=e.edge(r).weight;if(s+=h?f:-f,o=n,c=l,t.hasEdge(o,c)){var d=t.edge(n,l).cutvalue;s+=h?-d:d}}})),s}function d(t,e){arguments.length<2&&(e=t.nodes()[0]),p(t,{},1,e)}function p(t,e,n,i,a){var o=n,s=t.node(i);return e[i]=!0,r.forEach(t.neighbors(i),(function(a){r.has(e,a)||(n=p(t,e,n,a,i))})),s.low=o,s.lim=n++,a?s.parent=a:delete s.parent,n}function y(t){return r.find(t.edges(),(function(e){return t.edge(e).cutvalue<0}))}function g(t,e,n){var i=n.v,o=n.w;e.hasEdge(i,o)||(i=n.w,o=n.v);var s=t.node(i),c=t.node(o),u=s,l=!1;s.lim>c.lim&&(u=c,l=!0);var h=r.filter(e.edges(),(function(e){return l===v(0,t.node(e.v),u)&&l!==v(0,t.node(e.w),u)}));return r.minBy(h,(function(t){return a(e,t)}))}function m(t,e,n,i){var a=n.v,o=n.w;t.removeEdge(a,o),t.setEdge(i.v,i.w,{}),d(t),h(t,e),function(t,e){var n=r.find(t.nodes(),(function(t){return!e.node(t).parent})),i=s(t,n);i=i.slice(1),r.forEach(i,(function(n){var r=t.node(n).parent,i=e.edge(n,r),a=!1;i||(i=e.edge(r,n),a=!0),e.node(n).rank=e.node(r).rank+(a?i.minlen:-i.minlen)}))}(t,e)}function v(t,e,n){return n.low<=e.lim&&e.lim<=n.lim}t.exports=l,l.initLowLimValues=d,l.initCutValues=h,l.calcCutValue=f,l.leaveEdge=y,l.enterEdge=g,l.exchangeEdges=m},6681:(t,e,n)=>{"use strict";var r=n(8436);t.exports={longestPath:function(t){var e={};r.forEach(t.sources(),(function n(i){var a=t.node(i);if(r.has(e,i))return a.rank;e[i]=!0;var o=r.min(r.map(t.outEdges(i),(function(e){return n(e.w)-t.edge(e).minlen})));return o!==Number.POSITIVE_INFINITY&&null!=o||(o=0),a.rank=o}))},slack:function(t,e){return t.node(e.w).rank-t.node(e.v).rank-t.edge(e).minlen}}},1138:(t,e,n)=>{"use strict";var r=n(8436),i=n(574).Graph;function a(t,e,n,i){var a;do{a=r.uniqueId(i)}while(t.hasNode(a));return n.dummy=e,t.setNode(a,n),a}function o(t){return r.max(r.map(t.nodes(),(function(e){var n=t.node(e).rank;if(!r.isUndefined(n))return n})))}t.exports={addDummyNode:a,simplify:function(t){var e=(new i).setGraph(t.graph());return r.forEach(t.nodes(),(function(n){e.setNode(n,t.node(n))})),r.forEach(t.edges(),(function(n){var r=e.edge(n.v,n.w)||{weight:0,minlen:1},i=t.edge(n);e.setEdge(n.v,n.w,{weight:r.weight+i.weight,minlen:Math.max(r.minlen,i.minlen)})})),e},asNonCompoundGraph:function(t){var e=new i({multigraph:t.isMultigraph()}).setGraph(t.graph());return r.forEach(t.nodes(),(function(n){t.children(n).length||e.setNode(n,t.node(n))})),r.forEach(t.edges(),(function(n){e.setEdge(n,t.edge(n))})),e},successorWeights:function(t){var e=r.map(t.nodes(),(function(e){var n={};return r.forEach(t.outEdges(e),(function(e){n[e.w]=(n[e.w]||0)+t.edge(e).weight})),n}));return r.zipObject(t.nodes(),e)},predecessorWeights:function(t){var e=r.map(t.nodes(),(function(e){var n={};return r.forEach(t.inEdges(e),(function(e){n[e.v]=(n[e.v]||0)+t.edge(e).weight})),n}));return r.zipObject(t.nodes(),e)},intersectRect:function(t,e){var n,r,i=t.x,a=t.y,o=e.x-i,s=e.y-a,c=t.width/2,u=t.height/2;if(!o&&!s)throw new Error("Not possible to find intersection inside of the rectangle");return Math.abs(s)*c>Math.abs(o)*u?(s<0&&(u=-u),n=u*o/s,r=u):(o<0&&(c=-c),n=c,r=c*s/o),{x:i+n,y:a+r}},buildLayerMatrix:function(t){var e=r.map(r.range(o(t)+1),(function(){return[]}));return r.forEach(t.nodes(),(function(n){var i=t.node(n),a=i.rank;r.isUndefined(a)||(e[a][i.order]=n)})),e},normalizeRanks:function(t){var e=r.min(r.map(t.nodes(),(function(e){return t.node(e).rank})));r.forEach(t.nodes(),(function(n){var i=t.node(n);r.has(i,"rank")&&(i.rank-=e)}))},removeEmptyRanks:function(t){var e=r.min(r.map(t.nodes(),(function(e){return t.node(e).rank}))),n=[];r.forEach(t.nodes(),(function(r){var i=t.node(r).rank-e;n[i]||(n[i]=[]),n[i].push(r)}));var i=0,a=t.graph().nodeRankFactor;r.forEach(n,(function(e,n){r.isUndefined(e)&&n%a!=0?--i:i&&r.forEach(e,(function(e){t.node(e).rank+=i}))}))},addBorderNode:function(t,e,n,r){var i={width:0,height:0};return arguments.length>=4&&(i.rank=n,i.order=r),a(t,"border",i,e)},maxRank:o,partition:function(t,e){var n={lhs:[],rhs:[]};return r.forEach(t,(function(t){e(t)?n.lhs.push(t):n.rhs.push(t)})),n},time:function(t,e){var n=r.now();try{return e()}finally{console.log(t+" time: "+(r.now()-n)+"ms")}},notime:function(t,e){return e()}}},8177:t=>{t.exports="0.8.5"},7856:function(t){t.exports=function(){"use strict";var t=Object.hasOwnProperty,e=Object.setPrototypeOf,n=Object.isFrozen,r=Object.getPrototypeOf,i=Object.getOwnPropertyDescriptor,a=Object.freeze,o=Object.seal,s=Object.create,c="undefined"!=typeof Reflect&&Reflect,u=c.apply,l=c.construct;u||(u=function(t,e,n){return t.apply(e,n)}),a||(a=function(t){return t}),o||(o=function(t){return t}),l||(l=function(t,e){return new(Function.prototype.bind.apply(t,[null].concat(function(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e<t.length;e++)n[e]=t[e];return n}return Array.from(t)}(e))))});var h,f=w(Array.prototype.forEach),d=w(Array.prototype.pop),p=w(Array.prototype.push),y=w(String.prototype.toLowerCase),g=w(String.prototype.match),m=w(String.prototype.replace),v=w(String.prototype.indexOf),b=w(String.prototype.trim),_=w(RegExp.prototype.test),x=(h=TypeError,function(){for(var t=arguments.length,e=Array(t),n=0;n<t;n++)e[n]=arguments[n];return l(h,e)});function w(t){return function(e){for(var n=arguments.length,r=Array(n>1?n-1:0),i=1;i<n;i++)r[i-1]=arguments[i];return u(t,e,r)}}function k(t,r){e&&e(t,null);for(var i=r.length;i--;){var a=r[i];if("string"==typeof a){var o=y(a);o!==a&&(n(r)||(r[i]=o),a=o)}t[a]=!0}return t}function T(e){var n=s(null),r=void 0;for(r in e)u(t,e,[r])&&(n[r]=e[r]);return n}function E(t,e){for(;null!==t;){var n=i(t,e);if(n){if(n.get)return w(n.get);if("function"==typeof n.value)return w(n.value)}t=r(t)}return function(t){return console.warn("fallback value for",t),null}}var C=a(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dialog","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),S=a(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","filter","font","g","glyph","glyphref","hkern","image","line","lineargradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),A=a(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),M=a(["animate","color-profile","cursor","discard","fedropshadow","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignobject","hatch","hatchpath","mesh","meshgradient","meshpatch","meshrow","missing-glyph","script","set","solidcolor","unknown","use"]),N=a(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover"]),D=a(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),O=a(["#text"]),B=a(["accept","action","align","alt","autocapitalize","autocomplete","autopictureinpicture","autoplay","background","bgcolor","border","capture","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","controlslist","coords","crossorigin","datetime","decoding","default","dir","disabled","disablepictureinpicture","disableremoteplayback","download","draggable","enctype","enterkeyhint","face","for","headers","height","hidden","high","href","hreflang","id","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","muted","name","nonce","noshade","novalidate","nowrap","open","optimum","pattern","placeholder","playsinline","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","span","srclang","start","src","srcset","step","style","summary","tabindex","title","translate","type","usemap","valign","value","width","xmlns","slot"]),L=a(["accent-height","accumulate","additive","alignment-baseline","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clippathunits","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","specularconstant","specularexponent","spreadmethod","startoffset","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","systemlanguage","tabindex","targetx","targety","transform","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),I=a(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),R=a(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),F=o(/\{\{[\s\S]*|[\s\S]*\}\}/gm),P=o(/<%[\s\S]*|[\s\S]*%>/gm),j=o(/^data-[\-\w.\u00B7-\uFFFF]/),Y=o(/^aria-[\-\w]+$/),z=o(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),U=o(/^(?:\w+script|data):/i),q=o(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),H="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};function $(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e<t.length;e++)n[e]=t[e];return n}return Array.from(t)}var W=function(){return"undefined"==typeof window?null:window},V=function(t,e){if("object"!==(void 0===t?"undefined":H(t))||"function"!=typeof t.createPolicy)return null;var n=null,r="data-tt-policy-suffix";e.currentScript&&e.currentScript.hasAttribute(r)&&(n=e.currentScript.getAttribute(r));var i="dompurify"+(n?"#"+n:"");try{return t.createPolicy(i,{createHTML:function(t){return t}})}catch(t){return console.warn("TrustedTypes policy "+i+" could not be created."),null}};return function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:W(),n=function(e){return t(e)};if(n.version="2.3.4",n.removed=[],!e||!e.document||9!==e.document.nodeType)return n.isSupported=!1,n;var r=e.document,i=e.document,o=e.DocumentFragment,s=e.HTMLTemplateElement,c=e.Node,u=e.Element,l=e.NodeFilter,h=e.NamedNodeMap,w=void 0===h?e.NamedNodeMap||e.MozNamedAttrMap:h,G=e.HTMLFormElement,X=e.DOMParser,Z=e.trustedTypes,Q=u.prototype,K=E(Q,"cloneNode"),J=E(Q,"nextSibling"),tt=E(Q,"childNodes"),et=E(Q,"parentNode");if("function"==typeof s){var nt=i.createElement("template");nt.content&&nt.content.ownerDocument&&(i=nt.content.ownerDocument)}var rt=V(Z,r),it=rt&&Rt?rt.createHTML(""):"",at=i,ot=at.implementation,st=at.createNodeIterator,ct=at.createDocumentFragment,ut=at.getElementsByTagName,lt=r.importNode,ht={};try{ht=T(i).documentMode?i.documentMode:{}}catch(t){}var ft={};n.isSupported="function"==typeof et&&ot&&void 0!==ot.createHTMLDocument&&9!==ht;var dt=F,pt=P,yt=j,gt=Y,mt=U,vt=q,bt=z,_t=null,xt=k({},[].concat($(C),$(S),$(A),$(N),$(O))),wt=null,kt=k({},[].concat($(B),$(L),$(I),$(R))),Tt=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Et=null,Ct=null,St=!0,At=!0,Mt=!1,Nt=!1,Dt=!1,Ot=!1,Bt=!1,Lt=!1,It=!1,Rt=!1,Ft=!0,Pt=!0,jt=!1,Yt={},zt=null,Ut=k({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]),qt=null,Ht=k({},["audio","video","img","source","image","track"]),$t=null,Wt=k({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Vt="http://www.w3.org/1998/Math/MathML",Gt="http://www.w3.org/2000/svg",Xt="http://www.w3.org/1999/xhtml",Zt=Xt,Qt=!1,Kt=void 0,Jt=["application/xhtml+xml","text/html"],te="text/html",ee=void 0,ne=null,re=i.createElement("form"),ie=function(t){return t instanceof RegExp||t instanceof Function},ae=function(t){ne&&ne===t||(t&&"object"===(void 0===t?"undefined":H(t))||(t={}),t=T(t),_t="ALLOWED_TAGS"in t?k({},t.ALLOWED_TAGS):xt,wt="ALLOWED_ATTR"in t?k({},t.ALLOWED_ATTR):kt,$t="ADD_URI_SAFE_ATTR"in t?k(T(Wt),t.ADD_URI_SAFE_ATTR):Wt,qt="ADD_DATA_URI_TAGS"in t?k(T(Ht),t.ADD_DATA_URI_TAGS):Ht,zt="FORBID_CONTENTS"in t?k({},t.FORBID_CONTENTS):Ut,Et="FORBID_TAGS"in t?k({},t.FORBID_TAGS):{},Ct="FORBID_ATTR"in t?k({},t.FORBID_ATTR):{},Yt="USE_PROFILES"in t&&t.USE_PROFILES,St=!1!==t.ALLOW_ARIA_ATTR,At=!1!==t.ALLOW_DATA_ATTR,Mt=t.ALLOW_UNKNOWN_PROTOCOLS||!1,Nt=t.SAFE_FOR_TEMPLATES||!1,Dt=t.WHOLE_DOCUMENT||!1,Lt=t.RETURN_DOM||!1,It=t.RETURN_DOM_FRAGMENT||!1,Rt=t.RETURN_TRUSTED_TYPE||!1,Bt=t.FORCE_BODY||!1,Ft=!1!==t.SANITIZE_DOM,Pt=!1!==t.KEEP_CONTENT,jt=t.IN_PLACE||!1,bt=t.ALLOWED_URI_REGEXP||bt,Zt=t.NAMESPACE||Xt,t.CUSTOM_ELEMENT_HANDLING&&ie(t.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Tt.tagNameCheck=t.CUSTOM_ELEMENT_HANDLING.tagNameCheck),t.CUSTOM_ELEMENT_HANDLING&&ie(t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Tt.attributeNameCheck=t.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),t.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(Tt.allowCustomizedBuiltInElements=t.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Kt=Kt=-1===Jt.indexOf(t.PARSER_MEDIA_TYPE)?te:t.PARSER_MEDIA_TYPE,ee="application/xhtml+xml"===Kt?function(t){return t}:y,Nt&&(At=!1),It&&(Lt=!0),Yt&&(_t=k({},[].concat($(O))),wt=[],!0===Yt.html&&(k(_t,C),k(wt,B)),!0===Yt.svg&&(k(_t,S),k(wt,L),k(wt,R)),!0===Yt.svgFilters&&(k(_t,A),k(wt,L),k(wt,R)),!0===Yt.mathMl&&(k(_t,N),k(wt,I),k(wt,R))),t.ADD_TAGS&&(_t===xt&&(_t=T(_t)),k(_t,t.ADD_TAGS)),t.ADD_ATTR&&(wt===kt&&(wt=T(wt)),k(wt,t.ADD_ATTR)),t.ADD_URI_SAFE_ATTR&&k($t,t.ADD_URI_SAFE_ATTR),t.FORBID_CONTENTS&&(zt===Ut&&(zt=T(zt)),k(zt,t.FORBID_CONTENTS)),Pt&&(_t["#text"]=!0),Dt&&k(_t,["html","head","body"]),_t.table&&(k(_t,["tbody"]),delete Et.tbody),a&&a(t),ne=t)},oe=k({},["mi","mo","mn","ms","mtext"]),se=k({},["foreignobject","desc","title","annotation-xml"]),ce=k({},S);k(ce,A),k(ce,M);var ue=k({},N);k(ue,D);var le=function(t){var e=et(t);e&&e.tagName||(e={namespaceURI:Xt,tagName:"template"});var n=y(t.tagName),r=y(e.tagName);if(t.namespaceURI===Gt)return e.namespaceURI===Xt?"svg"===n:e.namespaceURI===Vt?"svg"===n&&("annotation-xml"===r||oe[r]):Boolean(ce[n]);if(t.namespaceURI===Vt)return e.namespaceURI===Xt?"math"===n:e.namespaceURI===Gt?"math"===n&&se[r]:Boolean(ue[n]);if(t.namespaceURI===Xt){if(e.namespaceURI===Gt&&!se[r])return!1;if(e.namespaceURI===Vt&&!oe[r])return!1;var i=k({},["title","style","font","a","script"]);return!ue[n]&&(i[n]||!ce[n])}return!1},he=function(t){p(n.removed,{element:t});try{t.parentNode.removeChild(t)}catch(e){try{t.outerHTML=it}catch(e){t.remove()}}},fe=function(t,e){try{p(n.removed,{attribute:e.getAttributeNode(t),from:e})}catch(t){p(n.removed,{attribute:null,from:e})}if(e.removeAttribute(t),"is"===t&&!wt[t])if(Lt||It)try{he(e)}catch(t){}else try{e.setAttribute(t,"")}catch(t){}},de=function(t){var e=void 0,n=void 0;if(Bt)t="<remove></remove>"+t;else{var r=g(t,/^[\r\n\t ]+/);n=r&&r[0]}"application/xhtml+xml"===Kt&&(t='<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>'+t+"</body></html>");var a=rt?rt.createHTML(t):t;if(Zt===Xt)try{e=(new X).parseFromString(a,Kt)}catch(t){}if(!e||!e.documentElement){e=ot.createDocument(Zt,"template",null);try{e.documentElement.innerHTML=Qt?"":a}catch(t){}}var o=e.body||e.documentElement;return t&&n&&o.insertBefore(i.createTextNode(n),o.childNodes[0]||null),Zt===Xt?ut.call(e,Dt?"html":"body")[0]:Dt?e.documentElement:o},pe=function(t){return st.call(t.ownerDocument||t,t,l.SHOW_ELEMENT|l.SHOW_COMMENT|l.SHOW_TEXT,null,!1)},ye=function(t){return t instanceof G&&("string"!=typeof t.nodeName||"string"!=typeof t.textContent||"function"!=typeof t.removeChild||!(t.attributes instanceof w)||"function"!=typeof t.removeAttribute||"function"!=typeof t.setAttribute||"string"!=typeof t.namespaceURI||"function"!=typeof t.insertBefore)},ge=function(t){return"object"===(void 0===c?"undefined":H(c))?t instanceof c:t&&"object"===(void 0===t?"undefined":H(t))&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName},me=function(t,e,r){ft[t]&&f(ft[t],(function(t){t.call(n,e,r,ne)}))},ve=function(t){var e=void 0;if(me("beforeSanitizeElements",t,null),ye(t))return he(t),!0;if(g(t.nodeName,/[\u0080-\uFFFF]/))return he(t),!0;var r=ee(t.nodeName);if(me("uponSanitizeElement",t,{tagName:r,allowedTags:_t}),!ge(t.firstElementChild)&&(!ge(t.content)||!ge(t.content.firstElementChild))&&_(/<[/\w]/g,t.innerHTML)&&_(/<[/\w]/g,t.textContent))return he(t),!0;if("select"===r&&_(/<template/i,t.innerHTML))return he(t),!0;if(!_t[r]||Et[r]){if(Pt&&!zt[r]){var i=et(t)||t.parentNode,a=tt(t)||t.childNodes;if(a&&i)for(var o=a.length-1;o>=0;--o)i.insertBefore(K(a[o],!0),J(t))}if(!Et[r]&&_e(r)){if(Tt.tagNameCheck instanceof RegExp&&_(Tt.tagNameCheck,r))return!1;if(Tt.tagNameCheck instanceof Function&&Tt.tagNameCheck(r))return!1}return he(t),!0}return t instanceof u&&!le(t)?(he(t),!0):"noscript"!==r&&"noembed"!==r||!_(/<\/no(script|embed)/i,t.innerHTML)?(Nt&&3===t.nodeType&&(e=t.textContent,e=m(e,dt," "),e=m(e,pt," "),t.textContent!==e&&(p(n.removed,{element:t.cloneNode()}),t.textContent=e)),me("afterSanitizeElements",t,null),!1):(he(t),!0)},be=function(t,e,n){if(Ft&&("id"===e||"name"===e)&&(n in i||n in re))return!1;if(At&&!Ct[e]&&_(yt,e));else if(St&&_(gt,e));else if(!wt[e]||Ct[e]){if(!(_e(t)&&(Tt.tagNameCheck instanceof RegExp&&_(Tt.tagNameCheck,t)||Tt.tagNameCheck instanceof Function&&Tt.tagNameCheck(t))&&(Tt.attributeNameCheck instanceof RegExp&&_(Tt.attributeNameCheck,e)||Tt.attributeNameCheck instanceof Function&&Tt.attributeNameCheck(e))||"is"===e&&Tt.allowCustomizedBuiltInElements&&(Tt.tagNameCheck instanceof RegExp&&_(Tt.tagNameCheck,n)||Tt.tagNameCheck instanceof Function&&Tt.tagNameCheck(n))))return!1}else if($t[e]);else if(_(bt,m(n,vt,"")));else if("src"!==e&&"xlink:href"!==e&&"href"!==e||"script"===t||0!==v(n,"data:")||!qt[t])if(Mt&&!_(mt,m(n,vt,"")));else if(n)return!1;return!0},_e=function(t){return t.indexOf("-")>0},xe=function(t){var e=void 0,r=void 0,i=void 0,a=void 0;me("beforeSanitizeAttributes",t,null);var o=t.attributes;if(o){var s={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:wt};for(a=o.length;a--;){var c=e=o[a],u=c.name,l=c.namespaceURI;if(r=b(e.value),i=ee(u),s.attrName=i,s.attrValue=r,s.keepAttr=!0,s.forceKeepAttr=void 0,me("uponSanitizeAttribute",t,s),r=s.attrValue,!s.forceKeepAttr&&(fe(u,t),s.keepAttr))if(_(/\/>/i,r))fe(u,t);else{Nt&&(r=m(r,dt," "),r=m(r,pt," "));var h=ee(t.nodeName);if(be(h,i,r))try{l?t.setAttributeNS(l,u,r):t.setAttribute(u,r),d(n.removed)}catch(t){}}}me("afterSanitizeAttributes",t,null)}},we=function t(e){var n=void 0,r=pe(e);for(me("beforeSanitizeShadowDOM",e,null);n=r.nextNode();)me("uponSanitizeShadowNode",n,null),ve(n)||(n.content instanceof o&&t(n.content),xe(n));me("afterSanitizeShadowDOM",e,null)};return n.sanitize=function(t,i){var a=void 0,s=void 0,u=void 0,l=void 0,h=void 0;if((Qt=!t)&&(t="\x3c!--\x3e"),"string"!=typeof t&&!ge(t)){if("function"!=typeof t.toString)throw x("toString is not a function");if("string"!=typeof(t=t.toString()))throw x("dirty is not a string, aborting")}if(!n.isSupported){if("object"===H(e.toStaticHTML)||"function"==typeof e.toStaticHTML){if("string"==typeof t)return e.toStaticHTML(t);if(ge(t))return e.toStaticHTML(t.outerHTML)}return t}if(Ot||ae(i),n.removed=[],"string"==typeof t&&(jt=!1),jt);else if(t instanceof c)1===(s=(a=de("\x3c!----\x3e")).ownerDocument.importNode(t,!0)).nodeType&&"BODY"===s.nodeName||"HTML"===s.nodeName?a=s:a.appendChild(s);else{if(!Lt&&!Nt&&!Dt&&-1===t.indexOf("<"))return rt&&Rt?rt.createHTML(t):t;if(!(a=de(t)))return Lt?null:it}a&&Bt&&he(a.firstChild);for(var f=pe(jt?t:a);u=f.nextNode();)3===u.nodeType&&u===l||ve(u)||(u.content instanceof o&&we(u.content),xe(u),l=u);if(l=null,jt)return t;if(Lt){if(It)for(h=ct.call(a.ownerDocument);a.firstChild;)h.appendChild(a.firstChild);else h=a;return wt.shadowroot&&(h=lt.call(r,h,!0)),h}var d=Dt?a.outerHTML:a.innerHTML;return Nt&&(d=m(d,dt," "),d=m(d,pt," ")),rt&&Rt?rt.createHTML(d):d},n.setConfig=function(t){ae(t),Ot=!0},n.clearConfig=function(){ne=null,Ot=!1},n.isValidAttribute=function(t,e,n){ne||ae({});var r=ee(t),i=ee(e);return be(r,i,n)},n.addHook=function(t,e){"function"==typeof e&&(ft[t]=ft[t]||[],p(ft[t],e))},n.removeHook=function(t){ft[t]&&d(ft[t])},n.removeHooks=function(t){ft[t]&&(ft[t]=[])},n.removeAllHooks=function(){ft={}},n}()}()},8282:(t,e,n)=>{var r=n(2354);t.exports={Graph:r.Graph,json:n(8974),alg:n(2440),version:r.version}},2842:(t,e,n)=>{var r=n(9126);t.exports=function(t){var e,n={},i=[];function a(i){r.has(n,i)||(n[i]=!0,e.push(i),r.each(t.successors(i),a),r.each(t.predecessors(i),a))}return r.each(t.nodes(),(function(t){e=[],a(t),e.length&&i.push(e)})),i}},3984:(t,e,n)=>{var r=n(9126);function i(t,e,n,a,o,s){r.has(a,e)||(a[e]=!0,n||s.push(e),r.each(o(e),(function(e){i(t,e,n,a,o,s)})),n&&s.push(e))}t.exports=function(t,e,n){r.isArray(e)||(e=[e]);var a=(t.isDirected()?t.successors:t.neighbors).bind(t),o=[],s={};return r.each(e,(function(e){if(!t.hasNode(e))throw new Error("Graph does not have node: "+e);i(t,e,"post"===n,s,a,o)})),o}},4847:(t,e,n)=>{var r=n(3763),i=n(9126);t.exports=function(t,e,n){return i.transform(t.nodes(),(function(i,a){i[a]=r(t,a,e,n)}),{})}},3763:(t,e,n)=>{var r=n(9126),i=n(9675);t.exports=function(t,e,n,r){return function(t,e,n,r){var a,o,s={},c=new i,u=function(t){var e=t.v!==a?t.v:t.w,r=s[e],i=n(t),u=o.distance+i;if(i<0)throw new Error("dijkstra does not allow negative edge weights. Bad edge: "+t+" Weight: "+i);u<r.distance&&(r.distance=u,r.predecessor=a,c.decrease(e,u))};for(t.nodes().forEach((function(t){var n=t===e?0:Number.POSITIVE_INFINITY;s[t]={distance:n},c.add(t,n)}));c.size()>0&&(a=c.removeMin(),(o=s[a]).distance!==Number.POSITIVE_INFINITY);)r(a).forEach(u);return s}(t,String(e),n||a,r||function(e){return t.outEdges(e)})};var a=r.constant(1)},9096:(t,e,n)=>{var r=n(9126),i=n(5023);t.exports=function(t){return r.filter(i(t),(function(e){return e.length>1||1===e.length&&t.hasEdge(e[0],e[0])}))}},8924:(t,e,n)=>{var r=n(9126);t.exports=function(t,e,n){return function(t,e,n){var r={},i=t.nodes();return i.forEach((function(t){r[t]={},r[t][t]={distance:0},i.forEach((function(e){t!==e&&(r[t][e]={distance:Number.POSITIVE_INFINITY})})),n(t).forEach((function(n){var i=n.v===t?n.w:n.v,a=e(n);r[t][i]={distance:a,predecessor:t}}))})),i.forEach((function(t){var e=r[t];i.forEach((function(n){var a=r[n];i.forEach((function(n){var r=a[t],i=e[n],o=a[n],s=r.distance+i.distance;s<o.distance&&(o.distance=s,o.predecessor=i.predecessor)}))}))})),r}(t,e||i,n||function(e){return t.outEdges(e)})};var i=r.constant(1)},2440:(t,e,n)=>{t.exports={components:n(2842),dijkstra:n(3763),dijkstraAll:n(4847),findCycles:n(9096),floydWarshall:n(8924),isAcyclic:n(2707),postorder:n(8828),preorder:n(2648),prim:n(514),tarjan:n(5023),topsort:n(2166)}},2707:(t,e,n)=>{var r=n(2166);t.exports=function(t){try{r(t)}catch(t){if(t instanceof r.CycleException)return!1;throw t}return!0}},8828:(t,e,n)=>{var r=n(3984);t.exports=function(t,e){return r(t,e,"post")}},2648:(t,e,n)=>{var r=n(3984);t.exports=function(t,e){return r(t,e,"pre")}},514:(t,e,n)=>{var r=n(9126),i=n(771),a=n(9675);t.exports=function(t,e){var n,o=new i,s={},c=new a;function u(t){var r=t.v===n?t.w:t.v,i=c.priority(r);if(void 0!==i){var a=e(t);a<i&&(s[r]=n,c.decrease(r,a))}}if(0===t.nodeCount())return o;r.each(t.nodes(),(function(t){c.add(t,Number.POSITIVE_INFINITY),o.setNode(t)})),c.decrease(t.nodes()[0],0);for(var l=!1;c.size()>0;){if(n=c.removeMin(),r.has(s,n))o.setEdge(n,s[n]);else{if(l)throw new Error("Input graph is not connected: "+t);l=!0}t.nodeEdges(n).forEach(u)}return o}},5023:(t,e,n)=>{var r=n(9126);t.exports=function(t){var e=0,n=[],i={},a=[];function o(s){var c=i[s]={onStack:!0,lowlink:e,index:e++};if(n.push(s),t.successors(s).forEach((function(t){r.has(i,t)?i[t].onStack&&(c.lowlink=Math.min(c.lowlink,i[t].index)):(o(t),c.lowlink=Math.min(c.lowlink,i[t].lowlink))})),c.lowlink===c.index){var u,l=[];do{u=n.pop(),i[u].onStack=!1,l.push(u)}while(s!==u);a.push(l)}}return t.nodes().forEach((function(t){r.has(i,t)||o(t)})),a}},2166:(t,e,n)=>{var r=n(9126);function i(t){var e={},n={},i=[];if(r.each(t.sinks(),(function o(s){if(r.has(n,s))throw new a;r.has(e,s)||(n[s]=!0,e[s]=!0,r.each(t.predecessors(s),o),delete n[s],i.push(s))})),r.size(e)!==t.nodeCount())throw new a;return i}function a(){}t.exports=i,i.CycleException=a,a.prototype=new Error},9675:(t,e,n)=>{var r=n(9126);function i(){this._arr=[],this._keyIndices={}}t.exports=i,i.prototype.size=function(){return this._arr.length},i.prototype.keys=function(){return this._arr.map((function(t){return t.key}))},i.prototype.has=function(t){return r.has(this._keyIndices,t)},i.prototype.priority=function(t){var e=this._keyIndices[t];if(void 0!==e)return this._arr[e].priority},i.prototype.min=function(){if(0===this.size())throw new Error("Queue underflow");return this._arr[0].key},i.prototype.add=function(t,e){var n=this._keyIndices;if(t=String(t),!r.has(n,t)){var i=this._arr,a=i.length;return n[t]=a,i.push({key:t,priority:e}),this._decrease(a),!0}return!1},i.prototype.removeMin=function(){this._swap(0,this._arr.length-1);var t=this._arr.pop();return delete this._keyIndices[t.key],this._heapify(0),t.key},i.prototype.decrease=function(t,e){var n=this._keyIndices[t];if(e>this._arr[n].priority)throw new Error("New priority is greater than current priority. Key: "+t+" Old: "+this._arr[n].priority+" New: "+e);this._arr[n].priority=e,this._decrease(n)},i.prototype._heapify=function(t){var e=this._arr,n=2*t,r=n+1,i=t;n<e.length&&(i=e[n].priority<e[i].priority?n:i,r<e.length&&(i=e[r].priority<e[i].priority?r:i),i!==t&&(this._swap(t,i),this._heapify(i)))},i.prototype._decrease=function(t){for(var e,n=this._arr,r=n[t].priority;0!==t&&!(n[e=t>>1].priority<r);)this._swap(t,e),t=e},i.prototype._swap=function(t,e){var n=this._arr,r=this._keyIndices,i=n[t],a=n[e];n[t]=a,n[e]=i,r[a.key]=t,r[i.key]=e}},771:(t,e,n)=>{"use strict";var r=n(9126);t.exports=a;var i="\0";function a(t){this._isDirected=!r.has(t,"directed")||t.directed,this._isMultigraph=!!r.has(t,"multigraph")&&t.multigraph,this._isCompound=!!r.has(t,"compound")&&t.compound,this._label=void 0,this._defaultNodeLabelFn=r.constant(void 0),this._defaultEdgeLabelFn=r.constant(void 0),this._nodes={},this._isCompound&&(this._parent={},this._children={},this._children["\0"]={}),this._in={},this._preds={},this._out={},this._sucs={},this._edgeObjs={},this._edgeLabels={}}function o(t,e){t[e]?t[e]++:t[e]=1}function s(t,e){--t[e]||delete t[e]}function c(t,e,n,i){var a=""+e,o=""+n;if(!t&&a>o){var s=a;a=o,o=s}return a+""+o+""+(r.isUndefined(i)?"\0":i)}function u(t,e,n,r){var i=""+e,a=""+n;if(!t&&i>a){var o=i;i=a,a=o}var s={v:i,w:a};return r&&(s.name=r),s}function l(t,e){return c(t,e.v,e.w,e.name)}a.prototype._nodeCount=0,a.prototype._edgeCount=0,a.prototype.isDirected=function(){return this._isDirected},a.prototype.isMultigraph=function(){return this._isMultigraph},a.prototype.isCompound=function(){return this._isCompound},a.prototype.setGraph=function(t){return this._label=t,this},a.prototype.graph=function(){return this._label},a.prototype.setDefaultNodeLabel=function(t){return r.isFunction(t)||(t=r.constant(t)),this._defaultNodeLabelFn=t,this},a.prototype.nodeCount=function(){return this._nodeCount},a.prototype.nodes=function(){return r.keys(this._nodes)},a.prototype.sources=function(){var t=this;return r.filter(this.nodes(),(function(e){return r.isEmpty(t._in[e])}))},a.prototype.sinks=function(){var t=this;return r.filter(this.nodes(),(function(e){return r.isEmpty(t._out[e])}))},a.prototype.setNodes=function(t,e){var n=arguments,i=this;return r.each(t,(function(t){n.length>1?i.setNode(t,e):i.setNode(t)})),this},a.prototype.setNode=function(t,e){return r.has(this._nodes,t)?(arguments.length>1&&(this._nodes[t]=e),this):(this._nodes[t]=arguments.length>1?e:this._defaultNodeLabelFn(t),this._isCompound&&(this._parent[t]=i,this._children[t]={},this._children["\0"][t]=!0),this._in[t]={},this._preds[t]={},this._out[t]={},this._sucs[t]={},++this._nodeCount,this)},a.prototype.node=function(t){return this._nodes[t]},a.prototype.hasNode=function(t){return r.has(this._nodes,t)},a.prototype.removeNode=function(t){var e=this;if(r.has(this._nodes,t)){var n=function(t){e.removeEdge(e._edgeObjs[t])};delete this._nodes[t],this._isCompound&&(this._removeFromParentsChildList(t),delete this._parent[t],r.each(this.children(t),(function(t){e.setParent(t)})),delete this._children[t]),r.each(r.keys(this._in[t]),n),delete this._in[t],delete this._preds[t],r.each(r.keys(this._out[t]),n),delete this._out[t],delete this._sucs[t],--this._nodeCount}return this},a.prototype.setParent=function(t,e){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(r.isUndefined(e))e=i;else{for(var n=e+="";!r.isUndefined(n);n=this.parent(n))if(n===t)throw new Error("Setting "+e+" as parent of "+t+" would create a cycle");this.setNode(e)}return this.setNode(t),this._removeFromParentsChildList(t),this._parent[t]=e,this._children[e][t]=!0,this},a.prototype._removeFromParentsChildList=function(t){delete this._children[this._parent[t]][t]},a.prototype.parent=function(t){if(this._isCompound){var e=this._parent[t];if(e!==i)return e}},a.prototype.children=function(t){if(r.isUndefined(t)&&(t=i),this._isCompound){var e=this._children[t];if(e)return r.keys(e)}else{if(t===i)return this.nodes();if(this.hasNode(t))return[]}},a.prototype.predecessors=function(t){var e=this._preds[t];if(e)return r.keys(e)},a.prototype.successors=function(t){var e=this._sucs[t];if(e)return r.keys(e)},a.prototype.neighbors=function(t){var e=this.predecessors(t);if(e)return r.union(e,this.successors(t))},a.prototype.isLeaf=function(t){return 0===(this.isDirected()?this.successors(t):this.neighbors(t)).length},a.prototype.filterNodes=function(t){var e=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});e.setGraph(this.graph());var n=this;r.each(this._nodes,(function(n,r){t(r)&&e.setNode(r,n)})),r.each(this._edgeObjs,(function(t){e.hasNode(t.v)&&e.hasNode(t.w)&&e.setEdge(t,n.edge(t))}));var i={};function a(t){var r=n.parent(t);return void 0===r||e.hasNode(r)?(i[t]=r,r):r in i?i[r]:a(r)}return this._isCompound&&r.each(e.nodes(),(function(t){e.setParent(t,a(t))})),e},a.prototype.setDefaultEdgeLabel=function(t){return r.isFunction(t)||(t=r.constant(t)),this._defaultEdgeLabelFn=t,this},a.prototype.edgeCount=function(){return this._edgeCount},a.prototype.edges=function(){return r.values(this._edgeObjs)},a.prototype.setPath=function(t,e){var n=this,i=arguments;return r.reduce(t,(function(t,r){return i.length>1?n.setEdge(t,r,e):n.setEdge(t,r),r})),this},a.prototype.setEdge=function(){var t,e,n,i,a=!1,s=arguments[0];"object"==typeof s&&null!==s&&"v"in s?(t=s.v,e=s.w,n=s.name,2===arguments.length&&(i=arguments[1],a=!0)):(t=s,e=arguments[1],n=arguments[3],arguments.length>2&&(i=arguments[2],a=!0)),t=""+t,e=""+e,r.isUndefined(n)||(n=""+n);var l=c(this._isDirected,t,e,n);if(r.has(this._edgeLabels,l))return a&&(this._edgeLabels[l]=i),this;if(!r.isUndefined(n)&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(t),this.setNode(e),this._edgeLabels[l]=a?i:this._defaultEdgeLabelFn(t,e,n);var h=u(this._isDirected,t,e,n);return t=h.v,e=h.w,Object.freeze(h),this._edgeObjs[l]=h,o(this._preds[e],t),o(this._sucs[t],e),this._in[e][l]=h,this._out[t][l]=h,this._edgeCount++,this},a.prototype.edge=function(t,e,n){var r=1===arguments.length?l(this._isDirected,arguments[0]):c(this._isDirected,t,e,n);return this._edgeLabels[r]},a.prototype.hasEdge=function(t,e,n){var i=1===arguments.length?l(this._isDirected,arguments[0]):c(this._isDirected,t,e,n);return r.has(this._edgeLabels,i)},a.prototype.removeEdge=function(t,e,n){var r=1===arguments.length?l(this._isDirected,arguments[0]):c(this._isDirected,t,e,n),i=this._edgeObjs[r];return i&&(t=i.v,e=i.w,delete this._edgeLabels[r],delete this._edgeObjs[r],s(this._preds[e],t),s(this._sucs[t],e),delete this._in[e][r],delete this._out[t][r],this._edgeCount--),this},a.prototype.inEdges=function(t,e){var n=this._in[t];if(n){var i=r.values(n);return e?r.filter(i,(function(t){return t.v===e})):i}},a.prototype.outEdges=function(t,e){var n=this._out[t];if(n){var i=r.values(n);return e?r.filter(i,(function(t){return t.w===e})):i}},a.prototype.nodeEdges=function(t,e){var n=this.inEdges(t,e);if(n)return n.concat(this.outEdges(t,e))}},2354:(t,e,n)=>{t.exports={Graph:n(771),version:n(9631)}},8974:(t,e,n)=>{var r=n(9126),i=n(771);function a(t){return r.map(t.nodes(),(function(e){var n=t.node(e),i=t.parent(e),a={v:e};return r.isUndefined(n)||(a.value=n),r.isUndefined(i)||(a.parent=i),a}))}function o(t){return r.map(t.edges(),(function(e){var n=t.edge(e),i={v:e.v,w:e.w};return r.isUndefined(e.name)||(i.name=e.name),r.isUndefined(n)||(i.value=n),i}))}t.exports={write:function(t){var e={options:{directed:t.isDirected(),multigraph:t.isMultigraph(),compound:t.isCompound()},nodes:a(t),edges:o(t)};return r.isUndefined(t.graph())||(e.value=r.clone(t.graph())),e},read:function(t){var e=new i(t.options).setGraph(t.value);return r.each(t.nodes,(function(t){e.setNode(t.v,t.value),t.parent&&e.setParent(t.v,t.parent)})),r.each(t.edges,(function(t){e.setEdge({v:t.v,w:t.w,name:t.name},t.value)})),e}}},9126:(t,e,n)=>{var r;try{r={clone:n(6678),constant:n(5703),each:n(6073),filter:n(3105),has:n(8721),isArray:n(1469),isEmpty:n(1609),isFunction:n(3560),isUndefined:n(2353),keys:n(3674),map:n(5161),reduce:n(4061),size:n(4238),transform:n(8718),union:n(3386),values:n(2628)}}catch(t){}r||(r=window._),t.exports=r},9631:t=>{t.exports="2.1.8"},1773:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(7628),a=function(){function t(t,e){this.color=e,this.changed=!1,this.data=t,this.type=new i.default}return t.prototype.set=function(t,e){return this.color=e,this.changed=!1,this.data=t,this.type.type=0,this},t.prototype._ensureHSL=function(){var t=this.data,e=t.h,n=t.s,i=t.l;void 0===e&&(t.h=r.default.channel.rgb2hsl(t,"h")),void 0===n&&(t.s=r.default.channel.rgb2hsl(t,"s")),void 0===i&&(t.l=r.default.channel.rgb2hsl(t,"l"))},t.prototype._ensureRGB=function(){var t=this.data,e=t.r,n=t.g,i=t.b;void 0===e&&(t.r=r.default.channel.hsl2rgb(t,"r")),void 0===n&&(t.g=r.default.channel.hsl2rgb(t,"g")),void 0===i&&(t.b=r.default.channel.hsl2rgb(t,"b"))},Object.defineProperty(t.prototype,"r",{get:function(){var t=this.data,e=t.r;return this.type.is(2)||void 0===e?(this._ensureHSL(),r.default.channel.hsl2rgb(t,"r")):e},set:function(t){this.type.set(1),this.changed=!0,this.data.r=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"g",{get:function(){var t=this.data,e=t.g;return this.type.is(2)||void 0===e?(this._ensureHSL(),r.default.channel.hsl2rgb(t,"g")):e},set:function(t){this.type.set(1),this.changed=!0,this.data.g=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"b",{get:function(){var t=this.data,e=t.b;return this.type.is(2)||void 0===e?(this._ensureHSL(),r.default.channel.hsl2rgb(t,"b")):e},set:function(t){this.type.set(1),this.changed=!0,this.data.b=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"h",{get:function(){var t=this.data,e=t.h;return this.type.is(1)||void 0===e?(this._ensureRGB(),r.default.channel.rgb2hsl(t,"h")):e},set:function(t){this.type.set(2),this.changed=!0,this.data.h=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"s",{get:function(){var t=this.data,e=t.s;return this.type.is(1)||void 0===e?(this._ensureRGB(),r.default.channel.rgb2hsl(t,"s")):e},set:function(t){this.type.set(2),this.changed=!0,this.data.s=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"l",{get:function(){var t=this.data,e=t.l;return this.type.is(1)||void 0===e?(this._ensureRGB(),r.default.channel.rgb2hsl(t,"l")):e},set:function(t){this.type.set(2),this.changed=!0,this.data.l=t},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"a",{get:function(){return this.data.a},set:function(t){this.changed=!0,this.data.a=t},enumerable:!0,configurable:!0}),t}();e.default=a},8167:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=new(n(1773).default)({r:0,g:0,b:0,a:0},"transparent");e.default=r},7628:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(){this.type=0}return t.prototype.get=function(){return this.type},t.prototype.set=function(t){if(this.type&&this.type!==t)throw new Error("Cannot change both RGB and HSL channels at the same time");this.type=t},t.prototype.reset=function(){this.type=0},t.prototype.is=function(t){return this.type===t},t}();e.default=n},1655:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(8167),i=n(6061),a={re:/^#((?:[a-f0-9]{2}){2,4}|[a-f0-9]{3})$/i,parse:function(t){if(35===t.charCodeAt(0)){var e=t.match(a.re);if(e){var n=e[1],i=parseInt(n,16),o=n.length,s=o%4==0,c=o>4,u=c?1:17,l=c?8:4,h=s?0:-1,f=c?255:15;return r.default.set({r:(i>>l*(h+3)&f)*u,g:(i>>l*(h+2)&f)*u,b:(i>>l*(h+1)&f)*u,a:s?(i&f)*u/255:1},t)}}},stringify:function(t){var e=t.r,n=t.g,r=t.b,a=t.a;return a<1?"#"+i.DEC2HEX[Math.round(e)]+i.DEC2HEX[Math.round(n)]+i.DEC2HEX[Math.round(r)]+i.DEC2HEX[Math.round(255*a)]:"#"+i.DEC2HEX[Math.round(e)]+i.DEC2HEX[Math.round(n)]+i.DEC2HEX[Math.round(r)]}};e.default=a},8589:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(8167),a={re:/^hsla?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(?:deg|grad|rad|turn)?)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(%)?))?\s*?\)$/i,hueRe:/^(.+?)(deg|grad|rad|turn)$/i,_hue2deg:function(t){var e=t.match(a.hueRe);if(e){var n=e[1];switch(e[2]){case"grad":return r.default.channel.clamp.h(.9*parseFloat(n));case"rad":return r.default.channel.clamp.h(180*parseFloat(n)/Math.PI);case"turn":return r.default.channel.clamp.h(360*parseFloat(n))}}return r.default.channel.clamp.h(parseFloat(t))},parse:function(t){var e=t.charCodeAt(0);if(104===e||72===e){var n=t.match(a.re);if(n){var o=n[1],s=n[2],c=n[3],u=n[4],l=n[5];return i.default.set({h:a._hue2deg(o),s:r.default.channel.clamp.s(parseFloat(s)),l:r.default.channel.clamp.l(parseFloat(c)),a:u?r.default.channel.clamp.a(l?parseFloat(u)/100:parseFloat(u)):1},t)}}},stringify:function(t){var e=t.h,n=t.s,i=t.l,a=t.a;return a<1?"hsla("+r.default.lang.round(e)+", "+r.default.lang.round(n)+"%, "+r.default.lang.round(i)+"%, "+a+")":"hsl("+r.default.lang.round(e)+", "+r.default.lang.round(n)+"%, "+r.default.lang.round(i)+"%)"}};e.default=a},2191:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1655),i=n(7538),a=n(6762),o=n(8589),s={format:{keyword:i.default,hex:r.default,rgb:a.default,rgba:a.default,hsl:o.default,hsla:o.default},parse:function(t){if("string"!=typeof t)return t;var e=r.default.parse(t)||a.default.parse(t)||o.default.parse(t)||i.default.parse(t);if(e)return e;throw new Error('Unsupported color format: "'+t+'"')},stringify:function(t){return!t.changed&&t.color?t.color:t.type.is(2)||void 0===t.data.r?o.default.stringify(t):t.a<1||!Number.isInteger(t.r)||!Number.isInteger(t.g)||!Number.isInteger(t.b)?a.default.stringify(t):r.default.stringify(t)}};e.default=s},7538:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1655),i={colors:{aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyanaqua:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",transparent:"#00000000",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},parse:function(t){t=t.toLowerCase();var e=i.colors[t];if(e)return r.default.parse(e)},stringify:function(t){var e=r.default.stringify(t);for(var n in i.colors)if(i.colors[n]===e)return n}};e.default=i},6762:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(8167),a={re:/^rgba?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?)))?\s*?\)$/i,parse:function(t){var e=t.charCodeAt(0);if(114===e||82===e){var n=t.match(a.re);if(n){var o=n[1],s=n[2],c=n[3],u=n[4],l=n[5],h=n[6],f=n[7],d=n[8];return i.default.set({r:r.default.channel.clamp.r(s?2.55*parseFloat(o):parseFloat(o)),g:r.default.channel.clamp.g(u?2.55*parseFloat(c):parseFloat(c)),b:r.default.channel.clamp.b(h?2.55*parseFloat(l):parseFloat(l)),a:f?r.default.channel.clamp.a(d?parseFloat(f)/100:parseFloat(f)):1},t)}}},stringify:function(t){var e=t.r,n=t.g,i=t.b,a=t.a;return a<1?"rgba("+r.default.lang.round(e)+", "+r.default.lang.round(n)+", "+r.default.lang.round(i)+", "+r.default.lang.round(a)+")":"rgb("+r.default.lang.round(e)+", "+r.default.lang.round(n)+", "+r.default.lang.round(i)+")"}};e.default=a},6061:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i={};e.DEC2HEX=i;for(var a=0;a<=255;a++)i[a]=r.default.unit.dec2hex(a)},8613:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0}),function(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}(n(1203))},5371:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(2191),i=n(418);e.default=function(t,e){var n=r.default.parse(t),a={};for(var o in e)e[o]&&(a[o]=n[o]+e[o]);return i.default(t,a)}},1416:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(2191);e.default=function(t,e,n){var a=i.default.parse(t),o=a[e],s=r.default.channel.clamp[e](o+n);return o!==s&&(a[e]=s),i.default.stringify(a)}},9353:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(6197);e.default=function(t){return r.default(t,"a")}},3394:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(6197);e.default=function(t){return r.default(t,"b")}},418:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(2191);e.default=function(t,e){var n=i.default.parse(t);for(var a in e)n[a]=r.default.channel.clamp[a](e[a]);return i.default.stringify(n)}},6197:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(2191);e.default=function(t,e){return r.default.lang.round(i.default.parse(t)[e])}},7361:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1416);e.default=function(t){return r.default(t,"h",180)}},3042:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(8346);e.default=function(t,e){var n=i.default(t),a=i.default(e),o=Math.max(n,a),s=Math.min(n,a),c=(o+Number.EPSILON)/(s+Number.EPSILON);return r.default.lang.round(r.default.lang.clamp(c,1,10))}},1364:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1416);e.default=function(t,e){return r.default(t,"l",-e)}},9610:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1416);e.default=function(t,e){return r.default(t,"s",-e)}},572:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(418);e.default=function(t){return r.default(t,{s:0})}},2299:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(6197);e.default=function(t){return r.default(t,"g")}},3116:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(8167),a=n(2191);e.default=function(t,e,n,o){void 0===o&&(o=1);var s=i.default.set({h:r.default.channel.clamp.h(t),s:r.default.channel.clamp.s(e),l:r.default.channel.clamp.l(n),a:r.default.channel.clamp.a(o)});return a.default.stringify(s)}},3008:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(6197);e.default=function(t){return r.default(t,"h")}},1203:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(6538);e.hex=r.default;var i=n(6538);e.rgb=i.default;var a=n(6538);e.rgba=a.default;var o=n(3116);e.hsl=o.default;var s=n(3116);e.hsla=s.default;var c=n(2619);e.toKeyword=c.default;var u=n(4307);e.toHex=u.default;var l=n(4125);e.toRgba=l.default;var h=n(7329);e.toHsla=h.default;var f=n(6197);e.channel=f.default;var d=n(9640);e.red=d.default;var p=n(2299);e.green=p.default;var y=n(3394);e.blue=y.default;var g=n(3008);e.hue=g.default;var m=n(6451);e.saturation=m.default;var v=n(9235);e.lightness=v.default;var b=n(9353);e.alpha=b.default;var _=n(9353);e.opacity=_.default;var x=n(3042);e.contrast=x.default;var w=n(8346);e.luminance=w.default;var k=n(4117);e.isDark=k.default;var T=n(2224);e.isLight=T.default;var E=n(585);e.isValid=E.default;var C=n(1080);e.saturate=C.default;var S=n(9610);e.desaturate=S.default;var A=n(3235);e.lighten=A.default;var M=n(1364);e.darken=M.default;var N=n(7189);e.opacify=N.default;var D=n(7189);e.fadeIn=D.default;var O=n(4989);e.transparentize=O.default;var B=n(4989);e.fadeOut=B.default;var L=n(7361);e.complement=L.default;var I=n(572);e.grayscale=I.default;var R=n(5371);e.adjust=R.default;var F=n(418);e.change=F.default;var P=n(566);e.invert=P.default;var j=n(1861);e.mix=j.default;var Y=n(7081);e.scale=Y.default},566:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(2191),i=n(1861);e.default=function(t,e){void 0===e&&(e=100);var n=r.default.parse(t);return n.r=255-n.r,n.g=255-n.g,n.b=255-n.b,i.default(n,t,e)}},4117:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(2224);e.default=function(t){return!r.default(t)}},2224:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(8346);e.default=function(t){return r.default(t)>=.5}},585:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(2191);e.default=function(t){try{return r.default.parse(t),!0}catch(t){return!1}}},3235:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1416);e.default=function(t,e){return r.default(t,"l",e)}},9235:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(6197);e.default=function(t){return r.default(t,"l")}},8346:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(2191);e.default=function(t){var e=i.default.parse(t),n=e.r,a=e.g,o=e.b,s=.2126*r.default.channel.toLinear(n)+.7152*r.default.channel.toLinear(a)+.0722*r.default.channel.toLinear(o);return r.default.lang.round(s)}},1861:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(2191),i=n(6538);e.default=function(t,e,n){void 0===n&&(n=50);var a=r.default.parse(t),o=a.r,s=a.g,c=a.b,u=a.a,l=r.default.parse(e),h=l.r,f=l.g,d=l.b,p=l.a,y=n/100,g=2*y-1,m=u-p,v=((g*m==-1?g:(g+m)/(1+g*m))+1)/2,b=1-v,_=o*v+h*b,x=s*v+f*b,w=c*v+d*b,k=u*y+p*(1-y);return i.default(_,x,w,k)}},7189:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1416);e.default=function(t,e){return r.default(t,"a",e)}},9640:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(6197);e.default=function(t){return r.default(t,"r")}},6538:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(8167),a=n(2191),o=n(418);e.default=function(t,e,n,s){if(void 0===n&&(n=0),void 0===s&&(s=1),"number"!=typeof t)return o.default(t,{a:e});var c=i.default.set({r:r.default.channel.clamp.r(t),g:r.default.channel.clamp.g(e),b:r.default.channel.clamp.b(n),a:r.default.channel.clamp.a(s)});return a.default.stringify(c)}},1080:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1416);e.default=function(t,e){return r.default(t,"s",e)}},6451:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(6197);e.default=function(t){return r.default(t,"s")}},7081:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1083),i=n(2191),a=n(5371);e.default=function(t,e){var n,o,s,c=i.default.parse(t),u={};for(var l in e)u[l]=(n=c[l],o=e[l],s=r.default.channel.max[l],o>0?(s-n)*o/100:n*o/100);return a.default(t,u)}},4307:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(2191);e.default=function(t){return r.default.format.hex.stringify(r.default.parse(t))}},7329:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(2191);e.default=function(t){return r.default.format.hsla.stringify(r.default.parse(t))}},2619:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(2191);e.default=function(t){return r.default.format.keyword.stringify(r.default.parse(t))}},4125:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(2191);e.default=function(t){return r.default.format.rgba.stringify(r.default.parse(t))}},4989:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(1416);e.default=function(t,e){return r.default(t,"a",-e)}},7994:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n={min:{r:0,g:0,b:0,s:0,l:0,a:0},max:{r:255,g:255,b:255,h:360,s:100,l:100,a:1},clamp:{r:function(t){return t>=255?255:t<0?0:t},g:function(t){return t>=255?255:t<0?0:t},b:function(t){return t>=255?255:t<0?0:t},h:function(t){return t%360},s:function(t){return t>=100?100:t<0?0:t},l:function(t){return t>=100?100:t<0?0:t},a:function(t){return t>=1?1:t<0?0:t}},toLinear:function(t){var e=t/255;return t>.03928?Math.pow((e+.055)/1.055,2.4):e/12.92},hue2rgb:function(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+(e-t)*(2/3-n)*6:t},hsl2rgb:function(t,e){var r=t.h,i=t.s,a=t.l;if(!i)return 2.55*a;r/=360,i/=100;var o=(a/=100)<.5?a*(1+i):a+i-a*i,s=2*a-o;switch(e){case"r":return 255*n.hue2rgb(s,o,r+1/3);case"g":return 255*n.hue2rgb(s,o,r);case"b":return 255*n.hue2rgb(s,o,r-1/3)}},rgb2hsl:function(t,e){var n=t.r,r=t.g,i=t.b;n/=255,r/=255,i/=255;var a=Math.max(n,r,i),o=Math.min(n,r,i),s=(a+o)/2;if("l"===e)return 100*s;if(a===o)return 0;var c=a-o;if("s"===e)return 100*(s>.5?c/(2-a-o):c/(a+o));switch(a){case n:return 60*((r-i)/c+(r<i?6:0));case r:return 60*((i-n)/c+2);case i:return 60*((n-r)/c+4);default:return-1}}};e.default=n},1083:(t,e,n)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(7994),i=n(4027),a=n(318),o={channel:r.default,lang:i.default,unit:a.default};e.default=o},4027:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n={clamp:function(t,e,n){return e>n?Math.min(e,Math.max(n,t)):Math.min(n,Math.max(e,t))},round:function(t){return Math.round(1e10*t)/1e10}};e.default=n},318:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n={dec2hex:function(t){var e=Math.round(t).toString(16);return e.length>1?e:"0"+e}};e.default=n},8552:(t,e,n)=>{var r=n(852)(n(5639),"DataView");t.exports=r},1989:(t,e,n)=>{var r=n(1789),i=n(401),a=n(7667),o=n(1327),s=n(1866);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}c.prototype.clear=r,c.prototype.delete=i,c.prototype.get=a,c.prototype.has=o,c.prototype.set=s,t.exports=c},8407:(t,e,n)=>{var r=n(7040),i=n(2188),a=n(2117),o=n(7518),s=n(4705);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}c.prototype.clear=r,c.prototype.delete=i,c.prototype.get=a,c.prototype.has=o,c.prototype.set=s,t.exports=c},7071:(t,e,n)=>{var r=n(852)(n(5639),"Map");t.exports=r},3369:(t,e,n)=>{var r=n(4785),i=n(1285),a=n(6e3),o=n(9916),s=n(5265);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}c.prototype.clear=r,c.prototype.delete=i,c.prototype.get=a,c.prototype.has=o,c.prototype.set=s,t.exports=c},3818:(t,e,n)=>{var r=n(852)(n(5639),"Promise");t.exports=r},8525:(t,e,n)=>{var r=n(852)(n(5639),"Set");t.exports=r},8668:(t,e,n)=>{var r=n(3369),i=n(619),a=n(2385);function o(t){var e=-1,n=null==t?0:t.length;for(this.__data__=new r;++e<n;)this.add(t[e])}o.prototype.add=o.prototype.push=i,o.prototype.has=a,t.exports=o},6384:(t,e,n)=>{var r=n(8407),i=n(7465),a=n(3779),o=n(7599),s=n(4758),c=n(4309);function u(t){var e=this.__data__=new r(t);this.size=e.size}u.prototype.clear=i,u.prototype.delete=a,u.prototype.get=o,u.prototype.has=s,u.prototype.set=c,t.exports=u},2705:(t,e,n)=>{var r=n(5639).Symbol;t.exports=r},1149:(t,e,n)=>{var r=n(5639).Uint8Array;t.exports=r},577:(t,e,n)=>{var r=n(852)(n(5639),"WeakMap");t.exports=r},6874:t=>{t.exports=function(t,e,n){switch(n.length){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}},7412:t=>{t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length;++n<r&&!1!==e(t[n],n,t););return t}},4963:t=>{t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length,i=0,a=[];++n<r;){var o=t[n];e(o,n,t)&&(a[i++]=o)}return a}},7443:(t,e,n)=>{var r=n(2118);t.exports=function(t,e){return!(null==t||!t.length)&&r(t,e,0)>-1}},1196:t=>{t.exports=function(t,e,n){for(var r=-1,i=null==t?0:t.length;++r<i;)if(n(e,t[r]))return!0;return!1}},4636:(t,e,n)=>{var r=n(2545),i=n(5694),a=n(1469),o=n(4144),s=n(5776),c=n(6719),u=Object.prototype.hasOwnProperty;t.exports=function(t,e){var n=a(t),l=!n&&i(t),h=!n&&!l&&o(t),f=!n&&!l&&!h&&c(t),d=n||l||h||f,p=d?r(t.length,String):[],y=p.length;for(var g in t)!e&&!u.call(t,g)||d&&("length"==g||h&&("offset"==g||"parent"==g)||f&&("buffer"==g||"byteLength"==g||"byteOffset"==g)||s(g,y))||p.push(g);return p}},9932:t=>{t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length,i=Array(r);++n<r;)i[n]=e(t[n],n,t);return i}},2488:t=>{t.exports=function(t,e){for(var n=-1,r=e.length,i=t.length;++n<r;)t[i+n]=e[n];return t}},2663:t=>{t.exports=function(t,e,n,r){var i=-1,a=null==t?0:t.length;for(r&&a&&(n=t[++i]);++i<a;)n=e(n,t[i],i,t);return n}},2908:t=>{t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length;++n<r;)if(e(t[n],n,t))return!0;return!1}},8983:(t,e,n)=>{var r=n(371)("length");t.exports=r},6556:(t,e,n)=>{var r=n(9465),i=n(7813);t.exports=function(t,e,n){(void 0!==n&&!i(t[e],n)||void 0===n&&!(e in t))&&r(t,e,n)}},4865:(t,e,n)=>{var r=n(9465),i=n(7813),a=Object.prototype.hasOwnProperty;t.exports=function(t,e,n){var o=t[e];a.call(t,e)&&i(o,n)&&(void 0!==n||e in t)||r(t,e,n)}},8470:(t,e,n)=>{var r=n(7813);t.exports=function(t,e){for(var n=t.length;n--;)if(r(t[n][0],e))return n;return-1}},4037:(t,e,n)=>{var r=n(8363),i=n(3674);t.exports=function(t,e){return t&&r(e,i(e),t)}},3886:(t,e,n)=>{var r=n(8363),i=n(1704);t.exports=function(t,e){return t&&r(e,i(e),t)}},9465:(t,e,n)=>{var r=n(8777);t.exports=function(t,e,n){"__proto__"==e&&r?r(t,e,{configurable:!0,enumerable:!0,value:n,writable:!0}):t[e]=n}},5990:(t,e,n)=>{var r=n(6384),i=n(7412),a=n(4865),o=n(4037),s=n(3886),c=n(4626),u=n(278),l=n(8805),h=n(1911),f=n(8234),d=n(6904),p=n(4160),y=n(3824),g=n(9148),m=n(8517),v=n(1469),b=n(4144),_=n(6688),x=n(3218),w=n(2928),k=n(3674),T=n(1704),E="[object Arguments]",C="[object Function]",S="[object Object]",A={};A[E]=A["[object Array]"]=A["[object ArrayBuffer]"]=A["[object DataView]"]=A["[object Boolean]"]=A["[object Date]"]=A["[object Float32Array]"]=A["[object Float64Array]"]=A["[object Int8Array]"]=A["[object Int16Array]"]=A["[object Int32Array]"]=A["[object Map]"]=A["[object Number]"]=A[S]=A["[object RegExp]"]=A["[object Set]"]=A["[object String]"]=A["[object Symbol]"]=A["[object Uint8Array]"]=A["[object Uint8ClampedArray]"]=A["[object Uint16Array]"]=A["[object Uint32Array]"]=!0,A["[object Error]"]=A[C]=A["[object WeakMap]"]=!1,t.exports=function t(e,n,M,N,D,O){var B,L=1&n,I=2&n,R=4&n;if(M&&(B=D?M(e,N,D,O):M(e)),void 0!==B)return B;if(!x(e))return e;var F=v(e);if(F){if(B=y(e),!L)return u(e,B)}else{var P=p(e),j=P==C||"[object GeneratorFunction]"==P;if(b(e))return c(e,L);if(P==S||P==E||j&&!D){if(B=I||j?{}:m(e),!L)return I?h(e,s(B,e)):l(e,o(B,e))}else{if(!A[P])return D?e:{};B=g(e,P,L)}}O||(O=new r);var Y=O.get(e);if(Y)return Y;O.set(e,B),w(e)?e.forEach((function(r){B.add(t(r,n,M,r,e,O))})):_(e)&&e.forEach((function(r,i){B.set(i,t(r,n,M,i,e,O))}));var z=F?void 0:(R?I?d:f:I?T:k)(e);return i(z||e,(function(r,i){z&&(r=e[i=r]),a(B,i,t(r,n,M,i,e,O))})),B}},3118:(t,e,n)=>{var r=n(3218),i=Object.create,a=function(){function t(){}return function(e){if(!r(e))return{};if(i)return i(e);t.prototype=e;var n=new t;return t.prototype=void 0,n}}();t.exports=a},9881:(t,e,n)=>{var r=n(7816),i=n(9291)(r);t.exports=i},6029:(t,e,n)=>{var r=n(3448);t.exports=function(t,e,n){for(var i=-1,a=t.length;++i<a;){var o=t[i],s=e(o);if(null!=s&&(void 0===c?s==s&&!r(s):n(s,c)))var c=s,u=o}return u}},760:(t,e,n)=>{var r=n(9881);t.exports=function(t,e){var n=[];return r(t,(function(t,r,i){e(t,r,i)&&n.push(t)})),n}},1848:t=>{t.exports=function(t,e,n,r){for(var i=t.length,a=n+(r?1:-1);r?a--:++a<i;)if(e(t[a],a,t))return a;return-1}},1078:(t,e,n)=>{var r=n(2488),i=n(7285);t.exports=function t(e,n,a,o,s){var c=-1,u=e.length;for(a||(a=i),s||(s=[]);++c<u;){var l=e[c];n>0&&a(l)?n>1?t(l,n-1,a,o,s):r(s,l):o||(s[s.length]=l)}return s}},8483:(t,e,n)=>{var r=n(5063)();t.exports=r},7816:(t,e,n)=>{var r=n(8483),i=n(3674);t.exports=function(t,e){return t&&r(t,e,i)}},7786:(t,e,n)=>{var r=n(1811),i=n(327);t.exports=function(t,e){for(var n=0,a=(e=r(e,t)).length;null!=t&&n<a;)t=t[i(e[n++])];return n&&n==a?t:void 0}},8866:(t,e,n)=>{var r=n(2488),i=n(1469);t.exports=function(t,e,n){var a=e(t);return i(t)?a:r(a,n(t))}},4239:(t,e,n)=>{var r=n(2705),i=n(9607),a=n(2333),o=r?r.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":o&&o in Object(t)?i(t):a(t)}},3325:t=>{t.exports=function(t,e){return t>e}},8565:t=>{var e=Object.prototype.hasOwnProperty;t.exports=function(t,n){return null!=t&&e.call(t,n)}},13:t=>{t.exports=function(t,e){return null!=t&&e in Object(t)}},2118:(t,e,n)=>{var r=n(1848),i=n(2722),a=n(2351);t.exports=function(t,e,n){return e==e?a(t,e,n):r(t,i,n)}},9454:(t,e,n)=>{var r=n(4239),i=n(7005);t.exports=function(t){return i(t)&&"[object Arguments]"==r(t)}},939:(t,e,n)=>{var r=n(2492),i=n(7005);t.exports=function t(e,n,a,o,s){return e===n||(null==e||null==n||!i(e)&&!i(n)?e!=e&&n!=n:r(e,n,a,o,t,s))}},2492:(t,e,n)=>{var r=n(6384),i=n(7114),a=n(8351),o=n(6096),s=n(4160),c=n(1469),u=n(4144),l=n(6719),h="[object Arguments]",f="[object Array]",d="[object Object]",p=Object.prototype.hasOwnProperty;t.exports=function(t,e,n,y,g,m){var v=c(t),b=c(e),_=v?f:s(t),x=b?f:s(e),w=(_=_==h?d:_)==d,k=(x=x==h?d:x)==d,T=_==x;if(T&&u(t)){if(!u(e))return!1;v=!0,w=!1}if(T&&!w)return m||(m=new r),v||l(t)?i(t,e,n,y,g,m):a(t,e,_,n,y,g,m);if(!(1&n)){var E=w&&p.call(t,"__wrapped__"),C=k&&p.call(e,"__wrapped__");if(E||C){var S=E?t.value():t,A=C?e.value():e;return m||(m=new r),g(S,A,n,y,m)}}return!!T&&(m||(m=new r),o(t,e,n,y,g,m))}},5588:(t,e,n)=>{var r=n(4160),i=n(7005);t.exports=function(t){return i(t)&&"[object Map]"==r(t)}},2958:(t,e,n)=>{var r=n(6384),i=n(939);t.exports=function(t,e,n,a){var o=n.length,s=o,c=!a;if(null==t)return!s;for(t=Object(t);o--;){var u=n[o];if(c&&u[2]?u[1]!==t[u[0]]:!(u[0]in t))return!1}for(;++o<s;){var l=(u=n[o])[0],h=t[l],f=u[1];if(c&&u[2]){if(void 0===h&&!(l in t))return!1}else{var d=new r;if(a)var p=a(h,f,l,t,e,d);if(!(void 0===p?i(f,h,3,a,d):p))return!1}}return!0}},2722:t=>{t.exports=function(t){return t!=t}},8458:(t,e,n)=>{var r=n(3560),i=n(5346),a=n(3218),o=n(346),s=/^\[object .+?Constructor\]$/,c=Function.prototype,u=Object.prototype,l=c.toString,h=u.hasOwnProperty,f=RegExp("^"+l.call(h).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=function(t){return!(!a(t)||i(t))&&(r(t)?f:s).test(o(t))}},9221:(t,e,n)=>{var r=n(4160),i=n(7005);t.exports=function(t){return i(t)&&"[object Set]"==r(t)}},8749:(t,e,n)=>{var r=n(4239),i=n(1780),a=n(7005),o={};o["[object Float32Array]"]=o["[object Float64Array]"]=o["[object Int8Array]"]=o["[object Int16Array]"]=o["[object Int32Array]"]=o["[object Uint8Array]"]=o["[object Uint8ClampedArray]"]=o["[object Uint16Array]"]=o["[object Uint32Array]"]=!0,o["[object Arguments]"]=o["[object Array]"]=o["[object ArrayBuffer]"]=o["[object Boolean]"]=o["[object DataView]"]=o["[object Date]"]=o["[object Error]"]=o["[object Function]"]=o["[object Map]"]=o["[object Number]"]=o["[object Object]"]=o["[object RegExp]"]=o["[object Set]"]=o["[object String]"]=o["[object WeakMap]"]=!1,t.exports=function(t){return a(t)&&i(t.length)&&!!o[r(t)]}},7206:(t,e,n)=>{var r=n(1573),i=n(6432),a=n(6557),o=n(1469),s=n(9601);t.exports=function(t){return"function"==typeof t?t:null==t?a:"object"==typeof t?o(t)?i(t[0],t[1]):r(t):s(t)}},280:(t,e,n)=>{var r=n(5726),i=n(6916),a=Object.prototype.hasOwnProperty;t.exports=function(t){if(!r(t))return i(t);var e=[];for(var n in Object(t))a.call(t,n)&&"constructor"!=n&&e.push(n);return e}},313:(t,e,n)=>{var r=n(3218),i=n(5726),a=n(3498),o=Object.prototype.hasOwnProperty;t.exports=function(t){if(!r(t))return a(t);var e=i(t),n=[];for(var s in t)("constructor"!=s||!e&&o.call(t,s))&&n.push(s);return n}},433:t=>{t.exports=function(t,e){return t<e}},9199:(t,e,n)=>{var r=n(9881),i=n(8612);t.exports=function(t,e){var n=-1,a=i(t)?Array(t.length):[];return r(t,(function(t,r,i){a[++n]=e(t,r,i)})),a}},1573:(t,e,n)=>{var r=n(2958),i=n(1499),a=n(2634);t.exports=function(t){var e=i(t);return 1==e.length&&e[0][2]?a(e[0][0],e[0][1]):function(n){return n===t||r(n,t,e)}}},6432:(t,e,n)=>{var r=n(939),i=n(1917),a=n(9095),o=n(5403),s=n(9162),c=n(2634),u=n(327);t.exports=function(t,e){return o(t)&&s(e)?c(u(t),e):function(n){var o=i(n,t);return void 0===o&&o===e?a(n,t):r(e,o,3)}}},2980:(t,e,n)=>{var r=n(6384),i=n(6556),a=n(8483),o=n(9783),s=n(3218),c=n(1704),u=n(6390);t.exports=function t(e,n,l,h,f){e!==n&&a(n,(function(a,c){if(f||(f=new r),s(a))o(e,n,c,l,t,h,f);else{var d=h?h(u(e,c),a,c+"",e,n,f):void 0;void 0===d&&(d=a),i(e,c,d)}}),c)}},9783:(t,e,n)=>{var r=n(6556),i=n(4626),a=n(7133),o=n(278),s=n(8517),c=n(5694),u=n(1469),l=n(9246),h=n(4144),f=n(3560),d=n(3218),p=n(8630),y=n(6719),g=n(6390),m=n(3678);t.exports=function(t,e,n,v,b,_,x){var w=g(t,n),k=g(e,n),T=x.get(k);if(T)r(t,n,T);else{var E=_?_(w,k,n+"",t,e,x):void 0,C=void 0===E;if(C){var S=u(k),A=!S&&h(k),M=!S&&!A&&y(k);E=k,S||A||M?u(w)?E=w:l(w)?E=o(w):A?(C=!1,E=i(k,!0)):M?(C=!1,E=a(k,!0)):E=[]:p(k)||c(k)?(E=w,c(w)?E=m(w):d(w)&&!f(w)||(E=s(k))):C=!1}C&&(x.set(k,E),b(E,k,v,_,x),x.delete(k)),r(t,n,E)}}},9556:(t,e,n)=>{var r=n(9932),i=n(7786),a=n(7206),o=n(9199),s=n(1131),c=n(1717),u=n(5022),l=n(6557),h=n(1469);t.exports=function(t,e,n){e=e.length?r(e,(function(t){return h(t)?function(e){return i(e,1===t.length?t[0]:t)}:t})):[l];var f=-1;e=r(e,c(a));var d=o(t,(function(t,n,i){return{criteria:r(e,(function(e){return e(t)})),index:++f,value:t}}));return s(d,(function(t,e){return u(t,e,n)}))}},5970:(t,e,n)=>{var r=n(3012),i=n(9095);t.exports=function(t,e){return r(t,e,(function(e,n){return i(t,n)}))}},3012:(t,e,n)=>{var r=n(7786),i=n(611),a=n(1811);t.exports=function(t,e,n){for(var o=-1,s=e.length,c={};++o<s;){var u=e[o],l=r(t,u);n(l,u)&&i(c,a(u,t),l)}return c}},371:t=>{t.exports=function(t){return function(e){return null==e?void 0:e[t]}}},9152:(t,e,n)=>{var r=n(7786);t.exports=function(t){return function(e){return r(e,t)}}},98:t=>{var e=Math.ceil,n=Math.max;t.exports=function(t,r,i,a){for(var o=-1,s=n(e((r-t)/(i||1)),0),c=Array(s);s--;)c[a?s:++o]=t,t+=i;return c}},107:t=>{t.exports=function(t,e,n,r,i){return i(t,(function(t,i,a){n=r?(r=!1,t):e(n,t,i,a)})),n}},5976:(t,e,n)=>{var r=n(6557),i=n(5357),a=n(61);t.exports=function(t,e){return a(i(t,e,r),t+"")}},611:(t,e,n)=>{var r=n(4865),i=n(1811),a=n(5776),o=n(3218),s=n(327);t.exports=function(t,e,n,c){if(!o(t))return t;for(var u=-1,l=(e=i(e,t)).length,h=l-1,f=t;null!=f&&++u<l;){var d=s(e[u]),p=n;if("__proto__"===d||"constructor"===d||"prototype"===d)return t;if(u!=h){var y=f[d];void 0===(p=c?c(y,d,f):void 0)&&(p=o(y)?y:a(e[u+1])?[]:{})}r(f,d,p),f=f[d]}return t}},6560:(t,e,n)=>{var r=n(5703),i=n(8777),a=n(6557),o=i?function(t,e){return i(t,"toString",{configurable:!0,enumerable:!1,value:r(e),writable:!0})}:a;t.exports=o},1131:t=>{t.exports=function(t,e){var n=t.length;for(t.sort(e);n--;)t[n]=t[n].value;return t}},2545:t=>{t.exports=function(t,e){for(var n=-1,r=Array(t);++n<t;)r[n]=e(n);return r}},531:(t,e,n)=>{var r=n(2705),i=n(9932),a=n(1469),o=n(3448),s=r?r.prototype:void 0,c=s?s.toString:void 0;t.exports=function t(e){if("string"==typeof e)return e;if(a(e))return i(e,t)+"";if(o(e))return c?c.call(e):"";var n=e+"";return"0"==n&&1/e==-1/0?"-0":n}},7561:(t,e,n)=>{var r=n(7990),i=/^\s+/;t.exports=function(t){return t?t.slice(0,r(t)+1).replace(i,""):t}},1717:t=>{t.exports=function(t){return function(e){return t(e)}}},5652:(t,e,n)=>{var r=n(8668),i=n(7443),a=n(1196),o=n(4757),s=n(3593),c=n(1814);t.exports=function(t,e,n){var u=-1,l=i,h=t.length,f=!0,d=[],p=d;if(n)f=!1,l=a;else if(h>=200){var y=e?null:s(t);if(y)return c(y);f=!1,l=o,p=new r}else p=e?[]:d;t:for(;++u<h;){var g=t[u],m=e?e(g):g;if(g=n||0!==g?g:0,f&&m==m){for(var v=p.length;v--;)if(p[v]===m)continue t;e&&p.push(m),d.push(g)}else l(p,m,n)||(p!==d&&p.push(m),d.push(g))}return d}},7415:(t,e,n)=>{var r=n(9932);t.exports=function(t,e){return r(e,(function(e){return t[e]}))}},1757:t=>{t.exports=function(t,e,n){for(var r=-1,i=t.length,a=e.length,o={};++r<i;){var s=r<a?e[r]:void 0;n(o,t[r],s)}return o}},4757:t=>{t.exports=function(t,e){return t.has(e)}},4290:(t,e,n)=>{var r=n(6557);t.exports=function(t){return"function"==typeof t?t:r}},1811:(t,e,n)=>{var r=n(1469),i=n(5403),a=n(5514),o=n(9833);t.exports=function(t,e){return r(t)?t:i(t,e)?[t]:a(o(t))}},4318:(t,e,n)=>{var r=n(1149);t.exports=function(t){var e=new t.constructor(t.byteLength);return new r(e).set(new r(t)),e}},4626:(t,e,n)=>{t=n.nmd(t);var r=n(5639),i=e&&!e.nodeType&&e,a=i&&t&&!t.nodeType&&t,o=a&&a.exports===i?r.Buffer:void 0,s=o?o.allocUnsafe:void 0;t.exports=function(t,e){if(e)return t.slice();var n=t.length,r=s?s(n):new t.constructor(n);return t.copy(r),r}},7157:(t,e,n)=>{var r=n(4318);t.exports=function(t,e){var n=e?r(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.byteLength)}},3147:t=>{var e=/\w*$/;t.exports=function(t){var n=new t.constructor(t.source,e.exec(t));return n.lastIndex=t.lastIndex,n}},419:(t,e,n)=>{var r=n(2705),i=r?r.prototype:void 0,a=i?i.valueOf:void 0;t.exports=function(t){return a?Object(a.call(t)):{}}},7133:(t,e,n)=>{var r=n(4318);t.exports=function(t,e){var n=e?r(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.length)}},6393:(t,e,n)=>{var r=n(3448);t.exports=function(t,e){if(t!==e){var n=void 0!==t,i=null===t,a=t==t,o=r(t),s=void 0!==e,c=null===e,u=e==e,l=r(e);if(!c&&!l&&!o&&t>e||o&&s&&u&&!c&&!l||i&&s&&u||!n&&u||!a)return 1;if(!i&&!o&&!l&&t<e||l&&n&&a&&!i&&!o||c&&n&&a||!s&&a||!u)return-1}return 0}},5022:(t,e,n)=>{var r=n(6393);t.exports=function(t,e,n){for(var i=-1,a=t.criteria,o=e.criteria,s=a.length,c=n.length;++i<s;){var u=r(a[i],o[i]);if(u)return i>=c?u:u*("desc"==n[i]?-1:1)}return t.index-e.index}},278:t=>{t.exports=function(t,e){var n=-1,r=t.length;for(e||(e=Array(r));++n<r;)e[n]=t[n];return e}},8363:(t,e,n)=>{var r=n(4865),i=n(9465);t.exports=function(t,e,n,a){var o=!n;n||(n={});for(var s=-1,c=e.length;++s<c;){var u=e[s],l=a?a(n[u],t[u],u,n,t):void 0;void 0===l&&(l=t[u]),o?i(n,u,l):r(n,u,l)}return n}},8805:(t,e,n)=>{var r=n(8363),i=n(9551);t.exports=function(t,e){return r(t,i(t),e)}},1911:(t,e,n)=>{var r=n(8363),i=n(1442);t.exports=function(t,e){return r(t,i(t),e)}},4429:(t,e,n)=>{var r=n(5639)["__core-js_shared__"];t.exports=r},1750:(t,e,n)=>{var r=n(5976),i=n(6612);t.exports=function(t){return r((function(e,n){var r=-1,a=n.length,o=a>1?n[a-1]:void 0,s=a>2?n[2]:void 0;for(o=t.length>3&&"function"==typeof o?(a--,o):void 0,s&&i(n[0],n[1],s)&&(o=a<3?void 0:o,a=1),e=Object(e);++r<a;){var c=n[r];c&&t(e,c,r,o)}return e}))}},9291:(t,e,n)=>{var r=n(8612);t.exports=function(t,e){return function(n,i){if(null==n)return n;if(!r(n))return t(n,i);for(var a=n.length,o=e?a:-1,s=Object(n);(e?o--:++o<a)&&!1!==i(s[o],o,s););return n}}},5063:t=>{t.exports=function(t){return function(e,n,r){for(var i=-1,a=Object(e),o=r(e),s=o.length;s--;){var c=o[t?s:++i];if(!1===n(a[c],c,a))break}return e}}},7740:(t,e,n)=>{var r=n(7206),i=n(8612),a=n(3674);t.exports=function(t){return function(e,n,o){var s=Object(e);if(!i(e)){var c=r(n,3);e=a(e),n=function(t){return c(s[t],t,s)}}var u=t(e,n,o);return u>-1?s[c?e[u]:u]:void 0}}},7445:(t,e,n)=>{var r=n(98),i=n(6612),a=n(8601);t.exports=function(t){return function(e,n,o){return o&&"number"!=typeof o&&i(e,n,o)&&(n=o=void 0),e=a(e),void 0===n?(n=e,e=0):n=a(n),o=void 0===o?e<n?1:-1:a(o),r(e,n,o,t)}}},3593:(t,e,n)=>{var r=n(8525),i=n(308),a=n(1814),o=r&&1/a(new r([,-0]))[1]==1/0?function(t){return new r(t)}:i;t.exports=o},8777:(t,e,n)=>{var r=n(852),i=function(){try{var t=r(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();t.exports=i},7114:(t,e,n)=>{var r=n(8668),i=n(2908),a=n(4757);t.exports=function(t,e,n,o,s,c){var u=1&n,l=t.length,h=e.length;if(l!=h&&!(u&&h>l))return!1;var f=c.get(t),d=c.get(e);if(f&&d)return f==e&&d==t;var p=-1,y=!0,g=2&n?new r:void 0;for(c.set(t,e),c.set(e,t);++p<l;){var m=t[p],v=e[p];if(o)var b=u?o(v,m,p,e,t,c):o(m,v,p,t,e,c);if(void 0!==b){if(b)continue;y=!1;break}if(g){if(!i(e,(function(t,e){if(!a(g,e)&&(m===t||s(m,t,n,o,c)))return g.push(e)}))){y=!1;break}}else if(m!==v&&!s(m,v,n,o,c)){y=!1;break}}return c.delete(t),c.delete(e),y}},8351:(t,e,n)=>{var r=n(2705),i=n(1149),a=n(7813),o=n(7114),s=n(8776),c=n(1814),u=r?r.prototype:void 0,l=u?u.valueOf:void 0;t.exports=function(t,e,n,r,u,h,f){switch(n){case"[object DataView]":if(t.byteLength!=e.byteLength||t.byteOffset!=e.byteOffset)return!1;t=t.buffer,e=e.buffer;case"[object ArrayBuffer]":return!(t.byteLength!=e.byteLength||!h(new i(t),new i(e)));case"[object Boolean]":case"[object Date]":case"[object Number]":return a(+t,+e);case"[object Error]":return t.name==e.name&&t.message==e.message;case"[object RegExp]":case"[object String]":return t==e+"";case"[object Map]":var d=s;case"[object Set]":var p=1&r;if(d||(d=c),t.size!=e.size&&!p)return!1;var y=f.get(t);if(y)return y==e;r|=2,f.set(t,e);var g=o(d(t),d(e),r,u,h,f);return f.delete(t),g;case"[object Symbol]":if(l)return l.call(t)==l.call(e)}return!1}},6096:(t,e,n)=>{var r=n(8234),i=Object.prototype.hasOwnProperty;t.exports=function(t,e,n,a,o,s){var c=1&n,u=r(t),l=u.length;if(l!=r(e).length&&!c)return!1;for(var h=l;h--;){var f=u[h];if(!(c?f in e:i.call(e,f)))return!1}var d=s.get(t),p=s.get(e);if(d&&p)return d==e&&p==t;var y=!0;s.set(t,e),s.set(e,t);for(var g=c;++h<l;){var m=t[f=u[h]],v=e[f];if(a)var b=c?a(v,m,f,e,t,s):a(m,v,f,t,e,s);if(!(void 0===b?m===v||o(m,v,n,a,s):b)){y=!1;break}g||(g="constructor"==f)}if(y&&!g){var _=t.constructor,x=e.constructor;_==x||!("constructor"in t)||!("constructor"in e)||"function"==typeof _&&_ instanceof _&&"function"==typeof x&&x instanceof x||(y=!1)}return s.delete(t),s.delete(e),y}},9021:(t,e,n)=>{var r=n(5564),i=n(5357),a=n(61);t.exports=function(t){return a(i(t,void 0,r),t+"")}},1957:(t,e,n)=>{var r="object"==typeof n.g&&n.g&&n.g.Object===Object&&n.g;t.exports=r},8234:(t,e,n)=>{var r=n(8866),i=n(9551),a=n(3674);t.exports=function(t){return r(t,a,i)}},6904:(t,e,n)=>{var r=n(8866),i=n(1442),a=n(1704);t.exports=function(t){return r(t,a,i)}},5050:(t,e,n)=>{var r=n(7019);t.exports=function(t,e){var n=t.__data__;return r(e)?n["string"==typeof e?"string":"hash"]:n.map}},1499:(t,e,n)=>{var r=n(9162),i=n(3674);t.exports=function(t){for(var e=i(t),n=e.length;n--;){var a=e[n],o=t[a];e[n]=[a,o,r(o)]}return e}},852:(t,e,n)=>{var r=n(8458),i=n(7801);t.exports=function(t,e){var n=i(t,e);return r(n)?n:void 0}},5924:(t,e,n)=>{var r=n(5569)(Object.getPrototypeOf,Object);t.exports=r},9607:(t,e,n)=>{var r=n(2705),i=Object.prototype,a=i.hasOwnProperty,o=i.toString,s=r?r.toStringTag:void 0;t.exports=function(t){var e=a.call(t,s),n=t[s];try{t[s]=void 0;var r=!0}catch(t){}var i=o.call(t);return r&&(e?t[s]=n:delete t[s]),i}},9551:(t,e,n)=>{var r=n(4963),i=n(479),a=Object.prototype.propertyIsEnumerable,o=Object.getOwnPropertySymbols,s=o?function(t){return null==t?[]:(t=Object(t),r(o(t),(function(e){return a.call(t,e)})))}:i;t.exports=s},1442:(t,e,n)=>{var r=n(2488),i=n(5924),a=n(9551),o=n(479),s=Object.getOwnPropertySymbols?function(t){for(var e=[];t;)r(e,a(t)),t=i(t);return e}:o;t.exports=s},4160:(t,e,n)=>{var r=n(8552),i=n(7071),a=n(3818),o=n(8525),s=n(577),c=n(4239),u=n(346),l="[object Map]",h="[object Promise]",f="[object Set]",d="[object WeakMap]",p="[object DataView]",y=u(r),g=u(i),m=u(a),v=u(o),b=u(s),_=c;(r&&_(new r(new ArrayBuffer(1)))!=p||i&&_(new i)!=l||a&&_(a.resolve())!=h||o&&_(new o)!=f||s&&_(new s)!=d)&&(_=function(t){var e=c(t),n="[object Object]"==e?t.constructor:void 0,r=n?u(n):"";if(r)switch(r){case y:return p;case g:return l;case m:return h;case v:return f;case b:return d}return e}),t.exports=_},7801:t=>{t.exports=function(t,e){return null==t?void 0:t[e]}},222:(t,e,n)=>{var r=n(1811),i=n(5694),a=n(1469),o=n(5776),s=n(1780),c=n(327);t.exports=function(t,e,n){for(var u=-1,l=(e=r(e,t)).length,h=!1;++u<l;){var f=c(e[u]);if(!(h=null!=t&&n(t,f)))break;t=t[f]}return h||++u!=l?h:!!(l=null==t?0:t.length)&&s(l)&&o(f,l)&&(a(t)||i(t))}},2689:t=>{var e=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]");t.exports=function(t){return e.test(t)}},1789:(t,e,n)=>{var r=n(4536);t.exports=function(){this.__data__=r?r(null):{},this.size=0}},401:t=>{t.exports=function(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e}},7667:(t,e,n)=>{var r=n(4536),i=Object.prototype.hasOwnProperty;t.exports=function(t){var e=this.__data__;if(r){var n=e[t];return"__lodash_hash_undefined__"===n?void 0:n}return i.call(e,t)?e[t]:void 0}},1327:(t,e,n)=>{var r=n(4536),i=Object.prototype.hasOwnProperty;t.exports=function(t){var e=this.__data__;return r?void 0!==e[t]:i.call(e,t)}},1866:(t,e,n)=>{var r=n(4536);t.exports=function(t,e){var n=this.__data__;return this.size+=this.has(t)?0:1,n[t]=r&&void 0===e?"__lodash_hash_undefined__":e,this}},3824:t=>{var e=Object.prototype.hasOwnProperty;t.exports=function(t){var n=t.length,r=new t.constructor(n);return n&&"string"==typeof t[0]&&e.call(t,"index")&&(r.index=t.index,r.input=t.input),r}},9148:(t,e,n)=>{var r=n(4318),i=n(7157),a=n(3147),o=n(419),s=n(7133);t.exports=function(t,e,n){var c=t.constructor;switch(e){case"[object ArrayBuffer]":return r(t);case"[object Boolean]":case"[object Date]":return new c(+t);case"[object DataView]":return i(t,n);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[object Uint16Array]":case"[object Uint32Array]":return s(t,n);case"[object Map]":case"[object Set]":return new c;case"[object Number]":case"[object String]":return new c(t);case"[object RegExp]":return a(t);case"[object Symbol]":return o(t)}}},8517:(t,e,n)=>{var r=n(3118),i=n(5924),a=n(5726);t.exports=function(t){return"function"!=typeof t.constructor||a(t)?{}:r(i(t))}},7285:(t,e,n)=>{var r=n(2705),i=n(5694),a=n(1469),o=r?r.isConcatSpreadable:void 0;t.exports=function(t){return a(t)||i(t)||!!(o&&t&&t[o])}},5776:t=>{var e=/^(?:0|[1-9]\d*)$/;t.exports=function(t,n){var r=typeof t;return!!(n=null==n?9007199254740991:n)&&("number"==r||"symbol"!=r&&e.test(t))&&t>-1&&t%1==0&&t<n}},6612:(t,e,n)=>{var r=n(7813),i=n(8612),a=n(5776),o=n(3218);t.exports=function(t,e,n){if(!o(n))return!1;var s=typeof e;return!!("number"==s?i(n)&&a(e,n.length):"string"==s&&e in n)&&r(n[e],t)}},5403:(t,e,n)=>{var r=n(1469),i=n(3448),a=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,o=/^\w*$/;t.exports=function(t,e){if(r(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!i(t))||o.test(t)||!a.test(t)||null!=e&&t in Object(e)}},7019:t=>{t.exports=function(t){var e=typeof t;return"string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t}},5346:(t,e,n)=>{var r,i=n(4429),a=(r=/[^.]+$/.exec(i&&i.keys&&i.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";t.exports=function(t){return!!a&&a in t}},5726:t=>{var e=Object.prototype;t.exports=function(t){var n=t&&t.constructor;return t===("function"==typeof n&&n.prototype||e)}},9162:(t,e,n)=>{var r=n(3218);t.exports=function(t){return t==t&&!r(t)}},7040:t=>{t.exports=function(){this.__data__=[],this.size=0}},2188:(t,e,n)=>{var r=n(8470),i=Array.prototype.splice;t.exports=function(t){var e=this.__data__,n=r(e,t);return!(n<0||(n==e.length-1?e.pop():i.call(e,n,1),--this.size,0))}},2117:(t,e,n)=>{var r=n(8470);t.exports=function(t){var e=this.__data__,n=r(e,t);return n<0?void 0:e[n][1]}},7518:(t,e,n)=>{var r=n(8470);t.exports=function(t){return r(this.__data__,t)>-1}},4705:(t,e,n)=>{var r=n(8470);t.exports=function(t,e){var n=this.__data__,i=r(n,t);return i<0?(++this.size,n.push([t,e])):n[i][1]=e,this}},4785:(t,e,n)=>{var r=n(1989),i=n(8407),a=n(7071);t.exports=function(){this.size=0,this.__data__={hash:new r,map:new(a||i),string:new r}}},1285:(t,e,n)=>{var r=n(5050);t.exports=function(t){var e=r(this,t).delete(t);return this.size-=e?1:0,e}},6e3:(t,e,n)=>{var r=n(5050);t.exports=function(t){return r(this,t).get(t)}},9916:(t,e,n)=>{var r=n(5050);t.exports=function(t){return r(this,t).has(t)}},5265:(t,e,n)=>{var r=n(5050);t.exports=function(t,e){var n=r(this,t),i=n.size;return n.set(t,e),this.size+=n.size==i?0:1,this}},8776:t=>{t.exports=function(t){var e=-1,n=Array(t.size);return t.forEach((function(t,r){n[++e]=[r,t]})),n}},2634:t=>{t.exports=function(t,e){return function(n){return null!=n&&n[t]===e&&(void 0!==e||t in Object(n))}}},4523:(t,e,n)=>{var r=n(8306);t.exports=function(t){var e=r(t,(function(t){return 500===n.size&&n.clear(),t})),n=e.cache;return e}},4536:(t,e,n)=>{var r=n(852)(Object,"create");t.exports=r},6916:(t,e,n)=>{var r=n(5569)(Object.keys,Object);t.exports=r},3498:t=>{t.exports=function(t){var e=[];if(null!=t)for(var n in Object(t))e.push(n);return e}},1167:(t,e,n)=>{t=n.nmd(t);var r=n(1957),i=e&&!e.nodeType&&e,a=i&&t&&!t.nodeType&&t,o=a&&a.exports===i&&r.process,s=function(){try{return a&&a.require&&a.require("util").types||o&&o.binding&&o.binding("util")}catch(t){}}();t.exports=s},2333:t=>{var e=Object.prototype.toString;t.exports=function(t){return e.call(t)}},5569:t=>{t.exports=function(t,e){return function(n){return t(e(n))}}},5357:(t,e,n)=>{var r=n(6874),i=Math.max;t.exports=function(t,e,n){return e=i(void 0===e?t.length-1:e,0),function(){for(var a=arguments,o=-1,s=i(a.length-e,0),c=Array(s);++o<s;)c[o]=a[e+o];o=-1;for(var u=Array(e+1);++o<e;)u[o]=a[o];return u[e]=n(c),r(t,this,u)}}},5639:(t,e,n)=>{var r=n(1957),i="object"==typeof self&&self&&self.Object===Object&&self,a=r||i||Function("return this")();t.exports=a},6390:t=>{t.exports=function(t,e){if(("constructor"!==e||"function"!=typeof t[e])&&"__proto__"!=e)return t[e]}},619:t=>{t.exports=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this}},2385:t=>{t.exports=function(t){return this.__data__.has(t)}},1814:t=>{t.exports=function(t){var e=-1,n=Array(t.size);return t.forEach((function(t){n[++e]=t})),n}},61:(t,e,n)=>{var r=n(6560),i=n(1275)(r);t.exports=i},1275:t=>{var e=Date.now;t.exports=function(t){var n=0,r=0;return function(){var i=e(),a=16-(i-r);if(r=i,a>0){if(++n>=800)return arguments[0]}else n=0;return t.apply(void 0,arguments)}}},7465:(t,e,n)=>{var r=n(8407);t.exports=function(){this.__data__=new r,this.size=0}},3779:t=>{t.exports=function(t){var e=this.__data__,n=e.delete(t);return this.size=e.size,n}},7599:t=>{t.exports=function(t){return this.__data__.get(t)}},4758:t=>{t.exports=function(t){return this.__data__.has(t)}},4309:(t,e,n)=>{var r=n(8407),i=n(7071),a=n(3369);t.exports=function(t,e){var n=this.__data__;if(n instanceof r){var o=n.__data__;if(!i||o.length<199)return o.push([t,e]),this.size=++n.size,this;n=this.__data__=new a(o)}return n.set(t,e),this.size=n.size,this}},2351:t=>{t.exports=function(t,e,n){for(var r=n-1,i=t.length;++r<i;)if(t[r]===e)return r;return-1}},8016:(t,e,n)=>{var r=n(8983),i=n(2689),a=n(1903);t.exports=function(t){return i(t)?a(t):r(t)}},5514:(t,e,n)=>{var r=n(4523),i=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,a=/\\(\\)?/g,o=r((function(t){var e=[];return 46===t.charCodeAt(0)&&e.push(""),t.replace(i,(function(t,n,r,i){e.push(r?i.replace(a,"$1"):n||t)})),e}));t.exports=o},327:(t,e,n)=>{var r=n(3448);t.exports=function(t){if("string"==typeof t||r(t))return t;var e=t+"";return"0"==e&&1/t==-1/0?"-0":e}},346:t=>{var e=Function.prototype.toString;t.exports=function(t){if(null!=t){try{return e.call(t)}catch(t){}try{return t+""}catch(t){}}return""}},7990:t=>{var e=/\s/;t.exports=function(t){for(var n=t.length;n--&&e.test(t.charAt(n)););return n}},1903:t=>{var e="[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]",n="\\ud83c[\\udffb-\\udfff]",r="[^\\ud800-\\udfff]",i="(?:\\ud83c[\\udde6-\\uddff]){2}",a="[\\ud800-\\udbff][\\udc00-\\udfff]",o="(?:"+e+"|"+n+")?",s="[\\ufe0e\\ufe0f]?",c=s+o+"(?:\\u200d(?:"+[r,i,a].join("|")+")"+s+o+")*",u="(?:"+[r+e+"?",e,i,a,"[\\ud800-\\udfff]"].join("|")+")",l=RegExp(n+"(?="+n+")|"+u+c,"g");t.exports=function(t){for(var e=l.lastIndex=0;l.test(t);)++e;return e}},6678:(t,e,n)=>{var r=n(5990);t.exports=function(t){return r(t,4)}},361:(t,e,n)=>{var r=n(5990);t.exports=function(t){return r(t,5)}},5703:t=>{t.exports=function(t){return function(){return t}}},1747:(t,e,n)=>{var r=n(5976),i=n(7813),a=n(6612),o=n(1704),s=Object.prototype,c=s.hasOwnProperty,u=r((function(t,e){t=Object(t);var n=-1,r=e.length,u=r>2?e[2]:void 0;for(u&&a(e[0],e[1],u)&&(r=1);++n<r;)for(var l=e[n],h=o(l),f=-1,d=h.length;++f<d;){var p=h[f],y=t[p];(void 0===y||i(y,s[p])&&!c.call(t,p))&&(t[p]=l[p])}return t}));t.exports=u},6073:(t,e,n)=>{t.exports=n(4486)},7813:t=>{t.exports=function(t,e){return t===e||t!=t&&e!=e}},3105:(t,e,n)=>{var r=n(4963),i=n(760),a=n(7206),o=n(1469);t.exports=function(t,e){return(o(t)?r:i)(t,a(e,3))}},3311:(t,e,n)=>{var r=n(7740)(n(998));t.exports=r},998:(t,e,n)=>{var r=n(1848),i=n(7206),a=n(554),o=Math.max;t.exports=function(t,e,n){var s=null==t?0:t.length;if(!s)return-1;var c=null==n?0:a(n);return c<0&&(c=o(s+c,0)),r(t,i(e,3),c)}},5564:(t,e,n)=>{var r=n(1078);t.exports=function(t){return null!=t&&t.length?r(t,1):[]}},4486:(t,e,n)=>{var r=n(7412),i=n(9881),a=n(4290),o=n(1469);t.exports=function(t,e){return(o(t)?r:i)(t,a(e))}},2620:(t,e,n)=>{var r=n(8483),i=n(4290),a=n(1704);t.exports=function(t,e){return null==t?t:r(t,i(e),a)}},1917:(t,e,n)=>{var r=n(7786);t.exports=function(t,e,n){var i=null==t?void 0:r(t,e);return void 0===i?n:i}},8721:(t,e,n)=>{var r=n(8565),i=n(222);t.exports=function(t,e){return null!=t&&i(t,e,r)}},9095:(t,e,n)=>{var r=n(13),i=n(222);t.exports=function(t,e){return null!=t&&i(t,e,r)}},6557:t=>{t.exports=function(t){return t}},5694:(t,e,n)=>{var r=n(9454),i=n(7005),a=Object.prototype,o=a.hasOwnProperty,s=a.propertyIsEnumerable,c=r(function(){return arguments}())?r:function(t){return i(t)&&o.call(t,"callee")&&!s.call(t,"callee")};t.exports=c},1469:t=>{var e=Array.isArray;t.exports=e},8612:(t,e,n)=>{var r=n(3560),i=n(1780);t.exports=function(t){return null!=t&&i(t.length)&&!r(t)}},9246:(t,e,n)=>{var r=n(8612),i=n(7005);t.exports=function(t){return i(t)&&r(t)}},4144:(t,e,n)=>{t=n.nmd(t);var r=n(5639),i=n(5062),a=e&&!e.nodeType&&e,o=a&&t&&!t.nodeType&&t,s=o&&o.exports===a?r.Buffer:void 0,c=(s?s.isBuffer:void 0)||i;t.exports=c},1609:(t,e,n)=>{var r=n(280),i=n(4160),a=n(5694),o=n(1469),s=n(8612),c=n(4144),u=n(5726),l=n(6719),h=Object.prototype.hasOwnProperty;t.exports=function(t){if(null==t)return!0;if(s(t)&&(o(t)||"string"==typeof t||"function"==typeof t.splice||c(t)||l(t)||a(t)))return!t.length;var e=i(t);if("[object Map]"==e||"[object Set]"==e)return!t.size;if(u(t))return!r(t).length;for(var n in t)if(h.call(t,n))return!1;return!0}},3560:(t,e,n)=>{var r=n(4239),i=n(3218);t.exports=function(t){if(!i(t))return!1;var e=r(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}},1780:t=>{t.exports=function(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=9007199254740991}},6688:(t,e,n)=>{var r=n(5588),i=n(1717),a=n(1167),o=a&&a.isMap,s=o?i(o):r;t.exports=s},3218:t=>{t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},7005:t=>{t.exports=function(t){return null!=t&&"object"==typeof t}},8630:(t,e,n)=>{var r=n(4239),i=n(5924),a=n(7005),o=Function.prototype,s=Object.prototype,c=o.toString,u=s.hasOwnProperty,l=c.call(Object);t.exports=function(t){if(!a(t)||"[object Object]"!=r(t))return!1;var e=i(t);if(null===e)return!0;var n=u.call(e,"constructor")&&e.constructor;return"function"==typeof n&&n instanceof n&&c.call(n)==l}},2928:(t,e,n)=>{var r=n(9221),i=n(1717),a=n(1167),o=a&&a.isSet,s=o?i(o):r;t.exports=s},7037:(t,e,n)=>{var r=n(4239),i=n(1469),a=n(7005);t.exports=function(t){return"string"==typeof t||!i(t)&&a(t)&&"[object String]"==r(t)}},3448:(t,e,n)=>{var r=n(4239),i=n(7005);t.exports=function(t){return"symbol"==typeof t||i(t)&&"[object Symbol]"==r(t)}},6719:(t,e,n)=>{var r=n(8749),i=n(1717),a=n(1167),o=a&&a.isTypedArray,s=o?i(o):r;t.exports=s},2353:t=>{t.exports=function(t){return void 0===t}},3674:(t,e,n)=>{var r=n(4636),i=n(280),a=n(8612);t.exports=function(t){return a(t)?r(t):i(t)}},1704:(t,e,n)=>{var r=n(4636),i=n(313),a=n(8612);t.exports=function(t){return a(t)?r(t,!0):i(t)}},928:t=>{t.exports=function(t){var e=null==t?0:t.length;return e?t[e-1]:void 0}},5161:(t,e,n)=>{var r=n(9932),i=n(7206),a=n(9199),o=n(1469);t.exports=function(t,e){return(o(t)?r:a)(t,i(e,3))}},6604:(t,e,n)=>{var r=n(9465),i=n(7816),a=n(7206);t.exports=function(t,e){var n={};return e=a(e,3),i(t,(function(t,i,a){r(n,i,e(t,i,a))})),n}},6162:(t,e,n)=>{var r=n(6029),i=n(3325),a=n(6557);t.exports=function(t){return t&&t.length?r(t,a,i):void 0}},8306:(t,e,n)=>{var r=n(3369);function i(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw new TypeError("Expected a function");var n=function(){var r=arguments,i=e?e.apply(this,r):r[0],a=n.cache;if(a.has(i))return a.get(i);var o=t.apply(this,r);return n.cache=a.set(i,o)||a,o};return n.cache=new(i.Cache||r),n}i.Cache=r,t.exports=i},3857:(t,e,n)=>{var r=n(2980),i=n(1750)((function(t,e,n){r(t,e,n)}));t.exports=i},3632:(t,e,n)=>{var r=n(6029),i=n(433),a=n(6557);t.exports=function(t){return t&&t.length?r(t,a,i):void 0}},2762:(t,e,n)=>{var r=n(6029),i=n(7206),a=n(433);t.exports=function(t,e){return t&&t.length?r(t,i(e,2),a):void 0}},308:t=>{t.exports=function(){}},7771:(t,e,n)=>{var r=n(5639);t.exports=function(){return r.Date.now()}},9722:(t,e,n)=>{var r=n(5970),i=n(9021)((function(t,e){return null==t?{}:r(t,e)}));t.exports=i},9601:(t,e,n)=>{var r=n(371),i=n(9152),a=n(5403),o=n(327);t.exports=function(t){return a(t)?r(o(t)):i(t)}},6026:(t,e,n)=>{var r=n(7445)();t.exports=r},4061:(t,e,n)=>{var r=n(2663),i=n(9881),a=n(7206),o=n(107),s=n(1469);t.exports=function(t,e,n){var c=s(t)?r:o,u=arguments.length<3;return c(t,a(e,4),n,u,i)}},4238:(t,e,n)=>{var r=n(280),i=n(4160),a=n(8612),o=n(7037),s=n(8016);t.exports=function(t){if(null==t)return 0;if(a(t))return o(t)?s(t):t.length;var e=i(t);return"[object Map]"==e||"[object Set]"==e?t.size:r(t).length}},9734:(t,e,n)=>{var r=n(1078),i=n(9556),a=n(5976),o=n(6612),s=a((function(t,e){if(null==t)return[];var n=e.length;return n>1&&o(t,e[0],e[1])?e=[]:n>2&&o(e[0],e[1],e[2])&&(e=[e[0]]),i(t,r(e,1),[])}));t.exports=s},479:t=>{t.exports=function(){return[]}},5062:t=>{t.exports=function(){return!1}},8601:(t,e,n)=>{var r=n(4841);t.exports=function(t){return t?Infinity===(t=r(t))||t===-1/0?17976931348623157e292*(t<0?-1:1):t==t?t:0:0===t?t:0}},554:(t,e,n)=>{var r=n(8601);t.exports=function(t){var e=r(t),n=e%1;return e==e?n?e-n:e:0}},4841:(t,e,n)=>{var r=n(7561),i=n(3218),a=n(3448),o=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,c=/^0o[0-7]+$/i,u=parseInt;t.exports=function(t){if("number"==typeof t)return t;if(a(t))return NaN;if(i(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=i(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=r(t);var n=s.test(t);return n||c.test(t)?u(t.slice(2),n?2:8):o.test(t)?NaN:+t}},3678:(t,e,n)=>{var r=n(8363),i=n(1704);t.exports=function(t){return r(t,i(t))}},9833:(t,e,n)=>{var r=n(531);t.exports=function(t){return null==t?"":r(t)}},8718:(t,e,n)=>{var r=n(7412),i=n(3118),a=n(7816),o=n(7206),s=n(5924),c=n(1469),u=n(4144),l=n(3560),h=n(3218),f=n(6719);t.exports=function(t,e,n){var d=c(t),p=d||u(t)||f(t);if(e=o(e,4),null==n){var y=t&&t.constructor;n=p?d?new y:[]:h(t)&&l(y)?i(s(t)):{}}return(p?r:a)(t,(function(t,r,i){return e(n,t,r,i)})),n}},3386:(t,e,n)=>{var r=n(1078),i=n(5976),a=n(5652),o=n(9246),s=i((function(t){return a(r(t,1,o,!0))}));t.exports=s},3955:(t,e,n)=>{var r=n(9833),i=0;t.exports=function(t){var e=++i;return r(t)+e}},2628:(t,e,n)=>{var r=n(7415),i=n(3674);t.exports=function(t){return null==t?[]:r(t,i(t))}},7287:(t,e,n)=>{var r=n(4865),i=n(1757);t.exports=function(t,e){return i(t||[],e||[],r)}},9234:()=>{},1748:(t,e,n)=>{var r={"./locale":9234,"./locale.js":9234};function i(t){var e=a(t);return n(e)}function a(t){if(!n.o(r,t)){var e=new Error("Cannot find module '"+t+"'");throw e.code="MODULE_NOT_FOUND",e}return r[t]}i.keys=function(){return Object.keys(r)},i.resolve=a,t.exports=i,i.id=1748},1941:function(t,e,n){(t=n.nmd(t)).exports=function(){"use strict";var e,r;function i(){return e.apply(null,arguments)}function a(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function o(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function s(t){return void 0===t}function c(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function u(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function l(t,e){var n,r=[];for(n=0;n<t.length;++n)r.push(e(t[n],n));return r}function h(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function f(t,e){for(var n in e)h(e,n)&&(t[n]=e[n]);return h(e,"toString")&&(t.toString=e.toString),h(e,"valueOf")&&(t.valueOf=e.valueOf),t}function d(t,e,n,r){return be(t,e,n,r,!0).utc()}function p(t){return null==t._pf&&(t._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),t._pf}function y(t){if(null==t._isValid){var e=p(t),n=r.call(e.parsedDateParts,(function(t){return null!=t})),i=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.weekdayMismatch&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&n);if(t._strict&&(i=i&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour),null!=Object.isFrozen&&Object.isFrozen(t))return i;t._isValid=i}return t._isValid}function g(t){var e=d(NaN);return null!=t?f(p(e),t):p(e).userInvalidated=!0,e}r=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,r=0;r<n;r++)if(r in e&&t.call(this,e[r],r,e))return!0;return!1};var m=i.momentProperties=[];function v(t,e){var n,r,i;if(s(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),s(e._i)||(t._i=e._i),s(e._f)||(t._f=e._f),s(e._l)||(t._l=e._l),s(e._strict)||(t._strict=e._strict),s(e._tzm)||(t._tzm=e._tzm),s(e._isUTC)||(t._isUTC=e._isUTC),s(e._offset)||(t._offset=e._offset),s(e._pf)||(t._pf=p(e)),s(e._locale)||(t._locale=e._locale),0<m.length)for(n=0;n<m.length;n++)s(i=e[r=m[n]])||(t[r]=i);return t}var b=!1;function _(t){v(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===b&&(b=!0,i.updateOffset(this),b=!1)}function x(t){return t instanceof _||null!=t&&null!=t._isAMomentObject}function w(t){return t<0?Math.ceil(t)||0:Math.floor(t)}function k(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=w(e)),n}function T(t,e,n){var r,i=Math.min(t.length,e.length),a=Math.abs(t.length-e.length),o=0;for(r=0;r<i;r++)(n&&t[r]!==e[r]||!n&&k(t[r])!==k(e[r]))&&o++;return o+a}function E(t){!1===i.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function C(t,e){var n=!0;return f((function(){if(null!=i.deprecationHandler&&i.deprecationHandler(null,t),n){for(var r,a=[],o=0;o<arguments.length;o++){if(r="","object"==typeof arguments[o]){for(var s in r+="\n["+o+"] ",arguments[0])r+=s+": "+arguments[0][s]+", ";r=r.slice(0,-2)}else r=arguments[o];a.push(r)}E(t+"\nArguments: "+Array.prototype.slice.call(a).join("")+"\n"+(new Error).stack),n=!1}return e.apply(this,arguments)}),e)}var S,A={};function M(t,e){null!=i.deprecationHandler&&i.deprecationHandler(t,e),A[t]||(E(e),A[t]=!0)}function N(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function D(t,e){var n,r=f({},t);for(n in e)h(e,n)&&(o(t[n])&&o(e[n])?(r[n]={},f(r[n],t[n]),f(r[n],e[n])):null!=e[n]?r[n]=e[n]:delete r[n]);for(n in t)h(t,n)&&!h(e,n)&&o(t[n])&&(r[n]=f({},r[n]));return r}function O(t){null!=t&&this.set(t)}i.suppressDeprecationWarnings=!1,i.deprecationHandler=null,S=Object.keys?Object.keys:function(t){var e,n=[];for(e in t)h(t,e)&&n.push(e);return n};var B={};function L(t,e){var n=t.toLowerCase();B[n]=B[n+"s"]=B[e]=t}function I(t){return"string"==typeof t?B[t]||B[t.toLowerCase()]:void 0}function R(t){var e,n,r={};for(n in t)h(t,n)&&(e=I(n))&&(r[e]=t[n]);return r}var F={};function P(t,e){F[t]=e}function j(t,e,n){var r=""+Math.abs(t),i=e-r.length;return(0<=t?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+r}var Y=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,z=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,U={},q={};function H(t,e,n,r){var i=r;"string"==typeof r&&(i=function(){return this[r]()}),t&&(q[t]=i),e&&(q[e[0]]=function(){return j(i.apply(this,arguments),e[1],e[2])}),n&&(q[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),t)})}function $(t,e){return t.isValid()?(e=W(e,t.localeData()),U[e]=U[e]||function(t){var e,n,r,i=t.match(Y);for(e=0,n=i.length;e<n;e++)q[i[e]]?i[e]=q[i[e]]:i[e]=(r=i[e]).match(/\[[\s\S]/)?r.replace(/^\[|\]$/g,""):r.replace(/\\/g,"");return function(e){var r,a="";for(r=0;r<n;r++)a+=N(i[r])?i[r].call(e,t):i[r];return a}}(e),U[e](t)):t.localeData().invalidDate()}function W(t,e){var n=5;function r(t){return e.longDateFormat(t)||t}for(z.lastIndex=0;0<=n&&z.test(t);)t=t.replace(z,r),z.lastIndex=0,n-=1;return t}var V=/\d/,G=/\d\d/,X=/\d{3}/,Z=/\d{4}/,Q=/[+-]?\d{6}/,K=/\d\d?/,J=/\d\d\d\d?/,tt=/\d\d\d\d\d\d?/,et=/\d{1,3}/,nt=/\d{1,4}/,rt=/[+-]?\d{1,6}/,it=/\d+/,at=/[+-]?\d+/,ot=/Z|[+-]\d\d:?\d\d/gi,st=/Z|[+-]\d\d(?::?\d\d)?/gi,ct=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,ut={};function lt(t,e,n){ut[t]=N(e)?e:function(t,r){return t&&n?n:e}}function ht(t,e){return h(ut,t)?ut[t](e._strict,e._locale):new RegExp(ft(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,(function(t,e,n,r,i){return e||n||r||i}))))}function ft(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var dt={};function pt(t,e){var n,r=e;for("string"==typeof t&&(t=[t]),c(e)&&(r=function(t,n){n[e]=k(t)}),n=0;n<t.length;n++)dt[t[n]]=r}function yt(t,e){pt(t,(function(t,n,r,i){r._w=r._w||{},e(t,r._w,r,i)}))}function gt(t){return mt(t)?366:365}function mt(t){return t%4==0&&t%100!=0||t%400==0}H("Y",0,0,(function(){var t=this.year();return t<=9999?""+t:"+"+t})),H(0,["YY",2],0,(function(){return this.year()%100})),H(0,["YYYY",4],0,"year"),H(0,["YYYYY",5],0,"year"),H(0,["YYYYYY",6,!0],0,"year"),L("year","y"),P("year",1),lt("Y",at),lt("YY",K,G),lt("YYYY",nt,Z),lt("YYYYY",rt,Q),lt("YYYYYY",rt,Q),pt(["YYYYY","YYYYYY"],0),pt("YYYY",(function(t,e){e[0]=2===t.length?i.parseTwoDigitYear(t):k(t)})),pt("YY",(function(t,e){e[0]=i.parseTwoDigitYear(t)})),pt("Y",(function(t,e){e[0]=parseInt(t,10)})),i.parseTwoDigitYear=function(t){return k(t)+(68<k(t)?1900:2e3)};var vt,bt=_t("FullYear",!0);function _t(t,e){return function(n){return null!=n?(wt(this,t,n),i.updateOffset(this,e),this):xt(this,t)}}function xt(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function wt(t,e,n){t.isValid()&&!isNaN(n)&&("FullYear"===e&&mt(t.year())&&1===t.month()&&29===t.date()?t._d["set"+(t._isUTC?"UTC":"")+e](n,t.month(),kt(n,t.month())):t._d["set"+(t._isUTC?"UTC":"")+e](n))}function kt(t,e){if(isNaN(t)||isNaN(e))return NaN;var n=(e%12+12)%12;return t+=(e-n)/12,1===n?mt(t)?29:28:31-n%7%2}vt=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1},H("M",["MM",2],"Mo",(function(){return this.month()+1})),H("MMM",0,0,(function(t){return this.localeData().monthsShort(this,t)})),H("MMMM",0,0,(function(t){return this.localeData().months(this,t)})),L("month","M"),P("month",8),lt("M",K),lt("MM",K,G),lt("MMM",(function(t,e){return e.monthsShortRegex(t)})),lt("MMMM",(function(t,e){return e.monthsRegex(t)})),pt(["M","MM"],(function(t,e){e[1]=k(t)-1})),pt(["MMM","MMMM"],(function(t,e,n,r){var i=n._locale.monthsParse(t,r,n._strict);null!=i?e[1]=i:p(n).invalidMonth=t}));var Tt=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Et="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Ct="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function St(t,e){var n;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=k(e);else if(!c(e=t.localeData().monthsParse(e)))return t;return n=Math.min(t.date(),kt(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,n),t}function At(t){return null!=t?(St(this,t),i.updateOffset(this,!0),this):xt(this,"Month")}var Mt=ct,Nt=ct;function Dt(){function t(t,e){return e.length-t.length}var e,n,r=[],i=[],a=[];for(e=0;e<12;e++)n=d([2e3,e]),r.push(this.monthsShort(n,"")),i.push(this.months(n,"")),a.push(this.months(n,"")),a.push(this.monthsShort(n,""));for(r.sort(t),i.sort(t),a.sort(t),e=0;e<12;e++)r[e]=ft(r[e]),i[e]=ft(i[e]);for(e=0;e<24;e++)a[e]=ft(a[e]);this._monthsRegex=new RegExp("^("+a.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+r.join("|")+")","i")}function Ot(t){var e;if(t<100&&0<=t){var n=Array.prototype.slice.call(arguments);n[0]=t+400,e=new Date(Date.UTC.apply(null,n)),isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t)}else e=new Date(Date.UTC.apply(null,arguments));return e}function Bt(t,e,n){var r=7+e-n;return-(7+Ot(t,0,r).getUTCDay()-e)%7+r-1}function Lt(t,e,n,r,i){var a,o,s=1+7*(e-1)+(7+n-r)%7+Bt(t,r,i);return o=s<=0?gt(a=t-1)+s:s>gt(t)?(a=t+1,s-gt(t)):(a=t,s),{year:a,dayOfYear:o}}function It(t,e,n){var r,i,a=Bt(t.year(),e,n),o=Math.floor((t.dayOfYear()-a-1)/7)+1;return o<1?r=o+Rt(i=t.year()-1,e,n):o>Rt(t.year(),e,n)?(r=o-Rt(t.year(),e,n),i=t.year()+1):(i=t.year(),r=o),{week:r,year:i}}function Rt(t,e,n){var r=Bt(t,e,n),i=Bt(t+1,e,n);return(gt(t)-r+i)/7}function Ft(t,e){return t.slice(e,7).concat(t.slice(0,e))}H("w",["ww",2],"wo","week"),H("W",["WW",2],"Wo","isoWeek"),L("week","w"),L("isoWeek","W"),P("week",5),P("isoWeek",5),lt("w",K),lt("ww",K,G),lt("W",K),lt("WW",K,G),yt(["w","ww","W","WW"],(function(t,e,n,r){e[r.substr(0,1)]=k(t)})),H("d",0,"do","day"),H("dd",0,0,(function(t){return this.localeData().weekdaysMin(this,t)})),H("ddd",0,0,(function(t){return this.localeData().weekdaysShort(this,t)})),H("dddd",0,0,(function(t){return this.localeData().weekdays(this,t)})),H("e",0,0,"weekday"),H("E",0,0,"isoWeekday"),L("day","d"),L("weekday","e"),L("isoWeekday","E"),P("day",11),P("weekday",11),P("isoWeekday",11),lt("d",K),lt("e",K),lt("E",K),lt("dd",(function(t,e){return e.weekdaysMinRegex(t)})),lt("ddd",(function(t,e){return e.weekdaysShortRegex(t)})),lt("dddd",(function(t,e){return e.weekdaysRegex(t)})),yt(["dd","ddd","dddd"],(function(t,e,n,r){var i=n._locale.weekdaysParse(t,r,n._strict);null!=i?e.d=i:p(n).invalidWeekday=t})),yt(["d","e","E"],(function(t,e,n,r){e[r]=k(t)}));var Pt="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),jt="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Yt="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),zt=ct,Ut=ct,qt=ct;function Ht(){function t(t,e){return e.length-t.length}var e,n,r,i,a,o=[],s=[],c=[],u=[];for(e=0;e<7;e++)n=d([2e3,1]).day(e),r=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),a=this.weekdays(n,""),o.push(r),s.push(i),c.push(a),u.push(r),u.push(i),u.push(a);for(o.sort(t),s.sort(t),c.sort(t),u.sort(t),e=0;e<7;e++)s[e]=ft(s[e]),c[e]=ft(c[e]),u[e]=ft(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+c.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function $t(){return this.hours()%12||12}function Wt(t,e){H(t,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)}))}function Vt(t,e){return e._meridiemParse}H("H",["HH",2],0,"hour"),H("h",["hh",2],0,$t),H("k",["kk",2],0,(function(){return this.hours()||24})),H("hmm",0,0,(function(){return""+$t.apply(this)+j(this.minutes(),2)})),H("hmmss",0,0,(function(){return""+$t.apply(this)+j(this.minutes(),2)+j(this.seconds(),2)})),H("Hmm",0,0,(function(){return""+this.hours()+j(this.minutes(),2)})),H("Hmmss",0,0,(function(){return""+this.hours()+j(this.minutes(),2)+j(this.seconds(),2)})),Wt("a",!0),Wt("A",!1),L("hour","h"),P("hour",13),lt("a",Vt),lt("A",Vt),lt("H",K),lt("h",K),lt("k",K),lt("HH",K,G),lt("hh",K,G),lt("kk",K,G),lt("hmm",J),lt("hmmss",tt),lt("Hmm",J),lt("Hmmss",tt),pt(["H","HH"],3),pt(["k","kk"],(function(t,e,n){var r=k(t);e[3]=24===r?0:r})),pt(["a","A"],(function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t})),pt(["h","hh"],(function(t,e,n){e[3]=k(t),p(n).bigHour=!0})),pt("hmm",(function(t,e,n){var r=t.length-2;e[3]=k(t.substr(0,r)),e[4]=k(t.substr(r)),p(n).bigHour=!0})),pt("hmmss",(function(t,e,n){var r=t.length-4,i=t.length-2;e[3]=k(t.substr(0,r)),e[4]=k(t.substr(r,2)),e[5]=k(t.substr(i)),p(n).bigHour=!0})),pt("Hmm",(function(t,e,n){var r=t.length-2;e[3]=k(t.substr(0,r)),e[4]=k(t.substr(r))})),pt("Hmmss",(function(t,e,n){var r=t.length-4,i=t.length-2;e[3]=k(t.substr(0,r)),e[4]=k(t.substr(r,2)),e[5]=k(t.substr(i))}));var Gt,Xt=_t("Hours",!0),Zt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Et,monthsShort:Ct,week:{dow:0,doy:6},weekdays:Pt,weekdaysMin:Yt,weekdaysShort:jt,meridiemParse:/[ap]\.?m?\.?/i},Qt={},Kt={};function Jt(t){return t?t.toLowerCase().replace("_","-"):t}function te(e){var r=null;if(!Qt[e]&&t&&t.exports)try{r=Gt._abbr,n(1748)("./"+e),ee(r)}catch(e){}return Qt[e]}function ee(t,e){var n;return t&&((n=s(e)?re(t):ne(t,e))?Gt=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+t+" not found. Did you forget to load it?")),Gt._abbr}function ne(t,e){if(null===e)return delete Qt[t],null;var n,r=Zt;if(e.abbr=t,null!=Qt[t])M("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),r=Qt[t]._config;else if(null!=e.parentLocale)if(null!=Qt[e.parentLocale])r=Qt[e.parentLocale]._config;else{if(null==(n=te(e.parentLocale)))return Kt[e.parentLocale]||(Kt[e.parentLocale]=[]),Kt[e.parentLocale].push({name:t,config:e}),null;r=n._config}return Qt[t]=new O(D(r,e)),Kt[t]&&Kt[t].forEach((function(t){ne(t.name,t.config)})),ee(t),Qt[t]}function re(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return Gt;if(!a(t)){if(e=te(t))return e;t=[t]}return function(t){for(var e,n,r,i,a=0;a<t.length;){for(e=(i=Jt(t[a]).split("-")).length,n=(n=Jt(t[a+1]))?n.split("-"):null;0<e;){if(r=te(i.slice(0,e).join("-")))return r;if(n&&n.length>=e&&T(i,n,!0)>=e-1)break;e--}a++}return Gt}(t)}function ie(t){var e,n=t._a;return n&&-2===p(t).overflow&&(e=n[1]<0||11<n[1]?1:n[2]<1||n[2]>kt(n[0],n[1])?2:n[3]<0||24<n[3]||24===n[3]&&(0!==n[4]||0!==n[5]||0!==n[6])?3:n[4]<0||59<n[4]?4:n[5]<0||59<n[5]?5:n[6]<0||999<n[6]?6:-1,p(t)._overflowDayOfYear&&(e<0||2<e)&&(e=2),p(t)._overflowWeeks&&-1===e&&(e=7),p(t)._overflowWeekday&&-1===e&&(e=8),p(t).overflow=e),t}function ae(t,e,n){return null!=t?t:null!=e?e:n}function oe(t){var e,n,r,a,o,s=[];if(!t._d){var c,u;for(c=t,u=new Date(i.now()),r=c._useUTC?[u.getUTCFullYear(),u.getUTCMonth(),u.getUTCDate()]:[u.getFullYear(),u.getMonth(),u.getDate()],t._w&&null==t._a[2]&&null==t._a[1]&&function(t){var e,n,r,i,a,o,s,c;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)a=1,o=4,n=ae(e.GG,t._a[0],It(_e(),1,4).year),r=ae(e.W,1),((i=ae(e.E,1))<1||7<i)&&(c=!0);else{a=t._locale._week.dow,o=t._locale._week.doy;var u=It(_e(),a,o);n=ae(e.gg,t._a[0],u.year),r=ae(e.w,u.week),null!=e.d?((i=e.d)<0||6<i)&&(c=!0):null!=e.e?(i=e.e+a,(e.e<0||6<e.e)&&(c=!0)):i=a}r<1||r>Rt(n,a,o)?p(t)._overflowWeeks=!0:null!=c?p(t)._overflowWeekday=!0:(s=Lt(n,r,i,a,o),t._a[0]=s.year,t._dayOfYear=s.dayOfYear)}(t),null!=t._dayOfYear&&(o=ae(t._a[0],r[0]),(t._dayOfYear>gt(o)||0===t._dayOfYear)&&(p(t)._overflowDayOfYear=!0),n=Ot(o,0,t._dayOfYear),t._a[1]=n.getUTCMonth(),t._a[2]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=s[e]=r[e];for(;e<7;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[3]&&0===t._a[4]&&0===t._a[5]&&0===t._a[6]&&(t._nextDay=!0,t._a[3]=0),t._d=(t._useUTC?Ot:function(t,e,n,r,i,a,o){var s;return t<100&&0<=t?(s=new Date(t+400,e,n,r,i,a,o),isFinite(s.getFullYear())&&s.setFullYear(t)):s=new Date(t,e,n,r,i,a,o),s}).apply(null,s),a=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[3]=24),t._w&&void 0!==t._w.d&&t._w.d!==a&&(p(t).weekdayMismatch=!0)}}var se=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ce=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ue=/Z|[+-]\d\d(?::?\d\d)?/,le=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],he=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],fe=/^\/?Date\((\-?\d+)/i;function de(t){var e,n,r,i,a,o,s=t._i,c=se.exec(s)||ce.exec(s);if(c){for(p(t).iso=!0,e=0,n=le.length;e<n;e++)if(le[e][1].exec(c[1])){i=le[e][0],r=!1!==le[e][2];break}if(null==i)return void(t._isValid=!1);if(c[3]){for(e=0,n=he.length;e<n;e++)if(he[e][1].exec(c[3])){a=(c[2]||" ")+he[e][0];break}if(null==a)return void(t._isValid=!1)}if(!r&&null!=a)return void(t._isValid=!1);if(c[4]){if(!ue.exec(c[4]))return void(t._isValid=!1);o="Z"}t._f=i+(a||"")+(o||""),me(t)}else t._isValid=!1}var pe=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;var ye={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function ge(t){var e,n,r,i=pe.exec(t._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(i){var a=function(t,e,n,r,i,a){var o=[function(t){var e=parseInt(t,10);return e<=49?2e3+e:e<=999?1900+e:e}(t),Ct.indexOf(e),parseInt(n,10),parseInt(r,10),parseInt(i,10)];return a&&o.push(parseInt(a,10)),o}(i[4],i[3],i[2],i[5],i[6],i[7]);if(n=a,r=t,(e=i[1])&&jt.indexOf(e)!==new Date(n[0],n[1],n[2]).getDay()&&(p(r).weekdayMismatch=!0,!(r._isValid=!1)))return;t._a=a,t._tzm=function(t,e,n){if(t)return ye[t];if(e)return 0;var r=parseInt(n,10),i=r%100;return(r-i)/100*60+i}(i[8],i[9],i[10]),t._d=Ot.apply(null,t._a),t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),p(t).rfc2822=!0}else t._isValid=!1}function me(t){if(t._f!==i.ISO_8601)if(t._f!==i.RFC_2822){t._a=[],p(t).empty=!0;var e,n,r,a,o,s,c,u,l=""+t._i,f=l.length,d=0;for(r=W(t._f,t._locale).match(Y)||[],e=0;e<r.length;e++)a=r[e],(n=(l.match(ht(a,t))||[])[0])&&(0<(o=l.substr(0,l.indexOf(n))).length&&p(t).unusedInput.push(o),l=l.slice(l.indexOf(n)+n.length),d+=n.length),q[a]?(n?p(t).empty=!1:p(t).unusedTokens.push(a),s=a,u=t,null!=(c=n)&&h(dt,s)&&dt[s](c,u._a,u,s)):t._strict&&!n&&p(t).unusedTokens.push(a);p(t).charsLeftOver=f-d,0<l.length&&p(t).unusedInput.push(l),t._a[3]<=12&&!0===p(t).bigHour&&0<t._a[3]&&(p(t).bigHour=void 0),p(t).parsedDateParts=t._a.slice(0),p(t).meridiem=t._meridiem,t._a[3]=function(t,e,n){var r;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):(null!=t.isPM&&((r=t.isPM(n))&&e<12&&(e+=12),r||12!==e||(e=0)),e)}(t._locale,t._a[3],t._meridiem),oe(t),ie(t)}else ge(t);else de(t)}function ve(t){var e,n,r,h,d=t._i,m=t._f;return t._locale=t._locale||re(t._l),null===d||void 0===m&&""===d?g({nullInput:!0}):("string"==typeof d&&(t._i=d=t._locale.preparse(d)),x(d)?new _(ie(d)):(u(d)?t._d=d:a(m)?function(t){var e,n,r,i,a;if(0===t._f.length)return p(t).invalidFormat=!0,t._d=new Date(NaN);for(i=0;i<t._f.length;i++)a=0,e=v({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[i],me(e),y(e)&&(a+=p(e).charsLeftOver,a+=10*p(e).unusedTokens.length,p(e).score=a,(null==r||a<r)&&(r=a,n=e));f(t,n||e)}(t):m?me(t):s(n=(e=t)._i)?e._d=new Date(i.now()):u(n)?e._d=new Date(n.valueOf()):"string"==typeof n?(r=e,null===(h=fe.exec(r._i))?(de(r),!1===r._isValid&&(delete r._isValid,ge(r),!1===r._isValid&&(delete r._isValid,i.createFromInputFallback(r)))):r._d=new Date(+h[1])):a(n)?(e._a=l(n.slice(0),(function(t){return parseInt(t,10)})),oe(e)):o(n)?function(t){if(!t._d){var e=R(t._i);t._a=l([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],(function(t){return t&&parseInt(t,10)})),oe(t)}}(e):c(n)?e._d=new Date(n):i.createFromInputFallback(e),y(t)||(t._d=null),t))}function be(t,e,n,r,i){var s,c={};return!0!==n&&!1!==n||(r=n,n=void 0),(o(t)&&function(t){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(t).length;var e;for(e in t)if(t.hasOwnProperty(e))return!1;return!0}(t)||a(t)&&0===t.length)&&(t=void 0),c._isAMomentObject=!0,c._useUTC=c._isUTC=i,c._l=n,c._i=t,c._f=e,c._strict=r,(s=new _(ie(ve(c))))._nextDay&&(s.add(1,"d"),s._nextDay=void 0),s}function _e(t,e,n,r){return be(t,e,n,r,!1)}i.createFromInputFallback=C("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",(function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))})),i.ISO_8601=function(){},i.RFC_2822=function(){};var xe=C("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",(function(){var t=_e.apply(null,arguments);return this.isValid()&&t.isValid()?t<this?this:t:g()})),we=C("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",(function(){var t=_e.apply(null,arguments);return this.isValid()&&t.isValid()?this<t?this:t:g()}));function ke(t,e){var n,r;if(1===e.length&&a(e[0])&&(e=e[0]),!e.length)return _e();for(n=e[0],r=1;r<e.length;++r)e[r].isValid()&&!e[r][t](n)||(n=e[r]);return n}var Te=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ee(t){var e=R(t),n=e.year||0,r=e.quarter||0,i=e.month||0,a=e.week||e.isoWeek||0,o=e.day||0,s=e.hour||0,c=e.minute||0,u=e.second||0,l=e.millisecond||0;this._isValid=function(t){for(var e in t)if(-1===vt.call(Te,e)||null!=t[e]&&isNaN(t[e]))return!1;for(var n=!1,r=0;r<Te.length;++r)if(t[Te[r]]){if(n)return!1;parseFloat(t[Te[r]])!==k(t[Te[r]])&&(n=!0)}return!0}(e),this._milliseconds=+l+1e3*u+6e4*c+1e3*s*60*60,this._days=+o+7*a,this._months=+i+3*r+12*n,this._data={},this._locale=re(),this._bubble()}function Ce(t){return t instanceof Ee}function Se(t){return t<0?-1*Math.round(-1*t):Math.round(t)}function Ae(t,e){H(t,0,0,(function(){var t=this.utcOffset(),n="+";return t<0&&(t=-t,n="-"),n+j(~~(t/60),2)+e+j(~~t%60,2)}))}Ae("Z",":"),Ae("ZZ",""),lt("Z",st),lt("ZZ",st),pt(["Z","ZZ"],(function(t,e,n){n._useUTC=!0,n._tzm=Ne(st,t)}));var Me=/([\+\-]|\d\d)/gi;function Ne(t,e){var n=(e||"").match(t);if(null===n)return null;var r=((n[n.length-1]||[])+"").match(Me)||["-",0,0],i=60*r[1]+k(r[2]);return 0===i?0:"+"===r[0]?i:-i}function De(t,e){var n,r;return e._isUTC?(n=e.clone(),r=(x(t)||u(t)?t.valueOf():_e(t).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+r),i.updateOffset(n,!1),n):_e(t).local()}function Oe(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Be(){return!!this.isValid()&&this._isUTC&&0===this._offset}i.updateOffset=function(){};var Le=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Ie=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function Re(t,e){var n,r,i,a=t,o=null;return Ce(t)?a={ms:t._milliseconds,d:t._days,M:t._months}:c(t)?(a={},e?a[e]=t:a.milliseconds=t):(o=Le.exec(t))?(n="-"===o[1]?-1:1,a={y:0,d:k(o[2])*n,h:k(o[3])*n,m:k(o[4])*n,s:k(o[5])*n,ms:k(Se(1e3*o[6]))*n}):(o=Ie.exec(t))?(n="-"===o[1]?-1:1,a={y:Fe(o[2],n),M:Fe(o[3],n),w:Fe(o[4],n),d:Fe(o[5],n),h:Fe(o[6],n),m:Fe(o[7],n),s:Fe(o[8],n)}):null==a?a={}:"object"==typeof a&&("from"in a||"to"in a)&&(i=function(t,e){var n;return t.isValid()&&e.isValid()?(e=De(e,t),t.isBefore(e)?n=Pe(t,e):((n=Pe(e,t)).milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}(_e(a.from),_e(a.to)),(a={}).ms=i.milliseconds,a.M=i.months),r=new Ee(a),Ce(t)&&h(t,"_locale")&&(r._locale=t._locale),r}function Fe(t,e){var n=t&&parseFloat(t.replace(",","."));return(isNaN(n)?0:n)*e}function Pe(t,e){var n={};return n.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(n.months,"M").isAfter(e)&&--n.months,n.milliseconds=+e-+t.clone().add(n.months,"M"),n}function je(t,e){return function(n,r){var i;return null===r||isNaN(+r)||(M(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),i=n,n=r,r=i),Ye(this,Re(n="string"==typeof n?+n:n,r),t),this}}function Ye(t,e,n,r){var a=e._milliseconds,o=Se(e._days),s=Se(e._months);t.isValid()&&(r=null==r||r,s&&St(t,xt(t,"Month")+s*n),o&&wt(t,"Date",xt(t,"Date")+o*n),a&&t._d.setTime(t._d.valueOf()+a*n),r&&i.updateOffset(t,o||s))}Re.fn=Ee.prototype,Re.invalid=function(){return Re(NaN)};var ze=je(1,"add"),Ue=je(-1,"subtract");function qe(t,e){var n=12*(e.year()-t.year())+(e.month()-t.month()),r=t.clone().add(n,"months");return-(n+(e-r<0?(e-r)/(r-t.clone().add(n-1,"months")):(e-r)/(t.clone().add(n+1,"months")-r)))||0}function He(t){var e;return void 0===t?this._locale._abbr:(null!=(e=re(t))&&(this._locale=e),this)}i.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",i.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var $e=C("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",(function(t){return void 0===t?this.localeData():this.locale(t)}));function We(){return this._locale}var Ve=126227808e5;function Ge(t,e){return(t%e+e)%e}function Xe(t,e,n){return t<100&&0<=t?new Date(t+400,e,n)-Ve:new Date(t,e,n).valueOf()}function Ze(t,e,n){return t<100&&0<=t?Date.UTC(t+400,e,n)-Ve:Date.UTC(t,e,n)}function Qe(t,e){H(0,[t,t.length],0,e)}function Ke(t,e,n,r,i){var a;return null==t?It(this,r,i).year:((a=Rt(t,r,i))<e&&(e=a),function(t,e,n,r,i){var a=Lt(t,e,n,r,i),o=Ot(a.year,0,a.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}.call(this,t,e,n,r,i))}H(0,["gg",2],0,(function(){return this.weekYear()%100})),H(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),Qe("gggg","weekYear"),Qe("ggggg","weekYear"),Qe("GGGG","isoWeekYear"),Qe("GGGGG","isoWeekYear"),L("weekYear","gg"),L("isoWeekYear","GG"),P("weekYear",1),P("isoWeekYear",1),lt("G",at),lt("g",at),lt("GG",K,G),lt("gg",K,G),lt("GGGG",nt,Z),lt("gggg",nt,Z),lt("GGGGG",rt,Q),lt("ggggg",rt,Q),yt(["gggg","ggggg","GGGG","GGGGG"],(function(t,e,n,r){e[r.substr(0,2)]=k(t)})),yt(["gg","GG"],(function(t,e,n,r){e[r]=i.parseTwoDigitYear(t)})),H("Q",0,"Qo","quarter"),L("quarter","Q"),P("quarter",7),lt("Q",V),pt("Q",(function(t,e){e[1]=3*(k(t)-1)})),H("D",["DD",2],"Do","date"),L("date","D"),P("date",9),lt("D",K),lt("DD",K,G),lt("Do",(function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient})),pt(["D","DD"],2),pt("Do",(function(t,e){e[2]=k(t.match(K)[0])}));var Je=_t("Date",!0);H("DDD",["DDDD",3],"DDDo","dayOfYear"),L("dayOfYear","DDD"),P("dayOfYear",4),lt("DDD",et),lt("DDDD",X),pt(["DDD","DDDD"],(function(t,e,n){n._dayOfYear=k(t)})),H("m",["mm",2],0,"minute"),L("minute","m"),P("minute",14),lt("m",K),lt("mm",K,G),pt(["m","mm"],4);var tn=_t("Minutes",!1);H("s",["ss",2],0,"second"),L("second","s"),P("second",15),lt("s",K),lt("ss",K,G),pt(["s","ss"],5);var en,nn=_t("Seconds",!1);for(H("S",0,0,(function(){return~~(this.millisecond()/100)})),H(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),H(0,["SSS",3],0,"millisecond"),H(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),H(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),H(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),H(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),H(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),H(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),L("millisecond","ms"),P("millisecond",16),lt("S",et,V),lt("SS",et,G),lt("SSS",et,X),en="SSSS";en.length<=9;en+="S")lt(en,it);function rn(t,e){e[6]=k(1e3*("0."+t))}for(en="S";en.length<=9;en+="S")pt(en,rn);var an=_t("Milliseconds",!1);H("z",0,0,"zoneAbbr"),H("zz",0,0,"zoneName");var on=_.prototype;function sn(t){return t}on.add=ze,on.calendar=function(t,e){var n=t||_e(),r=De(n,this).startOf("day"),a=i.calendarFormat(this,r)||"sameElse",o=e&&(N(e[a])?e[a].call(this,n):e[a]);return this.format(o||this.localeData().calendar(a,this,_e(n)))},on.clone=function(){return new _(this)},on.diff=function(t,e,n){var r,i,a;if(!this.isValid())return NaN;if(!(r=De(t,this)).isValid())return NaN;switch(i=6e4*(r.utcOffset()-this.utcOffset()),e=I(e)){case"year":a=qe(this,r)/12;break;case"month":a=qe(this,r);break;case"quarter":a=qe(this,r)/3;break;case"second":a=(this-r)/1e3;break;case"minute":a=(this-r)/6e4;break;case"hour":a=(this-r)/36e5;break;case"day":a=(this-r-i)/864e5;break;case"week":a=(this-r-i)/6048e5;break;default:a=this-r}return n?a:w(a)},on.endOf=function(t){var e;if(void 0===(t=I(t))||"millisecond"===t||!this.isValid())return this;var n=this._isUTC?Ze:Xe;switch(t){case"year":e=n(this.year()+1,0,1)-1;break;case"quarter":e=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":e=n(this.year(),this.month()+1,1)-1;break;case"week":e=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":e=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":e=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":e=this._d.valueOf(),e+=36e5-Ge(e+(this._isUTC?0:6e4*this.utcOffset()),36e5)-1;break;case"minute":e=this._d.valueOf(),e+=6e4-Ge(e,6e4)-1;break;case"second":e=this._d.valueOf(),e+=1e3-Ge(e,1e3)-1}return this._d.setTime(e),i.updateOffset(this,!0),this},on.format=function(t){t||(t=this.isUtc()?i.defaultFormatUtc:i.defaultFormat);var e=$(this,t);return this.localeData().postformat(e)},on.from=function(t,e){return this.isValid()&&(x(t)&&t.isValid()||_e(t).isValid())?Re({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},on.fromNow=function(t){return this.from(_e(),t)},on.to=function(t,e){return this.isValid()&&(x(t)&&t.isValid()||_e(t).isValid())?Re({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},on.toNow=function(t){return this.to(_e(),t)},on.get=function(t){return N(this[t=I(t)])?this[t]():this},on.invalidAt=function(){return p(this).overflow},on.isAfter=function(t,e){var n=x(t)?t:_e(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=I(e)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(e).valueOf())},on.isBefore=function(t,e){var n=x(t)?t:_e(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=I(e)||"millisecond")?this.valueOf()<n.valueOf():this.clone().endOf(e).valueOf()<n.valueOf())},on.isBetween=function(t,e,n,r){var i=x(t)?t:_e(t),a=x(e)?e:_e(e);return!!(this.isValid()&&i.isValid()&&a.isValid())&&("("===(r=r||"()")[0]?this.isAfter(i,n):!this.isBefore(i,n))&&(")"===r[1]?this.isBefore(a,n):!this.isAfter(a,n))},on.isSame=function(t,e){var n,r=x(t)?t:_e(t);return!(!this.isValid()||!r.isValid())&&("millisecond"===(e=I(e)||"millisecond")?this.valueOf()===r.valueOf():(n=r.valueOf(),this.clone().startOf(e).valueOf()<=n&&n<=this.clone().endOf(e).valueOf()))},on.isSameOrAfter=function(t,e){return this.isSame(t,e)||this.isAfter(t,e)},on.isSameOrBefore=function(t,e){return this.isSame(t,e)||this.isBefore(t,e)},on.isValid=function(){return y(this)},on.lang=$e,on.locale=He,on.localeData=We,on.max=we,on.min=xe,on.parsingFlags=function(){return f({},p(this))},on.set=function(t,e){if("object"==typeof t)for(var n=function(t){var e=[];for(var n in t)e.push({unit:n,priority:F[n]});return e.sort((function(t,e){return t.priority-e.priority})),e}(t=R(t)),r=0;r<n.length;r++)this[n[r].unit](t[n[r].unit]);else if(N(this[t=I(t)]))return this[t](e);return this},on.startOf=function(t){var e;if(void 0===(t=I(t))||"millisecond"===t||!this.isValid())return this;var n=this._isUTC?Ze:Xe;switch(t){case"year":e=n(this.year(),0,1);break;case"quarter":e=n(this.year(),this.month()-this.month()%3,1);break;case"month":e=n(this.year(),this.month(),1);break;case"week":e=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":e=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":e=n(this.year(),this.month(),this.date());break;case"hour":e=this._d.valueOf(),e-=Ge(e+(this._isUTC?0:6e4*this.utcOffset()),36e5);break;case"minute":e=this._d.valueOf(),e-=Ge(e,6e4);break;case"second":e=this._d.valueOf(),e-=Ge(e,1e3)}return this._d.setTime(e),i.updateOffset(this,!0),this},on.subtract=Ue,on.toArray=function(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]},on.toObject=function(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}},on.toDate=function(){return new Date(this.valueOf())},on.toISOString=function(t){if(!this.isValid())return null;var e=!0!==t,n=e?this.clone().utc():this;return n.year()<0||9999<n.year()?$(n,e?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):N(Date.prototype.toISOString)?e?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",$(n,"Z")):$(n,e?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},on.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',r=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=e+'[")]';return this.format(n+r+"-MM-DD[T]HH:mm:ss.SSS"+i)},on.toJSON=function(){return this.isValid()?this.toISOString():null},on.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},on.unix=function(){return Math.floor(this.valueOf()/1e3)},on.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},on.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},on.year=bt,on.isLeapYear=function(){return mt(this.year())},on.weekYear=function(t){return Ke.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},on.isoWeekYear=function(t){return Ke.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},on.quarter=on.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},on.month=At,on.daysInMonth=function(){return kt(this.year(),this.month())},on.week=on.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},on.isoWeek=on.isoWeeks=function(t){var e=It(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},on.weeksInYear=function(){var t=this.localeData()._week;return Rt(this.year(),t.dow,t.doy)},on.isoWeeksInYear=function(){return Rt(this.year(),1,4)},on.date=Je,on.day=on.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e,n,r=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(e=t,n=this.localeData(),t="string"!=typeof e?e:isNaN(e)?"number"==typeof(e=n.weekdaysParse(e))?e:null:parseInt(e,10),this.add(t-r,"d")):r},on.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},on.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null==t)return this.day()||7;var e,n,r=(e=t,n=this.localeData(),"string"==typeof e?n.weekdaysParse(e)%7||7:isNaN(e)?null:e);return this.day(this.day()%7?r:r-7)},on.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},on.hour=on.hours=Xt,on.minute=on.minutes=tn,on.second=on.seconds=nn,on.millisecond=on.milliseconds=an,on.utcOffset=function(t,e,n){var r,a=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null==t)return this._isUTC?a:Oe(this);if("string"==typeof t){if(null===(t=Ne(st,t)))return this}else Math.abs(t)<16&&!n&&(t*=60);return!this._isUTC&&e&&(r=Oe(this)),this._offset=t,this._isUTC=!0,null!=r&&this.add(r,"m"),a!==t&&(!e||this._changeInProgress?Ye(this,Re(t-a,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,i.updateOffset(this,!0),this._changeInProgress=null)),this},on.utc=function(t){return this.utcOffset(0,t)},on.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Oe(this),"m")),this},on.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=Ne(ot,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},on.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?_e(t).utcOffset():0,(this.utcOffset()-t)%60==0)},on.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},on.isLocal=function(){return!!this.isValid()&&!this._isUTC},on.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},on.isUtc=Be,on.isUTC=Be,on.zoneAbbr=function(){return this._isUTC?"UTC":""},on.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},on.dates=C("dates accessor is deprecated. Use date instead.",Je),on.months=C("months accessor is deprecated. Use month instead",At),on.years=C("years accessor is deprecated. Use year instead",bt),on.zone=C("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",(function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()})),on.isDSTShifted=C("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",(function(){if(!s(this._isDSTShifted))return this._isDSTShifted;var t={};if(v(t,this),(t=ve(t))._a){var e=t._isUTC?d(t._a):_e(t._a);this._isDSTShifted=this.isValid()&&0<T(t._a,e.toArray())}else this._isDSTShifted=!1;return this._isDSTShifted}));var cn=O.prototype;function un(t,e,n,r){var i=re(),a=d().set(r,e);return i[n](a,t)}function ln(t,e,n){if(c(t)&&(e=t,t=void 0),t=t||"",null!=e)return un(t,e,n,"month");var r,i=[];for(r=0;r<12;r++)i[r]=un(t,r,n,"month");return i}function hn(t,e,n,r){"boolean"==typeof t?c(e)&&(n=e,e=void 0):(e=t,t=!1,c(n=e)&&(n=e,e=void 0)),e=e||"";var i,a=re(),o=t?a._week.dow:0;if(null!=n)return un(e,(n+o)%7,r,"day");var s=[];for(i=0;i<7;i++)s[i]=un(e,(i+o)%7,r,"day");return s}cn.calendar=function(t,e,n){var r=this._calendar[t]||this._calendar.sameElse;return N(r)?r.call(e,n):r},cn.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,(function(t){return t.slice(1)})),this._longDateFormat[t])},cn.invalidDate=function(){return this._invalidDate},cn.ordinal=function(t){return this._ordinal.replace("%d",t)},cn.preparse=sn,cn.postformat=sn,cn.relativeTime=function(t,e,n,r){var i=this._relativeTime[n];return N(i)?i(t,e,n,r):i.replace(/%d/i,t)},cn.pastFuture=function(t,e){var n=this._relativeTime[0<t?"future":"past"];return N(n)?n(e):n.replace(/%s/i,e)},cn.set=function(t){var e,n;for(n in t)N(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},cn.months=function(t,e){return t?a(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||Tt).test(e)?"format":"standalone"][t.month()]:a(this._months)?this._months:this._months.standalone},cn.monthsShort=function(t,e){return t?a(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[Tt.test(e)?"format":"standalone"][t.month()]:a(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},cn.monthsParse=function(t,e,n){var r,i,a;if(this._monthsParseExact)return function(t,e,n){var r,i,a,o=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],r=0;r<12;++r)a=d([2e3,r]),this._shortMonthsParse[r]=this.monthsShort(a,"").toLocaleLowerCase(),this._longMonthsParse[r]=this.months(a,"").toLocaleLowerCase();return n?"MMM"===e?-1!==(i=vt.call(this._shortMonthsParse,o))?i:null:-1!==(i=vt.call(this._longMonthsParse,o))?i:null:"MMM"===e?-1!==(i=vt.call(this._shortMonthsParse,o))||-1!==(i=vt.call(this._longMonthsParse,o))?i:null:-1!==(i=vt.call(this._longMonthsParse,o))||-1!==(i=vt.call(this._shortMonthsParse,o))?i:null}.call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),r=0;r<12;r++){if(i=d([2e3,r]),n&&!this._longMonthsParse[r]&&(this._longMonthsParse[r]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[r]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[r]||(a="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[r]=new RegExp(a.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[r].test(t))return r;if(n&&"MMM"===e&&this._shortMonthsParse[r].test(t))return r;if(!n&&this._monthsParse[r].test(t))return r}},cn.monthsRegex=function(t){return this._monthsParseExact?(h(this,"_monthsRegex")||Dt.call(this),t?this._monthsStrictRegex:this._monthsRegex):(h(this,"_monthsRegex")||(this._monthsRegex=Nt),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},cn.monthsShortRegex=function(t){return this._monthsParseExact?(h(this,"_monthsRegex")||Dt.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(h(this,"_monthsShortRegex")||(this._monthsShortRegex=Mt),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},cn.week=function(t){return It(t,this._week.dow,this._week.doy).week},cn.firstDayOfYear=function(){return this._week.doy},cn.firstDayOfWeek=function(){return this._week.dow},cn.weekdays=function(t,e){var n=a(this._weekdays)?this._weekdays:this._weekdays[t&&!0!==t&&this._weekdays.isFormat.test(e)?"format":"standalone"];return!0===t?Ft(n,this._week.dow):t?n[t.day()]:n},cn.weekdaysMin=function(t){return!0===t?Ft(this._weekdaysMin,this._week.dow):t?this._weekdaysMin[t.day()]:this._weekdaysMin},cn.weekdaysShort=function(t){return!0===t?Ft(this._weekdaysShort,this._week.dow):t?this._weekdaysShort[t.day()]:this._weekdaysShort},cn.weekdaysParse=function(t,e,n){var r,i,a;if(this._weekdaysParseExact)return function(t,e,n){var r,i,a,o=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],r=0;r<7;++r)a=d([2e3,1]).day(r),this._minWeekdaysParse[r]=this.weekdaysMin(a,"").toLocaleLowerCase(),this._shortWeekdaysParse[r]=this.weekdaysShort(a,"").toLocaleLowerCase(),this._weekdaysParse[r]=this.weekdays(a,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(i=vt.call(this._weekdaysParse,o))?i:null:"ddd"===e?-1!==(i=vt.call(this._shortWeekdaysParse,o))?i:null:-1!==(i=vt.call(this._minWeekdaysParse,o))?i:null:"dddd"===e?-1!==(i=vt.call(this._weekdaysParse,o))||-1!==(i=vt.call(this._shortWeekdaysParse,o))||-1!==(i=vt.call(this._minWeekdaysParse,o))?i:null:"ddd"===e?-1!==(i=vt.call(this._shortWeekdaysParse,o))||-1!==(i=vt.call(this._weekdaysParse,o))||-1!==(i=vt.call(this._minWeekdaysParse,o))?i:null:-1!==(i=vt.call(this._minWeekdaysParse,o))||-1!==(i=vt.call(this._weekdaysParse,o))||-1!==(i=vt.call(this._shortWeekdaysParse,o))?i:null}.call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),r=0;r<7;r++){if(i=d([2e3,1]).day(r),n&&!this._fullWeekdaysParse[r]&&(this._fullWeekdaysParse[r]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[r]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[r]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[r]||(a="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[r]=new RegExp(a.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[r].test(t))return r;if(n&&"ddd"===e&&this._shortWeekdaysParse[r].test(t))return r;if(n&&"dd"===e&&this._minWeekdaysParse[r].test(t))return r;if(!n&&this._weekdaysParse[r].test(t))return r}},cn.weekdaysRegex=function(t){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Ht.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(h(this,"_weekdaysRegex")||(this._weekdaysRegex=zt),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},cn.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Ht.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(h(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Ut),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},cn.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Ht.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(h(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=qt),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},cn.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},cn.meridiem=function(t,e,n){return 11<t?n?"pm":"PM":n?"am":"AM"},ee("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===k(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),i.lang=C("moment.lang is deprecated. Use moment.locale instead.",ee),i.langData=C("moment.langData is deprecated. Use moment.localeData instead.",re);var fn=Math.abs;function dn(t,e,n,r){var i=Re(e,n);return t._milliseconds+=r*i._milliseconds,t._days+=r*i._days,t._months+=r*i._months,t._bubble()}function pn(t){return t<0?Math.floor(t):Math.ceil(t)}function yn(t){return 4800*t/146097}function gn(t){return 146097*t/4800}function mn(t){return function(){return this.as(t)}}var vn=mn("ms"),bn=mn("s"),_n=mn("m"),xn=mn("h"),wn=mn("d"),kn=mn("w"),Tn=mn("M"),En=mn("Q"),Cn=mn("y");function Sn(t){return function(){return this.isValid()?this._data[t]:NaN}}var An=Sn("milliseconds"),Mn=Sn("seconds"),Nn=Sn("minutes"),Dn=Sn("hours"),On=Sn("days"),Bn=Sn("months"),Ln=Sn("years"),In=Math.round,Rn={ss:44,s:45,m:45,h:22,d:26,M:11},Fn=Math.abs;function Pn(t){return(0<t)-(t<0)||+t}function jn(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n=Fn(this._milliseconds)/1e3,r=Fn(this._days),i=Fn(this._months);e=w((t=w(n/60))/60),n%=60,t%=60;var a=w(i/12),o=i%=12,s=r,c=e,u=t,l=n?n.toFixed(3).replace(/\.?0+$/,""):"",h=this.asSeconds();if(!h)return"P0D";var f=h<0?"-":"",d=Pn(this._months)!==Pn(h)?"-":"",p=Pn(this._days)!==Pn(h)?"-":"",y=Pn(this._milliseconds)!==Pn(h)?"-":"";return f+"P"+(a?d+a+"Y":"")+(o?d+o+"M":"")+(s?p+s+"D":"")+(c||u||l?"T":"")+(c?y+c+"H":"")+(u?y+u+"M":"")+(l?y+l+"S":"")}var Yn=Ee.prototype;return Yn.isValid=function(){return this._isValid},Yn.abs=function(){var t=this._data;return this._milliseconds=fn(this._milliseconds),this._days=fn(this._days),this._months=fn(this._months),t.milliseconds=fn(t.milliseconds),t.seconds=fn(t.seconds),t.minutes=fn(t.minutes),t.hours=fn(t.hours),t.months=fn(t.months),t.years=fn(t.years),this},Yn.add=function(t,e){return dn(this,t,e,1)},Yn.subtract=function(t,e){return dn(this,t,e,-1)},Yn.as=function(t){if(!this.isValid())return NaN;var e,n,r=this._milliseconds;if("month"===(t=I(t))||"quarter"===t||"year"===t)switch(e=this._days+r/864e5,n=this._months+yn(e),t){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(e=this._days+Math.round(gn(this._months)),t){case"week":return e/7+r/6048e5;case"day":return e+r/864e5;case"hour":return 24*e+r/36e5;case"minute":return 1440*e+r/6e4;case"second":return 86400*e+r/1e3;case"millisecond":return Math.floor(864e5*e)+r;default:throw new Error("Unknown unit "+t)}},Yn.asMilliseconds=vn,Yn.asSeconds=bn,Yn.asMinutes=_n,Yn.asHours=xn,Yn.asDays=wn,Yn.asWeeks=kn,Yn.asMonths=Tn,Yn.asQuarters=En,Yn.asYears=Cn,Yn.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*k(this._months/12):NaN},Yn._bubble=function(){var t,e,n,r,i,a=this._milliseconds,o=this._days,s=this._months,c=this._data;return 0<=a&&0<=o&&0<=s||a<=0&&o<=0&&s<=0||(a+=864e5*pn(gn(s)+o),s=o=0),c.milliseconds=a%1e3,t=w(a/1e3),c.seconds=t%60,e=w(t/60),c.minutes=e%60,n=w(e/60),c.hours=n%24,s+=i=w(yn(o+=w(n/24))),o-=pn(gn(i)),r=w(s/12),s%=12,c.days=o,c.months=s,c.years=r,this},Yn.clone=function(){return Re(this)},Yn.get=function(t){return t=I(t),this.isValid()?this[t+"s"]():NaN},Yn.milliseconds=An,Yn.seconds=Mn,Yn.minutes=Nn,Yn.hours=Dn,Yn.days=On,Yn.weeks=function(){return w(this.days()/7)},Yn.months=Bn,Yn.years=Ln,Yn.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e,n,r,i,a,o,s,c,u,l,h=this.localeData(),f=(e=!t,n=h,r=Re(this).abs(),i=In(r.as("s")),a=In(r.as("m")),o=In(r.as("h")),s=In(r.as("d")),c=In(r.as("M")),u=In(r.as("y")),(l=i<=Rn.ss&&["s",i]||i<Rn.s&&["ss",i]||a<=1&&["m"]||a<Rn.m&&["mm",a]||o<=1&&["h"]||o<Rn.h&&["hh",o]||s<=1&&["d"]||s<Rn.d&&["dd",s]||c<=1&&["M"]||c<Rn.M&&["MM",c]||u<=1&&["y"]||["yy",u])[2]=e,l[3]=0<+this,l[4]=n,function(t,e,n,r,i){return i.relativeTime(e||1,!!n,t,r)}.apply(null,l));return t&&(f=h.pastFuture(+this,f)),h.postformat(f)},Yn.toISOString=jn,Yn.toString=jn,Yn.toJSON=jn,Yn.locale=He,Yn.localeData=We,Yn.toIsoString=C("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",jn),Yn.lang=$e,H("X",0,0,"unix"),H("x",0,0,"valueOf"),lt("x",at),lt("X",/[+-]?\d+(\.\d{1,3})?/),pt("X",(function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))})),pt("x",(function(t,e,n){n._d=new Date(k(t))})),i.version="2.24.0",e=_e,i.fn=on,i.min=function(){return ke("isBefore",[].slice.call(arguments,0))},i.max=function(){return ke("isAfter",[].slice.call(arguments,0))},i.now=function(){return Date.now?Date.now():+new Date},i.utc=d,i.unix=function(t){return _e(1e3*t)},i.months=function(t,e){return ln(t,e,"months")},i.isDate=u,i.locale=ee,i.invalid=g,i.duration=Re,i.isMoment=x,i.weekdays=function(t,e,n){return hn(t,e,n,"weekdays")},i.parseZone=function(){return _e.apply(null,arguments).parseZone()},i.localeData=re,i.isDuration=Ce,i.monthsShort=function(t,e){return ln(t,e,"monthsShort")},i.weekdaysMin=function(t,e,n){return hn(t,e,n,"weekdaysMin")},i.defineLocale=ne,i.updateLocale=function(t,e){if(null!=e){var n,r,i=Zt;null!=(r=te(t))&&(i=r._config),(n=new O(e=D(i,e))).parentLocale=Qt[t],Qt[t]=n,ee(t)}else null!=Qt[t]&&(null!=Qt[t].parentLocale?Qt[t]=Qt[t].parentLocale:null!=Qt[t]&&delete Qt[t]);return Qt[t]},i.locales=function(){return S(Qt)},i.weekdaysShort=function(t,e,n){return hn(t,e,n,"weekdaysShort")},i.normalizeUnits=I,i.relativeTimeRounding=function(t){return void 0===t?In:"function"==typeof t&&(In=t,!0)},i.relativeTimeThreshold=function(t,e){return void 0!==Rn[t]&&(void 0===e?Rn[t]:(Rn[t]=e,"s"===t&&(Rn.ss=e-1),!0))},i.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},i.prototype=on,i.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},i}()},6470:t=>{"use strict";function e(t){if("string"!=typeof t)throw new TypeError("Path must be a string. Received "+JSON.stringify(t))}function n(t,e){for(var n,r="",i=0,a=-1,o=0,s=0;s<=t.length;++s){if(s<t.length)n=t.charCodeAt(s);else{if(47===n)break;n=47}if(47===n){if(a===s-1||1===o);else if(a!==s-1&&2===o){if(r.length<2||2!==i||46!==r.charCodeAt(r.length-1)||46!==r.charCodeAt(r.length-2))if(r.length>2){var c=r.lastIndexOf("/");if(c!==r.length-1){-1===c?(r="",i=0):i=(r=r.slice(0,c)).length-1-r.lastIndexOf("/"),a=s,o=0;continue}}else if(2===r.length||1===r.length){r="",i=0,a=s,o=0;continue}e&&(r.length>0?r+="/..":r="..",i=2)}else r.length>0?r+="/"+t.slice(a+1,s):r=t.slice(a+1,s),i=s-a-1;a=s,o=0}else 46===n&&-1!==o?++o:o=-1}return r}var r={resolve:function(){for(var t,r="",i=!1,a=arguments.length-1;a>=-1&&!i;a--){var o;a>=0?o=arguments[a]:(void 0===t&&(t=process.cwd()),o=t),e(o),0!==o.length&&(r=o+"/"+r,i=47===o.charCodeAt(0))}return r=n(r,!i),i?r.length>0?"/"+r:"/":r.length>0?r:"."},normalize:function(t){if(e(t),0===t.length)return".";var r=47===t.charCodeAt(0),i=47===t.charCodeAt(t.length-1);return 0!==(t=n(t,!r)).length||r||(t="."),t.length>0&&i&&(t+="/"),r?"/"+t:t},isAbsolute:function(t){return e(t),t.length>0&&47===t.charCodeAt(0)},join:function(){if(0===arguments.length)return".";for(var t,n=0;n<arguments.length;++n){var i=arguments[n];e(i),i.length>0&&(void 0===t?t=i:t+="/"+i)}return void 0===t?".":r.normalize(t)},relative:function(t,n){if(e(t),e(n),t===n)return"";if((t=r.resolve(t))===(n=r.resolve(n)))return"";for(var i=1;i<t.length&&47===t.charCodeAt(i);++i);for(var a=t.length,o=a-i,s=1;s<n.length&&47===n.charCodeAt(s);++s);for(var c=n.length-s,u=o<c?o:c,l=-1,h=0;h<=u;++h){if(h===u){if(c>u){if(47===n.charCodeAt(s+h))return n.slice(s+h+1);if(0===h)return n.slice(s+h)}else o>u&&(47===t.charCodeAt(i+h)?l=h:0===h&&(l=0));break}var f=t.charCodeAt(i+h);if(f!==n.charCodeAt(s+h))break;47===f&&(l=h)}var d="";for(h=i+l+1;h<=a;++h)h!==a&&47!==t.charCodeAt(h)||(0===d.length?d+="..":d+="/..");return d.length>0?d+n.slice(s+l):(s+=l,47===n.charCodeAt(s)&&++s,n.slice(s))},_makeLong:function(t){return t},dirname:function(t){if(e(t),0===t.length)return".";for(var n=t.charCodeAt(0),r=47===n,i=-1,a=!0,o=t.length-1;o>=1;--o)if(47===(n=t.charCodeAt(o))){if(!a){i=o;break}}else a=!1;return-1===i?r?"/":".":r&&1===i?"//":t.slice(0,i)},basename:function(t,n){if(void 0!==n&&"string"!=typeof n)throw new TypeError('"ext" argument must be a string');e(t);var r,i=0,a=-1,o=!0;if(void 0!==n&&n.length>0&&n.length<=t.length){if(n.length===t.length&&n===t)return"";var s=n.length-1,c=-1;for(r=t.length-1;r>=0;--r){var u=t.charCodeAt(r);if(47===u){if(!o){i=r+1;break}}else-1===c&&(o=!1,c=r+1),s>=0&&(u===n.charCodeAt(s)?-1==--s&&(a=r):(s=-1,a=c))}return i===a?a=c:-1===a&&(a=t.length),t.slice(i,a)}for(r=t.length-1;r>=0;--r)if(47===t.charCodeAt(r)){if(!o){i=r+1;break}}else-1===a&&(o=!1,a=r+1);return-1===a?"":t.slice(i,a)},extname:function(t){e(t);for(var n=-1,r=0,i=-1,a=!0,o=0,s=t.length-1;s>=0;--s){var c=t.charCodeAt(s);if(47!==c)-1===i&&(a=!1,i=s+1),46===c?-1===n?n=s:1!==o&&(o=1):-1!==n&&(o=-1);else if(!a){r=s+1;break}}return-1===n||-1===i||0===o||1===o&&n===i-1&&n===r+1?"":t.slice(n,i)},format:function(t){if(null===t||"object"!=typeof t)throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof t);return function(t,e){var n=e.dir||e.root,r=e.base||(e.name||"")+(e.ext||"");return n?n===e.root?n+r:n+"/"+r:r}(0,t)},parse:function(t){e(t);var n={root:"",dir:"",base:"",ext:"",name:""};if(0===t.length)return n;var r,i=t.charCodeAt(0),a=47===i;a?(n.root="/",r=1):r=0;for(var o=-1,s=0,c=-1,u=!0,l=t.length-1,h=0;l>=r;--l)if(47!==(i=t.charCodeAt(l)))-1===c&&(u=!1,c=l+1),46===i?-1===o?o=l:1!==h&&(h=1):-1!==o&&(h=-1);else if(!u){s=l+1;break}return-1===o||-1===c||0===h||1===h&&o===c-1&&o===s+1?-1!==c&&(n.base=n.name=0===s&&a?t.slice(1,c):t.slice(s,c)):(0===s&&a?(n.name=t.slice(1,o),n.base=t.slice(1,c)):(n.name=t.slice(s,o),n.base=t.slice(s,c)),n.ext=t.slice(o,c)),s>0?n.dir=t.slice(0,s-1):a&&(n.dir="/"),n},sep:"/",delimiter:":",win32:null,posix:null};r.posix=r,t.exports=r},8218:()=>{},8009:()=>{},5354:()=>{},6878:()=>{},8183:()=>{},1428:()=>{},4551:()=>{},8800:()=>{},1993:()=>{},3069:()=>{},9143:()=>{}},e={};function n(r){var i=e[r];if(void 0!==i)return i.exports;var a=e[r]={id:r,loaded:!1,exports:{}};return t[r].call(a.exports,a,a.exports,n),a.loaded=!0,a.exports}n.c=e,n.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var r in e)n.o(e,r)&&!n.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),n.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.nmd=t=>(t.paths=[],t.children||(t.children=[]),t);var r=n(n.s=7458);return r.default})()}));
+//# sourceMappingURL=mermaid.min.js.map
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
new file mode 100644
index 0000000..fcedb99
--- /dev/null
+++ b/book/src/SUMMARY.md
@@ -0,0 +1,23 @@
+# Summary
+
+- [Rust ❤️  pre-existing C++](index.md)
+- [Tutorial](tutorial.md)
+- [Workflow](workflow.md)
+- [Allowlist and syntax](allowlist.md)
+- [Building](building.md)
+- [C++ structs, enums and classes](cpp_types.md)
+- [Pointers, references, values](references_etc.md)
+- [Storage - stack and heaps](storage.md)
+- [Built-in types](primitives.md)
+- [C++ type and function names](naming.md)
+- [C++ functions](cpp_functions.md)
+- [Callbacks into Rust](rust_calls.md)
+- [Other C++ features](other_features.md)
+- [Safety](safety.md)
+- [Rustic bindings](rustic.md)
+- [Large codebases](large_codebase.md)
+- [Examples](examples.md)
+- [Credits](credits.md)
+- [Contributing](contributing.md)
+- [Code of Conduct](code-of-conduct.md)
+
diff --git a/book/src/allowlist.md b/book/src/allowlist.md
new file mode 100644
index 0000000..2834ee6
--- /dev/null
+++ b/book/src/allowlist.md
@@ -0,0 +1,31 @@
+# The allowlist and `include_cpp` syntax
+
+To include C++ in your Rust codebase using `autocxx`, you will need
+at least one [`include_cpp` macro](https://docs.rs/autocxx/latest/autocxx/macro.include_cpp.html).
+
+The simplest is:
+
+```rust,ignore
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "my_header.h"
+    generate!("MyAPIFunction")
+}
+```
+
+You need to include [`generate!` directives](https://docs.rs/autocxx/latest/autocxx/macro.generate.html)
+for every *type* or *function* you wish to access from Rust. You don't need to specify this for member functions
+of types that you've added - they'll be generated automatically. (If a particular member function can't
+be generated, some placeholder item with explanatory documentation [will be generated instead](workflow.md)).
+
+Various other directives are possible inside this macro, most notably:
+
+* You can ask to generate all the items in a namespace using
+  [`generate_ns!`](https://docs.rs/autocxx/latest/autocxx/macro.generate_ns.html)
+* You might sometimes want to ask that a type is generated as 'plain old data' using
+  [`generate_pod!`](https://docs.rs/autocxx/latest/autocxx/macro.generate_pod.html) instead of `generate!` -
+  see the chapter on [C++ types](cpp_types.md).
+* You'll probaly want to specify a [`safety!` policy](safety.md)
+
+See [the docs.rs documentation for the full list](https://docs.rs/autocxx/latest/autocxx/).
diff --git a/book/src/building.md b/book/src/building.md
new file mode 100644
index 0000000..4d5d919
--- /dev/null
+++ b/book/src/building.md
@@ -0,0 +1,60 @@
+# Building
+
+## Building if you're using cargo
+
+The basics of building in a `cargo` environment are explained in [the tutorial](tutorial.md).
+
+If your build depends on later editions of the C++ standard library, you will need to ensure that both `libclang` and the compiler are sent the appropriate flag, like this:
+
+```rust,ignore
+fn main() {
+    let path = std::path::PathBuf::from("src"); // include path
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path])
+        .extra_clang_args(&["-std=c++17"])
+        .expect_build();
+    b.flag_if_supported("-std=c++17")
+        .compile("autocxx-demo"); // arbitrary library name, pick anything
+    println!("cargo:rerun-if-changed=src/main.rs");
+    // Add instructions to link to any C++ libraries you need.
+}
+```
+
+## Building - if you're not using cargo
+
+See the `autocxx-gen` crate. You'll need to:
+
+* Run the `codegen` phase. You'll need to use the [`autocxx-gen`](https://crates.io/crates/autocxx-gen)
+  tool to process the .rs code into C++ header and
+  implementation files. This will also generate `.rs` side bindings.
+* Educate the procedural macro about where to find the generated `.rs` bindings. Set the
+  `AUTOCXX_RS` environment variable to a list of directories to search.
+  If you use `autocxx-build`, this happens automatically. (You can alternatively
+  specify `AUTOCXX_RS_FILE` to give a precise filename as opposed to a directory to search,
+  though this isn't recommended unless your build system specifically requires it
+  because it allows only a single `include_cpp!` block per `.rs` file.) See `gen --help`
+  for details on the naming of the generated files.
+
+```mermaid
+flowchart TB
+    s(Rust source with include_cpp!)
+    c(Existing C++ headers)
+    cg(autocxx-gen or autocxx-build)
+    genrs(Generated .rs file)
+    gencpp(Generated .cpp and .h files)
+    rsb(Rust/Cargo build)
+    cppb(C++ build)
+    l(Linker)
+    s --> cg
+    c --> cg
+    cg --> genrs
+    cg --> gencpp
+    m(autocxx-macro)
+    s --> m
+    genrs-. included .->m
+    m --> rsb
+    gencpp --> cppb
+    cppb --> l
+    rsb --> l
+```
+
+This interop inevitably involves lots of fiddly small functions. It's likely to perform far better if you can achieve cross-language link-time-optimization (LTO). [This issue](https://github.com/dtolnay/cxx/issues/371) may give some useful hints - see also all the build-related help in [the cxx manual](https://cxx.rs/) which all applies here too.
diff --git a/book/src/code-of-conduct.md b/book/src/code-of-conduct.md
new file mode 100644
index 0000000..f8b12cb
--- /dev/null
+++ b/book/src/code-of-conduct.md
@@ -0,0 +1,63 @@
+# Google Open Source Community Guidelines
+
+At Google, we recognize and celebrate the creativity and collaboration of open
+source contributors and the diversity of skills, experiences, cultures, and
+opinions they bring to the projects and communities they participate in.
+
+Every one of Google's open source projects and communities are inclusive
+environments, based on treating all individuals respectfully, regardless of
+gender identity and expression, sexual orientation, disabilities,
+neurodiversity, physical appearance, body size, ethnicity, nationality, race,
+age, religion, or similar personal characteristic.
+
+We value diverse opinions, but we value respectful behavior more.
+
+Respectful behavior includes:
+
+* Being considerate, kind, constructive, and helpful.
+* Not engaging in demeaning, discriminatory, harassing, hateful, sexualized, or
+  physically threatening behavior, speech, and imagery.
+* Not engaging in unwanted physical contact.
+
+Some Google open source projects [may adopt][] an explicit project code of
+conduct, which may have additional detailed expectations for participants. Most
+of those projects will use our [modified Contributor Covenant][].
+
+[may adopt]: https://opensource.google/docs/releasing/preparing/#conduct
+[modified Contributor Covenant]: https://opensource.google/docs/releasing/template/CODE_OF_CONDUCT/
+
+## Resolve peacefully
+
+We do not believe that all conflict is necessarily bad; healthy debate and
+disagreement often yields positive results. However, it is never okay to be
+disrespectful.
+
+If you see someone behaving disrespectfully, you are encouraged to address the
+behavior directly with those involved. Many issues can be resolved quickly and
+easily, and this gives people more control over the outcome of their dispute.
+If you are unable to resolve the matter for any reason, or if the behavior is
+threatening or harassing, report it. We are dedicated to providing an
+environment where participants feel welcome and safe.
+
+## Reporting problems
+
+Some Google open source projects may adopt a project-specific code of conduct.
+In those cases, a Google employee will be identified as the Project Steward,
+who will receive and handle reports of code of conduct violations. In the event
+that a project hasn’t identified a Project Steward, you can report problems by
+emailing opensource@google.com.
+
+We will investigate every complaint, but you may not receive a direct response.
+We will use our discretion in determining when and how to follow up on reported
+incidents, which may range from not taking action to permanent expulsion from
+the project and project-sponsored spaces. We will notify the accused of the
+report and provide them an opportunity to discuss it before any action is
+taken. The identity of the reporter will be omitted from the details of the
+report supplied to the accused. In potentially harmful situations, such as
+ongoing harassment or threats to anyone's safety, we may take action without
+notice.
+
+*This document was adapted from the [IndieWeb Code of Conduct][] and can also
+be found at <https://opensource.google/conduct/>.*
+
+[IndieWeb Code of Conduct]: https://indieweb.org/code-of-conduct
diff --git a/book/src/contributing.md b/book/src/contributing.md
new file mode 100644
index 0000000..1f00bc9
--- /dev/null
+++ b/book/src/contributing.md
@@ -0,0 +1,108 @@
+# How to Contribute
+
+We'd love to accept your patches and contributions to this project. There are
+just a few small guidelines you need to follow.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution;
+this simply gives us permission to use and redistribute your contributions as
+part of the project. Head over to <https://cla.developers.google.com/> to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+information on using pull requests.
+
+## Community Guidelines
+
+This project follows [Google's Open Source Community
+Guidelines](https://opensource.google/conduct/).
+
+## Directory structure
+
+* `book` - you're reading it!
+* `demo` - a very simple demo example
+* `examples` - will gradually fill with more complex examples
+* `parser` - code which parses a single `include_cpp!` macro. Used by both the macro
+  (which doesn't do much) and the code generator (which does much more, by means of
+  `engine` below)
+* `engine` - all the core code for actual code generation.
+* `macro` - the procedural macro which expands the Rust code.
+* `gen/build` - a library to be used from `build.rs` scripts to generate .cc and .h
+  files from an `include_cxx` section.
+* `gen/cmd` - a command-line tool which does the same.
+* `src` (outermost project) - a wrapper crate which imports the procedural macro and
+  a few other things.
+
+## Where to start reading
+
+The main algorithm is in `engine/src/lib.rs`, in the function `generate()`. This asks
+`bindgen` to generate a heap of Rust code and then passes it into
+`engine/src/conversion` to convert it to be a format suitable for input
+to `cxx`.
+
+However, most of the actual code is in `engine/src/conversion/mod.rs`.
+
+At the moment we're using a slightly branched version of `bindgen` called `autocxx-bindgen`.
+It's hoped this is temporary; some of our changes are sufficiently weird that it would be
+presumptious to try to get them accepted upstream until we're sure `autocxx` has roughly the right approach.
+
+## How to develop
+
+If you're making a change, here's what you need to do to get useful diagnostics etc.
+First of all, `cargo run` in the `demo` directory. If it breaks, you don't get much
+in the way of useful diagnostics, because `stdout` is swallowed by cargo build scripts.
+So, practically speaking, you would almost always move onto running one of the tests
+in the test suite. With suitable options, you can get plenty of output. For instance:
+
+```ignore
+RUST_BACKTRACE=1 RUST_LOG=autocxx_engine=info cargo test --all test_cycle_string_full_pipeline -- --nocapture
+```
+
+This is especially valuable to see the `bindgen` output Rust code, and then the converted Rust code which we pass into cxx. Usually, most problems are due to some mis-conversion somewhere
+in `engine/src/conversion`. See [here](https://docs.rs/autocxx-engine/latest/autocxx_engine/struct.IncludeCppEngine.html) for documentation and diagrams on how the engine works.
+
+You may also wish to set `AUTOCXX_ASAN=1` on Linux when running tests.
+
+## Reporting bugs
+
+If you've found a problem, and you're reading this, *thank you*! Your diligence
+in reporting the bug is much appreciated and will make `autocxx` better. In
+order of preference here's how we would like to hear about your problem:
+
+* Raise a pull request adding a new failing integration test to
+  `engine/src/integration_tests.rs`.
+* Minimize the test using `tools/reduce`, something like this:
+  `target/debug/autocxx-reduce file -d "safety!(unsafe_ffi)" -d
+  'generate_pod!("A")' -I ~/my-include-dir -h my-header.h -p
+  problem-error-message -- --remove-pass pass_line_markers`
+  This is a wrapper for the amazing `creduce` which will take thousands of lines
+  of C++, preprocess it, and then identify the minimum required lines to
+  reproduce the same problem.
+* Use the C++ preprocessor to give a single complete C++ file which demonstrates
+  the problem, along with the `include_cpp!` directive you use.
+  Alternatively, run your build using `AUTOCXX_REPRO_CASE=repro.json` which should
+  put everything we need into `output.h`. If necessary, you can use the `CLANG_PATH`
+  or `CXX` environment variables to specify the path to the Clang compiler to use.
+* Failing all else, build using
+  `cargo clean -p <your package name> && RUST_LOG=autocxx_engine=info cargo build -vvv`
+  and send the _entire_ log to us. This will include two key bits of logging:
+  the C++ bindings as distilled by `bindgen`, and then the version which
+  we've converted and moulded to be suitable for use by `cxx`.
+
+## How to contribute to this manual
+
+More examples in this manual are _very_ welcome!
+
+Because `autocxx` examples require both Rust and C++ code to be linked together,
+a custom preprocessor is used for this manual. See one of the existing examples
+such as in `index.md` to see how to do this.
diff --git a/book/src/cpp_functions.md b/book/src/cpp_functions.md
new file mode 100644
index 0000000..436f79f
--- /dev/null
+++ b/book/src/cpp_functions.md
@@ -0,0 +1,266 @@
+# C++ functions
+
+Calling C++ functions is largly as you might expect.
+
+## Value and rvalue parameters
+
+Functions taking [non-POD](cpp_types.md) value parameters can take a `cxx::UniquePtr<T>`
+or a `&T`. This gives you the choice of Rust semantics - where a parameter
+is absorbed and destroyed - or C++ semantics where the parameter is copied.
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"
+Goat::Goat() : horn_count(0) {}
+void feed_goat(Goat) {}
+",
+"#include <cstdint>
+
+struct Goat {
+    Goat();
+    uint32_t horn_count;
+};
+
+void feed_goat(Goat g); // takes goat by value
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("Goat")
+    generate!("feed_goat")
+}
+
+fn main() {
+    let goat = ffi::Goat::new().within_unique_ptr(); // returns a cxx::UniquePtr, i.e. a std::unique_ptr
+    // C++-like semantics...
+    ffi::feed_goat(&goat);
+    // ... you've still got the goat!
+    ffi::feed_goat(&goat);
+    // Or, Rust-like semantics, where the goat is consumed.
+    ffi::feed_goat(goat);
+    // No goat any more...
+    // ffi::feed_goat(&goat); // doesn't compile
+}
+}
+)
+```
+
+Specifically, you can pass anything which implements [`ValueParam<T>`](https://docs.rs/autocxx/latest/autocxx/trait.ValueParam.html).
+
+If you're keeping non-POD values on the Rust stack, you need to explicitly use [`as_mov`](https://docs.rs/autocxx/latest/autocxx/prelude/fn.as_mov.html) to indicate that you want to consume the object using move semantics:
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"
+Blimp::Blimp() : tons_of_helium(3) {}
+void burst(Blimp) {}
+",
+"#include <cstdint>
+
+struct Blimp {
+    Blimp();
+    uint32_t tons_of_helium;
+};
+
+void burst(Blimp b); // consumes blimp,
+    // but because C++ is amazing, may copy the blimp first.
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("Blimp")
+    generate!("burst")
+}
+
+fn main() {
+    moveit! {
+        let mut blimp = ffi::Blimp::new();
+    }
+    ffi::burst(&*blimp); // pass by copy
+    ffi::burst(as_copy(blimp.as_ref())); // explicitly say you want to pass by copy
+    ffi::burst(as_mov(blimp)); // consume, using move constructor
+}
+}
+)
+```
+
+RValue parameters are a little simpler, because (as you'd hope) they consume
+the object you're passing in.
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"
+Cake::Cake() {}
+void eat(Cake&&) {}
+",
+"#include <cstdint>
+
+struct Cake {
+    Cake();
+    uint32_t tons_of_sugar;
+};
+
+void eat(Cake&& c); // consumes the cake. You can't have your cake and eat it.
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("Cake")
+    generate!("eat")
+}
+
+fn main() {
+    moveit! {
+        let mut stack_cake = ffi::Cake::new();
+    }
+    ffi::eat(stack_cake);
+    // No more cake.
+
+    // Still peckish.
+    let heap_cake = ffi::Cake::new().within_unique_ptr();
+    ffi::eat(heap_cake);
+    // Really no more cake now.
+}
+}
+)
+```
+
+## Default parameters
+
+Are not yet supported[^default].
+
+[^default]: the work is [planned here](https://github.com/google/autocxx/issues/563).
+
+## Return values
+
+Any C++ function which returns a [non-POD](cpp_types.md) type to Rust in fact gives you an opaque
+object implementing [`moveit::New`](https://docs.rs/moveit/latest/moveit/new/trait.New.html).
+This enables you to "emplace" the resulting object either on the stack or heap,
+in exactly the same way as if you're constructying an object. See [the section on construction](cpp_types.md#construction)
+for how to turn this opaque object into something useful (spoiler: just append `.within_unique_ptr()`).
+
+## Overloads - and identifiers ending in digits
+
+C++ allows function overloads; Rust doesn't. `autocxx` follows the lead
+of `bindgen` here and generating overloads as `func`, `func1`, `func2` etc.
+This is essentially awful without `rust-analyzer` IDE support - see the
+[workflows chapter](workflow.md) for why you should be using an IDE.
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"
+void saw(const View&) {}
+void saw(const Tree&) {}",
+"
+#include <string>
+struct View {
+    std::string of_what; // go and watch In Bruges, it's great
+};
+
+struct Tree {
+    int dendrochronologically_determined_age;
+};
+
+void saw(const View&);
+void saw(const Tree&);
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("Tree")
+    generate!("View")
+    generate!("saw")
+    generate!("saw1")
+}
+
+fn main() {
+    let view = ffi::View::new().within_unique_ptr();
+    ffi::saw(&view);
+    let tree = ffi::Tree::new().within_unique_ptr();
+    ffi::saw1(&tree); // yuck, overload
+}
+}
+)
+```
+
+`autocxx` doesn't yet support default parameters.
+
+It's fairly likely we'll change the model here in the future, such that
+we can pass tuples of different parameter types into a single function
+implementation.
+
+## Methods
+
+Calling a *const* method is simple:
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"",
+"
+class Sloth {
+public:
+    void sleep() const {} // sloths unchanged by sleep
+};
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("Sloth")
+}
+
+fn main() {
+    let sloth = ffi::Sloth::new().within_unique_ptr();
+    sloth.sleep();
+    sloth.sleep();
+}
+}
+)
+```
+
+Calling a non-const method is a bit more of a pain. Per `cxx` norms, all mutable
+references to C++ objects must be [pinned](https://doc.rust-lang.org/std/pin/).
+In practice, this means you must call [`.pin_mut()`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html#method.pin_mut)
+every time you call a method:
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"",
+"
+class Sloth {
+public:
+    void unpeel_from_tree() {} // sloths get agitated when removed from
+        // trees, probably shouldn't be const
+};
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("Sloth")
+}
+
+fn main() {
+    let mut sloth = ffi::Sloth::new().within_unique_ptr();
+    sloth.pin_mut().unpeel_from_tree();
+    sloth.pin_mut().unpeel_from_tree();
+}
+}
+)
+```
\ No newline at end of file
diff --git a/book/src/cpp_types.md b/book/src/cpp_types.md
new file mode 100644
index 0000000..284d64b
--- /dev/null
+++ b/book/src/cpp_types.md
@@ -0,0 +1,242 @@
+# C++ structs, enums and classes
+
+If you add a C++ struct, class or enum to the [allowlist](allowlist.md), Rust bindings will be generated to that type and to any methods it has.
+Even if you don't add it to the allowlist, the type may be generated if it's required by some other function - but in this case
+all its methods won't be generated.
+
+Rust and C++ differ in an important way:
+
+* In Rust, the compiler is free to pick up some data and move it to somewhere else (in a `memcpy` sense). The object is none the wiser.
+* In C++, once created, an object stays where it is, until or unless it has its "move constructor" invoked.
+
+This makes a big difference: C++ objects can have self-referential pointers, and any such pointer would be invalidated by Rust doing
+a memcpy. Such self-referential pointers are common - even some implementations of `std::string` do it.
+
+## POD and non-POD
+
+When asking `autocxx` to generate bindings for a type, then, you have to make a choice.
+
+* *This C++ type is trivial*. It has no destructor or move constructor (or they're trivial), and thus Rust is free to move it around the stack as it wishes. `autocxx` calls these types POD ("plain old data"). Alternatively,
+* *This C++ type has a non-trivial destructor or move constructor, so we can't allow Rust to move this around*. `autocxx` calls these types non-POD.
+
+POD types are nicer:
+
+* You can just use them as regular Rust types.
+* You get direct field access.
+* No funny business.
+
+Non-POD types are awkward:
+
+* You can't just _have_ one as a Rust variable. Normally you hold them in a [`cxx::UniquePtr`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html), though there are other options.
+* There is no access to fields (yet).
+* You can't even have a `&mut` reference to one, because then you might be able to use [`std::mem::swap`](https://doc.rust-lang.org/stable/std/mem/fn.swap.html) or similar. You can have a `Pin<&mut>` reference, which is more fiddly.
+
+By default, `autocxx` generates non-POD types. You can request a POD type using [`generate_pod!`](https://docs.rs/autocxx/latest/autocxx/macro.generate_pod.html). Don't worry: you can't mess this up. If the C++ type doesn't in fact comply with the requirements for a POD type, your build will fail thanks to some static assertions generated in the C++. (If you're _really_ sure your type is freely relocatable, because you implemented the move constructor and destructor and you promise they're trivial, you can override these assertions using the C++ trait `IsRelocatable` per the instructions in [cxx.h](https://github.com/dtolnay/cxx/blob/master/include/cxx.h)).
+
+See [the chapter on storage](storage.md) for lots more detail on how you can hold onto non-POD types.
+
+## Construction
+
+Constructing a POD object is simple: call its `new` associated function. [Bob's your uncle!](https://en.wikipedia.org/wiki/Bob%27s_your_uncle)
+
+Multiple constructors (aka constructor overloading) follows the same [rules as other functions](cpp_functions.html#overloads---and-identifiers-ending-in-digits).
+
+Constructing a non-POD object requires two steps.
+
+* Call the `new` associated function in the same way. This will give you something implementing [`moveit::New`](https://docs.rs/moveit/latest/moveit/new/trait.New.html)/
+* Use this to make the object on the heap or stack, in any of the following ways:
+
+| Where you want to create it | How to create it | What you get | Example |
+| --------------------------- | ---------------- | ------------ | ------- |
+| C++ heap (*recommended for simplicity*) | [`Within.within_unique_ptr()`](https://docs.rs/autocxx/latest/autocxx/trait.Within.html) or [`UniquePtr::emplace`](https://docs.rs/moveit/latest/moveit/new/trait.EmplaceUnpinned.html#method.emplace) | [`cxx::UniquePtr<T>`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html) | `let mut obj = ffi::Goldfish::new().within_unique_ptr()` or `let mut obj = UniquePtr::emplace(ffi::Goldfish::new())` |
+| Rust heap | [`Within.within_box()`](https://docs.rs/autocxx/latest/autocxx/trait.Within.html) or [`Box::emplace`](https://docs.rs/moveit/latest/moveit/new/trait.Emplace.html#method.emplace) | `Pin<Box<T>>` | `let mut obj = ffi::Goldfish::new().within_box()` or `let mut obj = Box::emplace(ffi::Goldfish::new())` |
+| Rust stack | [`moveit` macro](https://docs.rs/moveit/latest/moveit/macro.moveit.html) | `&mut T` (more or less) | `moveit! { let mut obj = ffi::Goldfish::new() }` |
+
+For heap construction, the prefix (`emplace`) and postfix (`.within_...`) forms are exactly identical. Choose whichever suits your needs best.
+
+### Should you construct on the Rust heap or the C++ heap?
+
+Use `.within_unique_ptr()` to create objects on the C++ heap. This gives you a [`cxx::UniquePtr<T>`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html) which works well with other autocxx and cxx APIs.
+
+There is a small disadvantage - [`cxx::UniquePtr<T>`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html) is able to store `NULL` values. Therefore, each time you use the resulting object, there is an `unwrap()` (explicit or implicit). If this bothers you, use the `Box` option instead which can never be `NULL`.
+
+### Construction sounds complicated. Do you have a code example?
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"void A::set(uint32_t val) { a = val; }
+uint32_t A::get() const { return a; }",
+"#include <stdint.h>
+#include <string>
+struct A {
+    A() {}
+    void set(uint32_t val);
+    uint32_t get() const;
+    uint32_t a;
+};
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("A")
+}
+
+fn main() {
+    moveit! {
+        let mut stack_obj = ffi::A::new();
+    }
+    stack_obj.as_mut().set(42);
+    assert_eq!(stack_obj.get(), 42);
+
+    let mut heap_obj = ffi::A::new().within_unique_ptr();
+    heap_obj.pin_mut().set(42);
+    assert_eq!(heap_obj.get(), 42);
+
+    let mut another_heap_obj = ffi::A::new().within_box();
+    another_heap_obj.as_mut().set(42);
+    assert_eq!(another_heap_obj.get(), 42);
+}
+}
+)
+```
+
+## Forward declarations
+
+A type which is incomplete in the C++ headers (i.e. represented only by a forward
+declaration) can't be held in a `UniquePtr` within Rust (because Rust can't know
+if it has a destructor that will need to be called if the object is dropped.)
+Naturally, such an object can't be passed by value either; it can still be
+referenced in Rust references.
+
+## Generic (templated) types
+
+If you're using one of the generic types which is supported natively by cxx,
+e.g. `std::unique_ptr`, it should work as you expect. For other generic types,
+we synthesize a concrete Rust type, corresponding to a C++ typedef, for each
+concrete instantiation of the type. Such generated types are always opaque,
+and never have methods attached. That's therefore enough to pass them
+between return types and parameters of other functions within [`cxx::UniquePtr`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html)s
+but not really enough to do anything else with these types yet[^templated].
+
+[^templated]: Future improvements tracked [here](https://github.com/google/autocxx/issues/349)
+
+To make them more useful, you might have to add extra C++ functions to extract
+data or otherwise deal with them.
+
+Usually, such concrete types are synthesized automatically because they're
+parameters or return values from functions. Very rarely, you may
+want to synthesize them yourself - you can do this using the
+[`concrete!`](https://docs.rs/autocxx/latest/autocxx/macro.concrete.html)
+directive. As noted, though, these types are currently opaque and fairly
+useless without passing them back and forth to C++, so this is not a commonly
+used facility. It does, however, allow you to give a more descriptive name
+to the type in Rust:
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"",
+"#include <string>
+struct Tapioca {
+  std::string yuck;
+};
+template<typename Floaters>
+struct Tea {
+  Tea() : floaters(nullptr) {}
+  Floaters* floaters;
+};
+inline Tea<Tapioca> prepare() {
+  Tea<Tapioca> mixture;
+  // prepare...
+  return mixture;
+}
+inline void drink(const Tea<Tapioca>&) {}
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("prepare")
+    generate!("drink")
+    concrete!("Tea<Tapioca>", Boba)
+}
+
+fn main() {
+    let nicer_than_it_sounds: cxx::UniquePtr<ffi::Boba> = ffi::prepare();
+    ffi::drink(&nicer_than_it_sounds);
+}
+}
+)
+```
+
+## Implicit member functions
+
+Most of the API of a C++ type is contained within the type, so `autocxx` can
+understand what is available for Rust to call when that type is analyzed.
+However, there is an important exception for the so-called special
+member functions, which will be implicitly generated by the C++ compiler for
+some types. `autocxx` makes use of these types of special members:
+* Default constructor
+* Destructor
+* Copy constructor
+* Move constructor
+
+Explicitly declared versions of these special members are easy: `autocxx` knows
+they exist and uses them.
+
+`autocxx` currently uses its own analysis to determine when implicit versions of
+these exist. This analysis tries to be conservative (avoid generating wrappers
+that require the existence of C++ functions that don't exist), but sometimes
+this goes wrong and understanding the details is necessary to get the correct
+Rust wrappers generated.
+
+In particular, determing whether an implicit version of any of these exists
+requires analyzing the types of all bases and members. `autocxx` only analyzes
+types when requested, because some may be un-analyzable. If the types of any
+bases or members are not analyzed, `autocxx` will assume a public destructor
+exists (in the absence of any other destructors), and avoid using any other
+implicit special member functions. Notably this includes the default
+constructor, so types with un-analyzed bases or members and no explicit
+constructors will not get a `make_unique` or `new` generated. If `autocxx` isn't
+generating a `make_unique` or `CopyNew` or `MoveNew` for a type which permits
+the corresponding operations in C++, make sure the types of all bases and
+members are analyzed or implement it explicitly.
+
+`autocxx` currently does not take member initializers (`const int x = 5`) into
+account when determining whether a default constructor
+exists[^member-initializers]. Explicitly declared default destructors still
+work though.
+
+Currently, `autocxx` assumes that an explicitly defaulted (`= default`) member
+function exists, although it is valid C++ for that to be
+deleted[^explicitly-defaulted]. Clang's
+[-Wdefaulted-function-deleted](https://clang.llvm.org/docs/DiagnosticsReference.html#wdefaulted-function-deleted)
+flag (enabled by default) will warn about types like this.
+
+A C++ type which can be instantiated but has an inaccessible constructor will
+be leaked by Rust[^inaccessible-destructor]. The object's memory itself will be
+freed without calling any C++ destructor, which will leak any resources tracked
+by the C++ implementation.
+
+Many of the special members may be overloaded in C++. This generally means
+adding `const` or `volatile` qualifiers or extra arguments with defaults.
+`autocxx` avoids using any overloaded special members because choosing which
+one to call from Rust gets tricky.
+
+[^member-initializers]: Handling of member initializers is tracked
+[here](https://github.com/google/autocxx/issues/816).
+[^explicitly-defaulted]: Fix for explicitly defaulted special member functions
+that are deleted is tracked [here](https://github.com/google/autocxx/issues/815).
+[^inaccessible-destructor]: Discussion around what to do about inaccessible or
+deleted destructors [here](https://github.com/google/autocxx/issues/829).
+
+## Abstract types
+
+`autocxx` does not allow instantiation of abstract types[^abstract] (aka types with pure virtual methods).
+
+[^abstract]: `autocxx`'s determination of abstract types is a bit approximate and
+[could be improved](https://github.com/google/autocxx/issues/774).
\ No newline at end of file
diff --git a/book/src/credits.md b/book/src/credits.md
new file mode 100644
index 0000000..811db55
--- /dev/null
+++ b/book/src/credits.md
@@ -0,0 +1,10 @@
+# Credits
+
+David Tolnay did much of the hard work here, by inventing the underlying cxx crate, and in fact nearly all of the parsing infrastructure on which this crate depends. `bindgen` is also awesome. This crate stands on the shoulders of giants!
+
+Miguel Young also did all the hard thinking about whether non-trivial C++ objects can safely exist on the Rust
+stack. They can! He also draws nifty cartoons. 
+
+Thanks to all the other contributors to cxx, bindgen and autocxx.
+
+And thanks to [all in the Chromium community for inspiring this tool](https://www.chromium.org/Home/chromium-security/memory-safety/rust-and-c-interoperability/).
\ No newline at end of file
diff --git a/book/src/examples.md b/book/src/examples.md
new file mode 100644
index 0000000..d0246f5
--- /dev/null
+++ b/book/src/examples.md
@@ -0,0 +1,10 @@
+# Examples
+
+* [Demo](https://github.com/google/autocxx/tree/main/demo) - simplest possible demo
+* [S2 example](https://github.com/google/autocxx/tree/main/examples/s2) - example using S2 geometry library
+* [Steam example](https://github.com/google/autocxx/tree/main/examples/steam-mini) - example using (something like) the Steam client library
+* [Subclass example](https://github.com/google/autocxx/tree/main/examples/subclass) - example using subclasses
+* [Integration tests](https://github.com/google/autocxx/blob/main/integration-tests/src/tests.rs)
+  - hundreds of small snippets
+
+Contributions of more examples to the `examples` directory are much appreciated!
diff --git a/book/src/index.md b/book/src/index.md
new file mode 100644
index 0000000..3e158e7
--- /dev/null
+++ b/book/src/index.md
@@ -0,0 +1,110 @@
+[![GitHub](https://img.shields.io/crates/l/autocxx)](https://github.com/google/autocxx)
+[![crates.io](https://img.shields.io/crates/d/autocxx)](https://crates.io/crates/autocxx)
+[![docs.rs](https://docs.rs/autocxx/badge.svg)](https://docs.rs/autocxx)
+
+# autocxx — automatic safe interop between Rust and C++
+
+Welcome to `autocxx` and thank you for reading!
+
+Use `autocxx` if you have a large existing C++ codebase and you want to use its types and functions from Rust with maximal safety and minimal fuss.
+
+`autocxx` is like `bindgen`, in that it enables you to use C++ functions and types from within Rust. But it automates a lot of the fiddly things you need to do with `bindgen` bindings: calling destructors, converting strings, unsafely handling raw pointers. C++ functions and types within `autocxx` bindings should behave naturally and ergonomically, _almost_ as if they were safe Rust functions and types themselves. These ergonomics and safety improvements come from the [`cxx`](https://cxx.rs) project - hence the name of this tool, `autocxx`.
+
+`autocxx` combines the safety and ergonomics of `cxx` with the automatic bindings generation of `bindgen`. It stands on the shoulders of those giants!
+
+## When is `autocxx` the right tool?
+
+Not always:
+
+* If you are making bindings to C code, as opposed to C++, use [`bindgen`](https://rust-lang.github.io/rust-bindgen/) instead.
+* If you can make unrestricted changes to the C++ code, use [`cxx`](https://cxx.rs) instead.
+* If your C++ to Rust interface is just a few functions or types, use [`cxx`](https://cxx.rs) instead.
+
+But sometimes:
+
+* If you need to call arbitrary functions and use arbitrary types within an existing C++ codebase, use `autocxx`. You're in the right place!
+* Like `cxx`, but unlike `bindgen`, `autocxx` helps with calls from C++ to Rust, too.
+
+## Examples to give you a feel for `autocxx`
+
+Here's a code example:
+
+```rust,ignore,autocxx
+autocxx_integration_tests::doctest(
+"",
+"#include <stdint.h>
+inline uint32_t do_math(uint32_t a, uint32_t b) { return a+b; }",
+{
+// Use all the autocxx types which might be handy.
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("do_math") // allowlist a function
+}
+
+fn main() {
+    assert_eq!(ffi::do_math(12, 13), 25);
+}
+}
+)
+```
+
+A more complex example:
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"
+#include <sstream>
+void Goat::add_a_horn() { horns++; }
+Goat::Goat() : horns(0) {}
+Goat::~Goat() {}
+std::string Goat::describe() const {
+    std::ostringstream oss;
+    std::string plural = horns == 1 ? \"\" : \"s\";
+    oss << \"This goat has \" << horns << \" horn\" << plural << \".\";
+    return oss.str();
+}
+",
+"#include <cstdint>
+#include <string>
+
+class Goat {
+public:
+    Goat();
+    ~Goat();
+    void add_a_horn();
+    std::string describe() const;
+private:
+    uint32_t horns;
+};
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("Goat") // allowlist a type and all its methods
+}
+
+fn main() {
+    let mut goat = ffi::Goat::new().within_unique_ptr(); // returns a cxx::UniquePtr, i.e. a std::unique_ptr
+    goat.pin_mut().add_a_horn();
+    goat.pin_mut().add_a_horn();
+    assert_eq!(goat.describe().as_ref().unwrap().to_string_lossy(), "This goat has 2 horns.");
+}
+}
+)
+```
+
+This is typical `autocxx` code: the C++ objects behave much like Rust objects, but
+sometimes extra steps are required to handle cases like null pointers or converting strings that may not be UTF-8.
+
+Still, fundamentally, you can interact with C++ objects without using `unsafe` in the majority of cases.
+`cxx` takes care of the fundamentals of lifetimes and destructors.
+
+## How to read this book
+
+We'd recommend starting with [tutorial](tutorial.md) and then [workflow](workflow.md).
\ No newline at end of file
diff --git a/book/src/large_codebase.md b/book/src/large_codebase.md
new file mode 100644
index 0000000..67cffe9
--- /dev/null
+++ b/book/src/large_codebase.md
@@ -0,0 +1,56 @@
+# Structuring a large codebase
+
+If you have multiple modules, it may be inconvenient to generate all bindings in one `include_cpp!` invocation.
+There is _limited_ support to refer from one set of bindings to another, using the `extern_cpp_type!` directive.
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"void handle_a(const A&) {
+}
+A create_a(B) {
+    A a;
+    return a;
+}",
+"#include <cstdint>
+struct A {
+    A() : a(0) {}
+    int a;
+};
+enum B {
+    VARIANT,
+};
+void handle_a(const A& a);
+A create_a(B);
+",
+{
+use autocxx::prelude::*;
+
+pub mod base {
+    autocxx::include_cpp! {
+        #include "input.h"
+        name!(ffi2)
+        safety!(unsafe_ffi)
+        generate!("A")
+        generate!("B")
+    }
+    pub use ffi2::*;
+}
+pub mod dependent {
+    autocxx::include_cpp! {
+        #include "input.h"
+        safety!(unsafe_ffi)
+        generate!("handle_a")
+        generate!("create_a")
+        extern_cpp_type!("A", crate::base::A)
+        extern_cpp_type!("B", super::super::base::B)
+        pod!("B")
+    }
+    pub use ffi::*;
+}
+fn main() {
+    let a = dependent::create_a(base::B::VARIANT).within_unique_ptr();
+    dependent::handle_a(&a);
+}
+}
+)
+```
diff --git a/book/src/naming.md b/book/src/naming.md
new file mode 100644
index 0000000..6bfc338
--- /dev/null
+++ b/book/src/naming.md
@@ -0,0 +1,77 @@
+# Naming
+
+## Namespaces
+
+The C++ namespace structure is reflected in mods within the generated
+ffi mod. However, at present there is an internal limitation that
+autocxx can't handle multiple types with the same identifier, even
+if they're in different namespaces. This will be fixed in future.
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"
+void generations::hey_boomer() {}
+void submarines::hey_boomer() {}",
+"
+namespace generations {
+  void hey_boomer();
+}
+namespace submarines {
+  void hey_boomer();
+}
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("submarines::hey_boomer")
+    generate!("generations::hey_boomer")
+}
+
+fn main() {
+    ffi::generations::hey_boomer(); // insults your elders and betters
+    ffi::submarines::hey_boomer(); // launches missiles
+}
+}
+)
+```
+
+## Nested types
+
+There is support for generating bindings of nested types, with some
+restrictions. Currently the C++ type `A::B` will be given the Rust name
+`A_B` in the same module as its enclosing namespace.
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"",
+"
+struct Turkey {
+    struct Duck {
+        struct Hen {
+            int wings;
+        };
+    };
+};
+",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate_pod!("Turkey_Duck_Hen")
+}
+
+fn main() {
+    let _turducken = ffi::Turkey_Duck_Hen::new().within_box();
+}
+}
+)
+```
+
+## Overloads
+
+See [the chapter on C++ functions](cpp_functions.md).
diff --git a/book/src/other_features.md b/book/src/other_features.md
new file mode 100644
index 0000000..2cc95cd
--- /dev/null
+++ b/book/src/other_features.md
@@ -0,0 +1,34 @@
+# Other C++ features
+
+You can make Rust subclasses of C++ classes - as these are mostly used to
+implement the Observer pattern, they're documented under [calls from C++ to Rust](rust_calls.md).
+
+## Exceptions
+
+Exceptions are not supported. If your C++ code is compiled with exceptions,
+you can expect serious runtime explosions. The underlying [`cxx`](https://cxx.rs) crate has
+exception support, so it would be possible to add them.
+
+## Preprocessor symbols
+
+`#define` and other preprocessor symbols will appear as constants.
+At present there is no way to do compile-time disablement of code
+(equivalent of `#ifdef`)[^ifdef].
+
+[^ifdef]: [This feature](https://github.com/google/autocxx/issues/57) should add ifdef support.
+
+## String constants
+
+Whether from a preprocessor symbol or from a C++ `char*` constant,
+strings appear as `[u8]` with a null terminator. To get a Rust string,
+do this:
+
+```cpp
+#define BOB "Hello"
+```
+
+```
+# mod ffi { pub static BOB: [u8; 6] = [72u8, 101u8, 108u8, 108u8, 111u8, 0u8]; }
+assert_eq!(std::str::from_utf8(&ffi::BOB).unwrap().trim_end_matches(char::from(0)), "Hello");
+```
+
diff --git a/book/src/primitives.md b/book/src/primitives.md
new file mode 100644
index 0000000..9eacc2a
--- /dev/null
+++ b/book/src/primitives.md
@@ -0,0 +1,78 @@
+# Built-in types
+
+`autocxx` relies primarily on the [standard cxx types](https://cxx.rs/bindings.html).
+In particular you should become familiar with [`cxx::UniquePtr`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html) and [`cxx::CxxString`](https://docs.rs/cxx/latest/cxx/struct.CxxString.html).
+
+There are a few additional integer types, such as [`c_int`](https://docs.rs/autocxx/latest/autocxx/struct.c_int.html),
+which are not yet upstreamed to `cxx`. These are to support those pesky C/C++ integer types
+which do not have a predictable number of bits on different machines.
+
+```rust,ignore,autocxx
+autocxx_integration_tests::doctest(
+"",
+"inline int do_math(int a, int b) { return a+b; }",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("do_math")
+}
+
+fn main() {
+    assert_eq!(ffi::do_math(c_int(12), c_int(13)), c_int(25));
+}
+}
+)
+```
+
+## Strings
+
+`autocxx` uses [`cxx::CxxString`](https://docs.rs/cxx/latest/cxx/struct.CxxString.html). However, as noted above, we can't
+just pass a C++ string by value, so we'll box and unbox it automatically
+such that you're really dealing with `UniquePtr<CxxString>` on the Rust
+side, even if the API just took or returned a plain old `std::string`.
+
+However, to ease ergonomics, functions that accept a `std::string` will
+actually accept anything that
+implements a trait called `ffi::ToCppString`. That may either be a
+`UniquePtr<CxxString>` or just a plain old Rust string - which will be
+converted transparently to a C++ string.
+
+This trait, and its implementations, are not present in the `autocxx`
+documentation because they're dynamically generated in _your_ code
+so that they can call through to a `make_string` implementation in
+the C++ that we're injecting into your C++ build system.
+
+(None of that happens if you use [`exclude_utilities`](https://docs.rs/autocxx/latest/autocxx/macro.exclude_utilities.html), so don't do that.)
+
+```rust,ignore,autocxx
+autocxx_integration_tests::doctest(
+"",
+"#include <string>
+#include <cstdint>
+inline uint32_t take_string(std::string a) { return a.size(); }",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("take_string")
+}
+
+fn main() {
+    assert_eq!(ffi::take_string("hello"), 5)
+}
+}
+)
+```
+
+If you need to create a blank `UniquePtr<CxxString>` in Rust, such that
+(for example) you can pass its mutable reference or pointer into some
+pre-existing C++ API, call `ffi::make_string("")` which will return
+a blank `UniquePtr<CxxString>`.
+
+If all you need is a _reference_ to a `CxxString`, you can alternatively use
+[`cxx::let_cxx_string`](https://docs.rs/cxx/latest/cxx/macro.let_cxx_string.html).
diff --git a/book/src/references_etc.md b/book/src/references_etc.md
new file mode 100644
index 0000000..a4b6d09
--- /dev/null
+++ b/book/src/references_etc.md
@@ -0,0 +1,66 @@
+# Pointers, references, values
+
+`autocxx` knows how to deal with C++ APIs which take C++ types:
+* By value
+* By reference (const or not)
+* By raw pointer
+* By `std::unique_ptr`
+* By `std::shared_ptr`
+* By `std::weak_ptr`
+* By rvalue reference (that is, as a move parameter)
+
+(all of this is because the underlying [`cxx`](https://cxx.rs) crate has such versatility).
+Some of these have some quirks in the way they're exposed in Rust, described below.
+
+## Passing between C++ and Rust by value
+
+See the section on [C++ types](cpp_types.md) for the distinction between POD and non-POD types.
+POD types can be passed around however you like. Non-POD types can be passed into functions
+in various ways - see [calling C++ functions](cpp_functions.md) for more details.
+
+## References and pointers
+
+We follow [`cxx`](https://cxx.rs) norms here. Specifically:
+
+* A C++ reference becomes a Rust reference
+* A C++ pointer becomes a Rust pointer.
+* If a reference is returned with an ambiguous lifetime, we don't generate
+  code for the function
+* Pointers require use of `unsafe`, references don't necessarily.
+
+That last point is key. If your C++ API takes pointers, you're going
+to have to use `unsafe`. Similarly, if your C++ API returns a pointer,
+you'll have to use `unsafe` to do anything useful with the pointer in Rust.
+This is intentional: a pointer from C++ might be subject to concurrent
+mutation, or it might have a lifetime that could disappear at any moment.
+As a human, you must promise that you understand the constraints around
+use of that pointer and that's what the `unsafe` keyword is for.
+
+Exactly the same issues apply to C++ references _in theory_, but in practice,
+they usually don't. Therefore [`cxx`](https://cxx.rs) has taken the view that we can "trust"
+a C++ reference to a higher degree than a pointer, and autocxx follows that
+lead. In practice, of course, references are rarely return values from C++
+APIs so we rarely have to navel-gaze about the trustworthiness of a
+reference.
+
+(See also the discussion of [`safety`](safety.md) - if you haven't specified
+an unsafety policy, _all_ C++ APIs require `unsafe` so the discussion is moot.)
+
+If you're given a C++ object by pointer, and you want to interact with it,
+you'll need to figure out the guarantees attached to the C++ object - most
+notably its lifetime. To see some of the decision making process involved
+see the [Steam example](https://github.com/google/autocxx/tree/main/examples/steam-mini/src/main.rs).
+
+## [`cxx::UniquePtr`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html)s tips
+
+We use [`cxx::UniquePtr`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html) in completely the normal way, but there are a few
+quirks which you're more likely to run into with `autocxx`.
+
+* You'll need to use [`.pin_mut()`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html#method.pin_mut) a lot -
+  see [the example at the bottom of C++ functions](cpp_functions.md).
+* If you need to pass a raw pointer to a function, lots of unsafety is required - something like this:
+  ```rust,ignore
+     let mut a = ffi::A::make_unique();
+     unsafe { ffi::TakePointerToA(std::pin::Pin::<&mut ffi::A>::into_inner_unchecked(a.pin_mut())) };
+  ```
+  This may be simplified in future.
diff --git a/book/src/rust_calls.md b/book/src/rust_calls.md
new file mode 100644
index 0000000..ebd37c5
--- /dev/null
+++ b/book/src/rust_calls.md
@@ -0,0 +1,177 @@
+# Callbacks into Rust
+
+`autocxx` is primarily to allow calls from Rust to C++, but like `cxx` it also allows you to expose Rust APIs to C++.
+
+You can:
+* Declare that Rust types should be available to C++ using [`extern_rust_type`](https://docs.rs/autocxx/latest/autocxx/extern_rust/attr.extern_rust_type.html)
+* Make Rust functions available to C++ using [`extern_rust_function`](https://docs.rs/autocxx/latest/autocxx/extern_rust/attr.extern_rust_function.html).
+* Allow Rust subclasses of C++ classes.
+
+This latter option is most commonly used for implementing "listeners" or ["observers"](https://en.wikipedia.org/wiki/Observer_pattern), so is often in practice how C++ will call into Rust. More details below.
+
+## Subclasses
+
+There is limited and experimental support for creating Rust subclasses of
+C++ classes. (Yes, even more experimental than all the rest of this!)
+See [`subclass::CppSubclass`](https://docs.rs/autocxx/latest/autocxx/subclass/trait.CppSubclass.html) for information about how you do this.
+This is useful primarily if you want to listen out for messages broadcast
+using the C++ observer/listener pattern.
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"
+GoatObserver* obs = NULL;
+int goat_feed = 0;
+
+void register_observer(const GoatObserver& observer) {
+    obs = const_cast<GoatObserver*>(&observer);
+}
+void deregister_observer() {
+    obs = NULL;
+};
+void feed_goat() {
+    goat_feed++;
+    if (goat_feed > 2 && obs) {
+        obs->goat_full();
+    }
+}
+",
+"#include <memory>
+class GoatObserver {
+public:
+    virtual void goat_full() const = 0;
+    virtual ~GoatObserver() {}
+};
+
+void register_observer(const GoatObserver& observer);
+void deregister_observer();
+void feed_goat();
+",
+{
+use autocxx::prelude::*;
+use autocxx::subclass::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("register_observer")
+    generate!("deregister_observer")
+    generate!("feed_goat")
+    subclass!("GoatObserver", MyGoatObserver)
+}
+
+use ffi::*;
+
+#[is_subclass(superclass("GoatObserver"))]
+#[derive(Default)]
+pub struct MyGoatObserver;
+
+impl GoatObserver_methods for MyGoatObserver {
+    fn goat_full(&self) {
+        println!("BURP!");
+    }
+}
+
+impl Drop for MyGoatObserver {
+    fn drop(&mut self) {
+        deregister_observer();
+    }
+}
+
+fn main() {
+    let goat_obs = MyGoatObserver::default_rust_owned();
+    // Register a reference to the superclass &ffi::GoatObserver
+    register_observer(goat_obs.as_ref().borrow().as_ref());
+    feed_goat();
+    feed_goat();
+    feed_goat(); // prints BURP!
+}
+}
+)
+```
+
+## Subclass ownership
+
+See [`subclass::CppSubclass`](https://docs.rs/autocxx/latest/autocxx/subclass/trait.CppSubclass.html)
+for full details, but you must decide who owns your subclass:
+
+* C++ owns it
+* Rust owns it
+* It's self-owned, and only ever frees itself (using [`delete_self`](https://docs.rs/autocxx/latest/autocxx/subclass/trait.CppSubclassSelfOwned.html#method.delete_self)).
+
+Please be careful: the observer pattern is a minefield for use-after-free bugs.
+It's recommended that you wrap any such subclass in some sort of Rust newtype
+wrapper which [enforces any ownership invariants](rustic.md) so that users
+of your types literally can't make any mistakes.
+
+## Calling superclass methods
+
+Each subclass also implements a trait called `<superclass name>_supers` which
+includes all superclass methods. You can call methods on that, and if you
+don't implement a particular method, that will be used as the default.
+
+```rust,ignore,autocxx,hidecpp
+autocxx_integration_tests::doctest(
+"",
+"
+#include <iostream>
+class Dinosaur {
+public:
+    Dinosaur() {}
+    virtual void eat() const {
+        std::cout << \"Roarrr!! I ate you!\n\";
+    }
+    virtual ~Dinosaur() {}
+};
+
+// Currently, autocxx requires at least one 'generate!' call.
+inline void do_a_thing() {};
+",
+{
+use autocxx::prelude::*;
+use autocxx::subclass::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    subclass!("Dinosaur", TRex)
+    subclass!("Dinosaur", Diplodocus)
+    generate!("do_a_thing")
+}
+
+use ffi::*;
+
+#[is_subclass(superclass("Dinosaur"))]
+#[derive(Default)]
+pub struct TRex;
+
+#[is_subclass(superclass("Dinosaur"))]
+#[derive(Default)]
+pub struct Diplodocus;
+
+impl Dinosaur_methods for TRex {
+    // TRex does NOT implement the 'eat' method
+    // so C++ behavior will be used
+}
+
+impl Dinosaur_methods for Diplodocus {
+    fn eat(&self) {
+        println!("Ahh, some nice juicy leaves.");
+        // Could call self.eat_super() if we
+        // developed unexpected carnivorous cravings.
+    }
+}
+
+fn main() {
+    let trex = TRex::default_rust_owned();
+    trex.borrow().as_ref().eat(); // eats human
+    let diplo = Diplodocus::default_rust_owned();
+    diplo.borrow().as_ref().eat(); // eats shoots and leaves
+}
+}
+)
+```
+
+## Subclass casting
+
+Subclasses implement `AsRef` to enable casting to superclasses.
diff --git a/book/src/rustic.md b/book/src/rustic.md
new file mode 100644
index 0000000..09511b6
--- /dev/null
+++ b/book/src/rustic.md
@@ -0,0 +1,13 @@
+# Using the generated bindings
+
+Congratulations, you've built some bindings using `autocxx`!
+
+But are they Rustic? How can you ensure that users of the bindings get Rust-like safety?
+
+The C++ API may have documented usage invariants. Your ideal is to encode as many as possible of those into compile-time checks in Rust.
+
+Some options to consider:
+
+* Wrap the bindings in a newtype wrapper which enforces compile-time variants in its APIs; for example, taking a mutable reference to enforce exclusive access.
+* Add extra `impl` blocks to add methods with a more Rustic API.
+* Read [the C++ to Rust design FAQ](https://cppfaq.rs).
diff --git a/book/src/safety.md b/book/src/safety.md
new file mode 100644
index 0000000..34724d2
--- /dev/null
+++ b/book/src/safety.md
@@ -0,0 +1,91 @@
+# Safety
+
+## Unsafety policies
+
+By default, every `autocxx` function is `unsafe`. That means you can only call C++ functions from `unsafe` blocks, and it's up to you to be sure that the C++ code upholds the invariants the Rust compiler expects.
+
+You can optionally specify:
+
+`safety!(unsafe)`
+
+within your `include_cpp!` macro invocation. If you do this, you are promising the Rust compiler that _all_ your C++ function calls are upholding the invariants which `rustc` expects, and thus each individual function is no longer `unsafe`.
+
+See [`safety!`](https://docs.rs/autocxx/latest/autocxx/macro.safety.html) in the documentation for more details.
+
+## Examples with and without `safety!(unsafe)`
+
+Without a `safety!` directive:
+
+```rust,ignore,autocxx
+autocxx_integration_tests::doctest(
+"",
+"#include <cstdint>
+inline uint32_t do_math(uint32_t a, uint32_t b) { return a+b; }",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    generate!("do_math")
+}
+
+fn main() {
+    assert_eq!(unsafe { ffi::do_math(12, 13) }, 25);
+}
+}
+)
+```
+
+With a `safety!` directive:
+
+```rust,ignore,autocxx
+autocxx_integration_tests::doctest(
+"",
+"#include <cstdint>
+inline uint32_t do_math(uint32_t a, uint32_t b) { return a+b; }",
+{
+use autocxx::prelude::*;
+
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe)
+    generate!("do_math")
+}
+
+fn main() {
+    assert_eq!(ffi::do_math(12, 13), 25);
+}
+}
+)
+```
+
+
+## Pragmatism in a complex C++ codebase
+
+This crate mostly intends to follow the lead of the `cxx` crate in where and when `unsafe` is required. But, this crate is opinionated. It believes some unsafety requires more careful review than other bits, along the following spectrum:
+
+* Rust unsafe code (requires most review)
+* Rust code calling C++ with raw pointers
+* Rust code calling C++ with shared pointers, or anything else where there can be concurrent mutation
+* Rust code calling C++ with unique pointers, where the Rust single-owner model nearly always applies (but we can't _prove_ that the C++ developer isn't doing something weird)
+* Rust safe code (requires least review)
+
+If your project is 90% Rust code, with small bits of C++, _don't use this crate_. You need something where all C++ interaction is marked with big red "this is terrifying" flags. This crate is aimed at cases where there's 90% C++ and small bits of Rust, and so we want the Rust code to be pragmatically reviewable without the signal:noise ratio of `unsafe` in the Rust code becoming so bad that `unsafe` loses all value.
+
+## Worked example
+
+Imagine you have this C++:
+
+```cpp
+struct Thing;
+void print_thing(const Thing& thing);
+```
+
+By using `autocxx` (or `cxx`), you're promising the Rust compiler that the `print_thing` function does sensible things with that
+reference:
+
+* It doesn't store a pointer to the thing anywhere and pass it back to Rust later.
+* It doesn't mutate it.
+* It doesn't delete it.
+* or any of the other things that you're not permitted to do in unsafe Rust.
+
diff --git a/book/src/storage.md b/book/src/storage.md
new file mode 100644
index 0000000..f8b2a72
--- /dev/null
+++ b/book/src/storage.md
@@ -0,0 +1,25 @@
+# Storage - stack and heaps
+
+Ensure you understand the distinction between [POD and non-POD types described in the C++ types section before proceeding](cpp_types.md).
+
+## POD types
+
+POD types are just regular Rust types! Store them on the stack, heap, in a `Vec`, a `HashMap`, whatever you want.
+
+## Non-POD types
+
+Non-POD types can be stored:
+
+* In a [`cxx::UniquePtr`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html). This is cxx's Rust wrapper for `std::unique_ptr` - so the object is stored in the C++ heap. Most of the time you handle a C++ object from `autocxx`, it will be stored in one of these.
+* In a [`Box`](https://doc.rust-lang.org/std/boxed/struct.Box.html) - so the object is stored on the Rust heap. This has the
+advantage that there's no possibility that the object can be NULL.
+* On the Rust stack, using the [`autocxx::moveit`](https://docs.rs/moveit/latest/moveit/macro.moveit.html) macro.
+
+If in doubt, use [`cxx::UniquePtr`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html). It's simple and ergonomic.
+
+See [C++ types](cpp_types.md#construction-sounds-complicated-do-you-have-a-code-example) for a code example showing a type existing on both the stack and the heap.
+
+## Whose heap is it anyway?
+
+Specifically [`cxx::UniquePtr`](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html) is a binding to `std::unique_ptr<T,std::default_delete<T>>` which means the object will be deleted using the C++ `delete` operator. This will respect any overridden `operator delete` on the type, and similarly, the functions which `autocxx` provides to _construct_ types should respect overridden `operator new`. This means: if your C++ type has code to create itself in some special or unusual heap partition, that should work fine.
+
diff --git a/book/src/tutorial.md b/book/src/tutorial.md
new file mode 100644
index 0000000..3bedb26
--- /dev/null
+++ b/book/src/tutorial.md
@@ -0,0 +1,69 @@
+# Tutorial
+
+If you're here, you want to call some C++ from Rust, right?
+
+Let's assume you're calling into some _existing_ C++ code.
+
+You will need:
+
+* Some C++ header files (`.h` files)
+* The C++ "include path". That is, the set of directories containing those headers. (That's not necessarily the directory in which each header _file_ lives; C++ might contain `#include "foo/bar.h"` and so your include path would need to include the directory _containing_ the `foo` directory).
+* A list of the APIs (types and functions) from those header files which you wish to make available in Rust.
+* To know how to link the C++ libraries into your Cargo project. This is beyond the scope of what `autocxx` helps with, but one solution is to emit a print from your [build script](https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib).
+* [LLVM to be installed](https://rust-lang.github.io/rust-bindgen/requirements.html).
+* Some patience. This is not a magic solution. C++/Rust interop is hard. Avoid it if you can!
+
+The rest of this 'getting started' section assumes Cargo - if you're using something else, see the [building](building.md) section.
+
+First, add `autocxx` *and `cxx`* to your `dependencies` and `autocxx-build` to your `build-dependencies` in your `Cargo.toml`.
+
+```toml
+[dependencies]
+autocxx = "0.22.0"
+cxx = "1.0"
+
+[build-dependencies]
+autocxx-build = "0.22.0"
+miette = { version="4.3", features=["fancy"] } # optional but gives nicer error messages!
+```
+
+Now, add a `build.rs` next to your `Cargo.toml` (this is a standard `cargo` [build script](https://doc.rust-lang.org/cargo/reference/build-scripts.html)). This is where you need your include path:
+
+```rust,ignore
+fn main() -> miette::Result<()> {
+    let path = std::path::PathBuf::from("src"); // include path
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path]).build()?;
+        // This assumes all your C++ bindings are in main.rs
+    b.flag_if_supported("-std=c++14")
+     .compile("autocxx-demo"); // arbitrary library name, pick anything
+    println!("cargo:rerun-if-changed=src/main.rs");
+    // Add instructions to link to any C++ libraries you need.
+    Ok(())
+}
+```
+
+See [the standard cargo build script output mechanisms for how you can direct Rust to link against pre-existing libraries](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script), and see the [building section of this book for more details about build options - for example, enabling C++17](building.md).
+
+Finally, in your `main.rs` you can use the [`include_cpp`](https://docs.rs/autocxx/latest/autocxx/macro.include_cpp.html) macro which is the heart of `autocxx`:
+
+```rust,ignore
+use autocxx::prelude::*; // use all the main autocxx functions
+
+include_cpp! {
+    #include "my_header.h" // your header file name
+    safety!(unsafe) // see details of unsafety policies described in the 'safety' section of the book
+    generate!("DeepThought") // add this line for each function or type you wish to generate
+}
+```
+
+You should then find you can call the function by referring to an `ffi` namespace:
+
+```rust,ignore
+fn main() {
+    println!("The answer to Life, The Universe and Everything is {}", ffi::DeepThought());
+}
+```
+
+C++ types such as `std::string` and `std::unique_ptr` are represented using the types provided by the marvellous [cxx](https://cxx.rs) library. This provides good ergonomics and safety norms, so unlike with normal `bindgen` bindings, you won't _normally_ need to write `unsafe` code for every function call.
+
+Next, read the section about [workflows](workflow.md).
diff --git a/book/src/vscode1.png b/book/src/vscode1.png
new file mode 100644
index 0000000..c57b4d0
--- /dev/null
+++ b/book/src/vscode1.png
Binary files differ
diff --git a/book/src/vscode2.png b/book/src/vscode2.png
new file mode 100644
index 0000000..c350617
--- /dev/null
+++ b/book/src/vscode2.png
Binary files differ
diff --git a/book/src/workflow.md b/book/src/workflow.md
new file mode 100644
index 0000000..960dedf
--- /dev/null
+++ b/book/src/workflow.md
@@ -0,0 +1,130 @@
+# Workflow
+
+C++ is complex, and `autocxx` can't ingest everything.
+
+First tip - use an IDE. Type annotation and autocompletion is _incredibly_ helpful in an `autocxx`
+context, where you may be dealing with `UniquePtr<T>` and `Option<&T>` and `Pin<&mut T>` very often.
+![VSCode autocompletion of autocxx APIs](vscode1.png)
+
+As you'll see, it's also _essential_ when `autocxx` can't produce bindings for some reason.
+
+## What if `autocxx` can't generate bindings?
+
+This bit is important.
+
+When you use `autocxx`, you'll ask it to generate Rust bindings for [C++ types or functions](allowlist.md) using
+`generate!` directives.
+
+If you ask to generate bindings for a specific function, and it can't: the build will fail.
+
+If you ask to generate bindings for an entire type, `autocxx` will generate bindings for as
+many methods as possible. For those methods where it can't generate bindings, it will instead
+generate some placeholder function or struct with documentation explaining what went wrong:
+
+![VSCode showing an error for an API where autocxx couldn't generate bindings](vscode2.png)
+
+_This_ is why it's crucial to use an IDE with `autocxx`.
+
+## How can I see what bindings `autocxx` has generated?
+
+Options:
+
+* Use an IDE. (Did we mention, you should use an IDE?)
+* Run `cargo doc --document-private-items`.
+* Use `cargo expand`.
+
+## How to work around cases where `autocxx` can't generate bindings
+
+Your options are:
+
+* Write extra C++ functions with simpler parameters or return types, and generate
+  bindings to them, instead.
+* Write some manual `#[cxx::bridge]` bindings - see below.
+
+Usually, you can solve problems by writing a bit of additional C++ code. For example,
+supposing autocxx can't understand your type `Sandwich<Ham>`. Instead it will give
+you a fairly useless opaque type such as `Sandwich_Ham`. You can write additional
+C++ functions to unpack the opaque type into something useful:
+
+```cpp
+const Ham& get_filling(const Sandwich<Ham>& ham_sandwich);
+```
+
+## Mixing manual and automated bindings
+
+`autocxx` uses [`cxx`](https://cxx.rs) underneath, and its build process will happily spot and
+process manually-crafted [`cxx::bridge` mods](https://cxx.rs/concepts.html) which you include in your
+Rust source code. A common pattern could be to use `autocxx` to generate
+all the bindings possible, then hand-craft a `cxx::bridge` mod for the
+remainder where `autocxx` falls short.
+
+To do this, you'll need to use the [ability of one cxx::bridge mod to refer to types from another](https://cxx.rs/extern-c++.html#reusing-existing-binding-types),
+for example:
+
+```rust,ignore
+autocxx::include_cpp! {
+    #include "foo.h"
+    safety!(unsafe_ffi)
+    generate!("take_A")
+    generate!("A")
+}
+#[cxx::bridge]
+mod ffi2 {
+    unsafe extern "C++" {
+        include!("foo.h");
+        type A = crate::ffi::A;
+        fn give_A() -> UniquePtr<A>; // in practice, autocxx could happily do this
+    }
+}
+fn main() {
+    let a = ffi2::give_A();
+    assert_eq!(ffi::take_A(&a), autocxx::c_int(5));
+}
+```
+
+In the example above, we're referring *from* manual bindings *to* automated bindings.
+
+You can also do it the other way round using `extern_cpp_opaque_type!`:
+
+```rust,ignore
+autocxx::include_cpp! {
+    #hexathorpe include "input.h"
+    safety!(unsafe_ffi)
+    generate!("handle_a")
+    generate!("create_a")
+    extern_cpp_opaque_type!("A", ffi2::A)
+}
+#[cxx::bridge]
+pub mod ffi2 {
+    unsafe extern "C++" {
+        include!("input.h");
+        type A;
+    }
+    impl UniquePtr<A> {}
+}
+fn main() {
+    let a = ffi::create_a();
+    ffi::handle_a(&a);
+}
+```
+
+## My build entirely failed
+
+`autocxx` should nearly always successfully parse the C++ codebase and
+generate _some_ APIs. It's reliant on `bindgen`, but `bindgen` is excellent
+and rarely bails out entirely.
+
+If it does, you may be able to use the [`block!` macro](https://docs.rs/autocxx/latest/autocxx/macro.block.html).
+
+We'd appreciate a minimized bug report of the troublesome code - see [contributing](contributing.md).
+
+## Enabling autocompletion in a rust-analyzer IDE
+
+You'll need to enable _both_:
+* Rust-analyzer: Proc Macro: Enable
+* Rust-analyzer: Experimental: Proc Attr Macros
+
+## Next steps
+
+Now you've read what can go wrong with `autocxx`, and how to diagnose problems - the next step is to give it a try!
+Treat the rest of this manual as a reference.
diff --git a/demo/Cargo.toml b/demo/Cargo.toml
new file mode 100644
index 0000000..c6a7227
--- /dev/null
+++ b/demo/Cargo.toml
@@ -0,0 +1,21 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-demo"
+version = "0.22.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+[dependencies]
+cxx = "1.0.54"
+autocxx = { path = "..", version="0.22.0" }
+
+[build-dependencies]
+autocxx-build = { path = "../gen/build", version="0.22.0" }
+miette = { version="4.3", features=["fancy"]}
diff --git a/demo/build.rs b/demo/build.rs
new file mode 100644
index 0000000..9a16a34
--- /dev/null
+++ b/demo/build.rs
@@ -0,0 +1,17 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() -> miette::Result<()> {
+    let path = std::path::PathBuf::from("src");
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path]).build()?;
+    b.flag_if_supported("-std=c++14").compile("autocxx-demo");
+
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/input.h");
+    Ok(())
+}
diff --git a/demo/src/input.h b/demo/src/input.h
new file mode 100644
index 0000000..b6cdd87
--- /dev/null
+++ b/demo/src/input.h
@@ -0,0 +1,35 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#pragma once
+
+#include <cstdint>
+#include <sstream>
+#include <stdint.h>
+#include <string>
+
+class Goat {
+public:
+    Goat() : horns(0) {}
+    void add_a_horn();
+    std::string describe() const;
+private:
+    uint32_t horns;
+};
+
+inline uint32_t DoMath(uint32_t a) {
+    return a * 3;
+}
+
+inline void Goat::add_a_horn() { horns++; }
+inline std::string Goat::describe() const {
+    std::ostringstream oss;
+    std::string plural = horns == 1 ? "" : "s";
+    oss << "This goat has " << horns << " horn" << plural << ".";
+    return oss.str();
+}
diff --git a/demo/src/main.rs b/demo/src/main.rs
new file mode 100644
index 0000000..798f932
--- /dev/null
+++ b/demo/src/main.rs
@@ -0,0 +1,26 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*;
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate!("DoMath")
+    generate!("Goat")
+}
+
+fn main() {
+    println!("Hello, world! - C++ math should say 12={}", ffi::DoMath(4));
+    let mut goat = ffi::Goat::new().within_box();
+    goat.as_mut().add_a_horn();
+    goat.as_mut().add_a_horn();
+    assert_eq!(
+        goat.describe().as_ref().unwrap().to_string_lossy(),
+        "This goat has 2 horns."
+    );
+}
diff --git a/engine/Cargo.toml b/engine/Cargo.toml
new file mode 100644
index 0000000..964108e
--- /dev/null
+++ b/engine/Cargo.toml
@@ -0,0 +1,62 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-engine"
+version = "0.22.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+license = "MIT OR Apache-2.0"
+description = "Safe autogenerated interop between Rust and C++"
+repository = "https://github.com/google/autocxx"
+edition = "2021"
+keywords = ["ffi"]
+categories = ["development-tools::ffi", "api-bindings"]
+
+[features]
+default = [ "reproduction_case" ]
+build = ["cc"]
+nightly = [] # for doc generation purposes only; used by docs.rs
+reproduction_case = [ "serde_json", "autocxx-parser/reproduction_case" ]
+runtime = [ "autocxx-bindgen/runtime" ]
+static = [ "autocxx-bindgen/static" ]
+
+[dependencies]
+log = "0.4"
+proc-macro2 = "1.0.11"
+quote = "1.0"
+indoc = "1.0"
+autocxx-bindgen = "=0.59.16"
+#autocxx-bindgen = { git = "https://github.com/adetaylor/rust-bindgen", branch = "pollute-fewer-typedefs" }
+itertools = "0.10.3"
+cc = { version = "1.0", optional = true }
+# Note: Keep the patch-level version of cxx-gen and cxx in sync.
+# There can be interdependencies between the code generated by cxx-gen and
+# what cxx expects to be there.
+cxx-gen = "0.7.54"
+autocxx-parser = { version = "=0.22.0", path="../parser" }
+version_check = "0.9"
+aquamarine = "0.1" # docs
+tempfile = "3.1"
+once_cell = "1.7"
+strum_macros = "0.24"
+serde_json = { version = "1.0", optional = true }
+miette = "4.3"
+thiserror = "1"
+regex = "1.5"
+indexmap = "1.8"
+
+[dependencies.syn]
+version = "1.0.39"
+features = [ "full", "printing" ]
+#features = [ "full", "printing", "extra-traits" ]
+
+[package.metadata.docs.rs]
+features = ["build", "nightly"]
+
+[dev-dependencies]
+cc = "1.0"
diff --git a/engine/README.md b/engine/README.md
new file mode 100644
index 0000000..9b91d4a
--- /dev/null
+++ b/engine/README.md
@@ -0,0 +1 @@
+This crate is a [component of autocxx](https://google.github.io/autocxx/).
diff --git a/engine/src/ast_discoverer.rs b/engine/src/ast_discoverer.rs
new file mode 100644
index 0000000..8840899
--- /dev/null
+++ b/engine/src/ast_discoverer.rs
@@ -0,0 +1,726 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::set::IndexSet as HashSet;
+
+use autocxx_parser::{
+    directive_names::{EXTERN_RUST_FUN, EXTERN_RUST_TYPE},
+    RustFun, RustPath,
+};
+use itertools::Itertools;
+use proc_macro2::Ident;
+use syn::{
+    parse_quote, punctuated::Punctuated, Attribute, Binding, Expr, ExprAssign, ExprAssignOp,
+    ExprAwait, ExprBinary, ExprBox, ExprBreak, ExprCast, ExprField, ExprGroup, ExprLet, ExprParen,
+    ExprReference, ExprTry, ExprType, ExprUnary, ImplItem, Item, ItemEnum, ItemStruct, Pat, PatBox,
+    PatReference, PatSlice, PatTuple, Path, Receiver, ReturnType, Signature, Stmt, TraitItem, Type,
+    TypeArray, TypeGroup, TypeParamBound, TypeParen, TypePtr, TypeReference, TypeSlice,
+};
+use thiserror::Error;
+
+#[derive(Default)]
+pub(super) struct Discoveries {
+    pub(super) cpp_list: HashSet<String>,
+    pub(super) extern_rust_funs: Vec<RustFun>,
+    pub(super) extern_rust_types: Vec<RustPath>,
+}
+
+#[derive(Error, Debug)]
+pub enum DiscoveryErr {
+    #[error("#[extern_rust_function] was attached to a method in an impl block that was too complex for autocxx. autocxx supports only \"impl X {{...}}\" where X is a single identifier, not a path or more complex type.")]
+    FoundExternRustFunOnTypeWithoutClearReceiver,
+    #[error("#[extern_rust_function] was attached to a method taking no parameters.")]
+    NonReferenceReceiver,
+    #[error("#[extern_rust_function] was attached to a method taking a receiver by value.")]
+    NoParameterOnMethod,
+    #[error("#[extern_rust_function] was in an impl block nested wihtin another block. This is only supported in the outermost mod of a file, alongside the include_cpp!.")]
+    FoundExternRustFunWithinMod,
+}
+
+impl Discoveries {
+    pub(super) fn search_item(
+        &mut self,
+        item: &Item,
+        mod_path: Option<RustPath>,
+    ) -> Result<(), DiscoveryErr> {
+        let mut this_mod = PerModDiscoveries {
+            discoveries: self,
+            mod_path,
+        };
+        this_mod.search_item(item)
+    }
+
+    pub(crate) fn found_allowlist(&self) -> bool {
+        !self.cpp_list.is_empty()
+    }
+
+    pub(crate) fn found_rust(&self) -> bool {
+        !self.extern_rust_funs.is_empty() || !self.extern_rust_types.is_empty()
+    }
+
+    pub(crate) fn extend(&mut self, other: Self) {
+        self.cpp_list.extend(other.cpp_list);
+        self.extern_rust_funs.extend(other.extern_rust_funs);
+        self.extern_rust_types.extend(other.extern_rust_types);
+    }
+}
+
+struct PerModDiscoveries<'a> {
+    discoveries: &'a mut Discoveries,
+    mod_path: Option<RustPath>,
+}
+
+impl<'b> PerModDiscoveries<'b> {
+    fn deeper_path(&self, id: &Ident) -> RustPath {
+        match &self.mod_path {
+            None => RustPath::new_from_ident(id.clone()),
+            Some(mod_path) => mod_path.append(id.clone()),
+        }
+    }
+
+    fn search_item(&mut self, item: &Item) -> Result<(), DiscoveryErr> {
+        match item {
+            Item::Fn(fun) => {
+                for stmt in &fun.block.stmts {
+                    self.search_stmt(stmt)?
+                }
+                self.search_return_type(&fun.sig.output)?;
+                for i in &fun.sig.inputs {
+                    match i {
+                        syn::FnArg::Receiver(_) => {}
+                        syn::FnArg::Typed(pt) => {
+                            self.search_pat(&pt.pat)?;
+                            self.search_type(&pt.ty)?;
+                        }
+                    }
+                }
+                if Self::has_attr(&fun.attrs, EXTERN_RUST_FUN) {
+                    self.discoveries.extern_rust_funs.push(RustFun {
+                        path: self.deeper_path(&fun.sig.ident),
+                        sig: fun.sig.clone(),
+                        receiver: None,
+                    });
+                }
+            }
+            Item::Impl(imp) => {
+                let receiver = match imp.trait_ {
+                    // We do not allow 'extern_rust_fun' on trait impls
+                    Some(_) => None,
+                    None => match &*imp.self_ty {
+                        Type::Path(typ) => {
+                            let mut segs = typ.path.segments.iter();
+                            let id = segs.next();
+                            if let Some(seg) = id {
+                                if segs.next().is_some() {
+                                    None
+                                } else {
+                                    Some(self.deeper_path(&seg.ident))
+                                }
+                            } else {
+                                None
+                            }
+                        }
+                        _ => None,
+                    },
+                };
+                for item in &imp.items {
+                    self.search_impl_item(item, receiver.as_ref())?
+                }
+            }
+            Item::Mod(md) => {
+                if let Some((_, items)) = &md.content {
+                    let mod_path = Some(self.deeper_path(&md.ident));
+                    let mut new_mod = PerModDiscoveries {
+                        discoveries: self.discoveries,
+                        mod_path,
+                    };
+                    for item in items {
+                        new_mod.search_item(item)?
+                    }
+                }
+            }
+            Item::Trait(tr) => {
+                for item in &tr.items {
+                    self.search_trait_item(item)?
+                }
+            }
+            Item::Struct(ItemStruct { ident, attrs, .. })
+            | Item::Enum(ItemEnum { ident, attrs, .. })
+                if Self::has_attr(attrs, EXTERN_RUST_TYPE) =>
+            {
+                self.discoveries
+                    .extern_rust_types
+                    .push(self.deeper_path(ident));
+            }
+            _ => {}
+        }
+        Ok(())
+    }
+
+    fn search_path(&mut self, path: &Path) -> Result<(), DiscoveryErr> {
+        let mut seg_iter = path.segments.iter();
+        if let Some(first_seg) = seg_iter.next() {
+            if first_seg.ident == "ffi" {
+                self.discoveries
+                    .cpp_list
+                    .insert(seg_iter.map(|seg| seg.ident.to_string()).join("::"));
+            }
+        }
+        for seg in path.segments.iter() {
+            self.search_path_arguments(&seg.arguments)?;
+        }
+        Ok(())
+    }
+
+    fn search_trait_item(&mut self, itm: &TraitItem) -> Result<(), DiscoveryErr> {
+        if let TraitItem::Method(itm) = itm {
+            if let Some(block) = &itm.default {
+                self.search_stmts(block.stmts.iter())?
+            }
+        }
+        Ok(())
+    }
+
+    fn search_stmts<'a>(
+        &mut self,
+        stmts: impl Iterator<Item = &'a Stmt>,
+    ) -> Result<(), DiscoveryErr> {
+        for stmt in stmts {
+            self.search_stmt(stmt)?
+        }
+        Ok(())
+    }
+
+    fn search_stmt(&mut self, stmt: &Stmt) -> Result<(), DiscoveryErr> {
+        match stmt {
+            Stmt::Local(lcl) => {
+                if let Some((_, expr)) = &lcl.init {
+                    self.search_expr(expr)?
+                }
+                self.search_pat(&lcl.pat)
+            }
+            Stmt::Item(itm) => self.search_item(itm),
+            Stmt::Expr(exp) | Stmt::Semi(exp, _) => self.search_expr(exp),
+        }
+    }
+
+    fn search_expr(&mut self, expr: &Expr) -> Result<(), DiscoveryErr> {
+        match expr {
+            Expr::Path(exp) => {
+                self.search_path(&exp.path)?;
+            }
+            Expr::Macro(_) => {}
+            Expr::Array(array) => self.search_exprs(array.elems.iter())?,
+            Expr::Assign(ExprAssign { left, right, .. })
+            | Expr::AssignOp(ExprAssignOp { left, right, .. })
+            | Expr::Binary(ExprBinary { left, right, .. }) => {
+                self.search_expr(left)?;
+                self.search_expr(right)?;
+            }
+            Expr::Async(ass) => self.search_stmts(ass.block.stmts.iter())?,
+            Expr::Await(ExprAwait { base, .. }) | Expr::Field(ExprField { base, .. }) => {
+                self.search_expr(base)?
+            }
+            Expr::Block(blck) => self.search_stmts(blck.block.stmts.iter())?,
+            Expr::Box(ExprBox { expr, .. })
+            | Expr::Break(ExprBreak {
+                expr: Some(expr), ..
+            })
+            | Expr::Cast(ExprCast { expr, .. })
+            | Expr::Group(ExprGroup { expr, .. })
+            | Expr::Paren(ExprParen { expr, .. })
+            | Expr::Reference(ExprReference { expr, .. })
+            | Expr::Try(ExprTry { expr, .. })
+            | Expr::Type(ExprType { expr, .. })
+            | Expr::Unary(ExprUnary { expr, .. }) => self.search_expr(expr)?,
+            Expr::Call(exc) => {
+                self.search_expr(&exc.func)?;
+                self.search_exprs(exc.args.iter())?;
+            }
+            Expr::Closure(cls) => self.search_expr(&cls.body)?,
+            Expr::Continue(_)
+            | Expr::Lit(_)
+            | Expr::Break(ExprBreak { expr: None, .. })
+            | Expr::Verbatim(_) => {}
+            Expr::ForLoop(fl) => {
+                self.search_expr(&fl.expr)?;
+                self.search_stmts(fl.body.stmts.iter())?;
+            }
+            Expr::If(exif) => {
+                self.search_expr(&exif.cond)?;
+                self.search_stmts(exif.then_branch.stmts.iter())?;
+                if let Some((_, else_branch)) = &exif.else_branch {
+                    self.search_expr(else_branch)?;
+                }
+            }
+            Expr::Index(exidx) => {
+                self.search_expr(&exidx.expr)?;
+                self.search_expr(&exidx.index)?;
+            }
+            Expr::Let(ExprLet { expr, pat, .. }) => {
+                self.search_expr(expr)?;
+                self.search_pat(pat)?;
+            }
+            Expr::Loop(exloo) => self.search_stmts(exloo.body.stmts.iter())?,
+            Expr::Match(exm) => {
+                self.search_expr(&exm.expr)?;
+                for a in &exm.arms {
+                    self.search_expr(&a.body)?;
+                    if let Some((_, guard)) = &a.guard {
+                        self.search_expr(guard)?;
+                    }
+                }
+            }
+            Expr::MethodCall(mtc) => {
+                self.search_expr(&mtc.receiver)?;
+                self.search_exprs(mtc.args.iter())?;
+            }
+            Expr::Range(exr) => {
+                self.search_option_expr(&exr.from)?;
+                self.search_option_expr(&exr.to)?;
+            }
+            Expr::Repeat(exr) => {
+                self.search_expr(&exr.expr)?;
+                self.search_expr(&exr.len)?;
+            }
+            Expr::Return(exret) => {
+                if let Some(expr) = &exret.expr {
+                    self.search_expr(expr)?;
+                }
+            }
+            Expr::Struct(exst) => {
+                for f in &exst.fields {
+                    self.search_expr(&f.expr)?;
+                }
+                self.search_option_expr(&exst.rest)?;
+            }
+            Expr::TryBlock(extb) => self.search_stmts(extb.block.stmts.iter())?,
+            Expr::Tuple(ext) => self.search_exprs(ext.elems.iter())?,
+            Expr::Unsafe(exs) => self.search_stmts(exs.block.stmts.iter())?,
+            Expr::While(exw) => {
+                self.search_expr(&exw.cond)?;
+                self.search_stmts(exw.body.stmts.iter())?;
+            }
+            Expr::Yield(exy) => self.search_option_expr(&exy.expr)?,
+            _ => {}
+        }
+        Ok(())
+    }
+
+    fn search_option_expr(&mut self, expr: &Option<Box<Expr>>) -> Result<(), DiscoveryErr> {
+        if let Some(expr) = &expr {
+            self.search_expr(expr)?;
+        }
+        Ok(())
+    }
+
+    fn search_exprs<'a>(
+        &mut self,
+        exprs: impl Iterator<Item = &'a Expr>,
+    ) -> Result<(), DiscoveryErr> {
+        for e in exprs {
+            self.search_expr(e)?;
+        }
+        Ok(())
+    }
+
+    fn search_impl_item(
+        &mut self,
+        impl_item: &ImplItem,
+        receiver: Option<&RustPath>,
+    ) -> Result<(), DiscoveryErr> {
+        if let ImplItem::Method(itm) = impl_item {
+            if Self::has_attr(&itm.attrs, EXTERN_RUST_FUN) {
+                if self.mod_path.is_some() {
+                    return Err(DiscoveryErr::FoundExternRustFunWithinMod);
+                }
+                if let Some(receiver) = receiver {
+                    // We have a method which we want to put into the cxx::bridge's
+                    // "extern Rust" block.
+                    let sig = add_receiver(&itm.sig, receiver.get_final_ident())?;
+                    assert!(receiver.len() == 1);
+                    self.discoveries.extern_rust_funs.push(RustFun {
+                        path: self.deeper_path(&itm.sig.ident),
+                        sig,
+                        receiver: Some(receiver.get_final_ident().clone()),
+                    });
+                    self.discoveries.extern_rust_types.push(receiver.clone())
+                } else {
+                    return Err(DiscoveryErr::FoundExternRustFunOnTypeWithoutClearReceiver);
+                }
+            }
+            for stmt in &itm.block.stmts {
+                self.search_stmt(stmt)?
+            }
+        }
+        Ok(())
+    }
+
+    fn search_pat(&mut self, pat: &Pat) -> Result<(), DiscoveryErr> {
+        match pat {
+            Pat::Box(PatBox { pat, .. }) | Pat::Reference(PatReference { pat, .. }) => {
+                self.search_pat(pat)
+            }
+            Pat::Ident(_) | Pat::Lit(_) | Pat::Macro(_) | Pat::Range(_) | Pat::Rest(_) => Ok(()),
+            Pat::Or(pator) => {
+                for case in &pator.cases {
+                    self.search_pat(case)?;
+                }
+                Ok(())
+            }
+            Pat::Path(pp) => self.search_path(&pp.path),
+            Pat::Slice(PatSlice { elems, .. }) | Pat::Tuple(PatTuple { elems, .. }) => {
+                for case in elems {
+                    self.search_pat(case)?;
+                }
+                Ok(())
+            }
+            Pat::Struct(ps) => {
+                self.search_path(&ps.path)?;
+                for f in &ps.fields {
+                    self.search_pat(&f.pat)?;
+                }
+                Ok(())
+            }
+            Pat::TupleStruct(tps) => {
+                self.search_path(&tps.path)?;
+                for f in &tps.pat.elems {
+                    self.search_pat(f)?;
+                }
+                Ok(())
+            }
+            Pat::Type(pt) => {
+                self.search_pat(&pt.pat)?;
+                self.search_type(&pt.ty)
+            }
+            _ => Ok(()),
+        }
+    }
+
+    fn search_type(&mut self, ty: &Type) -> Result<(), DiscoveryErr> {
+        match ty {
+            Type::Array(TypeArray { elem, .. })
+            | Type::Group(TypeGroup { elem, .. })
+            | Type::Paren(TypeParen { elem, .. })
+            | Type::Ptr(TypePtr { elem, .. })
+            | Type::Reference(TypeReference { elem, .. })
+            | Type::Slice(TypeSlice { elem, .. }) => self.search_type(elem)?,
+            Type::BareFn(tf) => {
+                for input in &tf.inputs {
+                    self.search_type(&input.ty)?;
+                }
+                self.search_return_type(&tf.output)?;
+            }
+            Type::ImplTrait(tyit) => {
+                for b in &tyit.bounds {
+                    if let syn::TypeParamBound::Trait(tyt) = b {
+                        self.search_path(&tyt.path)?
+                    }
+                }
+            }
+            Type::Infer(_) | Type::Macro(_) | Type::Never(_) => {}
+            Type::Path(typ) => self.search_path(&typ.path)?,
+            Type::TraitObject(tto) => self.search_type_param_bounds(&tto.bounds)?,
+            Type::Tuple(tt) => {
+                for e in &tt.elems {
+                    self.search_type(e)?
+                }
+            }
+            _ => {}
+        }
+        Ok(())
+    }
+
+    fn search_type_param_bounds(
+        &mut self,
+        bounds: &Punctuated<TypeParamBound, syn::token::Add>,
+    ) -> Result<(), DiscoveryErr> {
+        for b in bounds {
+            if let syn::TypeParamBound::Trait(tpbt) = b {
+                self.search_path(&tpbt.path)?
+            }
+        }
+        Ok(())
+    }
+
+    fn search_return_type(&mut self, output: &ReturnType) -> Result<(), DiscoveryErr> {
+        if let ReturnType::Type(_, ty) = &output {
+            self.search_type(ty)
+        } else {
+            Ok(())
+        }
+    }
+
+    fn search_path_arguments(
+        &mut self,
+        arguments: &syn::PathArguments,
+    ) -> Result<(), DiscoveryErr> {
+        match arguments {
+            syn::PathArguments::None => {}
+            syn::PathArguments::AngleBracketed(paab) => {
+                for arg in &paab.args {
+                    match arg {
+                        syn::GenericArgument::Lifetime(_) => {}
+                        syn::GenericArgument::Type(ty)
+                        | syn::GenericArgument::Binding(Binding { ty, .. }) => {
+                            self.search_type(ty)?
+                        }
+                        syn::GenericArgument::Constraint(c) => {
+                            self.search_type_param_bounds(&c.bounds)?
+                        }
+                        syn::GenericArgument::Const(c) => self.search_expr(c)?,
+                    }
+                }
+            }
+            syn::PathArguments::Parenthesized(pas) => {
+                self.search_return_type(&pas.output)?;
+                for t in &pas.inputs {
+                    self.search_type(t)?;
+                }
+            }
+        }
+        Ok(())
+    }
+
+    fn has_attr(attrs: &[Attribute], attr_name: &str) -> bool {
+        attrs.iter().any(|attr| {
+            attr.path
+                .segments
+                .last()
+                .map(|seg| seg.ident == attr_name)
+                .unwrap_or_default()
+        })
+    }
+}
+
+/// Take a method signature that may be `fn a(&self)`
+/// and turn it into `fn a(self: &A)` which is what we will
+/// need to specify to cxx.
+fn add_receiver(sig: &Signature, receiver: &Ident) -> Result<Signature, DiscoveryErr> {
+    let mut sig = sig.clone();
+    match sig.inputs.iter_mut().next() {
+        Some(first_arg) => match first_arg {
+            syn::FnArg::Receiver(Receiver {
+                reference: Some(_),
+                mutability: Some(_),
+                ..
+            }) => {
+                *first_arg = parse_quote! {
+                    self: &mut #receiver
+                }
+            }
+            syn::FnArg::Receiver(Receiver {
+                reference: Some(_),
+                mutability: None,
+                ..
+            }) => {
+                *first_arg = parse_quote! {
+                    self: &#receiver
+                }
+            }
+            syn::FnArg::Receiver(..) => return Err(DiscoveryErr::NonReferenceReceiver),
+            syn::FnArg::Typed(_) => {}
+        },
+        None => return Err(DiscoveryErr::NoParameterOnMethod),
+    }
+    Ok(sig)
+}
+
+#[cfg(test)]
+mod tests {
+    use quote::{quote, ToTokens};
+    use syn::{parse_quote, ImplItemMethod};
+
+    use crate::{ast_discoverer::add_receiver, types::make_ident};
+
+    use super::Discoveries;
+
+    fn assert_cpp_found(discoveries: &Discoveries) {
+        assert!(!discoveries.cpp_list.is_empty());
+        assert!(discoveries.cpp_list.iter().next().unwrap() == "xxx");
+    }
+
+    #[test]
+    fn test_mod_plain_call() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            mod foo {
+                fn bar() {
+                    ffi::xxx()
+                }
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert_cpp_found(&discoveries);
+    }
+
+    #[test]
+    fn test_plain_call() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            fn bar() {
+                ffi::xxx()
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert_cpp_found(&discoveries);
+    }
+
+    #[test]
+    fn test_plain_call_with_semi() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            fn bar() {
+                ffi::xxx();
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert_cpp_found(&discoveries);
+    }
+
+    #[test]
+    fn test_in_ns() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            fn bar() {
+                ffi::a::b::xxx();
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert!(!discoveries.cpp_list.is_empty());
+        assert!(discoveries.cpp_list.iter().next().unwrap() == "a::b::xxx");
+    }
+
+    #[test]
+    fn test_deep_nested_thingy() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            fn bar() {
+                a + 3 * foo(ffi::xxx());
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert_cpp_found(&discoveries);
+    }
+
+    #[test]
+    fn test_ty_in_let() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            fn bar() {
+                let foo: ffi::xxx = bar();
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert_cpp_found(&discoveries);
+    }
+
+    #[test]
+    fn test_ty_in_fn() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            fn bar(a: &mut ffi::xxx) {
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert_cpp_found(&discoveries);
+    }
+
+    #[test]
+    fn test_ty_in_fn_up() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            fn bar(a: cxx::UniquePtr<ffi::xxx>) {
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert_cpp_found(&discoveries);
+    }
+
+    #[test]
+    fn test_extern_rust_fun() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            #[autocxx::extern_rust::extern_rust_function]
+            fn bar(a: cxx::UniquePtr<ffi::xxx>) {
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert!(discoveries.extern_rust_funs.get(0).unwrap().sig.ident == "bar");
+    }
+
+    #[test]
+    fn test_extern_rust_method() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            impl A {
+                #[autocxx::extern_rust::extern_rust_function]
+                fn bar(&self) {
+                }
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert!(discoveries.extern_rust_funs.get(0).unwrap().sig.ident == "bar");
+    }
+
+    #[test]
+    fn test_extern_rust_ty() {
+        let mut discoveries = Discoveries::default();
+        let itm = parse_quote! {
+            #[autocxx::extern_rust::extern_rust_type]
+            struct Bar {
+
+            }
+        };
+        discoveries.search_item(&itm, None).unwrap();
+        assert!(
+            discoveries
+                .extern_rust_types
+                .get(0)
+                .unwrap()
+                .get_final_ident()
+                == "Bar"
+        );
+    }
+
+    #[test]
+    fn test_add_receiver() {
+        let meth: ImplItemMethod = parse_quote! {
+            fn a(&self) {}
+        };
+        let a = make_ident("A");
+        assert_eq!(
+            add_receiver(&meth.sig, &a)
+                .unwrap()
+                .to_token_stream()
+                .to_string(),
+            quote! { fn a(self: &A) }.to_string()
+        );
+
+        let meth: ImplItemMethod = parse_quote! {
+            fn a(&mut self, b: u32) -> Foo {}
+        };
+        assert_eq!(
+            add_receiver(&meth.sig, &a)
+                .unwrap()
+                .to_token_stream()
+                .to_string(),
+            quote! { fn a(self: &mut A, b: u32) -> Foo }.to_string()
+        );
+
+        let meth: ImplItemMethod = parse_quote! {
+            fn a(self) {}
+        };
+        assert!(add_receiver(&meth.sig, &a).is_err());
+
+        let meth: ImplItemMethod = parse_quote! {
+            fn a() {}
+        };
+        assert!(add_receiver(&meth.sig, &a).is_err());
+    }
+}
diff --git a/engine/src/builder.rs b/engine/src/builder.rs
new file mode 100644
index 0000000..d0b5199
--- /dev/null
+++ b/engine/src/builder.rs
@@ -0,0 +1,301 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx_parser::file_locations::FileLocationStrategy;
+use miette::Diagnostic;
+use thiserror::Error;
+
+use crate::generate_rs_single;
+use crate::{strip_system_headers, CppCodegenOptions, ParseError, RebuildDependencyRecorder};
+use std::ffi::OsStr;
+use std::ffi::OsString;
+use std::fs::File;
+use std::io::Write;
+use std::marker::PhantomData;
+use std::path::{Path, PathBuf};
+
+/// Errors returned during creation of a [`cc::Build`] from an include_cxx
+/// macro.
+#[derive(Error, Diagnostic, Debug)]
+#[cfg_attr(feature = "nightly", doc(cfg(feature = "build")))]
+pub enum BuilderError {
+    #[error("cxx couldn't handle our generated bindings - could be a bug in autocxx: {0}")]
+    InvalidCxx(cxx_gen::Error),
+    #[error(transparent)]
+    #[diagnostic(transparent)]
+    ParseError(ParseError),
+    #[error("we couldn't write the generated code to disk at {1}: {0}")]
+    FileWriteFail(std::io::Error, PathBuf),
+    #[error("no include_cpp! macro was found")]
+    NoIncludeCxxMacrosFound,
+    #[error("could not create a directory {1}: {0}")]
+    UnableToCreateDirectory(std::io::Error, PathBuf),
+}
+
+#[cfg_attr(feature = "nightly", doc(cfg(feature = "build")))]
+pub type BuilderBuild = cc::Build;
+
+/// For test purposes only, a [`cc::Build`] and lists of Rust and C++
+/// files generated.
+#[cfg_attr(feature = "nightly", doc(cfg(feature = "build")))]
+pub struct BuilderSuccess(pub BuilderBuild, pub Vec<PathBuf>, pub Vec<PathBuf>);
+
+/// Results of a build.
+#[cfg_attr(feature = "nightly", doc(cfg(feature = "build")))]
+pub type BuilderResult = Result<BuilderSuccess, BuilderError>;
+
+/// The context in which a builder object lives. Callbacks for various
+/// purposes.
+#[cfg_attr(feature = "nightly", doc(cfg(feature = "build")))]
+pub trait BuilderContext {
+    /// Perform any initialization specific to the context in which this
+    /// builder lives.
+    fn setup() {}
+
+    /// Create a dependency recorder, if any.
+    fn get_dependency_recorder() -> Option<Box<dyn RebuildDependencyRecorder>>;
+}
+
+/// An object to allow building of bindings from a `build.rs` file.
+///
+/// It would be unusual to use this directly - see the `autocxx_build` or
+/// `autocxx_gen` crates.
+#[cfg_attr(feature = "nightly", doc(cfg(feature = "build")))]
+pub struct Builder<'a, BuilderContext> {
+    rs_file: PathBuf,
+    autocxx_incs: Vec<OsString>,
+    extra_clang_args: Vec<String>,
+    dependency_recorder: Option<Box<dyn RebuildDependencyRecorder>>,
+    custom_gendir: Option<PathBuf>,
+    auto_allowlist: bool,
+    cpp_codegen_options: CppCodegenOptions<'a>,
+    // This member is to ensure that this type is parameterized
+    // by a BuilderContext. The goal is to balance three needs:
+    // (1) have most of the functionality over in autocxx_engine,
+    // (2) expose this type to users of autocxx_build and to
+    //     make it easy for callers simply to call Builder::new,
+    // (3) ensure that such a Builder does a few tasks specific to its use
+    // in a cargo environment.
+    ctx: PhantomData<BuilderContext>,
+}
+
+impl<CTX: BuilderContext> Builder<'_, CTX> {
+    /// Create a new Builder object. You'll need to pass in the Rust file
+    /// which contains the bindings (typically an `include_cpp!` macro
+    /// though `autocxx` can also handle manually-crafted `cxx::bridge`
+    /// bindings), and a list of include directories which should be searched
+    /// by autocxx as it tries to hunt for the include files specified
+    /// within the `include_cpp!` macro.
+    ///
+    /// Usually after this you'd call [`build`].
+    pub fn new(
+        rs_file: impl AsRef<Path>,
+        autocxx_incs: impl IntoIterator<Item = impl AsRef<OsStr>>,
+    ) -> Self {
+        CTX::setup();
+        Self {
+            rs_file: rs_file.as_ref().to_path_buf(),
+            autocxx_incs: autocxx_incs
+                .into_iter()
+                .map(|s| s.as_ref().to_os_string())
+                .collect(),
+            extra_clang_args: Vec::new(),
+            dependency_recorder: CTX::get_dependency_recorder(),
+            custom_gendir: None,
+            auto_allowlist: false,
+            cpp_codegen_options: CppCodegenOptions::default(),
+            ctx: PhantomData,
+        }
+    }
+
+    /// Specify extra arguments for clang.
+    pub fn extra_clang_args(mut self, extra_clang_args: &[&str]) -> Self {
+        self.extra_clang_args = extra_clang_args.iter().map(|s| s.to_string()).collect();
+        self
+    }
+
+    /// Where to generate the code.
+    pub fn custom_gendir(mut self, custom_gendir: PathBuf) -> Self {
+        self.custom_gendir = Some(custom_gendir);
+        self
+    }
+
+    /// Update C++ code generation options. See [`CppCodegenOptions`] for details.
+    pub fn cpp_codegen_options<F>(mut self, modifier: F) -> Self
+    where
+        F: FnOnce(&mut CppCodegenOptions),
+    {
+        modifier(&mut self.cpp_codegen_options);
+        self
+    }
+
+    /// Automatically discover uses of the C++ `ffi` mod and generate the allowlist
+    /// from that.
+    /// This is a highly experimental option, not currently recommended.
+    /// It doesn't work in the following cases:
+    /// * Static function calls on types within the FFI mod.
+    /// * Anything inside a macro invocation.
+    /// * You're using a different name for your `ffi` mod
+    /// * You're using multiple FFI mods
+    /// * You've got usages scattered across files beyond that with the
+    ///   `include_cpp` invocation
+    /// * You're using `use` statements to rename mods or items. If this
+    /// proves to be a promising or helpful direction, autocxx would be happy
+    /// to accept pull requests to remove some of these limitations.
+    pub fn auto_allowlist(mut self, do_it: bool) -> Self {
+        self.auto_allowlist = do_it;
+        self
+    }
+
+    /// Whether to suppress inclusion of system headers (`memory`, `string` etc.)
+    /// from generated C++ bindings code. This should not normally be used,
+    /// but can occasionally be useful if you're reducing a test case and you
+    /// have a preprocessed header file which already contains absolutely everything
+    /// that the bindings could ever need.
+    pub fn suppress_system_headers(mut self, do_it: bool) -> Self {
+        self.cpp_codegen_options.suppress_system_headers = do_it;
+        self
+    }
+
+    /// An annotation optionally to include on each C++ function.
+    /// For example to export the symbol from a library.
+    pub fn cxx_impl_annotations(mut self, cxx_impl_annotations: Option<String>) -> Self {
+        self.cpp_codegen_options.cxx_impl_annotations = cxx_impl_annotations;
+        self
+    }
+
+    /// Build autocxx C++ files and return a [`cc::Build`] you can use to build
+    /// more from a build.rs file.
+    ///
+    /// The error type returned by this function supports [`miette::Diagnostic`],
+    /// so if you use the `miette` crate and its `fancy` feature, then simply
+    /// return a `miette::Result` from your main function, you should get nicely
+    /// printed diagnostics.
+    pub fn build(self) -> Result<BuilderBuild, BuilderError> {
+        self.build_listing_files().map(|r| r.0)
+    }
+
+    /// For use in tests only, this does the build and returns additional information
+    /// about the files generated which can subsequently be examined for correctness.
+    /// In production, please use simply [`build`].
+    pub fn build_listing_files(self) -> Result<BuilderSuccess, BuilderError> {
+        let clang_args = &self
+            .extra_clang_args
+            .iter()
+            .map(|s| &s[..])
+            .collect::<Vec<_>>();
+        rust_version_check();
+        let gen_location_strategy = match self.custom_gendir {
+            None => FileLocationStrategy::new(),
+            Some(custom_dir) => FileLocationStrategy::Custom(custom_dir),
+        };
+        let incdir = gen_location_strategy.get_include_dir();
+        ensure_created(&incdir)?;
+        let cxxdir = gen_location_strategy.get_cxx_dir();
+        ensure_created(&cxxdir)?;
+        let rsdir = gen_location_strategy.get_rs_dir();
+        ensure_created(&rsdir)?;
+        // We are incredibly unsophisticated in our directory arrangement here
+        // compared to cxx. I have no doubt that we will need to replicate just
+        // about everything cxx does, in due course...
+        // Write cxx.h to that location, as it may be needed by
+        // some of our generated code.
+        write_to_file(
+            &incdir,
+            "cxx.h",
+            &Self::get_cxx_header_bytes(self.cpp_codegen_options.suppress_system_headers),
+        )?;
+
+        let autocxx_inc = build_autocxx_inc(self.autocxx_incs, &incdir);
+        gen_location_strategy.set_cargo_env_vars_for_build();
+
+        let mut parsed_file = crate::parse_file(self.rs_file, self.auto_allowlist)
+            .map_err(BuilderError::ParseError)?;
+        parsed_file
+            .resolve_all(
+                autocxx_inc,
+                clang_args,
+                self.dependency_recorder,
+                &self.cpp_codegen_options,
+            )
+            .map_err(BuilderError::ParseError)?;
+        let mut counter = 0;
+        let mut builder = cc::Build::new();
+        builder.cpp(true);
+        if std::env::var_os("AUTOCXX_ASAN").is_some() {
+            builder.flag_if_supported("-fsanitize=address");
+        }
+        let mut generated_rs = Vec::new();
+        let mut generated_cpp = Vec::new();
+        builder.includes(parsed_file.include_dirs());
+        for include_cpp in parsed_file.get_cpp_buildables() {
+            let generated_code = include_cpp
+                .generate_h_and_cxx(&self.cpp_codegen_options)
+                .map_err(BuilderError::InvalidCxx)?;
+            for filepair in generated_code.0 {
+                let fname = format!("gen{}.cxx", counter);
+                counter += 1;
+                if let Some(implementation) = &filepair.implementation {
+                    let gen_cxx_path = write_to_file(&cxxdir, &fname, implementation)?;
+                    builder.file(&gen_cxx_path);
+                    generated_cpp.push(gen_cxx_path);
+                }
+                write_to_file(&incdir, &filepair.header_name, &filepair.header)?;
+                generated_cpp.push(incdir.join(filepair.header_name));
+            }
+        }
+
+        for rs_output in parsed_file.get_rs_outputs() {
+            let rs = generate_rs_single(rs_output);
+            generated_rs.push(write_to_file(&rsdir, &rs.filename, rs.code.as_bytes())?);
+        }
+        if counter == 0 {
+            Err(BuilderError::NoIncludeCxxMacrosFound)
+        } else {
+            Ok(BuilderSuccess(builder, generated_rs, generated_cpp))
+        }
+    }
+
+    fn get_cxx_header_bytes(suppress_system_headers: bool) -> Vec<u8> {
+        strip_system_headers(crate::HEADER.as_bytes().to_vec(), suppress_system_headers)
+    }
+}
+
+fn ensure_created(dir: &Path) -> Result<(), BuilderError> {
+    std::fs::create_dir_all(dir)
+        .map_err(|e| BuilderError::UnableToCreateDirectory(e, dir.to_path_buf()))
+}
+
+fn build_autocxx_inc<I, T>(paths: I, extra_path: &Path) -> Vec<PathBuf>
+where
+    I: IntoIterator<Item = T>,
+    T: AsRef<OsStr>,
+{
+    paths
+        .into_iter()
+        .map(|p| PathBuf::from(p.as_ref()))
+        .chain(std::iter::once(extra_path.to_path_buf()))
+        .collect()
+}
+
+fn write_to_file(dir: &Path, filename: &str, content: &[u8]) -> Result<PathBuf, BuilderError> {
+    let path = dir.join(filename);
+    try_write_to_file(&path, content).map_err(|e| BuilderError::FileWriteFail(e, path.clone()))?;
+    Ok(path)
+}
+
+fn try_write_to_file(path: &Path, content: &[u8]) -> std::io::Result<()> {
+    let mut f = File::create(path)?;
+    f.write_all(content)
+}
+
+fn rust_version_check() {
+    if !version_check::is_min_version("1.54.0").unwrap_or(false) {
+        panic!("Rust 1.54 or later is required.")
+    }
+}
diff --git a/engine/src/conversion/analysis/abstract_types.rs b/engine/src/conversion/analysis/abstract_types.rs
new file mode 100644
index 0000000..dac9684
--- /dev/null
+++ b/engine/src/conversion/analysis/abstract_types.rs
@@ -0,0 +1,174 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::{
+    fun::{
+        FnAnalysis, FnKind, FnPhase, FnPrePhase2, MethodKind, PodAndConstructorAnalysis,
+        TraitMethodKind,
+    },
+    pod::PodAnalysis,
+};
+use crate::conversion::{api::Api, apivec::ApiVec};
+use crate::conversion::{
+    api::TypeKind,
+    error_reporter::{convert_apis, convert_item_apis},
+    ConvertError,
+};
+use indexmap::set::IndexSet as HashSet;
+
+/// Spot types with pure virtual functions and mark them abstract.
+pub(crate) fn mark_types_abstract(mut apis: ApiVec<FnPrePhase2>) -> ApiVec<FnPrePhase2> {
+    let mut abstract_types: HashSet<_> = apis
+        .iter()
+        .filter_map(|api| match &api {
+            Api::Function {
+                analysis:
+                    FnAnalysis {
+                        kind:
+                            FnKind::Method {
+                                impl_for: self_ty_name,
+                                method_kind: MethodKind::PureVirtual(_),
+                                ..
+                            },
+                        ..
+                    },
+                ..
+            } => Some(self_ty_name.clone()),
+            _ => None,
+        })
+        .collect();
+
+    // Spot any derived classes (recursively). Also, any types which have a base
+    // class that's not on the allowlist are presumed to be abstract, because we
+    // have no way of knowing (as they're not on the allowlist, there will be
+    // no methods associated so we won't be able to spot pure virtual methods).
+    let mut iterate = true;
+    while iterate {
+        iterate = false;
+        apis = apis
+            .into_iter()
+            .map(|api| {
+                match api {
+                    Api::Struct {
+                        analysis:
+                            PodAndConstructorAnalysis {
+                                pod:
+                                    PodAnalysis {
+                                        bases,
+                                        kind: TypeKind::Pod | TypeKind::NonPod,
+                                        castable_bases,
+                                        field_deps,
+                                        field_info,
+                                        is_generic,
+                                        in_anonymous_namespace,
+                                    },
+                                constructors,
+                            },
+                        name,
+                        details,
+                    } if abstract_types.contains(&name.name)
+                        || !abstract_types.is_disjoint(&bases) =>
+                    {
+                        abstract_types.insert(name.name.clone());
+                        // Recurse in case there are further dependent types
+                        iterate = true;
+                        Api::Struct {
+                            analysis: PodAndConstructorAnalysis {
+                                pod: PodAnalysis {
+                                    bases,
+                                    kind: TypeKind::Abstract,
+                                    castable_bases,
+                                    field_deps,
+                                    field_info,
+                                    is_generic,
+                                    in_anonymous_namespace,
+                                },
+                                constructors,
+                            },
+                            name,
+                            details,
+                        }
+                    }
+                    _ => api,
+                }
+            })
+            .collect()
+    }
+
+    // We also need to remove any constructors belonging to these
+    // abstract types.
+    apis.retain(|api| {
+        !matches!(&api,
+        Api::Function {
+            analysis:
+                FnAnalysis {
+                    kind: FnKind::Method{impl_for: self_ty, method_kind: MethodKind::Constructor{..}, ..}
+                        | FnKind::TraitMethod{ kind: TraitMethodKind::CopyConstructor | TraitMethodKind::MoveConstructor, impl_for: self_ty, ..},
+                    ..
+                },
+                ..
+        } if abstract_types.contains(self_ty))
+    });
+
+    // Finally, if there are any types which are nested inside other types,
+    // they can't be abstract. This is due to two small limitations in cxx.
+    // Imagine we have class Foo { class Bar }
+    // 1) using "type Foo = super::bindgen::root::Foo_Bar" results
+    //    in the creation of std::unique_ptr code which isn't acceptable
+    //    for an abtract class
+    // 2) using "type Foo;" isn't possible unless Foo is a top-level item
+    //    within its namespace. Any outer names will be interpreted as namespace
+    //    names and result in cxx generating "namespace Foo { class Bar }"".
+    let mut results = ApiVec::new();
+    convert_item_apis(apis, &mut results, |api| match api {
+        Api::Struct {
+            analysis:
+                PodAndConstructorAnalysis {
+                    pod:
+                        PodAnalysis {
+                            kind: TypeKind::Abstract,
+                            ..
+                        },
+                    ..
+                },
+            ..
+        } if api
+            .cpp_name()
+            .as_ref()
+            .map(|n| n.contains("::"))
+            .unwrap_or_default() =>
+        {
+            Err(ConvertError::AbstractNestedType)
+        }
+        _ => Ok(Box::new(std::iter::once(api))),
+    });
+    results
+}
+
+pub(crate) fn discard_ignored_functions(apis: ApiVec<FnPhase>) -> ApiVec<FnPhase> {
+    // Some APIs can't be generated, e.g. because they're protected.
+    // Now we've finished analyzing abstract types and constructors, we'll
+    // convert them to IgnoredItems.
+    let mut apis_new = ApiVec::new();
+    convert_apis(
+        apis,
+        &mut apis_new,
+        |name, fun, analysis| {
+            analysis.ignore_reason.clone()?;
+            Ok(Box::new(std::iter::once(Api::Function {
+                name,
+                fun,
+                analysis,
+            })))
+        },
+        Api::struct_unchanged,
+        Api::enum_unchanged,
+        Api::typedef_unchanged,
+    );
+    apis_new
+}
diff --git a/engine/src/conversion/analysis/allocators.rs b/engine/src/conversion/analysis/allocators.rs
new file mode 100644
index 0000000..3695de0
--- /dev/null
+++ b/engine/src/conversion/analysis/allocators.rs
@@ -0,0 +1,111 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Code to create functions to alloc and free while unitialized.
+
+use syn::{parse_quote, punctuated::Punctuated, token::Comma, FnArg, ReturnType};
+
+use crate::{
+    conversion::{
+        api::{Api, ApiName, CppVisibility, FuncToConvert, Provenance, References, TraitSynthesis},
+        apivec::ApiVec,
+    },
+    types::{make_ident, QualifiedName},
+};
+
+use super::{
+    fun::function_wrapper::{CppFunctionBody, CppFunctionKind},
+    pod::PodPhase,
+};
+
+pub(crate) fn create_alloc_and_frees(apis: ApiVec<PodPhase>) -> ApiVec<PodPhase> {
+    apis.into_iter()
+        .flat_map(|api| -> Box<dyn Iterator<Item = Api<PodPhase>>> {
+            match &api {
+                Api::Struct { name, .. } => {
+                    Box::new(create_alloc_and_free(name.name.clone()).chain(std::iter::once(api)))
+                }
+                Api::Subclass { name, .. } => {
+                    Box::new(create_alloc_and_free(name.cpp()).chain(std::iter::once(api)))
+                }
+                _ => Box::new(std::iter::once(api)),
+            }
+        })
+        .collect()
+}
+
+fn create_alloc_and_free(ty_name: QualifiedName) -> impl Iterator<Item = Api<PodPhase>> {
+    let typ = ty_name.to_type_path();
+    let free_inputs: Punctuated<FnArg, Comma> = parse_quote! {
+        arg0: *mut #typ
+    };
+    let alloc_return: ReturnType = parse_quote! {
+        -> *mut #typ
+    };
+    [
+        (
+            TraitSynthesis::AllocUninitialized(ty_name.clone()),
+            get_alloc_name(&ty_name),
+            Punctuated::new(),
+            alloc_return,
+            CppFunctionBody::AllocUninitialized(ty_name.clone()),
+        ),
+        (
+            TraitSynthesis::FreeUninitialized(ty_name.clone()),
+            get_free_name(&ty_name),
+            free_inputs,
+            ReturnType::Default,
+            CppFunctionBody::FreeUninitialized(ty_name.clone()),
+        ),
+    ]
+    .into_iter()
+    .map(
+        move |(synthesis, name, inputs, output, cpp_function_body)| {
+            let ident = name.get_final_ident();
+            let api_name = ApiName::new_from_qualified_name(name);
+            Api::Function {
+                name: api_name,
+                fun: Box::new(FuncToConvert {
+                    ident,
+                    doc_attrs: Vec::new(),
+                    inputs,
+                    output,
+                    vis: parse_quote! { pub },
+                    virtualness: crate::conversion::api::Virtualness::None,
+                    cpp_vis: CppVisibility::Public,
+                    special_member: None,
+                    unused_template_param: false,
+                    references: References::default(),
+                    original_name: None,
+                    self_ty: None,
+                    synthesized_this_type: None,
+                    synthetic_cpp: Some((cpp_function_body, CppFunctionKind::Function)),
+                    add_to_trait: Some(synthesis),
+                    is_deleted: false,
+                    provenance: Provenance::SynthesizedOther,
+                    variadic: false,
+                }),
+                analysis: (),
+            }
+        },
+    )
+}
+
+pub(crate) fn get_alloc_name(ty_name: &QualifiedName) -> QualifiedName {
+    get_name(ty_name, "alloc")
+}
+
+pub(crate) fn get_free_name(ty_name: &QualifiedName) -> QualifiedName {
+    get_name(ty_name, "free")
+}
+
+fn get_name(ty_name: &QualifiedName, label: &str) -> QualifiedName {
+    let name = format!("{}_{}", ty_name.get_final_item(), label);
+    let name_id = make_ident(name);
+    QualifiedName::new(ty_name.get_namespace(), name_id)
+}
diff --git a/engine/src/conversion/analysis/casts.rs b/engine/src/conversion/analysis/casts.rs
new file mode 100644
index 0000000..5f493f9
--- /dev/null
+++ b/engine/src/conversion/analysis/casts.rs
@@ -0,0 +1,141 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use itertools::Itertools;
+use quote::quote;
+use syn::{parse_quote, FnArg};
+
+use crate::{
+    conversion::{
+        api::{Api, ApiName, CastMutability, Provenance, References, TraitSynthesis},
+        apivec::ApiVec,
+    },
+    types::{make_ident, QualifiedName},
+};
+
+/// If A is a base of B, we might want to be able to cast from
+/// &B to &A, or from Pin<&mut A> to &B, or from Pin<&mut A> to &B.
+/// The first is OK; the others turn out to be hard due to all
+/// the Pin stuff. For now therefore, we simply don't allow them.
+/// But the related code may be useful in future so I'm keeping it around.
+const SUPPORT_MUTABLE_CASTS: bool = false;
+
+use super::{
+    fun::function_wrapper::{CppFunctionBody, CppFunctionKind},
+    pod::{PodAnalysis, PodPhase},
+};
+
+pub(crate) fn add_casts(apis: ApiVec<PodPhase>) -> ApiVec<PodPhase> {
+    apis.into_iter()
+        .flat_map(|api| {
+            let mut resultant_apis = match api {
+                Api::Struct {
+                    ref name,
+                    details: _,
+                    ref analysis,
+                } => create_casts(&name.name, analysis).collect_vec(),
+                _ => Vec::new(),
+            };
+            resultant_apis.push(api);
+            resultant_apis.into_iter()
+        })
+        .collect()
+}
+
+fn create_casts<'a>(
+    name: &'a QualifiedName,
+    analysis: &'a PodAnalysis,
+) -> impl Iterator<Item = Api<PodPhase>> + 'a {
+    // Create casts only to base classes which are on the allowlist
+    // because otherwise we won't know for sure whether they're abstract or not.
+    analysis
+        .castable_bases
+        .iter()
+        .flat_map(move |base| cast_types().map(|mutable| create_cast(name, base, mutable)))
+}
+
+/// Iterate through the types of cast we should make.
+fn cast_types() -> impl Iterator<Item = CastMutability> {
+    if SUPPORT_MUTABLE_CASTS {
+        vec![
+            CastMutability::ConstToConst,
+            CastMutability::MutToConst,
+            CastMutability::MutToMut,
+        ]
+        .into_iter()
+    } else {
+        vec![CastMutability::ConstToConst].into_iter()
+    }
+}
+
+fn create_cast(from: &QualifiedName, to: &QualifiedName, mutable: CastMutability) -> Api<PodPhase> {
+    let name = name_for_cast(from, to, mutable);
+    let ident = name.get_final_ident();
+    let from_typ = from.to_type_path();
+    let to_typ = to.to_type_path();
+    let return_mutability = match mutable {
+        CastMutability::ConstToConst | CastMutability::MutToConst => quote! { const },
+        CastMutability::MutToMut => quote! { mut },
+    };
+    let param_mutability = match mutable {
+        CastMutability::ConstToConst => quote! { const },
+        CastMutability::MutToConst | CastMutability::MutToMut => quote! { mut },
+    };
+    let fnarg: FnArg = parse_quote! {
+        this: * #param_mutability #from_typ
+    };
+    Api::Function {
+        name: ApiName::new_from_qualified_name(name),
+        fun: Box::new(crate::conversion::api::FuncToConvert {
+            ident,
+            doc_attrs: Vec::new(),
+            inputs: [fnarg].into_iter().collect(),
+            output: parse_quote! {
+                -> * #return_mutability #to_typ
+            },
+            vis: parse_quote! { pub },
+            virtualness: crate::conversion::api::Virtualness::None,
+            cpp_vis: crate::conversion::api::CppVisibility::Public,
+            special_member: None,
+            unused_template_param: false,
+            references: References::new_with_this_and_return_as_reference(),
+            original_name: None,
+            self_ty: Some(from.clone()),
+            synthesized_this_type: None,
+            add_to_trait: Some(TraitSynthesis::Cast {
+                to_type: to.clone(),
+                mutable,
+            }),
+            synthetic_cpp: Some((CppFunctionBody::Cast, CppFunctionKind::Function)),
+            is_deleted: false,
+            provenance: Provenance::SynthesizedOther,
+            variadic: false,
+        }),
+        analysis: (),
+    }
+}
+
+fn name_for_cast(
+    from: &QualifiedName,
+    to: &QualifiedName,
+    mutable: CastMutability,
+) -> QualifiedName {
+    let suffix = match mutable {
+        CastMutability::ConstToConst => "",
+        CastMutability::MutToConst => "_to_const",
+        CastMutability::MutToMut => "_mut",
+    };
+    let name = format!(
+        "cast_{}_to_{}{}",
+        from.get_final_item(),
+        to.get_final_item(),
+        suffix
+    );
+    let name = make_ident(name);
+    QualifiedName::new(from.get_namespace(), name)
+}
diff --git a/engine/src/conversion/analysis/constructor_deps.rs b/engine/src/conversion/analysis/constructor_deps.rs
new file mode 100644
index 0000000..63b6dbe
--- /dev/null
+++ b/engine/src/conversion/analysis/constructor_deps.rs
@@ -0,0 +1,105 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+
+use crate::{
+    conversion::{
+        api::{Api, ApiName, StructDetails, TypeKind},
+        apivec::ApiVec,
+        convert_error::ConvertErrorWithContext,
+        error_reporter::convert_apis,
+    },
+    types::QualifiedName,
+};
+
+use super::fun::{
+    FnAnalysis, FnKind, FnPhase, FnPrePhase2, PodAndConstructorAnalysis, PodAndDepAnalysis,
+    TraitMethodKind,
+};
+
+/// We've now analyzed all functions (including both implicit and explicit
+/// constructors). Decorate each struct with a note of its constructors,
+/// which will later be used as edges in the garbage collection, because
+/// typically any use of a type will require us to call its copy or move
+/// constructor. The same applies to its alloc/free functions.
+pub(crate) fn decorate_types_with_constructor_deps(apis: ApiVec<FnPrePhase2>) -> ApiVec<FnPhase> {
+    let mut constructors_and_allocators_by_type = find_important_constructors(&apis);
+    let mut results = ApiVec::new();
+    convert_apis(
+        apis,
+        &mut results,
+        Api::fun_unchanged,
+        |name, details, pod| {
+            decorate_struct(name, details, pod, &mut constructors_and_allocators_by_type)
+        },
+        Api::enum_unchanged,
+        Api::typedef_unchanged,
+    );
+    results
+}
+
+fn decorate_struct(
+    name: ApiName,
+    details: Box<StructDetails>,
+    fn_struct: PodAndConstructorAnalysis,
+    constructors_and_allocators_by_type: &mut HashMap<QualifiedName, Vec<QualifiedName>>,
+) -> Result<Box<dyn Iterator<Item = Api<FnPhase>>>, ConvertErrorWithContext> {
+    let pod = fn_struct.pod;
+    let is_abstract = matches!(pod.kind, TypeKind::Abstract);
+    let constructor_and_allocator_deps = if is_abstract || pod.is_generic {
+        Vec::new()
+    } else {
+        constructors_and_allocators_by_type
+            .remove(&name.name)
+            .unwrap_or_default()
+    };
+    Ok(Box::new(std::iter::once(Api::Struct {
+        name,
+        details,
+        analysis: PodAndDepAnalysis {
+            pod,
+            constructor_and_allocator_deps,
+            constructors: fn_struct.constructors,
+        },
+    })))
+}
+
+fn find_important_constructors(
+    apis: &ApiVec<FnPrePhase2>,
+) -> HashMap<QualifiedName, Vec<QualifiedName>> {
+    let mut results: HashMap<QualifiedName, Vec<QualifiedName>> = HashMap::new();
+    for api in apis.iter() {
+        if let Api::Function {
+            name,
+            analysis:
+                FnAnalysis {
+                    kind:
+                        FnKind::TraitMethod {
+                            kind:
+                                TraitMethodKind::Alloc
+                                | TraitMethodKind::Dealloc
+                                | TraitMethodKind::CopyConstructor
+                                | TraitMethodKind::MoveConstructor,
+                            impl_for,
+                            ..
+                        },
+                    ignore_reason: Ok(_),
+                    ..
+                },
+            ..
+        } = api
+        {
+            results
+                .entry(impl_for.clone())
+                .or_default()
+                .push(name.name.clone())
+        }
+    }
+    results
+}
diff --git a/engine/src/conversion/analysis/ctypes.rs b/engine/src/conversion/analysis/ctypes.rs
new file mode 100644
index 0000000..b2ce840
--- /dev/null
+++ b/engine/src/conversion/analysis/ctypes.rs
@@ -0,0 +1,36 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+
+use syn::Ident;
+
+use crate::conversion::api::ApiName;
+use crate::conversion::apivec::ApiVec;
+use crate::types::Namespace;
+use crate::{conversion::api::Api, known_types::known_types, types::QualifiedName};
+
+use super::deps::HasDependencies;
+use super::fun::FnPhase;
+
+/// Spot any variable-length C types (e.g. unsigned long)
+/// used in the [Api]s and append those as extra APIs.
+pub(crate) fn append_ctype_information(apis: &mut ApiVec<FnPhase>) {
+    let ctypes: HashMap<Ident, QualifiedName> = apis
+        .iter()
+        .flat_map(|api| api.deps())
+        .filter(|ty| known_types().is_ctype(ty))
+        .map(|ty| (ty.get_final_ident(), ty.clone()))
+        .collect();
+    for (id, typename) in ctypes {
+        apis.push(Api::CType {
+            name: ApiName::new(&Namespace::new(), id),
+            typename,
+        });
+    }
+}
diff --git a/engine/src/conversion/analysis/deps.rs b/engine/src/conversion/analysis/deps.rs
new file mode 100644
index 0000000..7aca96c
--- /dev/null
+++ b/engine/src/conversion/analysis/deps.rs
@@ -0,0 +1,116 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use itertools::Itertools;
+
+use crate::{
+    conversion::api::{Api, TypeKind},
+    types::QualifiedName,
+};
+
+use super::{
+    fun::{FnPhase, FnPrePhase1, PodAndDepAnalysis},
+    pod::PodAnalysis,
+    tdef::TypedefAnalysis,
+};
+
+pub(crate) trait HasDependencies {
+    fn name(&self) -> &QualifiedName;
+    fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_>;
+
+    fn format_deps(&self) -> String {
+        self.deps().join(",")
+    }
+}
+
+impl HasDependencies for Api<FnPrePhase1> {
+    fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_> {
+        match self {
+            Api::Typedef {
+                old_tyname,
+                analysis: TypedefAnalysis { deps, .. },
+                ..
+            } => Box::new(old_tyname.iter().chain(deps.iter())),
+            Api::Struct {
+                analysis:
+                    PodAnalysis {
+                        kind: TypeKind::Pod,
+                        bases,
+                        field_deps,
+                        ..
+                    },
+                ..
+            } => Box::new(field_deps.iter().chain(bases.iter())),
+            Api::Function { analysis, .. } => Box::new(analysis.deps.iter()),
+            Api::Subclass {
+                name: _,
+                superclass,
+            } => Box::new(std::iter::once(superclass)),
+            Api::RustSubclassFn { details, .. } => Box::new(details.dependencies.iter()),
+            Api::RustFn { receiver, .. } => Box::new(receiver.iter()),
+            _ => Box::new(std::iter::empty()),
+        }
+    }
+
+    fn name(&self) -> &QualifiedName {
+        self.name()
+    }
+}
+
+impl HasDependencies for Api<FnPhase> {
+    /// Any dependencies on other APIs which this API has.
+    fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_> {
+        match self {
+            Api::Typedef {
+                old_tyname,
+                analysis: TypedefAnalysis { deps, .. },
+                ..
+            } => Box::new(old_tyname.iter().chain(deps.iter())),
+            Api::Struct {
+                analysis:
+                    PodAndDepAnalysis {
+                        pod:
+                            PodAnalysis {
+                                kind: TypeKind::Pod,
+                                bases,
+                                field_deps,
+                                ..
+                            },
+                        constructor_and_allocator_deps,
+                        ..
+                    },
+                ..
+            } => Box::new(
+                field_deps
+                    .iter()
+                    .chain(bases.iter())
+                    .chain(constructor_and_allocator_deps.iter()),
+            ),
+            Api::Struct {
+                analysis:
+                    PodAndDepAnalysis {
+                        constructor_and_allocator_deps,
+                        ..
+                    },
+                ..
+            } => Box::new(constructor_and_allocator_deps.iter()),
+            Api::Function { analysis, .. } => Box::new(analysis.deps.iter()),
+            Api::Subclass {
+                name: _,
+                superclass,
+            } => Box::new(std::iter::once(superclass)),
+            Api::RustSubclassFn { details, .. } => Box::new(details.dependencies.iter()),
+            Api::RustFn { receiver, .. } => Box::new(receiver.iter()),
+            _ => Box::new(std::iter::empty()),
+        }
+    }
+
+    fn name(&self) -> &QualifiedName {
+        self.name()
+    }
+}
diff --git a/engine/src/conversion/analysis/depth_first.rs b/engine/src/conversion/analysis/depth_first.rs
new file mode 100644
index 0000000..02459e1
--- /dev/null
+++ b/engine/src/conversion/analysis/depth_first.rs
@@ -0,0 +1,98 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::set::IndexSet as HashSet;
+use std::collections::VecDeque;
+use std::fmt::Debug;
+
+use itertools::Itertools;
+
+use crate::types::QualifiedName;
+
+use super::deps::HasDependencies;
+
+/// Return APIs in a depth-first order, i.e. those with no dependencies first.
+pub(super) fn depth_first<'a, T: HasDependencies + Debug + 'a>(
+    inputs: impl Iterator<Item = &'a T> + 'a,
+) -> impl Iterator<Item = &'a T> {
+    let queue: VecDeque<_> = inputs.collect();
+    let yet_to_do = queue.iter().map(|api| api.name()).collect();
+    DepthFirstIter { queue, yet_to_do }
+}
+
+struct DepthFirstIter<'a, T: HasDependencies + Debug> {
+    queue: VecDeque<&'a T>,
+    yet_to_do: HashSet<&'a QualifiedName>,
+}
+
+impl<'a, T: HasDependencies + Debug> Iterator for DepthFirstIter<'a, T> {
+    type Item = &'a T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let first_candidate = self.queue.get(0).map(|api| api.name());
+        while let Some(candidate) = self.queue.pop_front() {
+            if !candidate.deps().any(|d| self.yet_to_do.contains(&d)) {
+                self.yet_to_do.remove(candidate.name());
+                return Some(candidate);
+            }
+            self.queue.push_back(candidate);
+            if self.queue.get(0).map(|api| api.name()) == first_candidate {
+                panic!(
+                    "Failed to find a candidate; there must be a circular dependency. Queue is {}",
+                    self.queue
+                        .iter()
+                        .map(|item| format!("{}: {}", item.name(), item.deps().join(",")))
+                        .join("\n")
+                );
+            }
+        }
+        None
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::types::QualifiedName;
+
+    use super::{depth_first, HasDependencies};
+
+    #[derive(Debug)]
+    struct Thing(QualifiedName, Vec<QualifiedName>);
+
+    impl HasDependencies for Thing {
+        fn name(&self) -> &QualifiedName {
+            &self.0
+        }
+
+        fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_> {
+            Box::new(self.1.iter())
+        }
+    }
+
+    #[test]
+    fn test() {
+        let a = Thing(QualifiedName::new_from_cpp_name("a"), vec![]);
+        let b = Thing(
+            QualifiedName::new_from_cpp_name("b"),
+            vec![
+                QualifiedName::new_from_cpp_name("a"),
+                QualifiedName::new_from_cpp_name("c"),
+            ],
+        );
+        let c = Thing(
+            QualifiedName::new_from_cpp_name("c"),
+            vec![QualifiedName::new_from_cpp_name("a")],
+        );
+        let api_list = vec![a, b, c];
+        let mut it = depth_first(api_list.iter());
+        assert_eq!(it.next().unwrap().0, QualifiedName::new_from_cpp_name("a"));
+        assert_eq!(it.next().unwrap().0, QualifiedName::new_from_cpp_name("c"));
+        assert_eq!(it.next().unwrap().0, QualifiedName::new_from_cpp_name("b"));
+        assert!(it.next().is_none());
+    }
+}
diff --git a/engine/src/conversion/analysis/doc_label.rs b/engine/src/conversion/analysis/doc_label.rs
new file mode 100644
index 0000000..767da87
--- /dev/null
+++ b/engine/src/conversion/analysis/doc_label.rs
@@ -0,0 +1,17 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use proc_macro2::Span;
+use syn::{parse_quote, Attribute};
+
+pub(crate) fn make_doc_attrs(label: String) -> Vec<Attribute> {
+    let hexathorpe = syn::token::Pound(Span::call_site());
+    vec![parse_quote! {
+        #hexathorpe [doc = #label]
+    }]
+}
diff --git a/engine/src/conversion/analysis/fun/bridge_name_tracker.rs b/engine/src/conversion/analysis/fun/bridge_name_tracker.rs
new file mode 100644
index 0000000..7e81c59
--- /dev/null
+++ b/engine/src/conversion/analysis/fun/bridge_name_tracker.rs
@@ -0,0 +1,158 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::types::Namespace;
+use itertools::Itertools;
+use std::collections::HashMap;
+
+/// Type to generate unique names for entries in the [cxx::bridge]
+/// mod which is flat.
+///
+/// # All about the names involved in autocxx
+///
+/// A given function may have many, many names. From C++ to Rust...
+///
+/// 1. The actual C++ name. Fixed, obviously.
+/// 2. The name reported by bindgen. Not always the same, as
+///    bindgen may generate a different name for different overloads.
+///    See `overload_tracker` for the conversion here.
+/// 3. The name in the cxx::bridge mod. This is a flat namespace,
+///    and it's the responsibility of this type to generate a
+///    suitable name here.
+///    If this is different from the C++ name in (1), we'll
+///    add a #[cxx_name] attribute to the cxx::bridge declaration.
+/// 4. The name we wish to present to Rust users. Again, we have
+///    to take stock of the fact Rust doesn't support overloading
+///    so two different functions called 'get' may end up being
+///    'get' and 'get1'. Yet, this may not be the same as the
+///    bindgen name in (2) because we wish to generate such number
+///    sequences on a per-type basis, whilst bindgen does it globally.
+///
+/// This fourth name, the final Rust user name, may be finagled
+/// into place in three different ways:
+/// 1. For methods, we generate an 'impl' block where the
+///    method name is the intended name, but it calls the
+///    cxxbridge name.
+/// 2. For simple functions, we use the #[rust_name] attribute.
+/// 3. Occasionally, there can be conflicts in the rust_name
+///    namespace (if there are two identically named functions
+///    in different C++ namespaces). That's detected by
+///    rust_name_tracker.rs. In such a case, we'll omit the
+///    #[rust_name] attribute and instead generate a 'use A = B;'
+///    declaration in the mod which we generate for the output
+///    namespace.
+#[derive(Default)]
+pub(crate) struct BridgeNameTracker {
+    next_cxx_bridge_name_for_prefix: HashMap<String, usize>,
+}
+
+impl BridgeNameTracker {
+    pub(crate) fn new() -> Self {
+        Self::default()
+    }
+
+    /// Figure out the least confusing unique name for this function in the
+    /// cxx::bridge section, which has a flat namespace.
+    /// We mostly just qualify the name with the namespace_with_underscores.
+    /// It doesn't really matter; we'll rebind these things to
+    /// better Rust-side names so it's really just a matter of how it shows up
+    /// in stack traces and for our own sanity as maintainers of autocxx.
+    /// This may become unnecessary if and when cxx supports hierarchic
+    /// namespace mods.
+    /// There is a slight advantage in using the same name as either the
+    /// Rust or C++ symbols as it reduces the amount of rebinding required
+    /// by means of cxx_name or rust_name attributes. In extreme cases it
+    /// may even allow us to remove whole impl blocks. So we may wish to try
+    /// harder to find better names in future instead of always prepending
+    /// the namespace.
+    pub(crate) fn get_unique_cxx_bridge_name(
+        &mut self,
+        type_name: Option<&str>,
+        found_name: &str,
+        ns: &Namespace,
+    ) -> String {
+        let found_name = if found_name == "new" {
+            "new_autocxx"
+        } else {
+            found_name
+        };
+        let count = self
+            .next_cxx_bridge_name_for_prefix
+            .entry(found_name.to_string())
+            .or_default();
+        if *count == 0 {
+            // Oh, good, we can use this function name as-is.
+            *count += 1;
+            return found_name.to_string();
+        }
+        let prefix = ns
+            .iter()
+            .cloned()
+            .chain(type_name.iter().map(|x| x.to_string()))
+            .chain(std::iter::once(found_name.to_string()))
+            .join("_");
+        let count = self
+            .next_cxx_bridge_name_for_prefix
+            .entry(prefix.clone())
+            .or_default();
+        if *count == 0 {
+            *count += 1;
+            prefix
+        } else {
+            let r = format!("{}_autocxx{}", prefix, count);
+            *count += 1;
+            r
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::types::Namespace;
+
+    use super::BridgeNameTracker;
+
+    #[test]
+    fn test() {
+        let mut bnt = BridgeNameTracker::new();
+        let ns_root = Namespace::new();
+        let ns_a = Namespace::from_user_input("A");
+        let ns_b = Namespace::from_user_input("B");
+        let ns_ab = Namespace::from_user_input("A::B");
+        assert_eq!(bnt.get_unique_cxx_bridge_name(None, "do", &ns_root), "do");
+        assert_eq!(
+            bnt.get_unique_cxx_bridge_name(None, "do", &ns_root),
+            "do_autocxx1"
+        );
+        assert_eq!(bnt.get_unique_cxx_bridge_name(None, "did", &ns_root), "did");
+        assert_eq!(
+            bnt.get_unique_cxx_bridge_name(Some("ty1"), "do", &ns_root),
+            "ty1_do"
+        );
+        assert_eq!(
+            bnt.get_unique_cxx_bridge_name(Some("ty1"), "do", &ns_root),
+            "ty1_do_autocxx1"
+        );
+        assert_eq!(
+            bnt.get_unique_cxx_bridge_name(Some("ty2"), "do", &ns_root),
+            "ty2_do"
+        );
+        assert_eq!(
+            bnt.get_unique_cxx_bridge_name(Some("ty"), "do", &ns_a),
+            "A_ty_do"
+        );
+        assert_eq!(
+            bnt.get_unique_cxx_bridge_name(Some("ty"), "do", &ns_b),
+            "B_ty_do"
+        );
+        assert_eq!(
+            bnt.get_unique_cxx_bridge_name(Some("ty"), "do", &ns_ab),
+            "A_B_ty_do"
+        );
+    }
+}
diff --git a/engine/src/conversion/analysis/fun/function_wrapper.rs b/engine/src/conversion/analysis/fun/function_wrapper.rs
new file mode 100644
index 0000000..f2f6aaa
--- /dev/null
+++ b/engine/src/conversion/analysis/fun/function_wrapper.rs
@@ -0,0 +1,213 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::{
+    conversion::api::SubclassName,
+    types::{Namespace, QualifiedName},
+};
+use syn::{parse_quote, Ident, Type};
+
+#[derive(Clone, Debug)]
+pub(crate) enum CppConversionType {
+    None,
+    Move,
+    FromUniquePtrToValue,
+    FromPtrToValue,
+    FromValueToUniquePtr,
+    FromPtrToMove,
+    /// Ignored in the sense that it isn't passed into the C++ function.
+    IgnoredPlacementPtrParameter,
+    FromReturnValueToPlacementPtr,
+}
+
+impl CppConversionType {
+    /// If we've found a function which does X to its parameter, what
+    /// is the opposite of X? This is used for subclasses where calls
+    /// from Rust to C++ might also involve calls from C++ to Rust.
+    fn inverse(&self) -> Self {
+        match self {
+            CppConversionType::None => CppConversionType::None,
+            CppConversionType::FromUniquePtrToValue | CppConversionType::FromPtrToValue => {
+                CppConversionType::FromValueToUniquePtr
+            }
+            CppConversionType::FromValueToUniquePtr => CppConversionType::FromUniquePtrToValue,
+            _ => panic!("Did not expect to have to invert this conversion"),
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum RustConversionType {
+    None,
+    FromStr,
+    ToBoxedUpHolder(SubclassName),
+    FromPinMaybeUninitToPtr,
+    FromPinMoveRefToPtr,
+    FromTypeToPtr,
+    FromValueParamToPtr,
+    FromPlacementParamToNewReturn,
+    FromRValueParamToPtr,
+}
+
+impl RustConversionType {
+    pub(crate) fn requires_mutability(&self) -> Option<syn::token::Mut> {
+        match self {
+            Self::FromPinMoveRefToPtr => Some(parse_quote! { mut }),
+            _ => None,
+        }
+    }
+}
+
+/// A policy for converting types. Conversion may occur on both the Rust and
+/// C++ side. The most complex example is a C++ function which takes
+/// std::string by value, which might do this:
+/// * Client Rust code: `&str`
+/// * Rust wrapper function: converts `&str` to `UniquePtr<CxxString>`
+/// * cxx::bridge mod: refers to `UniquePtr<CxxString>`
+/// * C++ wrapper function converts `std::unique_ptr<std::string>` to just
+///   `std::string`
+/// * Finally, the actual C++ API receives a `std::string` by value.
+/// The implementation here is distributed across this file, and
+/// `function_wrapper_rs` and `function_wrapper_cpp`.
+#[derive(Clone)]
+pub(crate) struct TypeConversionPolicy {
+    pub(crate) unwrapped_type: Type,
+    pub(crate) cpp_conversion: CppConversionType,
+    pub(crate) rust_conversion: RustConversionType,
+}
+
+impl TypeConversionPolicy {
+    pub(crate) fn new_unconverted(ty: Type) -> Self {
+        TypeConversionPolicy {
+            unwrapped_type: ty,
+            cpp_conversion: CppConversionType::None,
+            rust_conversion: RustConversionType::None,
+        }
+    }
+
+    pub(crate) fn new_to_unique_ptr(ty: Type) -> Self {
+        TypeConversionPolicy {
+            unwrapped_type: ty,
+            cpp_conversion: CppConversionType::FromValueToUniquePtr,
+            rust_conversion: RustConversionType::None,
+        }
+    }
+
+    pub(crate) fn new_for_placement_return(ty: Type) -> Self {
+        TypeConversionPolicy {
+            unwrapped_type: ty,
+            cpp_conversion: CppConversionType::FromReturnValueToPlacementPtr,
+            // Rust conversion is marked as none here, since this policy
+            // will be applied to the return value, and the Rust-side
+            // shenanigans applies to the placement new *parameter*
+            rust_conversion: RustConversionType::None,
+        }
+    }
+
+    pub(crate) fn cpp_work_needed(&self) -> bool {
+        !matches!(self.cpp_conversion, CppConversionType::None)
+    }
+
+    pub(crate) fn unconverted_rust_type(&self) -> Type {
+        match self.cpp_conversion {
+            CppConversionType::FromValueToUniquePtr => self.make_unique_ptr_type(),
+            _ => self.unwrapped_type.clone(),
+        }
+    }
+
+    pub(crate) fn converted_rust_type(&self) -> Type {
+        match self.cpp_conversion {
+            CppConversionType::FromUniquePtrToValue => self.make_unique_ptr_type(),
+            CppConversionType::FromPtrToValue => {
+                let innerty = &self.unwrapped_type;
+                parse_quote! {
+                    *mut #innerty
+                }
+            }
+            _ => self.unwrapped_type.clone(),
+        }
+    }
+
+    fn make_unique_ptr_type(&self) -> Type {
+        let innerty = &self.unwrapped_type;
+        parse_quote! {
+            cxx::UniquePtr < #innerty >
+        }
+    }
+
+    pub(crate) fn rust_work_needed(&self) -> bool {
+        !matches!(self.rust_conversion, RustConversionType::None)
+    }
+
+    /// Subclass support involves calls from Rust -> C++, but
+    /// also from C++ -> Rust. Work out the correct argument conversion
+    /// type for the latter call, when given the former.
+    pub(crate) fn inverse(&self) -> Self {
+        Self {
+            unwrapped_type: self.unwrapped_type.clone(),
+            cpp_conversion: self.cpp_conversion.inverse(),
+            rust_conversion: self.rust_conversion.clone(),
+        }
+    }
+
+    pub(crate) fn bridge_unsafe_needed(&self) -> bool {
+        matches!(
+            self.rust_conversion,
+            RustConversionType::FromValueParamToPtr
+                | RustConversionType::FromRValueParamToPtr
+                | RustConversionType::FromPlacementParamToNewReturn
+        )
+    }
+
+    pub(crate) fn is_placement_parameter(&self) -> bool {
+        matches!(
+            self.cpp_conversion,
+            CppConversionType::IgnoredPlacementPtrParameter
+        )
+    }
+
+    pub(crate) fn populate_return_value(&self) -> bool {
+        !matches!(
+            self.cpp_conversion,
+            CppConversionType::FromReturnValueToPlacementPtr
+        )
+    }
+}
+
+#[derive(Clone)]
+pub(crate) enum CppFunctionBody {
+    FunctionCall(Namespace, Ident),
+    StaticMethodCall(Namespace, Ident, Ident),
+    PlacementNew(Namespace, Ident),
+    ConstructSuperclass(String),
+    Cast,
+    Destructor(Namespace, Ident),
+    AllocUninitialized(QualifiedName),
+    FreeUninitialized(QualifiedName),
+}
+
+#[derive(Clone)]
+pub(crate) enum CppFunctionKind {
+    Function,
+    Method,
+    Constructor,
+    ConstMethod,
+    SynthesizedConstructor,
+}
+
+#[derive(Clone)]
+pub(crate) struct CppFunction {
+    pub(crate) payload: CppFunctionBody,
+    pub(crate) wrapper_function_name: Ident,
+    pub(crate) original_cpp_name: String,
+    pub(crate) return_conversion: Option<TypeConversionPolicy>,
+    pub(crate) argument_conversion: Vec<TypeConversionPolicy>,
+    pub(crate) kind: CppFunctionKind,
+    pub(crate) pass_obs_field: bool,
+    pub(crate) qualification: Option<QualifiedName>,
+}
diff --git a/engine/src/conversion/analysis/fun/implicit_constructors.rs b/engine/src/conversion/analysis/fun/implicit_constructors.rs
new file mode 100644
index 0000000..469ed89
--- /dev/null
+++ b/engine/src/conversion/analysis/fun/implicit_constructors.rs
@@ -0,0 +1,695 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+use indexmap::{map::Entry, set::IndexSet as HashSet};
+
+use syn::{Type, TypeArray};
+
+use crate::{
+    conversion::{
+        analysis::{depth_first::depth_first, pod::PodAnalysis, type_converter::TypeKind},
+        api::{Api, ApiName, CppVisibility, FuncToConvert, SpecialMemberKind},
+        apivec::ApiVec,
+        convert_error::ConvertErrorWithContext,
+        ConvertError,
+    },
+    known_types::{known_types, KnownTypeConstructorDetails},
+    types::QualifiedName,
+};
+
+use super::{FnAnalysis, FnKind, FnPrePhase1, MethodKind, ReceiverMutability, TraitMethodKind};
+
+/// Indicates what we found out about a category of special member function.
+///
+/// In the end, we only care whether it's public and exists, but we track a bit more information to
+/// support determining the information for dependent classes.
+#[derive(Debug, Copy, Clone)]
+pub(super) enum SpecialMemberFound {
+    /// This covers being deleted in any way:
+    ///   * Explicitly deleted
+    ///   * Implicitly defaulted when that means being deleted
+    ///   * Explicitly defaulted when that means being deleted
+    ///
+    /// It also covers not being either user declared or implicitly defaulted.
+    NotPresent,
+    /// Implicit special member functions, indicated by this, are always public.
+    Implicit,
+    /// This covers being explicitly defaulted (when that is not deleted) or being user-defined.
+    Explicit(CppVisibility),
+}
+
+impl SpecialMemberFound {
+    /// Returns whether code outside of subclasses can call this special member function.
+    pub fn callable_any(&self) -> bool {
+        matches!(self, Self::Explicit(CppVisibility::Public) | Self::Implicit)
+    }
+
+    /// Returns whether code in a subclass can call this special member function.
+    pub fn callable_subclass(&self) -> bool {
+        matches!(
+            self,
+            Self::Explicit(CppVisibility::Public)
+                | Self::Explicit(CppVisibility::Protected)
+                | Self::Implicit
+        )
+    }
+
+    /// Returns whether this exists at all. Note that this will return true even if it's private,
+    /// which is generally not very useful, but does come into play for some rules around which
+    /// default special member functions are deleted vs don't exist.
+    pub fn exists(&self) -> bool {
+        matches!(self, Self::Explicit(_) | Self::Implicit)
+    }
+
+    pub fn exists_implicit(&self) -> bool {
+        matches!(self, Self::Implicit)
+    }
+
+    pub fn exists_explicit(&self) -> bool {
+        matches!(self, Self::Explicit(_))
+    }
+}
+
+/// Information about which special member functions exist based on the C++ rules.
+///
+/// Not all of this information is used directly, but we need to track it to determine the
+/// information we do need for classes which are used as members or base classes.
+#[derive(Debug, Clone)]
+pub(super) struct ItemsFound {
+    pub(super) default_constructor: SpecialMemberFound,
+    pub(super) destructor: SpecialMemberFound,
+    pub(super) const_copy_constructor: SpecialMemberFound,
+    /// Remember that [`const_copy_constructor`] may be used in place of this if it exists.
+    pub(super) non_const_copy_constructor: SpecialMemberFound,
+    pub(super) move_constructor: SpecialMemberFound,
+
+    /// The full name of the type. We identify instances by [`QualifiedName`], because that's
+    /// the only thing which [`FnKind::Method`] has to tie it to, and that's unique enough for
+    /// identification.  However, when generating functions for implicit special members, we need
+    /// the extra information here.
+    ///
+    /// Will always be `Some` if any of the other fields are [`SpecialMemberFound::Implict`],
+    /// otherwise optional.
+    pub(super) name: Option<ApiName>,
+}
+
+impl ItemsFound {
+    /// Returns whether we should generate a default constructor wrapper, because bindgen won't do
+    /// one for the implicit default constructor which exists.
+    pub(super) fn implicit_default_constructor_needed(&self) -> bool {
+        self.default_constructor.exists_implicit()
+    }
+
+    /// Returns whether we should generate a copy constructor wrapper, because bindgen won't do one
+    /// for the implicit copy constructor which exists.
+    pub(super) fn implicit_copy_constructor_needed(&self) -> bool {
+        let any_implicit_copy = self.const_copy_constructor.exists_implicit()
+            || self.non_const_copy_constructor.exists_implicit();
+        let no_explicit_copy = !(self.const_copy_constructor.exists_explicit()
+            || self.non_const_copy_constructor.exists_explicit());
+        any_implicit_copy && no_explicit_copy
+    }
+
+    /// Returns whether we should generate a move constructor wrapper, because bindgen won't do one
+    /// for the implicit move constructor which exists.
+    pub(super) fn implicit_move_constructor_needed(&self) -> bool {
+        self.move_constructor.exists_implicit()
+    }
+
+    /// Returns whether we should generate a destructor wrapper, because bindgen won't do one for
+    /// the implicit destructor which exists.
+    pub(super) fn implicit_destructor_needed(&self) -> bool {
+        self.destructor.exists_implicit()
+    }
+}
+#[derive(Hash, Eq, PartialEq)]
+enum ExplicitKind {
+    DefaultConstructor,
+    ConstCopyConstructor,
+    NonConstCopyConstructor,
+    MoveConstructor,
+    OtherConstructor,
+    Destructor,
+    ConstCopyAssignmentOperator,
+    NonConstCopyAssignmentOperator,
+    MoveAssignmentOperator,
+}
+
+/// Denotes a specific kind of explicit member function that we found.
+#[derive(Hash, Eq, PartialEq)]
+struct ExplicitType {
+    ty: QualifiedName,
+    kind: ExplicitKind,
+}
+
+/// Includes information about an explicit special member function which was found.
+// TODO: Add Defaulted(CppVisibility) for https://github.com/google/autocxx/issues/815.
+#[derive(Copy, Clone, Debug)]
+enum ExplicitFound {
+    UserDefined(CppVisibility),
+    /// Note that this always means explicitly deleted, because this enum only represents
+    /// explicit declarations.
+    Deleted,
+    /// Indicates that we found more than one explicit of this kind. This is possible with most of
+    /// them, and we just bail and mostly act as if they're deleted. We'd have to decide whether
+    /// they're ambiguous to use them, which is really complicated.
+    Multiple,
+}
+
+/// Analyzes which constructors are present for each type.
+///
+/// If a type has explicit constructors, bindgen will generate corresponding
+/// constructor functions, which we'll have already converted to make_unique methods.
+/// For types with implicit constructors, we enumerate them here.
+///
+/// It is tempting to make this a separate analysis phase, to be run later than
+/// the function analysis; but that would make the code much more complex as it
+/// would need to output a `FnAnalysisBody`. By running it as part of this phase
+/// we can simply generate the sort of thing bindgen generates, then ask
+/// the existing code in this phase to figure out what to do with it.
+pub(super) fn find_constructors_present(
+    apis: &ApiVec<FnPrePhase1>,
+) -> HashMap<QualifiedName, ItemsFound> {
+    let (explicits, unknown_types) = find_explicit_items(apis);
+
+    // These contain all the classes we've seen so far with the relevant properties on their
+    // constructors of each kind. We iterate via [`depth_first`], so analyzing later classes
+    // just needs to check these.
+    //
+    // Important only to ask for a depth-first analysis of structs, because
+    // when all APIs are considered there may be reference loops and that would
+    // panic.
+    //
+    // These analyses include all bases and members of each class.
+    let mut all_items_found: HashMap<QualifiedName, ItemsFound> = HashMap::new();
+
+    for api in depth_first(apis.iter()) {
+        if let Api::Struct {
+            name,
+            analysis:
+                PodAnalysis {
+                    bases,
+                    field_info,
+                    is_generic: false,
+                    in_anonymous_namespace: false,
+                    ..
+                },
+            details,
+            ..
+        } = api
+        {
+            let find_explicit = |kind: ExplicitKind| -> Option<&ExplicitFound> {
+                explicits.get(&ExplicitType {
+                    ty: name.name.clone(),
+                    kind,
+                })
+            };
+            let get_items_found = |qn: &QualifiedName| -> Option<ItemsFound> {
+                if let Some(constructor_details) = known_types().get_constructor_details(qn) {
+                    Some(known_type_items_found(constructor_details))
+                } else {
+                    all_items_found.get(qn).cloned()
+                }
+            };
+            let bases_items_found: Vec<_> = bases.iter().map_while(get_items_found).collect();
+            let fields_items_found: Vec<_> = field_info
+                .iter()
+                .filter_map(|field_info| match field_info.type_kind {
+                    TypeKind::Regular | TypeKind::SubclassHolder(_) => match field_info.ty {
+                        Type::Path(ref qn) => get_items_found(&QualifiedName::from_type_path(qn)),
+                        Type::Array(TypeArray { ref elem, .. }) => match elem.as_ref() {
+                            Type::Path(ref qn) => {
+                                get_items_found(&QualifiedName::from_type_path(qn))
+                            }
+                            _ => None,
+                        },
+                        _ => None,
+                    },
+                    // TODO: https://github.com/google/autocxx/issues/865 Figure out how to
+                    // differentiate between pointers and references coming from C++. Pointers
+                    // have a default constructor.
+                    TypeKind::Pointer
+                    | TypeKind::Reference
+                    | TypeKind::MutableReference
+                    | TypeKind::RValueReference => Some(ItemsFound {
+                        default_constructor: SpecialMemberFound::NotPresent,
+                        destructor: SpecialMemberFound::Implicit,
+                        const_copy_constructor: SpecialMemberFound::Implicit,
+                        non_const_copy_constructor: SpecialMemberFound::NotPresent,
+                        move_constructor: SpecialMemberFound::Implicit,
+                        name: Some(name.clone()),
+                    }),
+                })
+                .collect();
+            let has_rvalue_reference_fields = details.has_rvalue_reference_fields;
+
+            // Check that all the bases and field types are known first. This combined with
+            // iterating via [`depth_first`] means we can safely search in `items_found` for all of
+            // them.
+            //
+            // Conservatively, we will not acknowledge the existence of most defaulted or implicit
+            // special member functions for any struct/class where we don't fully understand all
+            // field types.  However, we can still look for explictly declared versions and use
+            // those. See below for destructors.
+            //
+            // We need to extend our knowledge to understand the constructor behavior of things in
+            // known_types.rs, then we'll be able to cope with types which contain strings,
+            // unique_ptrs etc.
+            let items_found = if bases_items_found.len() != bases.len()
+                || fields_items_found.len() != field_info.len()
+                || unknown_types.contains(&name.name)
+            {
+                let is_explicit = |kind: ExplicitKind| -> SpecialMemberFound {
+                    // TODO: For https://github.com/google/autocxx/issues/815, map
+                    // ExplicitFound::Defaulted(_) to NotPresent.
+                    match find_explicit(kind) {
+                        None => SpecialMemberFound::NotPresent,
+                        Some(ExplicitFound::Deleted | ExplicitFound::Multiple) => {
+                            SpecialMemberFound::NotPresent
+                        }
+                        Some(ExplicitFound::UserDefined(visibility)) => {
+                            SpecialMemberFound::Explicit(*visibility)
+                        }
+                    }
+                };
+                let items_found = ItemsFound {
+                    default_constructor: is_explicit(ExplicitKind::DefaultConstructor),
+                    destructor: match find_explicit(ExplicitKind::Destructor) {
+                        // Assume that unknown types have destructors. This is common, and allows
+                        // use to generate UniquePtr wrappers with them.
+                        //
+                        // However, this will generate C++ code that doesn't compile if the unknown
+                        // type does not have an accessible destructor. Maybe we should have a way
+                        // to disable that?
+                        //
+                        // TODO: For https://github.com/google/autocxx/issues/815, map
+                        // ExplicitFound::Defaulted(_) to Explicit.
+                        None => SpecialMemberFound::Implicit,
+                        // If there are multiple destructors, assume that one of them will be
+                        // selected by overload resolution.
+                        Some(ExplicitFound::Multiple) => {
+                            SpecialMemberFound::Explicit(CppVisibility::Public)
+                        }
+                        Some(ExplicitFound::Deleted) => SpecialMemberFound::NotPresent,
+                        Some(ExplicitFound::UserDefined(visibility)) => {
+                            SpecialMemberFound::Explicit(*visibility)
+                        }
+                    },
+                    const_copy_constructor: is_explicit(ExplicitKind::ConstCopyConstructor),
+                    non_const_copy_constructor: is_explicit(ExplicitKind::NonConstCopyConstructor),
+                    move_constructor: is_explicit(ExplicitKind::MoveConstructor),
+                    name: Some(name.clone()),
+                };
+                log::info!(
+                    "Special member functions (explicits only) found for {:?}: {:?}",
+                    name,
+                    items_found
+                );
+                items_found
+            } else {
+                // If no user-declared constructors of any kind are provided for a class type (struct, class, or union),
+                // the compiler will always declare a default constructor as an inline public member of its class.
+                //
+                // The implicitly-declared or defaulted default constructor for class T is defined as deleted if any of the following is true:
+                // T has a member of reference type without a default initializer.
+                // T has a non-const-default-constructible const member without a default member initializer.
+                // T has a member (without a default member initializer) which has a deleted default constructor, or its default constructor is ambiguous or inaccessible from this constructor.
+                // T has a direct or virtual base which has a deleted default constructor, or it is ambiguous or inaccessible from this constructor.
+                // T has a direct or virtual base or a non-static data member which has a deleted destructor, or a destructor that is inaccessible from this constructor.
+                // T is a union with at least one variant member with non-trivial default constructor, and no variant member of T has a default member initializer. // we don't support unions anyway
+                // T is a non-union class with a variant member M with a non-trivial default constructor, and no variant member of the anonymous union containing M has a default member initializer.
+                // T is a union and all of its variant members are const. // we don't support unions anyway
+                //
+                // Variant members are the members of anonymous unions.
+                let default_constructor = {
+                    let explicit = find_explicit(ExplicitKind::DefaultConstructor);
+                    // TODO: For https://github.com/google/autocxx/issues/815, replace the first term with:
+                    //   explicit.map_or(true, |explicit_found| matches!(explicit_found, ExplicitFound::Defaulted(_)))
+                    let have_defaulted = explicit.is_none()
+                        && !explicits.iter().any(|(ExplicitType { ty, kind }, _)| {
+                            ty == &name.name
+                                && match *kind {
+                                    ExplicitKind::DefaultConstructor => false,
+                                    ExplicitKind::ConstCopyConstructor => true,
+                                    ExplicitKind::NonConstCopyConstructor => true,
+                                    ExplicitKind::MoveConstructor => true,
+                                    ExplicitKind::OtherConstructor => true,
+                                    ExplicitKind::Destructor => false,
+                                    ExplicitKind::ConstCopyAssignmentOperator => false,
+                                    ExplicitKind::NonConstCopyAssignmentOperator => false,
+                                    ExplicitKind::MoveAssignmentOperator => false,
+                                }
+                        });
+                    if have_defaulted {
+                        let bases_allow = bases_items_found.iter().all(|items_found| {
+                            items_found.destructor.callable_subclass()
+                                && items_found.default_constructor.callable_subclass()
+                        });
+                        // TODO: Allow member initializers for
+                        // https://github.com/google/autocxx/issues/816.
+                        let members_allow = fields_items_found.iter().all(|items_found| {
+                            items_found.destructor.callable_any()
+                                && items_found.default_constructor.callable_any()
+                        });
+                        if !has_rvalue_reference_fields && bases_allow && members_allow {
+                            // TODO: For https://github.com/google/autocxx/issues/815, grab the
+                            // visibility from an explicit default if present.
+                            SpecialMemberFound::Implicit
+                        } else {
+                            SpecialMemberFound::NotPresent
+                        }
+                    } else if let Some(ExplicitFound::UserDefined(visibility)) = explicit {
+                        SpecialMemberFound::Explicit(*visibility)
+                    } else {
+                        SpecialMemberFound::NotPresent
+                    }
+                };
+
+                // If no user-declared prospective destructor is provided for a class type (struct, class, or union), the compiler will always declare a destructor as an inline public member of its class.
+                //
+                // The implicitly-declared or explicitly defaulted destructor for class T is defined as deleted if any of the following is true:
+                // T has a non-static data member that cannot be destructed (has deleted or inaccessible destructor)
+                // T has direct or virtual base class that cannot be destructed (has deleted or inaccessible destructors)
+                // T is a union and has a variant member with non-trivial destructor. // we don't support unions anyway
+                // The implicitly-declared destructor is virtual (because the base class has a virtual destructor) and the lookup for the deallocation function (operator delete()) results in a call to ambiguous, deleted, or inaccessible function.
+                let destructor = {
+                    let explicit = find_explicit(ExplicitKind::Destructor);
+                    // TODO: For https://github.com/google/autocxx/issues/815, replace the condition with:
+                    //   explicit.map_or(true, |explicit_found| matches!(explicit_found, ExplicitFound::Defaulted(_)))
+                    if explicit.is_none() {
+                        let bases_allow = bases_items_found
+                            .iter()
+                            .all(|items_found| items_found.destructor.callable_subclass());
+                        let members_allow = fields_items_found
+                            .iter()
+                            .all(|items_found| items_found.destructor.callable_any());
+                        if bases_allow && members_allow {
+                            // TODO: For https://github.com/google/autocxx/issues/815, grab the
+                            // visibility from an explicit default if present.
+                            SpecialMemberFound::Implicit
+                        } else {
+                            SpecialMemberFound::NotPresent
+                        }
+                    } else if let Some(ExplicitFound::UserDefined(visibility)) = explicit {
+                        SpecialMemberFound::Explicit(*visibility)
+                    } else {
+                        SpecialMemberFound::NotPresent
+                    }
+                };
+
+                // If no user-defined copy constructors are provided for a class type (struct, class, or union),
+                // the compiler will always declare a copy constructor as a non-explicit inline public member of its class.
+                // This implicitly-declared copy constructor has the form T::T(const T&) if all of the following are true:
+                //  each direct and virtual base B of T has a copy constructor whose parameters are const B& or const volatile B&;
+                //  each non-static data member M of T of class type or array of class type has a copy constructor whose parameters are const M& or const volatile M&.
+                //
+                // The implicitly-declared or defaulted copy constructor for class T is defined as deleted if any of the following conditions are true:
+                // T is a union-like class and has a variant member with non-trivial copy constructor; // we don't support unions anyway
+                // T has a user-defined move constructor or move assignment operator (this condition only causes the implicitly-declared, not the defaulted, copy constructor to be deleted).
+                // T has non-static data members that cannot be copied (have deleted, inaccessible, or ambiguous copy constructors);
+                // T has direct or virtual base class that cannot be copied (has deleted, inaccessible, or ambiguous copy constructors);
+                // T has direct or virtual base class or a non-static data member with a deleted or inaccessible destructor;
+                // T has a data member of rvalue reference type;
+                let (const_copy_constructor, non_const_copy_constructor) = {
+                    let explicit_const = find_explicit(ExplicitKind::ConstCopyConstructor);
+                    let explicit_non_const = find_explicit(ExplicitKind::NonConstCopyConstructor);
+                    let explicit_move = find_explicit(ExplicitKind::MoveConstructor);
+
+                    // TODO: For https://github.com/google/autocxx/issues/815, replace both terms with something like:
+                    //   explicit.map_or(true, |explicit_found| matches!(explicit_found, ExplicitFound::Defaulted(_)))
+                    let have_defaulted = explicit_const.is_none() && explicit_non_const.is_none();
+                    if have_defaulted {
+                        // TODO: For https://github.com/google/autocxx/issues/815, ignore this if
+                        // the relevant (based on bases_are_const) copy constructor is explicitly defaulted.
+                        let class_allows = explicit_move.is_none() && !has_rvalue_reference_fields;
+                        let bases_allow = bases_items_found.iter().all(|items_found| {
+                            items_found.destructor.callable_subclass()
+                                && (items_found.const_copy_constructor.callable_subclass()
+                                    || items_found.non_const_copy_constructor.callable_subclass())
+                        });
+                        let members_allow = fields_items_found.iter().all(|items_found| {
+                            items_found.destructor.callable_any()
+                                && (items_found.const_copy_constructor.callable_any()
+                                    || items_found.non_const_copy_constructor.callable_any())
+                        });
+                        if class_allows && bases_allow && members_allow {
+                            // TODO: For https://github.com/google/autocxx/issues/815, grab the
+                            // visibility and existence of const and non-const from an explicit default if present.
+                            let dependencies_are_const = bases_items_found
+                                .iter()
+                                .chain(fields_items_found.iter())
+                                .all(|items_found| items_found.const_copy_constructor.exists());
+                            if dependencies_are_const {
+                                (SpecialMemberFound::Implicit, SpecialMemberFound::NotPresent)
+                            } else {
+                                (SpecialMemberFound::NotPresent, SpecialMemberFound::Implicit)
+                            }
+                        } else {
+                            (
+                                SpecialMemberFound::NotPresent,
+                                SpecialMemberFound::NotPresent,
+                            )
+                        }
+                    } else {
+                        (
+                            if let Some(ExplicitFound::UserDefined(visibility)) = explicit_const {
+                                SpecialMemberFound::Explicit(*visibility)
+                            } else {
+                                SpecialMemberFound::NotPresent
+                            },
+                            if let Some(ExplicitFound::UserDefined(visibility)) = explicit_non_const
+                            {
+                                SpecialMemberFound::Explicit(*visibility)
+                            } else {
+                                SpecialMemberFound::NotPresent
+                            },
+                        )
+                    }
+                };
+
+                // If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:
+                // there are no user-declared copy constructors;
+                // there are no user-declared copy assignment operators;
+                // there are no user-declared move assignment operators;
+                // there is no user-declared destructor.
+                // then the compiler will declare a move constructor as a non-explicit inline public member of its class with the signature T::T(T&&).
+                //
+                // A class can have multiple move constructors, e.g. both T::T(const T&&) and T::T(T&&). If some user-defined move constructors are present, the user may still force the generation of the implicitly declared move constructor with the keyword default.
+                //
+                // The implicitly-declared or defaulted move constructor for class T is defined as deleted if any of the following is true:
+                // T has non-static data members that cannot be moved (have deleted, inaccessible, or ambiguous move constructors);
+                // T has direct or virtual base class that cannot be moved (has deleted, inaccessible, or ambiguous move constructors);
+                // T has direct or virtual base class with a deleted or inaccessible destructor;
+                // T is a union-like class and has a variant member with non-trivial move constructor. // we don't support unions anyway
+                let move_constructor = {
+                    let explicit = find_explicit(ExplicitKind::MoveConstructor);
+                    // TODO: For https://github.com/google/autocxx/issues/815, replace relevant terms with something like:
+                    //   explicit.map_or(true, |explicit_found| matches!(explicit_found, ExplicitFound::Defaulted(_)))
+                    let have_defaulted = !(explicit.is_some()
+                        || find_explicit(ExplicitKind::ConstCopyConstructor).is_some()
+                        || find_explicit(ExplicitKind::NonConstCopyConstructor).is_some()
+                        || find_explicit(ExplicitKind::ConstCopyAssignmentOperator).is_some()
+                        || find_explicit(ExplicitKind::NonConstCopyAssignmentOperator).is_some()
+                        || find_explicit(ExplicitKind::MoveAssignmentOperator).is_some()
+                        || find_explicit(ExplicitKind::Destructor).is_some());
+                    if have_defaulted {
+                        let bases_allow = bases_items_found.iter().all(|items_found| {
+                            items_found.destructor.callable_subclass()
+                                && items_found.move_constructor.callable_subclass()
+                        });
+                        let members_allow = fields_items_found
+                            .iter()
+                            .all(|items_found| items_found.move_constructor.callable_any());
+                        if bases_allow && members_allow {
+                            // TODO: For https://github.com/google/autocxx/issues/815, grab the
+                            // visibility from an explicit default if present.
+                            SpecialMemberFound::Implicit
+                        } else {
+                            SpecialMemberFound::NotPresent
+                        }
+                    } else if let Some(ExplicitFound::UserDefined(visibility)) = explicit {
+                        SpecialMemberFound::Explicit(*visibility)
+                    } else {
+                        SpecialMemberFound::NotPresent
+                    }
+                };
+
+                let items_found = ItemsFound {
+                    default_constructor,
+                    destructor,
+                    const_copy_constructor,
+                    non_const_copy_constructor,
+                    move_constructor,
+                    name: Some(name.clone()),
+                };
+                log::info!(
+                    "Special member items found for {:?}: {:?}",
+                    name,
+                    items_found
+                );
+                items_found
+            };
+            assert!(
+                all_items_found
+                    .insert(name.name.clone(), items_found)
+                    .is_none(),
+                "Duplicate struct: {:?}",
+                name
+            );
+        }
+    }
+
+    all_items_found
+}
+
+fn find_explicit_items(
+    apis: &ApiVec<FnPrePhase1>,
+) -> (HashMap<ExplicitType, ExplicitFound>, HashSet<QualifiedName>) {
+    let mut result = HashMap::new();
+    let mut merge_fun = |ty: QualifiedName, kind: ExplicitKind, fun: &FuncToConvert| match result
+        .entry(ExplicitType { ty, kind })
+    {
+        Entry::Vacant(entry) => {
+            entry.insert(if fun.is_deleted {
+                ExplicitFound::Deleted
+            } else {
+                ExplicitFound::UserDefined(fun.cpp_vis)
+            });
+        }
+        Entry::Occupied(mut entry) => {
+            entry.insert(ExplicitFound::Multiple);
+        }
+    };
+    let mut unknown_types = HashSet::new();
+    for api in apis.iter() {
+        match api {
+            Api::Function {
+                analysis:
+                    FnAnalysis {
+                        kind: FnKind::Method { impl_for, .. },
+                        param_details,
+                        ignore_reason:
+                            Ok(()) | Err(ConvertErrorWithContext(ConvertError::AssignmentOperator, _)),
+                        ..
+                    },
+                fun,
+                ..
+            } if matches!(
+                fun.special_member,
+                Some(SpecialMemberKind::AssignmentOperator)
+            ) =>
+            {
+                let is_move_assignment_operator = !fun.references.rvalue_ref_params.is_empty();
+                merge_fun(
+                    impl_for.clone(),
+                    if is_move_assignment_operator {
+                        ExplicitKind::MoveAssignmentOperator
+                    } else {
+                        let receiver_mutability = &param_details
+                            .iter()
+                            .next()
+                            .unwrap()
+                            .self_type
+                            .as_ref()
+                            .unwrap()
+                            .1;
+                        match receiver_mutability {
+                            ReceiverMutability::Const => ExplicitKind::ConstCopyAssignmentOperator,
+                            ReceiverMutability::Mutable => {
+                                ExplicitKind::NonConstCopyAssignmentOperator
+                            }
+                        }
+                    },
+                    fun,
+                )
+            }
+            Api::Function {
+                analysis:
+                    FnAnalysis {
+                        kind: FnKind::Method { impl_for, .. },
+                        ..
+                    },
+                fun,
+                ..
+            } if matches!(
+                fun.special_member,
+                Some(SpecialMemberKind::AssignmentOperator)
+            ) =>
+            {
+                unknown_types.insert(impl_for.clone());
+            }
+            Api::Function {
+                analysis:
+                    FnAnalysis {
+                        kind:
+                            FnKind::Method {
+                                impl_for,
+                                method_kind,
+                                ..
+                            },
+                        ..
+                    },
+                fun,
+                ..
+            } => match method_kind {
+                MethodKind::Constructor { is_default: true } => {
+                    Some(ExplicitKind::DefaultConstructor)
+                }
+                MethodKind::Constructor { is_default: false } => {
+                    Some(ExplicitKind::OtherConstructor)
+                }
+                _ => None,
+            }
+            .map_or((), |explicit_kind| {
+                merge_fun(impl_for.clone(), explicit_kind, fun)
+            }),
+            Api::Function {
+                analysis:
+                    FnAnalysis {
+                        kind: FnKind::TraitMethod { impl_for, kind, .. },
+                        ..
+                    },
+                fun,
+                ..
+            } => match kind {
+                TraitMethodKind::Destructor => Some(ExplicitKind::Destructor),
+                // In `analyze_foreign_fn` we mark non-const copy constructors as not being copy
+                // constructors for now, so we don't have to worry about them.
+                TraitMethodKind::CopyConstructor => Some(ExplicitKind::ConstCopyConstructor),
+                TraitMethodKind::MoveConstructor => Some(ExplicitKind::MoveConstructor),
+                _ => None,
+            }
+            .map_or((), |explicit_kind| {
+                merge_fun(impl_for.clone(), explicit_kind, fun)
+            }),
+            _ => (),
+        }
+    }
+    (result, unknown_types)
+}
+
+/// Returns the information for a given known type.
+fn known_type_items_found(constructor_details: KnownTypeConstructorDetails) -> ItemsFound {
+    let exists_public = SpecialMemberFound::Explicit(CppVisibility::Public);
+    let exists_public_if = |exists| {
+        if exists {
+            exists_public
+        } else {
+            SpecialMemberFound::NotPresent
+        }
+    };
+    ItemsFound {
+        default_constructor: exists_public,
+        destructor: exists_public,
+        const_copy_constructor: exists_public_if(constructor_details.has_const_copy_constructor),
+        non_const_copy_constructor: SpecialMemberFound::NotPresent,
+        move_constructor: exists_public_if(constructor_details.has_move_constructor),
+        name: None,
+    }
+}
diff --git a/engine/src/conversion/analysis/fun/mod.rs b/engine/src/conversion/analysis/fun/mod.rs
new file mode 100644
index 0000000..19340f9
--- /dev/null
+++ b/engine/src/conversion/analysis/fun/mod.rs
@@ -0,0 +1,2140 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod bridge_name_tracker;
+pub(crate) mod function_wrapper;
+mod implicit_constructors;
+mod overload_tracker;
+mod subclass;
+
+use crate::{
+    conversion::{
+        analysis::{
+            fun::function_wrapper::{CppConversionType, CppFunctionKind},
+            type_converter::{self, add_analysis, TypeConversionContext, TypeConverter},
+        },
+        api::{
+            ApiName, CastMutability, CppVisibility, FuncToConvert, NullPhase, Provenance,
+            References, SpecialMemberKind, SubclassName, TraitImplSignature, TraitSynthesis,
+            UnsafetyNeeded, Virtualness,
+        },
+        apivec::ApiVec,
+        convert_error::ErrorContext,
+        convert_error::{ConvertErrorWithContext, ErrorContextType},
+        error_reporter::{convert_apis, report_any_error},
+    },
+    known_types::known_types,
+    types::validate_ident_ok_for_rust,
+};
+use indexmap::map::IndexMap as HashMap;
+use indexmap::set::IndexSet as HashSet;
+
+use autocxx_parser::{ExternCppType, IncludeCppConfig, UnsafePolicy};
+use function_wrapper::{CppFunction, CppFunctionBody, TypeConversionPolicy};
+use itertools::Itertools;
+use proc_macro2::Span;
+use quote::quote;
+use syn::{
+    parse_quote, punctuated::Punctuated, token::Comma, FnArg, Ident, Pat, ReturnType, Type,
+    TypePtr, Visibility,
+};
+
+use crate::{
+    conversion::{
+        api::{AnalysisPhase, Api, TypeKind},
+        ConvertError,
+    },
+    types::{make_ident, validate_ident_ok_for_cxx, Namespace, QualifiedName},
+};
+
+use self::{
+    bridge_name_tracker::BridgeNameTracker,
+    function_wrapper::RustConversionType,
+    implicit_constructors::{find_constructors_present, ItemsFound},
+    overload_tracker::OverloadTracker,
+    subclass::{
+        create_subclass_constructor, create_subclass_fn_wrapper, create_subclass_function,
+        create_subclass_trait_item,
+    },
+};
+
+use super::{
+    doc_label::make_doc_attrs,
+    pod::{PodAnalysis, PodPhase},
+    tdef::TypedefAnalysis,
+    type_converter::{Annotated, PointerTreatment},
+};
+
+#[derive(Clone, Debug)]
+pub(crate) enum ReceiverMutability {
+    Const,
+    Mutable,
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum MethodKind {
+    Normal(ReceiverMutability),
+    Constructor { is_default: bool },
+    Static,
+    Virtual(ReceiverMutability),
+    PureVirtual(ReceiverMutability),
+}
+
+#[derive(Clone)]
+pub(crate) enum TraitMethodKind {
+    CopyConstructor,
+    MoveConstructor,
+    Cast,
+    Destructor,
+    Alloc,
+    Dealloc,
+}
+
+#[derive(Clone)]
+pub(crate) struct TraitMethodDetails {
+    pub(crate) trt: TraitImplSignature,
+    pub(crate) avoid_self: bool,
+    pub(crate) method_name: Ident,
+    /// For traits, where we're trying to implement a specific existing
+    /// interface, we may need to reorder the parameters to fit that
+    /// interface.
+    pub(crate) parameter_reordering: Option<Vec<usize>>,
+    /// The function we're calling from the trait requires unsafe even
+    /// though the trait and its function aren't.
+    pub(crate) trait_call_is_unsafe: bool,
+}
+
+#[derive(Clone)]
+pub(crate) enum FnKind {
+    Function,
+    Method {
+        method_kind: MethodKind,
+        impl_for: QualifiedName,
+    },
+    TraitMethod {
+        kind: TraitMethodKind,
+        /// The name of the type T for which we're implementing a trait,
+        /// though we may be actually implementing the trait for &mut T or
+        /// similar, so we store more details of both the type and the
+        /// method in `details`
+        impl_for: QualifiedName,
+        details: Box<TraitMethodDetails>,
+    },
+}
+
+/// Strategy for ensuring that the final, callable, Rust name
+/// is what the user originally expected.
+#[derive(Clone)]
+
+pub(crate) enum RustRenameStrategy {
+    /// cxx::bridge name matches user expectations
+    None,
+    /// Even the #[rust_name] attribute would cause conflicts, and we need
+    /// to use a 'use XYZ as ABC'
+    RenameInOutputMod(Ident),
+    /// This function requires us to generate a Rust function to do
+    /// parameter conversion.
+    RenameUsingWrapperFunction,
+}
+
+#[derive(Clone)]
+pub(crate) struct FnAnalysis {
+    /// Each entry in the cxx::bridge needs to have a unique name, even if
+    /// (from the perspective of Rust and C++) things are in different
+    /// namespaces/mods.
+    pub(crate) cxxbridge_name: Ident,
+    /// ... so record also the name under which we wish to expose it in Rust.
+    pub(crate) rust_name: String,
+    pub(crate) rust_rename_strategy: RustRenameStrategy,
+    pub(crate) params: Punctuated<FnArg, Comma>,
+    pub(crate) kind: FnKind,
+    pub(crate) ret_type: ReturnType,
+    pub(crate) param_details: Vec<ArgumentAnalysis>,
+    pub(crate) ret_conversion: Option<TypeConversionPolicy>,
+    pub(crate) requires_unsafe: UnsafetyNeeded,
+    pub(crate) vis: Visibility,
+    pub(crate) cpp_wrapper: Option<CppFunction>,
+    pub(crate) deps: HashSet<QualifiedName>,
+    /// Some methods still need to be recorded because we want
+    /// to (a) generate the ability to call superclasses, (b) create
+    /// subclass entries for them. But we do not want to have them
+    /// be externally callable.
+    pub(crate) ignore_reason: Result<(), ConvertErrorWithContext>,
+    /// Whether this can be called by external code. Not so for
+    /// protected methods.
+    pub(crate) externally_callable: bool,
+    /// Whether we need to generate a Rust-side calling function
+    pub(crate) rust_wrapper_needed: bool,
+}
+
+#[derive(Clone)]
+pub(crate) struct ArgumentAnalysis {
+    pub(crate) conversion: TypeConversionPolicy,
+    pub(crate) name: Pat,
+    pub(crate) self_type: Option<(QualifiedName, ReceiverMutability)>,
+    pub(crate) has_lifetime: bool,
+    pub(crate) deps: HashSet<QualifiedName>,
+    pub(crate) requires_unsafe: UnsafetyNeeded,
+    pub(crate) is_placement_return_destination: bool,
+}
+
+struct ReturnTypeAnalysis {
+    rt: ReturnType,
+    conversion: Option<TypeConversionPolicy>,
+    was_reference: bool,
+    deps: HashSet<QualifiedName>,
+    placement_param_needed: Option<(FnArg, ArgumentAnalysis)>,
+}
+
+impl Default for ReturnTypeAnalysis {
+    fn default() -> Self {
+        Self {
+            rt: parse_quote! {},
+            conversion: None,
+            was_reference: false,
+            deps: Default::default(),
+            placement_param_needed: None,
+        }
+    }
+}
+
+pub(crate) struct PodAndConstructorAnalysis {
+    pub(crate) pod: PodAnalysis,
+    pub(crate) constructors: PublicConstructors,
+}
+
+/// An analysis phase where we've analyzed each function, but
+/// haven't yet determined which constructors/etc. belong to each type.
+pub(crate) struct FnPrePhase1;
+
+impl AnalysisPhase for FnPrePhase1 {
+    type TypedefAnalysis = TypedefAnalysis;
+    type StructAnalysis = PodAnalysis;
+    type FunAnalysis = FnAnalysis;
+}
+
+/// An analysis phase where we've analyzed each function, and identified
+/// what implicit constructors/destructors are present in each type.
+pub(crate) struct FnPrePhase2;
+
+impl AnalysisPhase for FnPrePhase2 {
+    type TypedefAnalysis = TypedefAnalysis;
+    type StructAnalysis = PodAndConstructorAnalysis;
+    type FunAnalysis = FnAnalysis;
+}
+
+pub(crate) struct PodAndDepAnalysis {
+    pub(crate) pod: PodAnalysis,
+    pub(crate) constructor_and_allocator_deps: Vec<QualifiedName>,
+    pub(crate) constructors: PublicConstructors,
+}
+
+/// Analysis phase after we've finished analyzing functions and determined
+/// which constructors etc. belong to them.
+pub(crate) struct FnPhase;
+
+/// Indicates which kinds of public constructors are known to exist for a type.
+#[derive(Debug, Default, Copy, Clone)]
+pub(crate) struct PublicConstructors {
+    pub(crate) move_constructor: bool,
+    pub(crate) destructor: bool,
+}
+
+impl PublicConstructors {
+    fn from_items_found(items_found: &ItemsFound) -> Self {
+        Self {
+            move_constructor: items_found.move_constructor.callable_any(),
+            destructor: items_found.destructor.callable_any(),
+        }
+    }
+}
+
+impl AnalysisPhase for FnPhase {
+    type TypedefAnalysis = TypedefAnalysis;
+    type StructAnalysis = PodAndDepAnalysis;
+    type FunAnalysis = FnAnalysis;
+}
+
+/// Whether to allow highly optimized calls because this is a simple Rust->C++ call,
+/// or to use a simpler set of policies because this is a subclass call where
+/// we may have C++->Rust->C++ etc.
+#[derive(Copy, Clone)]
+enum TypeConversionSophistication {
+    Regular,
+    SimpleForSubclasses,
+}
+
+pub(crate) struct FnAnalyzer<'a> {
+    unsafe_policy: UnsafePolicy,
+    extra_apis: ApiVec<NullPhase>,
+    type_converter: TypeConverter<'a>,
+    bridge_name_tracker: BridgeNameTracker,
+    pod_safe_types: HashSet<QualifiedName>,
+    moveit_safe_types: HashSet<QualifiedName>,
+    config: &'a IncludeCppConfig,
+    overload_trackers_by_mod: HashMap<Namespace, OverloadTracker>,
+    subclasses_by_superclass: HashMap<QualifiedName, Vec<SubclassName>>,
+    nested_type_name_map: HashMap<QualifiedName, String>,
+    generic_types: HashSet<QualifiedName>,
+    types_in_anonymous_namespace: HashSet<QualifiedName>,
+    existing_superclass_trait_api_names: HashSet<QualifiedName>,
+}
+
+impl<'a> FnAnalyzer<'a> {
+    pub(crate) fn analyze_functions(
+        apis: ApiVec<PodPhase>,
+        unsafe_policy: UnsafePolicy,
+        config: &'a IncludeCppConfig,
+    ) -> ApiVec<FnPrePhase2> {
+        let mut me = Self {
+            unsafe_policy,
+            extra_apis: ApiVec::new(),
+            type_converter: TypeConverter::new(config, &apis),
+            bridge_name_tracker: BridgeNameTracker::new(),
+            config,
+            overload_trackers_by_mod: HashMap::new(),
+            pod_safe_types: Self::build_pod_safe_type_set(&apis),
+            moveit_safe_types: Self::build_correctly_sized_type_set(&apis),
+            subclasses_by_superclass: subclass::subclasses_by_superclass(&apis),
+            nested_type_name_map: Self::build_nested_type_map(&apis),
+            generic_types: Self::build_generic_type_set(&apis),
+            existing_superclass_trait_api_names: HashSet::new(),
+            types_in_anonymous_namespace: Self::build_types_in_anonymous_namespace(&apis),
+        };
+        let mut results = ApiVec::new();
+        convert_apis(
+            apis,
+            &mut results,
+            |name, fun, _| me.analyze_foreign_fn_and_subclasses(name, fun),
+            Api::struct_unchanged,
+            Api::enum_unchanged,
+            Api::typedef_unchanged,
+        );
+        let mut results = me.add_constructors_present(results);
+        me.add_subclass_constructors(&mut results);
+        results.extend(me.extra_apis.into_iter().map(add_analysis));
+        results
+    }
+
+    fn build_pod_safe_type_set(apis: &ApiVec<PodPhase>) -> HashSet<QualifiedName> {
+        apis.iter()
+            .filter_map(|api| match api {
+                Api::Struct {
+                    analysis:
+                        PodAnalysis {
+                            kind: TypeKind::Pod,
+                            ..
+                        },
+                    ..
+                } => Some(api.name().clone()),
+                Api::Enum { .. } => Some(api.name().clone()),
+                Api::ExternCppType { pod: true, .. } => Some(api.name().clone()),
+                _ => None,
+            })
+            .chain(
+                known_types()
+                    .get_pod_safe_types()
+                    .filter_map(
+                        |(tn, is_pod_safe)| {
+                            if is_pod_safe {
+                                Some(tn)
+                            } else {
+                                None
+                            }
+                        },
+                    ),
+            )
+            .collect()
+    }
+
+    /// Return the set of 'moveit safe' types. That must include only types where
+    /// the size is known to be correct.
+    fn build_correctly_sized_type_set(apis: &ApiVec<PodPhase>) -> HashSet<QualifiedName> {
+        apis.iter()
+            .filter(|api| {
+                matches!(
+                    api,
+                    Api::Struct { .. }
+                        | Api::Enum { .. }
+                        | Api::ExternCppType {
+                            details: ExternCppType { opaque: false, .. },
+                            ..
+                        }
+                )
+            })
+            .map(|api| api.name().clone())
+            .chain(known_types().get_moveit_safe_types())
+            .collect()
+    }
+
+    fn build_generic_type_set(apis: &ApiVec<PodPhase>) -> HashSet<QualifiedName> {
+        apis.iter()
+            .filter_map(|api| match api {
+                Api::Struct {
+                    analysis:
+                        PodAnalysis {
+                            is_generic: true, ..
+                        },
+                    ..
+                } => Some(api.name().clone()),
+                _ => None,
+            })
+            .collect()
+    }
+
+    fn build_types_in_anonymous_namespace(apis: &ApiVec<PodPhase>) -> HashSet<QualifiedName> {
+        apis.iter()
+            .filter_map(|api| match api {
+                Api::Struct {
+                    analysis:
+                        PodAnalysis {
+                            in_anonymous_namespace: true,
+                            ..
+                        },
+                    ..
+                } => Some(api.name().clone()),
+                _ => None,
+            })
+            .collect()
+    }
+
+    /// Builds a mapping from a qualified type name to the last 'nest'
+    /// of its name, if it has multiple elements.
+    fn build_nested_type_map(apis: &ApiVec<PodPhase>) -> HashMap<QualifiedName, String> {
+        apis.iter()
+            .filter_map(|api| match api {
+                Api::Struct { name, .. } | Api::Enum { name, .. } => {
+                    let cpp_name = name
+                        .cpp_name_if_present()
+                        .cloned()
+                        .unwrap_or_else(|| name.name.get_final_item().to_string());
+                    cpp_name
+                        .rsplit_once("::")
+                        .map(|(_, suffix)| (name.name.clone(), suffix.to_string()))
+                }
+                _ => None,
+            })
+            .collect()
+    }
+
+    fn convert_boxed_type(
+        &mut self,
+        ty: Box<Type>,
+        ns: &Namespace,
+        pointer_treatment: PointerTreatment,
+    ) -> Result<Annotated<Box<Type>>, ConvertError> {
+        let ctx = TypeConversionContext::OuterType { pointer_treatment };
+        let mut annotated = self.type_converter.convert_boxed_type(ty, ns, &ctx)?;
+        self.extra_apis.append(&mut annotated.extra_apis);
+        Ok(annotated)
+    }
+
+    fn get_cxx_bridge_name(
+        &mut self,
+        type_name: Option<&str>,
+        found_name: &str,
+        ns: &Namespace,
+    ) -> String {
+        self.bridge_name_tracker
+            .get_unique_cxx_bridge_name(type_name, found_name, ns)
+    }
+
+    fn is_on_allowlist(&self, type_name: &QualifiedName) -> bool {
+        self.config.is_on_allowlist(&type_name.to_cpp_name())
+    }
+
+    fn is_generic_type(&self, type_name: &QualifiedName) -> bool {
+        self.generic_types.contains(type_name)
+    }
+
+    #[allow(clippy::if_same_then_else)] // clippy bug doesn't notice the two
+                                        // closures below are different.
+    fn should_be_unsafe(
+        &self,
+        param_details: &[ArgumentAnalysis],
+        kind: &FnKind,
+    ) -> UnsafetyNeeded {
+        let unsafest_non_placement_param = UnsafetyNeeded::from_param_details(param_details, true);
+        let unsafest_param = UnsafetyNeeded::from_param_details(param_details, false);
+        match kind {
+            // Trait unsafety must always correspond to the norms for the
+            // trait we're implementing.
+            FnKind::TraitMethod {
+                kind:
+                    TraitMethodKind::CopyConstructor
+                    | TraitMethodKind::MoveConstructor
+                    | TraitMethodKind::Alloc
+                    | TraitMethodKind::Dealloc,
+                ..
+            } => UnsafetyNeeded::Always,
+            FnKind::TraitMethod { .. } => match unsafest_param {
+                UnsafetyNeeded::Always => UnsafetyNeeded::JustBridge,
+                _ => unsafest_param,
+            },
+            _ if self.unsafe_policy == UnsafePolicy::AllFunctionsUnsafe => UnsafetyNeeded::Always,
+            _ => match unsafest_non_placement_param {
+                UnsafetyNeeded::Always => UnsafetyNeeded::Always,
+                UnsafetyNeeded::JustBridge => match unsafest_param {
+                    UnsafetyNeeded::Always => UnsafetyNeeded::JustBridge,
+                    _ => unsafest_non_placement_param,
+                },
+                UnsafetyNeeded::None => match unsafest_param {
+                    UnsafetyNeeded::Always => UnsafetyNeeded::JustBridge,
+                    _ => unsafest_param,
+                },
+            },
+        }
+    }
+
+    fn add_subclass_constructors(&mut self, apis: &mut ApiVec<FnPrePhase2>) {
+        let mut results = ApiVec::new();
+
+        // Pre-assemble a list of types with known destructors, to avoid having to
+        // do a O(n^2) nested loop.
+        let types_with_destructors: HashSet<_> = apis
+            .iter()
+            .filter_map(|api| match api {
+                Api::Function {
+                    fun,
+                    analysis:
+                        FnAnalysis {
+                            kind: FnKind::TraitMethod { impl_for, .. },
+                            ..
+                        },
+                    ..
+                } if matches!(
+                    **fun,
+                    FuncToConvert {
+                        special_member: Some(SpecialMemberKind::Destructor),
+                        is_deleted: false,
+                        cpp_vis: CppVisibility::Public,
+                        ..
+                    }
+                ) =>
+                {
+                    Some(impl_for)
+                }
+                _ => None,
+            })
+            .cloned()
+            .collect();
+
+        for api in apis.iter() {
+            if let Api::Function {
+                fun,
+                analysis:
+                    analysis @ FnAnalysis {
+                        kind:
+                            FnKind::Method {
+                                impl_for: sup,
+                                method_kind: MethodKind::Constructor { .. },
+                                ..
+                            },
+                        ..
+                    },
+                ..
+            } = api
+            {
+                // If we don't have an accessible destructor, then std::unique_ptr cannot be
+                // instantiated for this C++ type.
+                if !types_with_destructors.contains(sup) {
+                    continue;
+                }
+
+                for sub in self.subclasses_by_superclass(sup) {
+                    // Create a subclass constructor. This is a synthesized function
+                    // which didn't exist in the original C++.
+                    let (subclass_constructor_func, subclass_constructor_name) =
+                        create_subclass_constructor(sub, analysis, sup, fun);
+                    self.analyze_and_add(
+                        subclass_constructor_name.clone(),
+                        subclass_constructor_func.clone(),
+                        &mut results,
+                        TypeConversionSophistication::Regular,
+                    );
+                }
+            }
+        }
+        apis.extend(results.into_iter());
+    }
+
+    /// Analyze a given function, and any permutations of that function which
+    /// we might additionally generate (e.g. for subclasses.)
+    ///
+    /// Leaves the [`FnKind::Method::type_constructors`] at its default for [`add_constructors_present`]
+    /// to fill out.
+    fn analyze_foreign_fn_and_subclasses(
+        &mut self,
+        name: ApiName,
+        fun: Box<FuncToConvert>,
+    ) -> Result<Box<dyn Iterator<Item = Api<FnPrePhase1>>>, ConvertErrorWithContext> {
+        let (analysis, name) =
+            self.analyze_foreign_fn(name, &fun, TypeConversionSophistication::Regular, None);
+        let mut results = ApiVec::new();
+
+        // Consider whether we need to synthesize subclass items.
+        if let FnKind::Method {
+            impl_for: sup,
+            method_kind:
+                MethodKind::Virtual(receiver_mutability) | MethodKind::PureVirtual(receiver_mutability),
+            ..
+        } = &analysis.kind
+        {
+            let (simpler_analysis, _) = self.analyze_foreign_fn(
+                name.clone(),
+                &fun,
+                TypeConversionSophistication::SimpleForSubclasses,
+                Some(analysis.rust_name.clone()),
+            );
+            for sub in self.subclasses_by_superclass(sup) {
+                // For each subclass, we need to create a plain-C++ method to call its superclass
+                // and a Rust/C++ bridge API to call _that_.
+                // What we're generating here is entirely about the subclass, so the
+                // superclass's namespace is irrelevant. We generate
+                // all subclasses in the root namespace.
+                let is_pure_virtual = matches!(
+                    &simpler_analysis.kind,
+                    FnKind::Method {
+                        method_kind: MethodKind::PureVirtual(..),
+                        ..
+                    }
+                );
+
+                let super_fn_call_name =
+                    SubclassName::get_super_fn_name(&Namespace::new(), &analysis.rust_name);
+                let super_fn_api_name = SubclassName::get_super_fn_name(
+                    &Namespace::new(),
+                    &analysis.cxxbridge_name.to_string(),
+                );
+                let trait_api_name = SubclassName::get_trait_api_name(sup, &analysis.rust_name);
+
+                let mut subclass_fn_deps = vec![trait_api_name.clone()];
+                if !is_pure_virtual {
+                    // Create a C++ API representing the superclass implementation (allowing
+                    // calls from Rust->C++)
+                    let maybe_wrap = create_subclass_fn_wrapper(&sub, &super_fn_call_name, &fun);
+                    let super_fn_name = ApiName::new_from_qualified_name(super_fn_api_name);
+                    let super_fn_call_api_name = self.analyze_and_add(
+                        super_fn_name,
+                        maybe_wrap,
+                        &mut results,
+                        TypeConversionSophistication::SimpleForSubclasses,
+                    );
+                    subclass_fn_deps.push(super_fn_call_api_name);
+                }
+
+                // Create the Rust API representing the subclass implementation (allowing calls
+                // from C++ -> Rust)
+                results.push(create_subclass_function(
+                    // RustSubclassFn
+                    &sub,
+                    &simpler_analysis,
+                    &name,
+                    receiver_mutability,
+                    sup,
+                    subclass_fn_deps,
+                ));
+
+                // Create the trait item for the <superclass>_methods and <superclass>_supers
+                // traits. This is required per-superclass, not per-subclass, so don't
+                // create it if it already exists.
+                if !self
+                    .existing_superclass_trait_api_names
+                    .contains(&trait_api_name)
+                {
+                    self.existing_superclass_trait_api_names
+                        .insert(trait_api_name.clone());
+                    results.push(create_subclass_trait_item(
+                        ApiName::new_from_qualified_name(trait_api_name),
+                        &simpler_analysis,
+                        receiver_mutability,
+                        sup.clone(),
+                        is_pure_virtual,
+                    ));
+                }
+            }
+        }
+
+        results.push(Api::Function {
+            fun,
+            analysis,
+            name,
+        });
+
+        Ok(Box::new(results.into_iter()))
+    }
+
+    /// Adds an API, usually a synthesized API. Returns the final calculated API name, which can be used
+    /// for others to depend on this.
+    fn analyze_and_add<P: AnalysisPhase<FunAnalysis = FnAnalysis>>(
+        &mut self,
+        name: ApiName,
+        new_func: Box<FuncToConvert>,
+        results: &mut ApiVec<P>,
+        sophistication: TypeConversionSophistication,
+    ) -> QualifiedName {
+        let (analysis, name) = self.analyze_foreign_fn(name, &new_func, sophistication, None);
+        results.push(Api::Function {
+            fun: new_func,
+            analysis,
+            name: name.clone(),
+        });
+        name.name
+    }
+
+    /// Determine how to materialize a function.
+    ///
+    /// The main job here is to determine whether a function can simply be noted
+    /// in the [cxx::bridge] mod and passed directly to cxx, or if it needs a Rust-side
+    /// wrapper function, or if it needs a C++-side wrapper function, or both.
+    /// We aim for the simplest case but, for example:
+    /// * We'll need a C++ wrapper for static methods
+    /// * We'll need a C++ wrapper for parameters which need to be wrapped and unwrapped
+    ///   to [cxx::UniquePtr]
+    /// * We'll need a Rust wrapper if we've got a C++ wrapper and it's a method.
+    /// * We may need wrappers if names conflict.
+    /// etc.
+    /// The other major thing we do here is figure out naming for the function.
+    /// This depends on overloads, and what other functions are floating around.
+    /// The output of this analysis phase is used by both Rust and C++ codegen.
+    fn analyze_foreign_fn(
+        &mut self,
+        name: ApiName,
+        fun: &FuncToConvert,
+        sophistication: TypeConversionSophistication,
+        predetermined_rust_name: Option<String>,
+    ) -> (FnAnalysis, ApiName) {
+        let mut cpp_name = name.cpp_name_if_present().cloned();
+        let ns = name.name.get_namespace();
+
+        // Let's gather some pre-wisdom about the name of the function.
+        // We're shortly going to plunge into analyzing the parameters,
+        // and it would be nice to have some idea of the function name
+        // for diagnostics whilst we do that.
+        let initial_rust_name = fun.ident.to_string();
+        let diagnostic_display_name = cpp_name.as_ref().unwrap_or(&initial_rust_name);
+
+        // Now let's analyze all the parameters.
+        // See if any have annotations which our fork of bindgen has craftily inserted...
+        let (param_details, bads): (Vec<_>, Vec<_>) = fun
+            .inputs
+            .iter()
+            .map(|i| {
+                self.convert_fn_arg(
+                    i,
+                    ns,
+                    diagnostic_display_name,
+                    &fun.synthesized_this_type,
+                    &fun.references,
+                    true,
+                    false,
+                    None,
+                    sophistication,
+                    false,
+                )
+            })
+            .partition(Result::is_ok);
+        let (mut params, mut param_details): (Punctuated<_, Comma>, Vec<_>) =
+            param_details.into_iter().map(Result::unwrap).unzip();
+
+        let params_deps: HashSet<_> = param_details
+            .iter()
+            .flat_map(|p| p.deps.iter().cloned())
+            .collect();
+        let self_ty = param_details
+            .iter()
+            .filter_map(|pd| pd.self_type.as_ref())
+            .next()
+            .cloned();
+
+        // End of parameter processing.
+        // Work out naming, part one.
+        // bindgen may have mangled the name either because it's invalid Rust
+        // syntax (e.g. a keyword like 'async') or it's an overload.
+        // If the former, we respect that mangling. If the latter, we don't,
+        // because we'll add our own overload counting mangling later.
+        // Cases:
+        //   function, IRN=foo,    CN=<none>                    output: foo    case 1
+        //   function, IRN=move_,  CN=move   (keyword problem)  output: move_  case 2
+        //   function, IRN=foo1,   CN=foo    (overload)         output: foo    case 3
+        //   method,   IRN=A_foo,  CN=foo                       output: foo    case 4
+        //   method,   IRN=A_move, CN=move   (keyword problem)  output: move_  case 5
+        //   method,   IRN=A_foo1, CN=foo    (overload)         output: foo    case 6
+        let ideal_rust_name = match &cpp_name {
+            None => initial_rust_name, // case 1
+            Some(cpp_name) => {
+                if initial_rust_name.ends_with('_') {
+                    initial_rust_name // case 2
+                } else if validate_ident_ok_for_rust(cpp_name).is_err() {
+                    format!("{}_", cpp_name) // case 5
+                } else {
+                    cpp_name.to_string() // cases 3, 4, 6
+                }
+            }
+        };
+
+        // Let's spend some time figuring out the kind of this function (i.e. method,
+        // virtual function, etc.)
+        // Part one, work out if this is a static method.
+        let (is_static_method, self_ty, receiver_mutability) = match self_ty {
+            None => {
+                // Even if we can't find a 'self' parameter this could conceivably
+                // be a static method.
+                let self_ty = fun.self_ty.clone();
+                (self_ty.is_some(), self_ty, None)
+            }
+            Some((self_ty, receiver_mutability)) => {
+                (false, Some(self_ty), Some(receiver_mutability))
+            }
+        };
+
+        // Part two, work out if this is a function, or method, or whatever.
+        // First determine if this is actually a trait implementation.
+        let trait_details = self.trait_creation_details_for_synthetic_function(
+            &fun.add_to_trait,
+            ns,
+            &ideal_rust_name,
+            &self_ty,
+        );
+        let (kind, error_context, rust_name) = if let Some(trait_details) = trait_details {
+            trait_details
+        } else if let Some(self_ty) = self_ty {
+            // Some kind of method or static method.
+            let type_ident = self_ty.get_final_item();
+            // bindgen generates methods with the name:
+            // {class}_{method name}
+            // It then generates an impl section for the Rust type
+            // with the original name, but we currently discard that impl section.
+            // We want to feed cxx methods with just the method name, so let's
+            // strip off the class name.
+            let mut rust_name = ideal_rust_name;
+            let nested_type_ident = self
+                .nested_type_name_map
+                .get(&self_ty)
+                .map(|s| s.as_str())
+                .unwrap_or_else(|| self_ty.get_final_item());
+            if matches!(
+                fun.special_member,
+                Some(SpecialMemberKind::CopyConstructor | SpecialMemberKind::MoveConstructor)
+            ) {
+                let is_move =
+                    matches!(fun.special_member, Some(SpecialMemberKind::MoveConstructor));
+                if let Some(constructor_suffix) = rust_name.strip_prefix(nested_type_ident) {
+                    rust_name = format!("new{}", constructor_suffix);
+                }
+                rust_name = predetermined_rust_name
+                    .unwrap_or_else(|| self.get_overload_name(ns, type_ident, rust_name));
+                let error_context = self.error_context_for_method(&self_ty, &rust_name);
+
+                // If this is 'None', then something weird is going on. We'll check for that
+                // later when we have enough context to generate useful errors.
+                let arg_is_reference = matches!(
+                    param_details
+                        .get(1)
+                        .map(|param| &param.conversion.unwrapped_type),
+                    Some(Type::Reference(_))
+                );
+                // Some exotic forms of copy constructor have const and/or volatile qualifiers.
+                // These are not sufficient to implement CopyNew, so we just treat them as regular
+                // constructors. We detect them by their argument being translated to Pin at this
+                // point.
+                if is_move || arg_is_reference {
+                    let (kind, method_name, trait_id) = if is_move {
+                        (
+                            TraitMethodKind::MoveConstructor,
+                            "move_new",
+                            quote! { MoveNew },
+                        )
+                    } else {
+                        (
+                            TraitMethodKind::CopyConstructor,
+                            "copy_new",
+                            quote! { CopyNew },
+                        )
+                    };
+                    let ty = Type::Path(self_ty.to_type_path());
+                    (
+                        FnKind::TraitMethod {
+                            kind,
+                            impl_for: self_ty,
+                            details: Box::new(TraitMethodDetails {
+                                trt: TraitImplSignature {
+                                    ty,
+                                    trait_signature: parse_quote! {
+                                        autocxx::moveit::new:: #trait_id
+                                    },
+                                    unsafety: Some(parse_quote! { unsafe }),
+                                },
+                                avoid_self: true,
+                                method_name: make_ident(method_name),
+                                parameter_reordering: Some(vec![1, 0]),
+                                trait_call_is_unsafe: false,
+                            }),
+                        },
+                        error_context,
+                        rust_name,
+                    )
+                } else {
+                    (
+                        FnKind::Method {
+                            impl_for: self_ty,
+                            method_kind: MethodKind::Constructor { is_default: false },
+                        },
+                        error_context,
+                        rust_name,
+                    )
+                }
+            } else if matches!(fun.special_member, Some(SpecialMemberKind::Destructor)) {
+                rust_name = predetermined_rust_name
+                    .unwrap_or_else(|| self.get_overload_name(ns, type_ident, rust_name));
+                let error_context = self.error_context_for_method(&self_ty, &rust_name);
+                let ty = Type::Path(self_ty.to_type_path());
+                (
+                    FnKind::TraitMethod {
+                        kind: TraitMethodKind::Destructor,
+                        impl_for: self_ty,
+                        details: Box::new(TraitMethodDetails {
+                            trt: TraitImplSignature {
+                                ty,
+                                trait_signature: parse_quote! {
+                                    Drop
+                                },
+                                unsafety: None,
+                            },
+                            avoid_self: false,
+                            method_name: make_ident("drop"),
+                            parameter_reordering: None,
+                            trait_call_is_unsafe: false,
+                        }),
+                    },
+                    error_context,
+                    rust_name,
+                )
+            } else {
+                let method_kind = if let Some(constructor_suffix) =
+                    constructor_with_suffix(&rust_name, nested_type_ident)
+                {
+                    // It's a constructor. bindgen generates
+                    // fn Type(this: *mut Type, ...args)
+                    // We want
+                    // fn new(this: *mut Type, ...args)
+                    // Later code will spot this and re-enter us, and we'll make
+                    // a duplicate function in the above 'if' clause like this:
+                    // fn make_unique(...args) -> Type
+                    // which later code will convert to
+                    // fn make_unique(...args) -> UniquePtr<Type>
+                    // If there are multiple constructors, bindgen generates
+                    // new, new1, new2 etc. and we'll keep those suffixes.
+                    rust_name = format!("new{}", constructor_suffix);
+                    MethodKind::Constructor {
+                        is_default: matches!(
+                            fun.special_member,
+                            Some(SpecialMemberKind::DefaultConstructor)
+                        ),
+                    }
+                } else if is_static_method {
+                    MethodKind::Static
+                } else {
+                    let receiver_mutability =
+                        receiver_mutability.expect("Failed to find receiver details");
+                    match fun.virtualness {
+                        Virtualness::None => MethodKind::Normal(receiver_mutability),
+                        Virtualness::Virtual => MethodKind::Virtual(receiver_mutability),
+                        Virtualness::PureVirtual => MethodKind::PureVirtual(receiver_mutability),
+                    }
+                };
+                // Disambiguate overloads.
+                let rust_name = predetermined_rust_name
+                    .unwrap_or_else(|| self.get_overload_name(ns, type_ident, rust_name));
+                let error_context = self.error_context_for_method(&self_ty, &rust_name);
+                (
+                    FnKind::Method {
+                        impl_for: self_ty,
+                        method_kind,
+                    },
+                    error_context,
+                    rust_name,
+                )
+            }
+        } else {
+            // Not a method.
+            // What shall we call this function? It may be overloaded.
+            let rust_name = self.get_function_overload_name(ns, ideal_rust_name);
+            (
+                FnKind::Function,
+                ErrorContext::new_for_item(make_ident(&rust_name)),
+                rust_name,
+            )
+        };
+
+        // If we encounter errors from here on, we can give some context around
+        // where the error occurred such that we can put a marker in the output
+        // Rust code to indicate that a problem occurred (benefiting people using
+        // rust-analyzer or similar). Make a closure to make this easy.
+        let mut ignore_reason = Ok(());
+        let mut set_ignore_reason =
+            |err| ignore_reason = Err(ConvertErrorWithContext(err, Some(error_context.clone())));
+
+        // Now we have figured out the type of function (from its parameters)
+        // we might have determined that we have a constructor. If so,
+        // annoyingly, we need to go back and fiddle with the parameters in a
+        // different way. This is because we want the first parameter to be a
+        // pointer not a reference. For copy + move constructors, we also
+        // enforce Rust-side conversions to comply with moveit traits.
+        match kind {
+            FnKind::Method {
+                method_kind: MethodKind::Constructor { .. },
+                ..
+            } => {
+                self.reanalyze_parameter(
+                    0,
+                    fun,
+                    ns,
+                    &rust_name,
+                    &mut params,
+                    &mut param_details,
+                    None,
+                    sophistication,
+                    true,
+                    false,
+                )
+                .unwrap_or_else(&mut set_ignore_reason);
+            }
+
+            FnKind::TraitMethod {
+                kind: TraitMethodKind::Destructor,
+                ..
+            } => {
+                self.reanalyze_parameter(
+                    0,
+                    fun,
+                    ns,
+                    &rust_name,
+                    &mut params,
+                    &mut param_details,
+                    Some(RustConversionType::FromTypeToPtr),
+                    sophistication,
+                    false,
+                    false,
+                )
+                .unwrap_or_else(&mut set_ignore_reason);
+            }
+            FnKind::TraitMethod {
+                kind: TraitMethodKind::CopyConstructor,
+                ..
+            } => {
+                if param_details.len() < 2 {
+                    set_ignore_reason(ConvertError::ConstructorWithOnlyOneParam);
+                }
+                if param_details.len() > 2 {
+                    set_ignore_reason(ConvertError::ConstructorWithMultipleParams);
+                }
+                self.reanalyze_parameter(
+                    0,
+                    fun,
+                    ns,
+                    &rust_name,
+                    &mut params,
+                    &mut param_details,
+                    Some(RustConversionType::FromPinMaybeUninitToPtr),
+                    sophistication,
+                    false,
+                    false,
+                )
+                .unwrap_or_else(&mut set_ignore_reason);
+            }
+
+            FnKind::TraitMethod {
+                kind: TraitMethodKind::MoveConstructor,
+                ..
+            } => {
+                if param_details.len() < 2 {
+                    set_ignore_reason(ConvertError::ConstructorWithOnlyOneParam);
+                }
+                if param_details.len() > 2 {
+                    set_ignore_reason(ConvertError::ConstructorWithMultipleParams);
+                }
+                self.reanalyze_parameter(
+                    0,
+                    fun,
+                    ns,
+                    &rust_name,
+                    &mut params,
+                    &mut param_details,
+                    Some(RustConversionType::FromPinMaybeUninitToPtr),
+                    sophistication,
+                    false,
+                    false,
+                )
+                .unwrap_or_else(&mut set_ignore_reason);
+                self.reanalyze_parameter(
+                    1,
+                    fun,
+                    ns,
+                    &rust_name,
+                    &mut params,
+                    &mut param_details,
+                    Some(RustConversionType::FromPinMoveRefToPtr),
+                    sophistication,
+                    false,
+                    true,
+                )
+                .unwrap_or_else(&mut set_ignore_reason);
+            }
+            _ => {}
+        }
+
+        // Now we can add context to the error, check for a variety of error
+        // cases. In each case, we continue to record the API, because it might
+        // influence our later decisions to generate synthetic constructors
+        // or note whether the type is abstract.
+        let externally_callable = match fun.cpp_vis {
+            CppVisibility::Private => {
+                set_ignore_reason(ConvertError::PrivateMethod);
+                false
+            }
+            CppVisibility::Protected => false,
+            CppVisibility::Public => true,
+        };
+        if fun.variadic {
+            set_ignore_reason(ConvertError::Variadic);
+        }
+        if let Some(problem) = bads.into_iter().next() {
+            match problem {
+                Ok(_) => panic!("No error in the error"),
+                Err(problem) => set_ignore_reason(problem),
+            }
+        } else if fun.unused_template_param {
+            // This indicates that bindgen essentially flaked out because templates
+            // were too complex.
+            set_ignore_reason(ConvertError::UnusedTemplateParam)
+        } else if matches!(
+            fun.special_member,
+            Some(SpecialMemberKind::AssignmentOperator)
+        ) {
+            // Be careful with the order of this if-else tree. Anything above here means we won't
+            // treat it as an assignment operator, but anything below we still consider when
+            // deciding which other C++ special member functions are implicitly defined.
+            set_ignore_reason(ConvertError::AssignmentOperator)
+        } else if fun.references.rvalue_ref_return {
+            set_ignore_reason(ConvertError::RValueReturn)
+        } else if fun.is_deleted {
+            set_ignore_reason(ConvertError::Deleted)
+        } else {
+            match kind {
+                FnKind::Method {
+                    ref impl_for,
+                    method_kind:
+                        MethodKind::Constructor { .. }
+                        | MethodKind::Normal(..)
+                        | MethodKind::PureVirtual(..)
+                        | MethodKind::Virtual(..),
+                    ..
+                } if !known_types().is_cxx_acceptable_receiver(impl_for) => {
+                    set_ignore_reason(ConvertError::UnsupportedReceiver);
+                }
+                FnKind::Method { ref impl_for, .. } if !self.is_on_allowlist(impl_for) => {
+                    // Bindgen will output methods for types which have been encountered
+                    // virally as arguments on other allowlisted types. But we don't want
+                    // to generate methods unless the user has specifically asked us to.
+                    // It may, for instance, be a private type.
+                    set_ignore_reason(ConvertError::MethodOfNonAllowlistedType);
+                }
+                FnKind::Method { ref impl_for, .. } | FnKind::TraitMethod { ref impl_for, .. } => {
+                    if self.is_generic_type(impl_for) {
+                        set_ignore_reason(ConvertError::MethodOfGenericType);
+                    }
+                    if self.types_in_anonymous_namespace.contains(impl_for) {
+                        set_ignore_reason(ConvertError::MethodInAnonymousNamespace);
+                    }
+                }
+                _ => {}
+            }
+        };
+
+        // The name we use within the cxx::bridge mod may be different
+        // from both the C++ name and the Rust name, because it's a flat
+        // namespace so we might need to prepend some stuff to make it unique.
+        let cxxbridge_name = self.get_cxx_bridge_name(
+            match kind {
+                FnKind::Method { ref impl_for, .. } => Some(impl_for.get_final_item()),
+                FnKind::Function => None,
+                FnKind::TraitMethod { ref impl_for, .. } => Some(impl_for.get_final_item()),
+            },
+            &rust_name,
+            ns,
+        );
+        if cxxbridge_name != rust_name && cpp_name.is_none() {
+            cpp_name = Some(rust_name.clone());
+        }
+        let mut cxxbridge_name = make_ident(&cxxbridge_name);
+
+        // Analyze the return type, just as we previously did for the
+        // parameters.
+        let mut return_analysis = self
+            .convert_return_type(&fun.output, ns, &fun.references, sophistication)
+            .unwrap_or_else(|err| {
+                set_ignore_reason(err);
+                ReturnTypeAnalysis::default()
+            });
+        let mut deps = params_deps;
+        deps.extend(return_analysis.deps.drain(..));
+
+        // Sometimes, the return type will actually be a value type
+        // for which we instead want to _pass_ a pointer into which the value
+        // can be constructed. Handle that case here.
+        if let Some((extra_param, extra_param_details)) = return_analysis.placement_param_needed {
+            param_details.push(extra_param_details);
+            params.push(extra_param);
+        }
+
+        let requires_unsafe = self.should_be_unsafe(&param_details, &kind);
+
+        let num_input_references = param_details.iter().filter(|pd| pd.has_lifetime).count();
+        if num_input_references != 1 && return_analysis.was_reference {
+            // cxx only allows functions to return a reference if they take exactly
+            // one reference as a parameter. Let's see...
+            set_ignore_reason(ConvertError::NotOneInputReference(rust_name.clone()));
+        }
+        let mut ret_type = return_analysis.rt;
+        let ret_type_conversion = return_analysis.conversion;
+
+        // Do we need to convert either parameters or return type?
+        let param_conversion_needed = param_details.iter().any(|b| b.conversion.cpp_work_needed());
+        let ret_type_conversion_needed = ret_type_conversion
+            .as_ref()
+            .map_or(false, |x| x.cpp_work_needed());
+        // See https://github.com/dtolnay/cxx/issues/878 for the reason for this next line.
+        let effective_cpp_name = cpp_name.as_ref().unwrap_or(&rust_name);
+        let cpp_name_incompatible_with_cxx =
+            validate_ident_ok_for_rust(effective_cpp_name).is_err();
+        // If possible, we'll put knowledge of the C++ API directly into the cxx::bridge
+        // mod. However, there are various circumstances where cxx can't work with the existing
+        // C++ API and we need to create a C++ wrapper function which is more cxx-compliant.
+        // That wrapper function is included in the cxx::bridge, and calls through to the
+        // original function.
+        let wrapper_function_needed = match kind {
+            FnKind::Method {
+                method_kind:
+                    MethodKind::Static
+                    | MethodKind::Constructor { .. }
+                    | MethodKind::Virtual(_)
+                    | MethodKind::PureVirtual(_),
+                ..
+            }
+            | FnKind::TraitMethod {
+                kind:
+                    TraitMethodKind::CopyConstructor
+                    | TraitMethodKind::MoveConstructor
+                    | TraitMethodKind::Destructor,
+                ..
+            } => true,
+            FnKind::Method { .. } if cxxbridge_name != rust_name => true,
+            _ if param_conversion_needed => true,
+            _ if ret_type_conversion_needed => true,
+            _ if cpp_name_incompatible_with_cxx => true,
+            _ if fun.synthetic_cpp.is_some() => true,
+            _ => false,
+        };
+
+        let cpp_wrapper = if wrapper_function_needed {
+            // Generate a new layer of C++ code to wrap/unwrap parameters
+            // and return values into/out of std::unique_ptrs.
+            let cpp_construction_ident = make_ident(&effective_cpp_name);
+            let joiner = if cxxbridge_name.to_string().ends_with('_') {
+                ""
+            } else {
+                "_"
+            };
+            cxxbridge_name = make_ident(&format!("{}{}autocxx_wrapper", cxxbridge_name, joiner));
+            let (payload, cpp_function_kind) = match fun.synthetic_cpp.as_ref().cloned() {
+                Some((payload, cpp_function_kind)) => (payload, cpp_function_kind),
+                None => match kind {
+                    FnKind::Method {
+                        ref impl_for,
+                        method_kind: MethodKind::Constructor { .. },
+                        ..
+                    }
+                    | FnKind::TraitMethod {
+                        kind: TraitMethodKind::CopyConstructor | TraitMethodKind::MoveConstructor,
+                        ref impl_for,
+                        ..
+                    } => (
+                        CppFunctionBody::PlacementNew(ns.clone(), impl_for.get_final_ident()),
+                        CppFunctionKind::Constructor,
+                    ),
+                    FnKind::TraitMethod {
+                        kind: TraitMethodKind::Destructor,
+                        ref impl_for,
+                        ..
+                    } => (
+                        CppFunctionBody::Destructor(ns.clone(), impl_for.get_final_ident()),
+                        CppFunctionKind::Function,
+                    ),
+                    FnKind::Method {
+                        ref impl_for,
+                        method_kind: MethodKind::Static,
+                        ..
+                    } => (
+                        CppFunctionBody::StaticMethodCall(
+                            ns.clone(),
+                            impl_for.get_final_ident(),
+                            cpp_construction_ident,
+                        ),
+                        CppFunctionKind::Function,
+                    ),
+                    FnKind::Method { .. } => (
+                        CppFunctionBody::FunctionCall(ns.clone(), cpp_construction_ident),
+                        CppFunctionKind::Method,
+                    ),
+                    _ => (
+                        CppFunctionBody::FunctionCall(ns.clone(), cpp_construction_ident),
+                        CppFunctionKind::Function,
+                    ),
+                },
+            };
+            // Now modify the cxx::bridge entry we're going to make.
+            if let Some(ref conversion) = ret_type_conversion {
+                if conversion.populate_return_value() {
+                    let new_ret_type = conversion.unconverted_rust_type();
+                    ret_type = parse_quote!(
+                        -> #new_ret_type
+                    );
+                }
+            }
+
+            // Amend parameters for the function which we're asking cxx to generate.
+            params.clear();
+            for pd in &param_details {
+                let type_name = pd.conversion.converted_rust_type();
+                let arg_name = if pd.self_type.is_some() {
+                    parse_quote!(autocxx_gen_this)
+                } else {
+                    pd.name.clone()
+                };
+                params.push(parse_quote!(
+                    #arg_name: #type_name
+                ));
+            }
+
+            Some(CppFunction {
+                payload,
+                wrapper_function_name: cxxbridge_name.clone(),
+                original_cpp_name: cpp_name
+                    .as_ref()
+                    .cloned()
+                    .unwrap_or_else(|| cxxbridge_name.to_string()),
+                return_conversion: ret_type_conversion.clone(),
+                argument_conversion: param_details.iter().map(|d| d.conversion.clone()).collect(),
+                kind: cpp_function_kind,
+                pass_obs_field: false,
+                qualification: None,
+            })
+        } else {
+            None
+        };
+
+        let vis = fun.vis.clone();
+
+        let any_param_needs_rust_conversion = param_details
+            .iter()
+            .any(|pd| pd.conversion.rust_work_needed());
+
+        let rust_wrapper_needed = match kind {
+            FnKind::TraitMethod { .. } => true,
+            FnKind::Method { .. } => any_param_needs_rust_conversion || cxxbridge_name != rust_name,
+            _ => any_param_needs_rust_conversion,
+        };
+
+        // Naming, part two.
+        // Work out our final naming strategy.
+        validate_ident_ok_for_cxx(&cxxbridge_name.to_string()).unwrap_or_else(set_ignore_reason);
+        let rust_name_ident = make_ident(&rust_name);
+        let rust_rename_strategy = match kind {
+            _ if rust_wrapper_needed => RustRenameStrategy::RenameUsingWrapperFunction,
+            FnKind::Function if cxxbridge_name != rust_name => {
+                RustRenameStrategy::RenameInOutputMod(rust_name_ident)
+            }
+            _ => RustRenameStrategy::None,
+        };
+
+        let analysis = FnAnalysis {
+            cxxbridge_name: cxxbridge_name.clone(),
+            rust_name: rust_name.clone(),
+            rust_rename_strategy,
+            params,
+            ret_conversion: ret_type_conversion,
+            kind,
+            ret_type,
+            param_details,
+            requires_unsafe,
+            vis,
+            cpp_wrapper,
+            deps,
+            ignore_reason,
+            externally_callable,
+            rust_wrapper_needed,
+        };
+        let name = ApiName::new_with_cpp_name(ns, cxxbridge_name, cpp_name);
+        (analysis, name)
+    }
+
+    fn error_context_for_method(&self, self_ty: &QualifiedName, rust_name: &str) -> ErrorContext {
+        if self.is_generic_type(self_ty) {
+            // A 'method' error context would end up in an
+            //   impl A {
+            //      fn error_thingy
+            //   }
+            // block. We can't impl A if it would need to be impl A<B>
+            ErrorContext::new_for_item(make_ident(rust_name))
+        } else {
+            ErrorContext::new_for_method(self_ty.get_final_ident(), make_ident(rust_name))
+        }
+    }
+
+    /// Applies a specific `force_rust_conversion` to the parameter at index
+    /// `param_idx`. Modifies `param_details` and `params` in place.
+    #[allow(clippy::too_many_arguments)] // it's true, but sticking with it for now
+    fn reanalyze_parameter(
+        &mut self,
+        param_idx: usize,
+        fun: &FuncToConvert,
+        ns: &Namespace,
+        rust_name: &str,
+        params: &mut Punctuated<FnArg, Comma>,
+        param_details: &mut [ArgumentAnalysis],
+        force_rust_conversion: Option<RustConversionType>,
+        sophistication: TypeConversionSophistication,
+        construct_into_self: bool,
+        is_move_constructor: bool,
+    ) -> Result<(), ConvertError> {
+        self.convert_fn_arg(
+            fun.inputs.iter().nth(param_idx).unwrap(),
+            ns,
+            rust_name,
+            &fun.synthesized_this_type,
+            &fun.references,
+            false,
+            is_move_constructor,
+            force_rust_conversion,
+            sophistication,
+            construct_into_self,
+        )
+        .map(|(new_arg, new_analysis)| {
+            param_details[param_idx] = new_analysis;
+            let mut params_before = params.clone().into_iter();
+            let prefix = params_before
+                .by_ref()
+                .take(param_idx)
+                .collect_vec()
+                .into_iter();
+            let suffix = params_before.skip(1);
+            *params = prefix
+                .chain(std::iter::once(new_arg))
+                .chain(suffix)
+                .collect()
+        })
+    }
+
+    fn get_overload_name(&mut self, ns: &Namespace, type_ident: &str, rust_name: String) -> String {
+        let overload_tracker = self.overload_trackers_by_mod.entry(ns.clone()).or_default();
+        overload_tracker.get_method_real_name(type_ident, rust_name)
+    }
+
+    /// Determine if this synthetic function should actually result in the implementation
+    /// of a trait, rather than a function/method.
+    fn trait_creation_details_for_synthetic_function(
+        &mut self,
+        synthesis: &Option<TraitSynthesis>,
+        ns: &Namespace,
+        ideal_rust_name: &str,
+        self_ty: &Option<QualifiedName>,
+    ) -> Option<(FnKind, ErrorContext, String)> {
+        synthesis.as_ref().and_then(|synthesis| match synthesis {
+            TraitSynthesis::Cast { to_type, mutable } => {
+                let rust_name = self.get_function_overload_name(ns, ideal_rust_name.to_string());
+                let from_type = self_ty.as_ref().unwrap();
+                let from_type_path = from_type.to_type_path();
+                let to_type = to_type.to_type_path();
+                let (trait_signature, ty, method_name) = match *mutable {
+                    CastMutability::ConstToConst => (
+                        parse_quote! {
+                            AsRef < #to_type >
+                        },
+                        Type::Path(from_type_path),
+                        "as_ref",
+                    ),
+                    CastMutability::MutToConst => (
+                        parse_quote! {
+                            AsRef < #to_type >
+                        },
+                        parse_quote! {
+                            &'a mut ::std::pin::Pin < &'a mut #from_type_path >
+                        },
+                        "as_ref",
+                    ),
+                    CastMutability::MutToMut => (
+                        parse_quote! {
+                            autocxx::PinMut < #to_type >
+                        },
+                        parse_quote! {
+                            ::std::pin::Pin < &'a mut #from_type_path >
+                        },
+                        "pin_mut",
+                    ),
+                };
+                let method_name = make_ident(method_name);
+                Some((
+                    FnKind::TraitMethod {
+                        kind: TraitMethodKind::Cast,
+                        impl_for: from_type.clone(),
+                        details: Box::new(TraitMethodDetails {
+                            trt: TraitImplSignature {
+                                ty,
+                                trait_signature,
+                                unsafety: None,
+                            },
+                            avoid_self: false,
+                            method_name,
+                            parameter_reordering: None,
+                            trait_call_is_unsafe: false,
+                        }),
+                    },
+                    ErrorContext::new_for_item(make_ident(&rust_name)),
+                    rust_name,
+                ))
+            }
+            TraitSynthesis::AllocUninitialized(ty) => self.generate_alloc_or_deallocate(
+                ideal_rust_name,
+                ty,
+                "allocate_uninitialized_cpp_storage",
+                TraitMethodKind::Alloc,
+            ),
+            TraitSynthesis::FreeUninitialized(ty) => self.generate_alloc_or_deallocate(
+                ideal_rust_name,
+                ty,
+                "free_uninitialized_cpp_storage",
+                TraitMethodKind::Dealloc,
+            ),
+        })
+    }
+
+    fn generate_alloc_or_deallocate(
+        &mut self,
+        ideal_rust_name: &str,
+        ty: &QualifiedName,
+        method_name: &str,
+        kind: TraitMethodKind,
+    ) -> Option<(FnKind, ErrorContext, String)> {
+        let rust_name =
+            self.get_function_overload_name(ty.get_namespace(), ideal_rust_name.to_string());
+        let typ = ty.to_type_path();
+        Some((
+            FnKind::TraitMethod {
+                impl_for: ty.clone(),
+                details: Box::new(TraitMethodDetails {
+                    trt: TraitImplSignature {
+                        ty: Type::Path(typ),
+                        trait_signature: parse_quote! { autocxx::moveit::MakeCppStorage },
+                        unsafety: Some(parse_quote! { unsafe }),
+                    },
+                    avoid_self: false,
+                    method_name: make_ident(method_name),
+                    parameter_reordering: None,
+                    trait_call_is_unsafe: false,
+                }),
+                kind,
+            },
+            ErrorContext::new_for_item(make_ident(&rust_name)),
+            rust_name,
+        ))
+    }
+
+    fn get_function_overload_name(&mut self, ns: &Namespace, ideal_rust_name: String) -> String {
+        let overload_tracker = self.overload_trackers_by_mod.entry(ns.clone()).or_default();
+        overload_tracker.get_function_real_name(ideal_rust_name)
+    }
+
+    fn subclasses_by_superclass(&self, sup: &QualifiedName) -> impl Iterator<Item = SubclassName> {
+        match self.subclasses_by_superclass.get(sup) {
+            Some(subs) => subs.clone().into_iter(),
+            None => Vec::new().into_iter(),
+        }
+    }
+
+    #[allow(clippy::too_many_arguments)] // currently reasonably clear
+    fn convert_fn_arg(
+        &mut self,
+        arg: &FnArg,
+        ns: &Namespace,
+        fn_name: &str,
+        virtual_this: &Option<QualifiedName>,
+        references: &References,
+        treat_this_as_reference: bool,
+        is_move_constructor: bool,
+        force_rust_conversion: Option<RustConversionType>,
+        sophistication: TypeConversionSophistication,
+        construct_into_self: bool,
+    ) -> Result<(FnArg, ArgumentAnalysis), ConvertError> {
+        Ok(match arg {
+            FnArg::Typed(pt) => {
+                let mut pt = pt.clone();
+                let mut self_type = None;
+                let old_pat = *pt.pat;
+                let mut pointer_treatment = PointerTreatment::Pointer;
+                let mut is_placement_return_destination = false;
+                let new_pat = match old_pat {
+                    syn::Pat::Ident(mut pp) if pp.ident == "this" => {
+                        let this_type = match pt.ty.as_ref() {
+                            Type::Ptr(TypePtr {
+                                elem, mutability, ..
+                            }) => match elem.as_ref() {
+                                Type::Path(typ) => {
+                                    let receiver_mutability = if mutability.is_some() {
+                                        ReceiverMutability::Mutable
+                                    } else {
+                                        ReceiverMutability::Const
+                                    };
+
+                                    let this_type = if let Some(virtual_this) = virtual_this {
+                                        let this_type_path = virtual_this.to_type_path();
+                                        let const_token = if mutability.is_some() {
+                                            None
+                                        } else {
+                                            Some(syn::Token![const](Span::call_site()))
+                                        };
+                                        pt.ty = Box::new(parse_quote! {
+                                            * #mutability #const_token #this_type_path
+                                        });
+                                        virtual_this.clone()
+                                    } else {
+                                        QualifiedName::from_type_path(typ)
+                                    };
+                                    Ok((this_type, receiver_mutability))
+                                }
+                                _ => Err(ConvertError::UnexpectedThisType(QualifiedName::new(
+                                    ns,
+                                    make_ident(fn_name),
+                                ))),
+                            },
+                            _ => Err(ConvertError::UnexpectedThisType(QualifiedName::new(
+                                ns,
+                                make_ident(fn_name),
+                            ))),
+                        }?;
+                        self_type = Some(this_type);
+                        is_placement_return_destination = construct_into_self;
+                        if treat_this_as_reference {
+                            pp.ident = Ident::new("self", pp.ident.span());
+                            pointer_treatment = PointerTreatment::Reference;
+                        }
+                        syn::Pat::Ident(pp)
+                    }
+                    syn::Pat::Ident(pp) => {
+                        validate_ident_ok_for_cxx(&pp.ident.to_string())?;
+                        pointer_treatment = references.param_treatment(&pp.ident);
+                        syn::Pat::Ident(pp)
+                    }
+                    _ => old_pat,
+                };
+                let is_placement_return_destination = is_placement_return_destination
+                    || matches!(
+                        force_rust_conversion,
+                        Some(RustConversionType::FromPlacementParamToNewReturn)
+                    );
+                let annotated_type = self.convert_boxed_type(pt.ty, ns, pointer_treatment)?;
+                let conversion = self.argument_conversion_details(
+                    &annotated_type,
+                    is_move_constructor,
+                    force_rust_conversion,
+                    sophistication,
+                );
+                let new_ty = annotated_type.ty;
+                pt.pat = Box::new(new_pat.clone());
+                pt.ty = new_ty;
+                let requires_unsafe =
+                    if matches!(annotated_type.kind, type_converter::TypeKind::Pointer)
+                        && !is_placement_return_destination
+                    {
+                        UnsafetyNeeded::Always
+                    } else if conversion.bridge_unsafe_needed() || is_placement_return_destination {
+                        UnsafetyNeeded::JustBridge
+                    } else {
+                        UnsafetyNeeded::None
+                    };
+                (
+                    FnArg::Typed(pt),
+                    ArgumentAnalysis {
+                        self_type,
+                        name: new_pat,
+                        conversion,
+                        has_lifetime: matches!(
+                            annotated_type.kind,
+                            type_converter::TypeKind::Reference
+                                | type_converter::TypeKind::MutableReference
+                        ),
+                        deps: annotated_type.types_encountered,
+                        requires_unsafe,
+                        is_placement_return_destination,
+                    },
+                )
+            }
+            _ => panic!("Did not expect FnArg::Receiver to be generated by bindgen"),
+        })
+    }
+
+    fn argument_conversion_details(
+        &self,
+        annotated_type: &Annotated<Box<Type>>,
+        is_move_constructor: bool,
+        force_rust_conversion: Option<RustConversionType>,
+        sophistication: TypeConversionSophistication,
+    ) -> TypeConversionPolicy {
+        let is_subclass_holder = match &annotated_type.kind {
+            type_converter::TypeKind::SubclassHolder(holder) => Some(holder),
+            _ => None,
+        };
+        let is_rvalue_ref = matches!(
+            annotated_type.kind,
+            type_converter::TypeKind::RValueReference
+        );
+        let ty = &*annotated_type.ty;
+        if let Some(holder_id) = is_subclass_holder {
+            let subclass = SubclassName::from_holder_name(holder_id);
+            return {
+                let ty = parse_quote! {
+                    rust::Box<#holder_id>
+                };
+                TypeConversionPolicy {
+                    unwrapped_type: ty,
+                    cpp_conversion: CppConversionType::Move,
+                    rust_conversion: RustConversionType::ToBoxedUpHolder(subclass),
+                }
+            };
+        } else if matches!(
+            force_rust_conversion,
+            Some(RustConversionType::FromPlacementParamToNewReturn)
+        ) && matches!(sophistication, TypeConversionSophistication::Regular)
+        {
+            return TypeConversionPolicy {
+                unwrapped_type: ty.clone(),
+                cpp_conversion: CppConversionType::IgnoredPlacementPtrParameter,
+                rust_conversion: RustConversionType::FromPlacementParamToNewReturn,
+            };
+        }
+        match ty {
+            Type::Path(p) => {
+                let ty = ty.clone();
+                let tn = QualifiedName::from_type_path(p);
+                if self.pod_safe_types.contains(&tn) {
+                    if known_types().lacks_copy_constructor(&tn) {
+                        TypeConversionPolicy {
+                            unwrapped_type: ty,
+                            cpp_conversion: CppConversionType::Move,
+                            rust_conversion: RustConversionType::None,
+                        }
+                    } else {
+                        TypeConversionPolicy::new_unconverted(ty)
+                    }
+                } else if known_types().convertible_from_strs(&tn)
+                    && !self.config.exclude_utilities()
+                {
+                    TypeConversionPolicy {
+                        unwrapped_type: ty,
+                        cpp_conversion: CppConversionType::FromUniquePtrToValue,
+                        rust_conversion: RustConversionType::FromStr,
+                    }
+                } else if matches!(
+                    sophistication,
+                    TypeConversionSophistication::SimpleForSubclasses
+                ) {
+                    TypeConversionPolicy {
+                        unwrapped_type: ty,
+                        cpp_conversion: CppConversionType::FromUniquePtrToValue,
+                        rust_conversion: RustConversionType::None,
+                    }
+                } else {
+                    TypeConversionPolicy {
+                        unwrapped_type: ty,
+                        cpp_conversion: CppConversionType::FromPtrToValue,
+                        rust_conversion: RustConversionType::FromValueParamToPtr,
+                    }
+                }
+            }
+            Type::Ptr(tp) => {
+                let rust_conversion = force_rust_conversion.unwrap_or(RustConversionType::None);
+                if is_move_constructor {
+                    TypeConversionPolicy {
+                        unwrapped_type: ty.clone(),
+                        cpp_conversion: CppConversionType::FromPtrToMove,
+                        rust_conversion,
+                    }
+                } else if is_rvalue_ref {
+                    TypeConversionPolicy {
+                        unwrapped_type: *tp.elem.clone(),
+                        cpp_conversion: CppConversionType::FromPtrToValue,
+                        rust_conversion: RustConversionType::FromRValueParamToPtr,
+                    }
+                } else {
+                    TypeConversionPolicy {
+                        unwrapped_type: ty.clone(),
+                        cpp_conversion: CppConversionType::None,
+                        rust_conversion,
+                    }
+                }
+            }
+            _ => {
+                let rust_conversion = force_rust_conversion.unwrap_or(RustConversionType::None);
+                TypeConversionPolicy {
+                    unwrapped_type: ty.clone(),
+                    cpp_conversion: CppConversionType::None,
+                    rust_conversion,
+                }
+            }
+        }
+    }
+
+    fn convert_return_type(
+        &mut self,
+        rt: &ReturnType,
+        ns: &Namespace,
+        references: &References,
+        sophistication: TypeConversionSophistication,
+    ) -> Result<ReturnTypeAnalysis, ConvertError> {
+        Ok(match rt {
+            ReturnType::Default => ReturnTypeAnalysis::default(),
+            ReturnType::Type(rarrow, boxed_type) => {
+                let annotated_type =
+                    self.convert_boxed_type(boxed_type.clone(), ns, references.return_treatment())?;
+                let boxed_type = annotated_type.ty;
+                let ty: &Type = boxed_type.as_ref();
+                match ty {
+                    Type::Path(p)
+                        if !self
+                            .pod_safe_types
+                            .contains(&QualifiedName::from_type_path(p)) =>
+                    {
+                        let tn = QualifiedName::from_type_path(p);
+                        if self.moveit_safe_types.contains(&tn)
+                            && matches!(sophistication, TypeConversionSophistication::Regular)
+                        {
+                            // This is a non-POD type we want to return to Rust as an `impl New` so that callers
+                            // can decide whether to store this on the stack or heap.
+                            // That means, we do not literally _return_ it from C++ to Rust. Instead, our call
+                            // from Rust to C++ will include an extra placement parameter into which the object
+                            // is constructed.
+                            let fnarg = parse_quote! {
+                                placement_return_type: *mut #ty
+                            };
+                            let (fnarg, analysis) = self.convert_fn_arg(
+                                &fnarg,
+                                ns,
+                                "",
+                                &None,
+                                &References::default(),
+                                false,
+                                false,
+                                Some(RustConversionType::FromPlacementParamToNewReturn),
+                                TypeConversionSophistication::Regular,
+                                false,
+                            )?;
+                            ReturnTypeAnalysis {
+                                rt: ReturnType::Default,
+                                conversion: Some(TypeConversionPolicy::new_for_placement_return(
+                                    ty.clone(),
+                                )),
+                                was_reference: false,
+                                deps: annotated_type.types_encountered,
+                                placement_param_needed: Some((fnarg, analysis)),
+                            }
+                        } else {
+                            // There are some types which we can't currently represent within a moveit::new::New.
+                            // That's either because we are obliged to stick to existing protocols for compatibility
+                            // (CxxString) or because they're a concrete type where we haven't attempted to do
+                            // the analysis to work out the type's size. For these, we always return a plain old
+                            // UniquePtr<T>. These restrictions may be fixed in future.
+                            let conversion =
+                                Some(TypeConversionPolicy::new_to_unique_ptr(ty.clone()));
+                            ReturnTypeAnalysis {
+                                rt: ReturnType::Type(*rarrow, boxed_type),
+                                conversion,
+                                was_reference: false,
+                                deps: annotated_type.types_encountered,
+                                placement_param_needed: None,
+                            }
+                        }
+                    }
+                    _ => {
+                        let was_reference = matches!(boxed_type.as_ref(), Type::Reference(_));
+                        let conversion = Some(TypeConversionPolicy::new_unconverted(ty.clone()));
+                        ReturnTypeAnalysis {
+                            rt: ReturnType::Type(*rarrow, boxed_type),
+                            conversion,
+                            was_reference,
+                            deps: annotated_type.types_encountered,
+                            placement_param_needed: None,
+                        }
+                    }
+                }
+            }
+        })
+    }
+
+    /// If a type has explicit constructors, bindgen will generate corresponding
+    /// constructor functions, which we'll have already converted to make_unique methods.
+    /// C++ mandates the synthesis of certain implicit constructors, to which we
+    /// need to create bindings too. We do that here.
+    /// It is tempting to make this a separate analysis phase, to be run later than
+    /// the function analysis; but that would make the code much more complex as it
+    /// would need to output a `FnAnalysisBody`. By running it as part of this phase
+    /// we can simply generate the sort of thing bindgen generates, then ask
+    /// the existing code in this phase to figure out what to do with it.
+    ///
+    /// Also fills out the [`PodAndConstructorAnalysis::constructors`] fields with information useful
+    /// for further analysis phases.
+    fn add_constructors_present(&mut self, mut apis: ApiVec<FnPrePhase1>) -> ApiVec<FnPrePhase2> {
+        let all_items_found = find_constructors_present(&apis);
+        for (self_ty, items_found) in all_items_found.iter() {
+            if self.config.exclude_impls {
+                // Remember that `find_constructors_present` mutates `apis`, so we always have to
+                // call that, even if we don't do anything with the return value. This is kind of
+                // messy, see the comment on this function for why.
+                continue;
+            }
+            if self
+                .config
+                .is_on_constructor_blocklist(&self_ty.to_cpp_name())
+            {
+                continue;
+            }
+            let path = self_ty.to_type_path();
+            if items_found.implicit_default_constructor_needed() {
+                self.synthesize_special_member(
+                    items_found,
+                    "default_ctor",
+                    &mut apis,
+                    SpecialMemberKind::DefaultConstructor,
+                    parse_quote! { this: *mut #path },
+                    References::default(),
+                );
+            }
+            if items_found.implicit_move_constructor_needed() {
+                self.synthesize_special_member(
+                    items_found,
+                    "move_ctor",
+                    &mut apis,
+                    SpecialMemberKind::MoveConstructor,
+                    parse_quote! { this: *mut #path, other: *mut #path },
+                    References {
+                        rvalue_ref_params: [make_ident("other")].into_iter().collect(),
+                        ..Default::default()
+                    },
+                )
+            }
+            if items_found.implicit_copy_constructor_needed() {
+                self.synthesize_special_member(
+                    items_found,
+                    "const_copy_ctor",
+                    &mut apis,
+                    SpecialMemberKind::CopyConstructor,
+                    parse_quote! { this: *mut #path, other: *const #path },
+                    References {
+                        ref_params: [make_ident("other")].into_iter().collect(),
+                        ..Default::default()
+                    },
+                )
+            }
+            if items_found.implicit_destructor_needed() {
+                self.synthesize_special_member(
+                    items_found,
+                    "destructor",
+                    &mut apis,
+                    SpecialMemberKind::Destructor,
+                    parse_quote! { this: *mut #path },
+                    References::default(),
+                );
+            }
+        }
+
+        // Also, annotate each type with the constructors we found.
+        let mut results = ApiVec::new();
+        convert_apis(
+            apis,
+            &mut results,
+            Api::fun_unchanged,
+            |name, details, analysis| {
+                let items_found = all_items_found.get(&name.name);
+                Ok(Box::new(std::iter::once(Api::Struct {
+                    name,
+                    details,
+                    analysis: PodAndConstructorAnalysis {
+                        pod: analysis,
+                        constructors: if let Some(items_found) = items_found {
+                            PublicConstructors::from_items_found(items_found)
+                        } else {
+                            PublicConstructors::default()
+                        },
+                    },
+                })))
+            },
+            Api::enum_unchanged,
+            Api::typedef_unchanged,
+        );
+        results
+    }
+
+    #[allow(clippy::too_many_arguments)] // it's true, but sticking with it for now
+    fn synthesize_special_member(
+        &mut self,
+        items_found: &ItemsFound,
+        label: &str,
+        apis: &mut ApiVec<FnPrePhase1>,
+        special_member: SpecialMemberKind,
+        inputs: Punctuated<FnArg, Comma>,
+        references: References,
+    ) {
+        let self_ty = items_found.name.as_ref().unwrap();
+        let ident = make_ident(self.config.uniquify_name_per_mod(&format!(
+            "{}_synthetic_{}",
+            self_ty.name.get_final_item(),
+            label
+        )));
+        let cpp_name = if matches!(special_member, SpecialMemberKind::DefaultConstructor) {
+            // Constructors (other than move or copy) are identified in `analyze_foreign_fn` by
+            // being suffixed with the cpp_name, so we have to produce that.
+            self.nested_type_name_map
+                .get(&self_ty.name)
+                .cloned()
+                .or_else(|| Some(self_ty.name.get_final_item().to_string()))
+        } else {
+            None
+        };
+        let fake_api_name =
+            ApiName::new_with_cpp_name(self_ty.name.get_namespace(), ident.clone(), cpp_name);
+        let self_ty = &self_ty.name;
+        let ns = self_ty.get_namespace().clone();
+        let mut any_errors = ApiVec::new();
+        apis.extend(
+            report_any_error(&ns, &mut any_errors, || {
+                self.analyze_foreign_fn_and_subclasses(
+                    fake_api_name,
+                    Box::new(FuncToConvert {
+                        self_ty: Some(self_ty.clone()),
+                        ident,
+                        doc_attrs: make_doc_attrs(format!("Synthesized {}.", special_member)),
+                        inputs,
+                        output: ReturnType::Default,
+                        vis: parse_quote! { pub },
+                        virtualness: Virtualness::None,
+                        cpp_vis: CppVisibility::Public,
+                        special_member: Some(special_member),
+                        unused_template_param: false,
+                        references,
+                        original_name: None,
+                        synthesized_this_type: None,
+                        is_deleted: false,
+                        add_to_trait: None,
+                        synthetic_cpp: None,
+                        provenance: Provenance::SynthesizedOther,
+                        variadic: false,
+                    }),
+                )
+            })
+            .into_iter()
+            .flatten(),
+        );
+        apis.append(&mut any_errors);
+    }
+}
+
+/// Attempts to determine whether this function name is a constructor, and if so,
+/// returns the suffix.
+fn constructor_with_suffix<'a>(rust_name: &'a str, nested_type_ident: &str) -> Option<&'a str> {
+    let suffix = rust_name.strip_prefix(nested_type_ident);
+    suffix.and_then(|suffix| {
+        if suffix.is_empty() || suffix.parse::<u32>().is_ok() {
+            Some(suffix)
+        } else {
+            None
+        }
+    })
+}
+
+impl Api<FnPhase> {
+    pub(crate) fn name_for_allowlist(&self) -> QualifiedName {
+        match &self {
+            Api::Function { analysis, .. } => match analysis.kind {
+                FnKind::Method { ref impl_for, .. } => impl_for.clone(),
+                FnKind::TraitMethod { ref impl_for, .. } => impl_for.clone(),
+                FnKind::Function => {
+                    QualifiedName::new(self.name().get_namespace(), make_ident(&analysis.rust_name))
+                }
+            },
+            Api::RustSubclassFn { subclass, .. } => subclass.0.name.clone(),
+            Api::IgnoredItem {
+                name,
+                ctx: Some(ctx),
+                ..
+            } => match ctx.get_type() {
+                ErrorContextType::Method { self_ty, .. } => {
+                    QualifiedName::new(name.name.get_namespace(), self_ty.clone())
+                }
+                ErrorContextType::Item(id) => {
+                    QualifiedName::new(name.name.get_namespace(), id.clone())
+                }
+                _ => name.name.clone(),
+            },
+            _ => self.name().clone(),
+        }
+    }
+
+    /// Whether this API requires generation of additional C++.
+    /// This seems an odd place for this function (as opposed to in the [codegen_cpp]
+    /// module) but, as it happens, even our Rust codegen phase needs to know if
+    /// more C++ is needed (so it can add #includes in the cxx mod).
+    /// And we can't answer the question _prior_ to this function analysis phase.
+    pub(crate) fn needs_cpp_codegen(&self) -> bool {
+        matches!(
+            &self,
+            Api::Function {
+                analysis: FnAnalysis {
+                    cpp_wrapper: Some(..),
+                    ignore_reason: Ok(_),
+                    externally_callable: true,
+                    ..
+                },
+                ..
+            } | Api::StringConstructor { .. }
+                | Api::ConcreteType { .. }
+                | Api::CType { .. }
+                | Api::RustSubclassFn { .. }
+                | Api::Subclass { .. }
+                | Api::Struct {
+                    analysis: PodAndDepAnalysis {
+                        pod: PodAnalysis {
+                            kind: TypeKind::Pod,
+                            ..
+                        },
+                        ..
+                    },
+                    ..
+                }
+        )
+    }
+
+    pub(crate) fn cxxbridge_name(&self) -> Option<Ident> {
+        match self {
+            Api::Function { ref analysis, .. } => Some(analysis.cxxbridge_name.clone()),
+            Api::StringConstructor { .. }
+            | Api::Const { .. }
+            | Api::IgnoredItem { .. }
+            | Api::RustSubclassFn { .. } => None,
+            _ => Some(self.name().get_final_ident()),
+        }
+    }
+}
diff --git a/engine/src/conversion/analysis/fun/overload_tracker.rs b/engine/src/conversion/analysis/fun/overload_tracker.rs
new file mode 100644
index 0000000..6fc532c
--- /dev/null
+++ b/engine/src/conversion/analysis/fun/overload_tracker.rs
@@ -0,0 +1,77 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::HashMap;
+
+type Offsets = HashMap<String, usize>;
+
+/// Registry of all the overloads of a function found within a given
+/// namespace (i.e. mod in bindgen's output). If necessary we'll append
+/// a _nnn suffix to a function's Rust name to disambiguate overloads.
+/// Note that this is NOT necessarily the same as the suffix added by
+/// bindgen to disambiguate overloads it discovers. Its suffix is
+/// global across all functions, whereas ours is local within a given
+/// type.
+/// If bindgen adds a suffix it will be included in 'found_name'
+/// but not 'original_name' which is an annotation added by our autocxx-bindgen
+/// fork.
+#[derive(Default)]
+pub(crate) struct OverloadTracker {
+    offset_by_name: Offsets,
+    offset_by_type_and_name: HashMap<String, Offsets>,
+}
+
+impl OverloadTracker {
+    pub(crate) fn get_function_real_name(&mut self, found_name: String) -> String {
+        self.get_name(None, found_name)
+    }
+
+    pub(crate) fn get_method_real_name(&mut self, type_name: &str, found_name: String) -> String {
+        self.get_name(Some(type_name), found_name)
+    }
+
+    fn get_name(&mut self, type_name: Option<&str>, cpp_method_name: String) -> String {
+        let registry = match type_name {
+            Some(type_name) => self
+                .offset_by_type_and_name
+                .entry(type_name.to_string())
+                .or_default(),
+            None => &mut self.offset_by_name,
+        };
+        let offset = registry.entry(cpp_method_name.clone()).or_default();
+        let this_offset = *offset;
+        *offset += 1;
+        if this_offset == 0 {
+            cpp_method_name
+        } else {
+            format!("{}{}", cpp_method_name, this_offset)
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::OverloadTracker;
+
+    #[test]
+    fn test_by_function() {
+        let mut ot = OverloadTracker::default();
+        assert_eq!(ot.get_function_real_name("bob".into()), "bob");
+        assert_eq!(ot.get_function_real_name("bob".into()), "bob1");
+        assert_eq!(ot.get_function_real_name("bob".into()), "bob2");
+    }
+
+    #[test]
+    fn test_by_method() {
+        let mut ot = OverloadTracker::default();
+        assert_eq!(ot.get_method_real_name("Ty1", "bob".into()), "bob");
+        assert_eq!(ot.get_method_real_name("Ty1", "bob".into()), "bob1");
+        assert_eq!(ot.get_method_real_name("Ty2", "bob".into()), "bob");
+        assert_eq!(ot.get_method_real_name("Ty2", "bob".into()), "bob1");
+    }
+}
diff --git a/engine/src/conversion/analysis/fun/subclass.rs b/engine/src/conversion/analysis/fun/subclass.rs
new file mode 100644
index 0000000..c017249
--- /dev/null
+++ b/engine/src/conversion/analysis/fun/subclass.rs
@@ -0,0 +1,249 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+
+use syn::{parse_quote, FnArg, PatType, Type, TypePtr};
+
+use crate::conversion::analysis::fun::{FnKind, MethodKind, ReceiverMutability};
+use crate::conversion::analysis::pod::PodPhase;
+use crate::conversion::api::{
+    CppVisibility, FuncToConvert, Provenance, RustSubclassFnDetails, SubclassConstructorDetails,
+    SubclassName, SuperclassMethod, UnsafetyNeeded, Virtualness,
+};
+use crate::conversion::apivec::ApiVec;
+use crate::{
+    conversion::{
+        analysis::fun::function_wrapper::{
+            CppFunction, CppFunctionBody, CppFunctionKind, TypeConversionPolicy,
+        },
+        api::{Api, ApiName},
+    },
+    types::{make_ident, Namespace, QualifiedName},
+};
+
+use super::{FnAnalysis, FnPrePhase1};
+
+pub(super) fn subclasses_by_superclass(
+    apis: &ApiVec<PodPhase>,
+) -> HashMap<QualifiedName, Vec<SubclassName>> {
+    let mut subclasses_per_superclass: HashMap<QualifiedName, Vec<SubclassName>> = HashMap::new();
+
+    for api in apis.iter() {
+        if let Api::Subclass { name, superclass } = api {
+            subclasses_per_superclass
+                .entry(superclass.clone())
+                .or_default()
+                .push(name.clone());
+        }
+    }
+    subclasses_per_superclass
+}
+
+pub(super) fn create_subclass_fn_wrapper(
+    sub: &SubclassName,
+    super_fn_name: &QualifiedName,
+    fun: &FuncToConvert,
+) -> Box<FuncToConvert> {
+    let self_ty = Some(sub.cpp());
+    Box::new(FuncToConvert {
+        synthesized_this_type: self_ty.clone(),
+        self_ty,
+        ident: super_fn_name.get_final_ident(),
+        doc_attrs: fun.doc_attrs.clone(),
+        inputs: fun.inputs.clone(),
+        output: fun.output.clone(),
+        vis: fun.vis.clone(),
+        virtualness: Virtualness::None,
+        cpp_vis: CppVisibility::Public,
+        special_member: None,
+        unused_template_param: fun.unused_template_param,
+        original_name: None,
+        references: fun.references.clone(),
+        add_to_trait: fun.add_to_trait.clone(),
+        is_deleted: fun.is_deleted,
+        synthetic_cpp: None,
+        provenance: Provenance::SynthesizedOther,
+        variadic: fun.variadic,
+    })
+}
+
+pub(super) fn create_subclass_trait_item(
+    name: ApiName,
+    analysis: &FnAnalysis,
+    receiver_mutability: &ReceiverMutability,
+    receiver: QualifiedName,
+    is_pure_virtual: bool,
+) -> Api<FnPrePhase1> {
+    let param_names = analysis
+        .param_details
+        .iter()
+        .map(|pd| pd.name.clone())
+        .collect();
+    Api::SubclassTraitItem {
+        name,
+        details: SuperclassMethod {
+            name: make_ident(&analysis.rust_name),
+            params: analysis.params.clone(),
+            ret_type: analysis.ret_type.clone(),
+            param_names,
+            receiver_mutability: receiver_mutability.clone(),
+            requires_unsafe: UnsafetyNeeded::from_param_details(&analysis.param_details, false),
+            is_pure_virtual,
+            receiver,
+        },
+    }
+}
+
+pub(super) fn create_subclass_function(
+    sub: &SubclassName,
+    analysis: &super::FnAnalysis,
+    name: &ApiName,
+    receiver_mutability: &ReceiverMutability,
+    superclass: &QualifiedName,
+    dependencies: Vec<QualifiedName>,
+) -> Api<FnPrePhase1> {
+    let cpp = sub.cpp();
+    let holder_name = sub.holder();
+    let rust_call_name = make_ident(format!(
+        "{}_{}",
+        sub.0.name.get_final_item(),
+        name.name.get_final_item()
+    ));
+    let params = std::iter::once(parse_quote! {
+        me: & #holder_name
+    })
+    .chain(analysis.params.iter().skip(1).cloned())
+    .collect();
+    let kind = if matches!(receiver_mutability, ReceiverMutability::Mutable) {
+        CppFunctionKind::Method
+    } else {
+        CppFunctionKind::ConstMethod
+    };
+    let argument_conversion = analysis
+        .param_details
+        .iter()
+        .skip(1)
+        .map(|p| p.conversion.clone())
+        .collect();
+    Api::RustSubclassFn {
+        name: ApiName::new_in_root_namespace(rust_call_name.clone()),
+        subclass: sub.clone(),
+        details: Box::new(RustSubclassFnDetails {
+            params,
+            ret: analysis.ret_type.clone(),
+            method_name: make_ident(&analysis.rust_name),
+            cpp_impl: CppFunction {
+                payload: CppFunctionBody::FunctionCall(Namespace::new(), rust_call_name),
+                wrapper_function_name: make_ident(&analysis.rust_name),
+                original_cpp_name: name.cpp_name(),
+                return_conversion: analysis.ret_conversion.clone(),
+                argument_conversion,
+                kind,
+                pass_obs_field: true,
+                qualification: Some(cpp),
+            },
+            superclass: superclass.clone(),
+            receiver_mutability: receiver_mutability.clone(),
+            dependencies,
+            requires_unsafe: UnsafetyNeeded::from_param_details(&analysis.param_details, false),
+            is_pure_virtual: matches!(
+                analysis.kind,
+                FnKind::Method {
+                    method_kind: MethodKind::PureVirtual(..),
+                    ..
+                }
+            ),
+        }),
+    }
+}
+
+pub(super) fn create_subclass_constructor(
+    sub: SubclassName,
+    analysis: &FnAnalysis,
+    sup: &QualifiedName,
+    fun: &FuncToConvert,
+) -> (Box<FuncToConvert>, ApiName) {
+    let holder = sub.holder();
+    let cpp = sub.cpp();
+    let wrapper_function_name = cpp.get_final_ident();
+    let initial_arg = TypeConversionPolicy::new_unconverted(parse_quote! {
+        rust::Box< #holder >
+    });
+    let args = std::iter::once(initial_arg).chain(
+        analysis
+            .param_details
+            .iter()
+            .skip(1) // skip placement new destination
+            .map(|aa| aa.conversion.clone()),
+    );
+    let cpp_impl = CppFunction {
+        payload: CppFunctionBody::ConstructSuperclass(sup.to_cpp_name()),
+        wrapper_function_name,
+        return_conversion: None,
+        argument_conversion: args.collect(),
+        kind: CppFunctionKind::SynthesizedConstructor,
+        pass_obs_field: false,
+        qualification: Some(cpp.clone()),
+        original_cpp_name: cpp.to_cpp_name(),
+    };
+    let subclass_constructor_details = Box::new(SubclassConstructorDetails {
+        subclass: sub.clone(),
+        is_trivial: analysis.param_details.len() == 1, // just placement new
+        // destination, no other parameters
+        cpp_impl,
+    });
+    let subclass_constructor_name =
+        make_ident(format!("{}_{}", cpp.get_final_item(), cpp.get_final_item()));
+    let mut existing_params = fun.inputs.clone();
+    if let Some(FnArg::Typed(PatType { ty, .. })) = existing_params.first_mut() {
+        if let Type::Ptr(TypePtr { elem, .. }) = &mut **ty {
+            *elem = Box::new(Type::Path(sub.cpp().to_type_path()));
+        } else {
+            panic!("Unexpected self type parameter when creating subclass constructor");
+        }
+    } else {
+        panic!("Unexpected self type parameter when creating subclass constructor");
+    }
+    let mut existing_params = existing_params.into_iter();
+    let self_param = existing_params.next();
+    let boxed_holder_param: FnArg = parse_quote! {
+        peer: rust::Box<#holder>
+    };
+    let inputs = self_param
+        .into_iter()
+        .chain(std::iter::once(boxed_holder_param))
+        .chain(existing_params)
+        .collect();
+    let maybe_wrap = Box::new(FuncToConvert {
+        ident: subclass_constructor_name.clone(),
+        doc_attrs: fun.doc_attrs.clone(),
+        inputs,
+        output: fun.output.clone(),
+        vis: fun.vis.clone(),
+        virtualness: Virtualness::None,
+        cpp_vis: CppVisibility::Public,
+        special_member: fun.special_member.clone(),
+        original_name: None,
+        unused_template_param: fun.unused_template_param,
+        references: fun.references.clone(),
+        synthesized_this_type: Some(cpp.clone()),
+        self_ty: Some(cpp),
+        add_to_trait: None,
+        is_deleted: fun.is_deleted,
+        synthetic_cpp: None,
+        provenance: Provenance::SynthesizedSubclassConstructor(subclass_constructor_details),
+        variadic: fun.variadic,
+    });
+    let subclass_constructor_name = ApiName::new_with_cpp_name(
+        &Namespace::new(),
+        subclass_constructor_name,
+        Some(sub.cpp().get_final_item().to_string()),
+    );
+    (maybe_wrap, subclass_constructor_name)
+}
diff --git a/engine/src/conversion/analysis/gc.rs b/engine/src/conversion/analysis/gc.rs
new file mode 100644
index 0000000..0734f15
--- /dev/null
+++ b/engine/src/conversion/analysis/gc.rs
@@ -0,0 +1,70 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+use indexmap::set::IndexSet as HashSet;
+
+use autocxx_parser::IncludeCppConfig;
+
+use crate::{
+    conversion::{api::Api, apivec::ApiVec},
+    types::QualifiedName,
+};
+
+use super::{deps::HasDependencies, fun::FnPhase};
+
+/// This is essentially mark-and-sweep garbage collection of the
+/// [Api]s that we've discovered. Why do we do this, you might wonder?
+/// It seems a bit strange given that we pass an explicit allowlist
+/// to bindgen.
+/// There are two circumstances under which we want to discard
+/// some of the APIs we encounter parsing the bindgen.
+/// 1) We simplify some struct to be non-POD. In this case, we'll
+///    discard all the fields within it. Those fields can be, and
+///    in fact often _are_, stuff which we have trouble converting
+///    e.g. std::string or std::string::value_type or
+///    my_derived_thing<std::basic_string::value_type> or some
+///    other permutation. In such cases, we want to discard those
+///    field types with prejudice.
+/// 2) block! may be used to ban certain APIs. This often eliminates
+///    some methods from a given struct/class. In which case, we
+///    don't care about the other parameter types passed into those
+///    APIs either.
+pub(crate) fn filter_apis_by_following_edges_from_allowlist(
+    apis: ApiVec<FnPhase>,
+    config: &IncludeCppConfig,
+) -> ApiVec<FnPhase> {
+    let mut todos: Vec<QualifiedName> = apis
+        .iter()
+        .filter(|api| {
+            let tnforal = api.name_for_allowlist();
+            config.is_on_allowlist(&tnforal.to_cpp_name())
+        })
+        .map(Api::name)
+        .cloned()
+        .collect();
+    let mut by_typename: HashMap<QualifiedName, ApiVec<FnPhase>> = HashMap::new();
+    for api in apis.into_iter() {
+        let tn = api.name().clone();
+        by_typename.entry(tn).or_default().push(api);
+    }
+    let mut done = HashSet::new();
+    let mut output = ApiVec::new();
+    while !todos.is_empty() {
+        let todo = todos.remove(0);
+        if done.contains(&todo) {
+            continue;
+        }
+        if let Some(mut these_apis) = by_typename.remove(&todo) {
+            todos.extend(these_apis.iter().flat_map(|api| api.deps().cloned()));
+            output.append(&mut these_apis);
+        } // otherwise, probably an intrinsic e.g. uint32_t.
+        done.insert(todo);
+    }
+    output
+}
diff --git a/engine/src/conversion/analysis/mod.rs b/engine/src/conversion/analysis/mod.rs
new file mode 100644
index 0000000..d733011
--- /dev/null
+++ b/engine/src/conversion/analysis/mod.rs
@@ -0,0 +1,28 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub(crate) mod abstract_types;
+pub(crate) mod allocators;
+pub(crate) mod casts;
+pub(crate) mod constructor_deps;
+pub(crate) mod ctypes;
+pub(crate) mod deps;
+mod depth_first;
+mod doc_label;
+pub(crate) mod fun;
+pub(crate) mod gc;
+mod name_check;
+pub(crate) mod pod; // hey, that rhymes
+pub(crate) mod remove_ignored;
+mod replace_hopeless_typedef_targets;
+pub(crate) mod tdef;
+mod type_converter;
+
+pub(crate) use name_check::check_names;
+pub(crate) use replace_hopeless_typedef_targets::replace_hopeless_typedef_targets;
+pub(crate) use type_converter::PointerTreatment;
diff --git a/engine/src/conversion/analysis/name_check.rs b/engine/src/conversion/analysis/name_check.rs
new file mode 100644
index 0000000..7547c7c
--- /dev/null
+++ b/engine/src/conversion/analysis/name_check.rs
@@ -0,0 +1,115 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+
+use syn::Ident;
+
+use crate::{
+    conversion::{
+        api::{Api, SubclassName},
+        apivec::ApiVec,
+        error_reporter::convert_item_apis,
+        ConvertError,
+    },
+    types::{validate_ident_ok_for_cxx, QualifiedName},
+};
+
+use super::fun::FnPhase;
+
+/// Do some final checks that the names we've come up with can be represented
+/// within cxx.
+pub(crate) fn check_names(apis: ApiVec<FnPhase>) -> ApiVec<FnPhase> {
+    // If any items have names which can't be represented by cxx,
+    // abort. This check should ideally be done at the times we fill in the
+    // `name` field of each `api` in the first place, at parse time, though
+    // as the `name` field of each API may change during various analysis phases,
+    // currently it seems better to do it here to ensure we respect
+    // the output of any such changes.
+    let mut intermediate = ApiVec::new();
+    convert_item_apis(apis, &mut intermediate, |api| match api {
+        Api::Typedef { ref name, .. }
+        | Api::ForwardDeclaration { ref name, .. }
+        | Api::OpaqueTypedef { ref name, .. }
+        | Api::Const { ref name, .. }
+        | Api::Enum { ref name, .. }
+        | Api::Struct { ref name, .. } => {
+            validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
+            if let Some(cpp_name) = name.cpp_name_if_present() {
+                // The C++ name might itself be outer_type::inner_type and thus may
+                // have multiple segments.
+                validate_all_segments_ok_for_cxx(
+                    QualifiedName::new_from_cpp_name(cpp_name).segment_iter(),
+                )?;
+            }
+            Ok(Box::new(std::iter::once(api)))
+        }
+        Api::Subclass {
+            name: SubclassName(ref name),
+            ref superclass,
+        } => {
+            validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
+            validate_all_segments_ok_for_cxx(superclass.segment_iter())?;
+            Ok(Box::new(std::iter::once(api)))
+        }
+        Api::Function { ref name, .. } => {
+            // we don't handle function names here because
+            // the function analysis does an equivalent check. Instead of just rejecting
+            // the function, it creates a wrapper function instead with a more
+            // palatable name. That's preferable to rejecting the API entirely.
+            validate_all_segments_ok_for_cxx(name.name.segment_iter())?;
+            Ok(Box::new(std::iter::once(api)))
+        }
+        Api::ConcreteType { .. }
+        | Api::CType { .. }
+        | Api::StringConstructor { .. }
+        | Api::RustType { .. }
+        | Api::RustSubclassFn { .. }
+        | Api::RustFn { .. }
+        | Api::SubclassTraitItem { .. }
+        | Api::ExternCppType { .. }
+        | Api::IgnoredItem { .. } => Ok(Box::new(std::iter::once(api))),
+    });
+
+    // Reject any names which are duplicates within the cxx bridge mod,
+    // that has a flat namespace.
+    let mut names_found: HashMap<Ident, Vec<String>> = HashMap::new();
+    for api in intermediate.iter() {
+        let my_name = api.cxxbridge_name();
+        if let Some(name) = my_name {
+            let e = names_found.entry(name).or_default();
+            e.push(api.name_info().name.to_string());
+        }
+    }
+    let mut results = ApiVec::new();
+    convert_item_apis(intermediate, &mut results, |api| {
+        let my_name = api.cxxbridge_name();
+        if let Some(name) = my_name {
+            let symbols_for_this_name = names_found.entry(name).or_default();
+            if symbols_for_this_name.len() > 1usize {
+                Err(ConvertError::DuplicateCxxBridgeName(
+                    symbols_for_this_name.clone(),
+                ))
+            } else {
+                Ok(Box::new(std::iter::once(api)))
+            }
+        } else {
+            Ok(Box::new(std::iter::once(api)))
+        }
+    });
+    results
+}
+
+fn validate_all_segments_ok_for_cxx(
+    items: impl Iterator<Item = String>,
+) -> Result<(), ConvertError> {
+    for seg in items {
+        validate_ident_ok_for_cxx(&seg)?;
+    }
+    Ok(())
+}
diff --git a/engine/src/conversion/analysis/pod/byvalue_checker.rs b/engine/src/conversion/analysis/pod/byvalue_checker.rs
new file mode 100644
index 0000000..de72eec
--- /dev/null
+++ b/engine/src/conversion/analysis/pod/byvalue_checker.rs
@@ -0,0 +1,343 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::conversion::apivec::ApiVec;
+use crate::{conversion::ConvertError, known_types::known_types};
+use crate::{
+    conversion::{
+        analysis::tdef::TypedefPhase,
+        api::{Api, TypedefKind},
+    },
+    types::{Namespace, QualifiedName},
+};
+use autocxx_parser::IncludeCppConfig;
+use std::collections::HashMap;
+use syn::{ItemStruct, Type};
+
+#[derive(Clone)]
+enum PodState {
+    UnsafeToBePod(String),
+    SafeToBePod,
+    IsPod,
+    IsAlias(QualifiedName),
+}
+
+#[derive(Clone)]
+struct StructDetails {
+    state: PodState,
+    dependent_structs: Vec<QualifiedName>,
+}
+
+impl StructDetails {
+    fn new(state: PodState) -> Self {
+        StructDetails {
+            state,
+            dependent_structs: Vec::new(),
+        }
+    }
+}
+
+/// Type which is able to check whether it's safe to make a type
+/// fully representable by cxx. For instance if it is a struct containing
+/// a struct containing a std::string, the answer is no, because that
+/// std::string contains a self-referential pointer.
+/// It is possible that this is duplicative of the information stored
+/// elsewhere in the `Api` list and could possibly be removed or simplified.
+pub struct ByValueChecker {
+    // Mapping from type name to whether it is safe to be POD
+    results: HashMap<QualifiedName, StructDetails>,
+}
+
+impl ByValueChecker {
+    pub fn new() -> Self {
+        let mut results = HashMap::new();
+        for (tn, by_value_safe) in known_types().get_pod_safe_types() {
+            let safety = if by_value_safe {
+                PodState::IsPod
+            } else {
+                PodState::UnsafeToBePod(format!("type {} is not safe for POD", tn))
+            };
+            results.insert(tn.clone(), StructDetails::new(safety));
+        }
+        ByValueChecker { results }
+    }
+
+    /// Scan APIs to work out which are by-value safe. Constructs a [ByValueChecker]
+    /// that others can use to query the results.
+    pub(crate) fn new_from_apis(
+        apis: &ApiVec<TypedefPhase>,
+        config: &IncludeCppConfig,
+    ) -> Result<ByValueChecker, ConvertError> {
+        let mut byvalue_checker = ByValueChecker::new();
+        for blocklisted in config.get_blocklist() {
+            let tn = QualifiedName::new_from_cpp_name(blocklisted);
+            let safety = PodState::UnsafeToBePod(format!("type {} is on the blocklist", &tn));
+            byvalue_checker
+                .results
+                .insert(tn, StructDetails::new(safety));
+        }
+        for api in apis.iter() {
+            match api {
+                Api::Typedef { analysis, .. } => {
+                    let name = api.name();
+                    let typedef_type = match analysis.kind {
+                        TypedefKind::Type(ref type_item) => match type_item.ty.as_ref() {
+                            Type::Path(typ) => {
+                                let target_tn = QualifiedName::from_type_path(typ);
+                                known_types().consider_substitution(&target_tn)
+                            }
+                            _ => None,
+                        },
+                        TypedefKind::Use(_, ref ty) => match **ty {
+                            Type::Path(ref typ) => {
+                                let target_tn = QualifiedName::from_type_path(typ);
+                                known_types().consider_substitution(&target_tn)
+                            }
+                            _ => None,
+                        },
+                    };
+                    match &typedef_type {
+                        Some(typ) => {
+                            byvalue_checker.results.insert(
+                                name.clone(),
+                                StructDetails::new(PodState::IsAlias(
+                                    QualifiedName::from_type_path(typ),
+                                )),
+                            );
+                        }
+                        None => byvalue_checker.ingest_nonpod_type(name.clone()),
+                    }
+                }
+                Api::Struct { details, .. } => {
+                    byvalue_checker.ingest_struct(&details.item, api.name().get_namespace())
+                }
+                Api::Enum { .. } => {
+                    byvalue_checker
+                        .results
+                        .insert(api.name().clone(), StructDetails::new(PodState::IsPod));
+                }
+                Api::ExternCppType { pod: true, .. } => {
+                    byvalue_checker
+                        .results
+                        .insert(api.name().clone(), StructDetails::new(PodState::IsPod));
+                }
+                _ => {}
+            }
+        }
+        let pod_requests = config
+            .get_pod_requests()
+            .iter()
+            .map(|ty| QualifiedName::new_from_cpp_name(ty))
+            .collect();
+        byvalue_checker
+            .satisfy_requests(pod_requests)
+            .map_err(ConvertError::UnsafePodType)?;
+        Ok(byvalue_checker)
+    }
+
+    fn ingest_struct(&mut self, def: &ItemStruct, ns: &Namespace) {
+        // For this struct, work out whether it _could_ be safe as a POD.
+        let tyname = QualifiedName::new(ns, def.ident.clone());
+        let mut field_safety_problem = PodState::SafeToBePod;
+        let fieldlist = Self::get_field_types(def);
+        for ty_id in &fieldlist {
+            match self.results.get(ty_id) {
+                None => {
+                    field_safety_problem = PodState::UnsafeToBePod(format!(
+                        "Type {} could not be POD because its dependent type {} isn't known",
+                        tyname, ty_id
+                    ));
+                    break;
+                }
+                Some(deets) => {
+                    if let PodState::UnsafeToBePod(reason) = &deets.state {
+                        let new_reason = format!("Type {} could not be POD because its dependent type {} isn't safe to be POD. Because: {}", tyname, ty_id, reason);
+                        field_safety_problem = PodState::UnsafeToBePod(new_reason);
+                        break;
+                    }
+                }
+            }
+        }
+        if Self::has_vtable(def) {
+            let reason = format!(
+                "Type {} could not be POD because it has virtual functions.",
+                tyname
+            );
+            field_safety_problem = PodState::UnsafeToBePod(reason);
+        }
+        let mut my_details = StructDetails::new(field_safety_problem);
+        my_details.dependent_structs = fieldlist;
+        self.results.insert(tyname, my_details);
+    }
+
+    fn ingest_nonpod_type(&mut self, tyname: QualifiedName) {
+        let new_reason = format!("Type {} is a typedef to a complex type", tyname);
+        self.results.insert(
+            tyname,
+            StructDetails::new(PodState::UnsafeToBePod(new_reason)),
+        );
+    }
+
+    fn satisfy_requests(&mut self, mut requests: Vec<QualifiedName>) -> Result<(), String> {
+        while !requests.is_empty() {
+            let ty_id = requests.remove(requests.len() - 1);
+            let deets = self.results.get_mut(&ty_id);
+            let mut alias_to_consider = None;
+            match deets {
+                None => {
+                    return Err(format!(
+                        "Unable to make {} POD because we never saw a struct definition",
+                        ty_id
+                    ))
+                }
+                Some(deets) => match &deets.state {
+                    PodState::UnsafeToBePod(error_msg) => return Err(error_msg.clone()),
+                    PodState::IsPod => {}
+                    PodState::SafeToBePod => {
+                        deets.state = PodState::IsPod;
+                        requests.extend_from_slice(&deets.dependent_structs);
+                    }
+                    PodState::IsAlias(target_type) => {
+                        alias_to_consider = Some(target_type.clone());
+                    }
+                },
+            }
+            // Do the following outside the match to avoid borrow checker violation.
+            if let Some(alias) = alias_to_consider {
+                match self.results.get(&alias) {
+                    None => requests.extend_from_slice(&[alias, ty_id]), // try again after resolving alias target
+                    Some(alias_target_deets) => {
+                        self.results.get_mut(&ty_id).unwrap().state =
+                            alias_target_deets.state.clone();
+                    }
+                }
+            }
+        }
+        Ok(())
+    }
+
+    /// Return whether a given type is POD (i.e. can be represented by value in Rust) or not.
+    /// Unless we've got a definite record that it _is_, we return false.
+    /// Some types won't be in our `results` map. For example: (a) AutocxxConcrete types
+    /// which we've synthesized; (b) types we couldn't parse but returned ignorable
+    /// errors so that we could continue. Assume non-POD for all such cases.
+    pub fn is_pod(&self, ty_id: &QualifiedName) -> bool {
+        matches!(
+            self.results.get(ty_id),
+            Some(StructDetails {
+                state: PodState::IsPod,
+                dependent_structs: _,
+            })
+        )
+    }
+
+    fn get_field_types(def: &ItemStruct) -> Vec<QualifiedName> {
+        let mut results = Vec::new();
+        for f in &def.fields {
+            let fty = &f.ty;
+            if let Type::Path(p) = fty {
+                results.push(QualifiedName::from_type_path(p));
+            }
+            // TODO handle anything else which bindgen might spit out, e.g. arrays?
+        }
+        results
+    }
+
+    fn has_vtable(def: &ItemStruct) -> bool {
+        for f in &def.fields {
+            if f.ident.as_ref().map(|id| id == "vtable_").unwrap_or(false) {
+                return true;
+            }
+        }
+        false
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::ByValueChecker;
+    use crate::types::{Namespace, QualifiedName};
+    use syn::{parse_quote, Ident, ItemStruct};
+
+    fn ty_from_ident(id: &Ident) -> QualifiedName {
+        QualifiedName::new_from_cpp_name(&id.to_string())
+    }
+
+    #[test]
+    fn test_primitive_by_itself() {
+        let bvc = ByValueChecker::new();
+        let t_id = QualifiedName::new_from_cpp_name("u32");
+        assert!(bvc.is_pod(&t_id));
+    }
+
+    #[test]
+    fn test_primitives() {
+        let mut bvc = ByValueChecker::new();
+        let t: ItemStruct = parse_quote! {
+            struct Foo {
+                a: i32,
+                b: i64,
+            }
+        };
+        let t_id = ty_from_ident(&t.ident);
+        bvc.ingest_struct(&t, &Namespace::new());
+        bvc.satisfy_requests(vec![t_id.clone()]).unwrap();
+        assert!(bvc.is_pod(&t_id));
+    }
+
+    #[test]
+    fn test_nested_primitives() {
+        let mut bvc = ByValueChecker::new();
+        let t: ItemStruct = parse_quote! {
+            struct Foo {
+                a: i32,
+                b: i64,
+            }
+        };
+        bvc.ingest_struct(&t, &Namespace::new());
+        let t: ItemStruct = parse_quote! {
+            struct Bar {
+                a: Foo,
+                b: i64,
+            }
+        };
+        let t_id = ty_from_ident(&t.ident);
+        bvc.ingest_struct(&t, &Namespace::new());
+        bvc.satisfy_requests(vec![t_id.clone()]).unwrap();
+        assert!(bvc.is_pod(&t_id));
+    }
+
+    #[test]
+    fn test_with_up() {
+        let mut bvc = ByValueChecker::new();
+        let t: ItemStruct = parse_quote! {
+            struct Bar {
+                a: cxx::UniquePtr<CxxString>,
+                b: i64,
+            }
+        };
+        let t_id = ty_from_ident(&t.ident);
+        bvc.ingest_struct(&t, &Namespace::new());
+        bvc.satisfy_requests(vec![t_id.clone()]).unwrap();
+        assert!(bvc.is_pod(&t_id));
+    }
+
+    #[test]
+    fn test_with_cxxstring() {
+        let mut bvc = ByValueChecker::new();
+        let t: ItemStruct = parse_quote! {
+            struct Bar {
+                a: CxxString,
+                b: i64,
+            }
+        };
+        let t_id = ty_from_ident(&t.ident);
+        bvc.ingest_struct(&t, &Namespace::new());
+        assert!(bvc.satisfy_requests(vec![t_id]).is_err());
+    }
+}
diff --git a/engine/src/conversion/analysis/pod/mod.rs b/engine/src/conversion/analysis/pod/mod.rs
new file mode 100644
index 0000000..6722c23
--- /dev/null
+++ b/engine/src/conversion/analysis/pod/mod.rs
@@ -0,0 +1,257 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod byvalue_checker;
+
+use indexmap::map::IndexMap as HashMap;
+use indexmap::set::IndexSet as HashSet;
+
+use autocxx_parser::IncludeCppConfig;
+use byvalue_checker::ByValueChecker;
+use syn::{ItemEnum, ItemStruct, Type, Visibility};
+
+use crate::{
+    conversion::{
+        analysis::type_converter::{self, add_analysis, TypeConversionContext, TypeConverter},
+        api::{AnalysisPhase, Api, ApiName, CppVisibility, NullPhase, StructDetails, TypeKind},
+        apivec::ApiVec,
+        convert_error::{ConvertErrorWithContext, ErrorContext},
+        error_reporter::convert_apis,
+        parse::BindgenSemanticAttributes,
+        ConvertError,
+    },
+    types::{Namespace, QualifiedName},
+};
+
+use super::tdef::{TypedefAnalysis, TypedefPhase};
+
+pub(crate) struct FieldInfo {
+    pub(crate) ty: Type,
+    pub(crate) type_kind: type_converter::TypeKind,
+}
+
+pub(crate) struct PodAnalysis {
+    pub(crate) kind: TypeKind,
+    pub(crate) bases: HashSet<QualifiedName>,
+    /// Base classes for which we should create casts.
+    /// That's just those which are on the allowlist,
+    /// because otherwise we don't know whether they're
+    /// abstract or not.
+    pub(crate) castable_bases: HashSet<QualifiedName>,
+    pub(crate) field_deps: HashSet<QualifiedName>,
+    pub(crate) field_info: Vec<FieldInfo>,
+    pub(crate) is_generic: bool,
+    pub(crate) in_anonymous_namespace: bool,
+}
+
+pub(crate) struct PodPhase;
+
+impl AnalysisPhase for PodPhase {
+    type TypedefAnalysis = TypedefAnalysis;
+    type StructAnalysis = PodAnalysis;
+    type FunAnalysis = ();
+}
+
+/// In our set of APIs, work out which ones are safe to represent
+/// by value in Rust (e.g. they don't have a destructor) and record
+/// as such. Return a set of APIs annotated with extra metadata,
+/// and an object which can be used to query the POD status of any
+/// type whether or not it's one of the [Api]s.
+pub(crate) fn analyze_pod_apis(
+    apis: ApiVec<TypedefPhase>,
+    config: &IncludeCppConfig,
+) -> Result<ApiVec<PodPhase>, ConvertError> {
+    // This next line will return an error if any of the 'generate_pod'
+    // directives from the user can't be met because, for instance,
+    // a type contains a std::string or some other type which can't be
+    // held safely by value in Rust.
+    let byvalue_checker = ByValueChecker::new_from_apis(&apis, config)?;
+    let mut extra_apis = ApiVec::new();
+    let mut type_converter = TypeConverter::new(config, &apis);
+    let mut results = ApiVec::new();
+    convert_apis(
+        apis,
+        &mut results,
+        Api::fun_unchanged,
+        |name, details, _| {
+            analyze_struct(
+                &byvalue_checker,
+                &mut type_converter,
+                &mut extra_apis,
+                name,
+                details,
+                config,
+            )
+        },
+        analyze_enum,
+        Api::typedef_unchanged,
+    );
+    // Conceivably, the process of POD-analysing the first set of APIs could result
+    // in us creating new APIs to concretize generic types.
+    let extra_apis: ApiVec<PodPhase> = extra_apis.into_iter().map(add_analysis).collect();
+    let mut more_extra_apis = ApiVec::new();
+    convert_apis(
+        extra_apis,
+        &mut results,
+        Api::fun_unchanged,
+        |name, details, _| {
+            analyze_struct(
+                &byvalue_checker,
+                &mut type_converter,
+                &mut more_extra_apis,
+                name,
+                details,
+                config,
+            )
+        },
+        analyze_enum,
+        Api::typedef_unchanged,
+    );
+    assert!(more_extra_apis.is_empty());
+    Ok(results)
+}
+
+fn analyze_enum(
+    name: ApiName,
+    mut item: ItemEnum,
+) -> Result<Box<dyn Iterator<Item = Api<PodPhase>>>, ConvertErrorWithContext> {
+    let metadata = BindgenSemanticAttributes::new_retaining_others(&mut item.attrs);
+    metadata.check_for_fatal_attrs(&name.name.get_final_ident())?;
+    Ok(Box::new(std::iter::once(Api::Enum { name, item })))
+}
+
+fn analyze_struct(
+    byvalue_checker: &ByValueChecker,
+    type_converter: &mut TypeConverter,
+    extra_apis: &mut ApiVec<NullPhase>,
+    name: ApiName,
+    mut details: Box<StructDetails>,
+    config: &IncludeCppConfig,
+) -> Result<Box<dyn Iterator<Item = Api<PodPhase>>>, ConvertErrorWithContext> {
+    let id = name.name.get_final_ident();
+    if details.vis != CppVisibility::Public {
+        return Err(ConvertErrorWithContext(
+            ConvertError::NonPublicNestedType,
+            Some(ErrorContext::new_for_item(id)),
+        ));
+    }
+    let metadata = BindgenSemanticAttributes::new_retaining_others(&mut details.item.attrs);
+    metadata.check_for_fatal_attrs(&id)?;
+    let bases = get_bases(&details.item);
+    let mut field_deps = HashSet::new();
+    let mut field_info = Vec::new();
+    let field_conversion_errors = get_struct_field_types(
+        type_converter,
+        name.name.get_namespace(),
+        &details.item,
+        &mut field_deps,
+        &mut field_info,
+        extra_apis,
+    );
+    let type_kind = if byvalue_checker.is_pod(&name.name) {
+        // It's POD so any errors encountered parsing its fields are important.
+        // Let's not allow anything to be POD if it's got rvalue reference fields.
+        if details.has_rvalue_reference_fields {
+            return Err(ConvertErrorWithContext(
+                ConvertError::RValueReferenceField,
+                Some(ErrorContext::new_for_item(id)),
+            ));
+        }
+        if let Some(err) = field_conversion_errors.into_iter().next() {
+            return Err(ConvertErrorWithContext(
+                err,
+                Some(ErrorContext::new_for_item(id)),
+            ));
+        }
+        TypeKind::Pod
+    } else {
+        TypeKind::NonPod
+    };
+    let castable_bases = bases
+        .iter()
+        .filter(|(_, is_public)| **is_public)
+        .map(|(base, _)| base)
+        .filter(|base| config.is_on_allowlist(&base.to_cpp_name()))
+        .cloned()
+        .collect();
+    let is_generic = !details.item.generics.params.is_empty();
+    let in_anonymous_namespace = name
+        .name
+        .ns_segment_iter()
+        .any(|ns| ns.starts_with("_bindgen_mod"));
+    Ok(Box::new(std::iter::once(Api::Struct {
+        name,
+        details,
+        analysis: PodAnalysis {
+            kind: type_kind,
+            bases: bases.into_keys().collect(),
+            castable_bases,
+            field_deps,
+            field_info,
+            is_generic,
+            in_anonymous_namespace,
+        },
+    })))
+}
+
+fn get_struct_field_types(
+    type_converter: &mut TypeConverter,
+    ns: &Namespace,
+    s: &ItemStruct,
+    field_deps: &mut HashSet<QualifiedName>,
+    field_info: &mut Vec<FieldInfo>,
+    extra_apis: &mut ApiVec<NullPhase>,
+) -> Vec<ConvertError> {
+    let mut convert_errors = Vec::new();
+    for f in &s.fields {
+        let annotated =
+            type_converter.convert_type(f.ty.clone(), ns, &TypeConversionContext::WithinReference);
+        match annotated {
+            Ok(mut r) => {
+                extra_apis.append(&mut r.extra_apis);
+                // Skip base classes represented as fields. Anything which wants to include bases can chain
+                // those to the list we're building.
+                if !f
+                    .ident
+                    .as_ref()
+                    .map(|id| {
+                        id.to_string().starts_with("_base")
+                            || id.to_string().starts_with("__bindgen_padding")
+                    })
+                    .unwrap_or(false)
+                {
+                    field_deps.extend(r.types_encountered);
+                    field_info.push(FieldInfo {
+                        ty: r.ty,
+                        type_kind: r.kind,
+                    });
+                }
+            }
+            Err(e) => convert_errors.push(e),
+        };
+    }
+    convert_errors
+}
+
+/// Map to whether the bases are public.
+fn get_bases(item: &ItemStruct) -> HashMap<QualifiedName, bool> {
+    item.fields
+        .iter()
+        .filter_map(|f| {
+            let is_public = matches!(f.vis, Visibility::Public(_));
+            match &f.ty {
+                Type::Path(typ) => f
+                    .ident
+                    .as_ref()
+                    .filter(|id| id.to_string().starts_with("_base"))
+                    .map(|_| (QualifiedName::from_type_path(typ), is_public)),
+                _ => None,
+            }
+        })
+        .collect()
+}
diff --git a/engine/src/conversion/analysis/remove_ignored.rs b/engine/src/conversion/analysis/remove_ignored.rs
new file mode 100644
index 0000000..bd11b13
--- /dev/null
+++ b/engine/src/conversion/analysis/remove_ignored.rs
@@ -0,0 +1,95 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::set::IndexSet as HashSet;
+
+use super::deps::HasDependencies;
+use super::fun::{FnAnalysis, FnKind, FnPhase};
+use crate::conversion::apivec::ApiVec;
+use crate::conversion::{convert_error::ErrorContext, ConvertError};
+use crate::{conversion::api::Api, known_types};
+
+/// Remove any APIs which depend on other items which have been ignored.
+/// We also eliminate any APIs that depend on some type that we just don't
+/// know about at all. In either case, we don't simply remove the type, but instead
+/// replace it with an error marker.
+pub(crate) fn filter_apis_by_ignored_dependents(mut apis: ApiVec<FnPhase>) -> ApiVec<FnPhase> {
+    let (ignored_items, valid_items): (Vec<&Api<_>>, Vec<&Api<_>>) = apis
+        .iter()
+        .partition(|api| matches!(api, Api::IgnoredItem { .. }));
+    let mut ignored_items: HashSet<_> = ignored_items
+        .into_iter()
+        .map(|api| api.name().clone())
+        .collect();
+    let valid_types: HashSet<_> = valid_items
+        .into_iter()
+        .flat_map(|api| api.valid_types())
+        .collect();
+    let mut iterate_again = true;
+    while iterate_again {
+        iterate_again = false;
+        apis = apis
+            .into_iter()
+            .map(|api| {
+                let ignored_dependents: HashSet<_> = api
+                    .deps()
+                    .filter(|dep| ignored_items.contains(*dep))
+                    .cloned()
+                    .collect();
+                if !ignored_dependents.is_empty() {
+                    iterate_again = true;
+                    ignored_items.insert(api.name().clone());
+                    create_ignore_item(api, ConvertError::IgnoredDependent(ignored_dependents))
+                } else {
+                    let mut missing_deps = api.deps().filter(|dep| {
+                        !valid_types.contains(*dep) && !known_types().is_known_type(dep)
+                    });
+                    let first = missing_deps.next();
+                    std::mem::drop(missing_deps);
+                    if let Some(missing_dep) = first.cloned() {
+                        create_ignore_item(api, ConvertError::UnknownDependentType(missing_dep))
+                    } else {
+                        api
+                    }
+                }
+            })
+            .collect();
+    }
+    apis
+}
+
+fn create_ignore_item(api: Api<FnPhase>, err: ConvertError) -> Api<FnPhase> {
+    let id = api.name().get_final_ident();
+    log::info!("Marking as ignored: {} because {}", id.to_string(), err);
+    Api::IgnoredItem {
+        name: api.name_info().clone(),
+        err,
+        ctx: match api {
+            Api::Function {
+                analysis:
+                    FnAnalysis {
+                        kind: FnKind::TraitMethod { .. },
+                        ..
+                    },
+                ..
+            } => None,
+            Api::Function {
+                analysis:
+                    FnAnalysis {
+                        kind:
+                            FnKind::Method {
+                                impl_for: self_ty, ..
+                            },
+                        ..
+                    },
+                ..
+            } => Some(ErrorContext::new_for_method(self_ty.get_final_ident(), id)),
+            _ => Some(ErrorContext::new_for_item(id)),
+        },
+    }
+}
diff --git a/engine/src/conversion/analysis/replace_hopeless_typedef_targets.rs b/engine/src/conversion/analysis/replace_hopeless_typedef_targets.rs
new file mode 100644
index 0000000..8d5d033
--- /dev/null
+++ b/engine/src/conversion/analysis/replace_hopeless_typedef_targets.rs
@@ -0,0 +1,100 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx_parser::IncludeCppConfig;
+use indexmap::set::IndexSet as HashSet;
+
+use crate::{
+    conversion::{
+        analysis::tdef::TypedefAnalysis,
+        api::Api,
+        apivec::ApiVec,
+        convert_error::{ConvertErrorWithContext, ErrorContext},
+        ConvertError,
+    },
+    types::QualifiedName,
+};
+
+use super::pod::PodPhase;
+/// Where we find a typedef pointing at something we can't represent,
+/// e.g. because it uses too many template parameters, break the link.
+/// Use the typedef as a first-class type.
+pub(crate) fn replace_hopeless_typedef_targets(
+    config: &IncludeCppConfig,
+    apis: ApiVec<PodPhase>,
+) -> ApiVec<PodPhase> {
+    let ignored_types: HashSet<QualifiedName> = apis
+        .iter()
+        .filter_map(|api| match api {
+            Api::IgnoredItem { .. } => Some(api.name()),
+            _ => None,
+        })
+        .cloned()
+        .collect();
+    let ignored_forward_declarations: HashSet<QualifiedName> = apis
+        .iter()
+        .filter_map(|api| match api {
+            Api::ForwardDeclaration { err: Some(_), .. } => Some(api.name()),
+            _ => None,
+        })
+        .cloned()
+        .collect();
+    // Convert any Typedefs which depend on these things into OpaqueTypedefs
+    // instead.
+    // And, after this point we no longer need special knowledge of forward
+    // declarations with errors, so just convert them into regular IgnoredItems too.
+    apis.into_iter()
+        .map(|api| match api {
+            Api::Typedef {
+                ref name,
+                analysis: TypedefAnalysis { ref deps, .. },
+                ..
+            } if !ignored_types.is_disjoint(deps) =>
+            // This typedef depended on something we ignored.
+            // Ideally, we'd turn it into an opaque item.
+            // We can't do that if this is an inner type,
+            // because we have no way to know if it's abstract or not,
+            // and we can't represent inner types in cxx without knowing
+            // that.
+            {
+                let name_id = name.name.get_final_ident();
+                if api
+                    .cpp_name()
+                    .as_ref()
+                    .map(|n| n.contains("::"))
+                    .unwrap_or_default()
+                {
+                    Api::IgnoredItem {
+                        name: api.name_info().clone(),
+                        err: ConvertError::NestedOpaqueTypedef,
+                        ctx: Some(ErrorContext::new_for_item(name_id)),
+                    }
+                } else {
+                    Api::OpaqueTypedef {
+                        name: api.name_info().clone(),
+                        forward_declaration: !config
+                            .instantiable
+                            .contains(&name.name.to_cpp_name()),
+                    }
+                }
+            }
+            Api::Typedef {
+                analysis: TypedefAnalysis { ref deps, .. },
+                ..
+            } if !ignored_forward_declarations.is_disjoint(deps) => Api::OpaqueTypedef {
+                name: api.name_info().clone(),
+                forward_declaration: true,
+            },
+            Api::ForwardDeclaration {
+                name,
+                err: Some(ConvertErrorWithContext(err, ctx)),
+            } => Api::IgnoredItem { name, err, ctx },
+            _ => api,
+        })
+        .collect()
+}
diff --git a/engine/src/conversion/analysis/tdef.rs b/engine/src/conversion/analysis/tdef.rs
new file mode 100644
index 0000000..5a635f8
--- /dev/null
+++ b/engine/src/conversion/analysis/tdef.rs
@@ -0,0 +1,128 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::set::IndexSet as HashSet;
+
+use autocxx_parser::IncludeCppConfig;
+use syn::ItemType;
+
+use crate::{
+    conversion::{
+        analysis::type_converter::{add_analysis, Annotated, TypeConversionContext, TypeConverter},
+        api::{AnalysisPhase, Api, ApiName, NullPhase, TypedefKind},
+        apivec::ApiVec,
+        convert_error::{ConvertErrorWithContext, ErrorContext},
+        error_reporter::convert_apis,
+        parse::BindgenSemanticAttributes,
+        ConvertError,
+    },
+    types::QualifiedName,
+};
+
+pub(crate) struct TypedefAnalysis {
+    pub(crate) kind: TypedefKind,
+    pub(crate) deps: HashSet<QualifiedName>,
+}
+
+/// Analysis phase where typedef analysis has been performed but no other
+/// analyses just yet.
+pub(crate) struct TypedefPhase;
+
+impl AnalysisPhase for TypedefPhase {
+    type TypedefAnalysis = TypedefAnalysis;
+    type StructAnalysis = ();
+    type FunAnalysis = ();
+}
+
+#[allow(clippy::needless_collect)] // we need the extra collect because the closure borrows extra_apis
+pub(crate) fn convert_typedef_targets(
+    config: &IncludeCppConfig,
+    apis: ApiVec<NullPhase>,
+) -> ApiVec<TypedefPhase> {
+    let mut type_converter = TypeConverter::new(config, &apis);
+    let mut extra_apis = ApiVec::new();
+    let mut results = ApiVec::new();
+    convert_apis(
+        apis,
+        &mut results,
+        Api::fun_unchanged,
+        Api::struct_unchanged,
+        Api::enum_unchanged,
+        |name, item, old_tyname, _| {
+            Ok(Box::new(std::iter::once(match item {
+                TypedefKind::Type(ity) => get_replacement_typedef(
+                    name,
+                    ity,
+                    old_tyname,
+                    &mut type_converter,
+                    &mut extra_apis,
+                )?,
+                TypedefKind::Use { .. } => Api::Typedef {
+                    name,
+                    item: item.clone(),
+                    old_tyname,
+                    analysis: TypedefAnalysis {
+                        kind: item,
+                        deps: HashSet::new(),
+                    },
+                },
+            })))
+        },
+    );
+    results.extend(extra_apis.into_iter().map(add_analysis));
+    results
+}
+
+fn get_replacement_typedef(
+    name: ApiName,
+    ity: ItemType,
+    old_tyname: Option<QualifiedName>,
+    type_converter: &mut TypeConverter,
+    extra_apis: &mut ApiVec<NullPhase>,
+) -> Result<Api<TypedefPhase>, ConvertErrorWithContext> {
+    if !ity.generics.params.is_empty() {
+        return Err(ConvertErrorWithContext(
+            ConvertError::TypedefTakesGenericParameters,
+            Some(ErrorContext::new_for_item(name.name.get_final_ident())),
+        ));
+    }
+    let mut converted_type = ity.clone();
+    let metadata = BindgenSemanticAttributes::new_retaining_others(&mut converted_type.attrs);
+    metadata.check_for_fatal_attrs(&ity.ident)?;
+    let type_conversion_results = type_converter.convert_type(
+        (*ity.ty).clone(),
+        name.name.get_namespace(),
+        &TypeConversionContext::WithinReference,
+    );
+    match type_conversion_results {
+        Err(err) => Err(ConvertErrorWithContext(
+            err,
+            Some(ErrorContext::new_for_item(name.name.get_final_ident())),
+        )),
+        Ok(Annotated {
+            ty: syn::Type::Path(ref typ),
+            ..
+        }) if QualifiedName::from_type_path(typ) == name.name => Err(ConvertErrorWithContext(
+            ConvertError::InfinitelyRecursiveTypedef(name.name.clone()),
+            Some(ErrorContext::new_for_item(name.name.get_final_ident())),
+        )),
+        Ok(mut final_type) => {
+            converted_type.ty = Box::new(final_type.ty.clone());
+            extra_apis.append(&mut final_type.extra_apis);
+            Ok(Api::Typedef {
+                name,
+                item: TypedefKind::Type(ity),
+                old_tyname,
+                analysis: TypedefAnalysis {
+                    kind: TypedefKind::Type(converted_type),
+                    deps: final_type.types_encountered,
+                },
+            })
+        }
+    }
+}
diff --git a/engine/src/conversion/analysis/type_converter.rs b/engine/src/conversion/analysis/type_converter.rs
new file mode 100644
index 0000000..afdda8a
--- /dev/null
+++ b/engine/src/conversion/analysis/type_converter.rs
@@ -0,0 +1,686 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::{
+    conversion::{
+        api::{AnalysisPhase, Api, ApiName, NullPhase, TypedefKind, UnanalyzedApi},
+        apivec::ApiVec,
+        codegen_cpp::type_to_cpp::type_to_cpp,
+        ConvertError,
+    },
+    known_types::{known_types, CxxGenericType},
+    types::{make_ident, Namespace, QualifiedName},
+};
+use autocxx_parser::IncludeCppConfig;
+use indexmap::map::IndexMap as HashMap;
+use indexmap::set::IndexSet as HashSet;
+use itertools::Itertools;
+use proc_macro2::Ident;
+use quote::ToTokens;
+use syn::{
+    parse_quote, punctuated::Punctuated, token::Comma, GenericArgument, PathArguments, PathSegment,
+    Type, TypePath, TypePtr,
+};
+
+use super::tdef::TypedefAnalysis;
+
+/// Certain kinds of type may require special handling by callers.
+#[derive(Debug)]
+pub(crate) enum TypeKind {
+    Regular,
+    Pointer,
+    SubclassHolder(Ident),
+    Reference,
+    RValueReference,
+    MutableReference,
+}
+
+/// Results of some type conversion, annotated with a list of every type encountered,
+/// and optionally any extra APIs we need in order to use this type.
+pub(crate) struct Annotated<T> {
+    pub(crate) ty: T,
+    pub(crate) types_encountered: HashSet<QualifiedName>,
+    pub(crate) extra_apis: ApiVec<NullPhase>,
+    pub(crate) kind: TypeKind,
+}
+
+impl<T> Annotated<T> {
+    fn new(
+        ty: T,
+        types_encountered: HashSet<QualifiedName>,
+        extra_apis: ApiVec<NullPhase>,
+        kind: TypeKind,
+    ) -> Self {
+        Self {
+            ty,
+            types_encountered,
+            extra_apis,
+            kind,
+        }
+    }
+
+    fn map<T2, F: FnOnce(T) -> T2>(self, fun: F) -> Annotated<T2> {
+        Annotated {
+            ty: fun(self.ty),
+            types_encountered: self.types_encountered,
+            extra_apis: self.extra_apis,
+            kind: self.kind,
+        }
+    }
+}
+
+/// How to interpret a pointer which we encounter during type conversion.
+#[derive(Clone, Copy)]
+pub(crate) enum PointerTreatment {
+    Pointer,
+    Reference,
+    RValueReference,
+}
+
+/// Options when converting a type.
+/// It's possible we could add more policies here in future.
+/// For example, Rust in general allows type names containing
+/// __, whereas cxx doesn't. If we could identify cases where
+/// a type will only ever be used in a bindgen context,
+/// we could be more liberal. At the moment though, all outputs
+/// from [TypeConverter] _might_ be used in the [cxx::bridge].
+pub(crate) enum TypeConversionContext {
+    WithinReference,
+    WithinContainer,
+    OuterType { pointer_treatment: PointerTreatment },
+}
+
+impl TypeConversionContext {
+    fn pointer_treatment(&self) -> PointerTreatment {
+        match self {
+            Self::WithinReference | Self::WithinContainer => PointerTreatment::Pointer,
+            Self::OuterType { pointer_treatment } => *pointer_treatment,
+        }
+    }
+    fn allow_instantiation_of_forward_declaration(&self) -> bool {
+        matches!(self, Self::WithinReference)
+    }
+}
+
+/// A type which can convert from a type encountered in `bindgen`
+/// output to the sort of type we should represeent to `cxx`.
+/// As a simple example, `std::string` should be replaced
+/// with [CxxString]. This also involves keeping track
+/// of typedefs, and any instantiated concrete types.
+///
+/// To do this conversion correctly, this type relies on
+/// inspecting the pre-existing list of APIs.
+pub(crate) struct TypeConverter<'a> {
+    types_found: HashSet<QualifiedName>,
+    typedefs: HashMap<QualifiedName, Type>,
+    concrete_templates: HashMap<String, QualifiedName>,
+    forward_declarations: HashSet<QualifiedName>,
+    ignored_types: HashSet<QualifiedName>,
+    config: &'a IncludeCppConfig,
+}
+
+impl<'a> TypeConverter<'a> {
+    pub(crate) fn new<A: AnalysisPhase>(config: &'a IncludeCppConfig, apis: &ApiVec<A>) -> Self
+    where
+        A::TypedefAnalysis: TypedefTarget,
+    {
+        Self {
+            types_found: find_types(apis),
+            typedefs: Self::find_typedefs(apis),
+            concrete_templates: Self::find_concrete_templates(apis),
+            forward_declarations: Self::find_incomplete_types(apis),
+            ignored_types: Self::find_ignored_types(apis),
+            config,
+        }
+    }
+
+    pub(crate) fn convert_boxed_type(
+        &mut self,
+        ty: Box<Type>,
+        ns: &Namespace,
+        ctx: &TypeConversionContext,
+    ) -> Result<Annotated<Box<Type>>, ConvertError> {
+        Ok(self.convert_type(*ty, ns, ctx)?.map(Box::new))
+    }
+
+    pub(crate) fn convert_type(
+        &mut self,
+        ty: Type,
+        ns: &Namespace,
+        ctx: &TypeConversionContext,
+    ) -> Result<Annotated<Type>, ConvertError> {
+        let result = match ty {
+            Type::Path(p) => {
+                let newp = self.convert_type_path(p, ns)?;
+                if let Type::Path(newpp) = &newp.ty {
+                    let qn = QualifiedName::from_type_path(newpp);
+                    if !ctx.allow_instantiation_of_forward_declaration()
+                        && self.forward_declarations.contains(&qn)
+                    {
+                        return Err(ConvertError::TypeContainingForwardDeclaration(qn));
+                    }
+                    // Special handling because rust_Str (as emitted by bindgen)
+                    // doesn't simply get renamed to a different type _identifier_.
+                    // This plain type-by-value (as far as bindgen is concerned)
+                    // is actually a &str.
+                    if known_types().should_dereference_in_cpp(&qn) {
+                        Annotated::new(
+                            Type::Reference(parse_quote! {
+                                &str
+                            }),
+                            newp.types_encountered,
+                            newp.extra_apis,
+                            TypeKind::Reference,
+                        )
+                    } else {
+                        newp
+                    }
+                } else {
+                    newp
+                }
+            }
+            Type::Reference(mut r) => {
+                let innerty =
+                    self.convert_boxed_type(r.elem, ns, &TypeConversionContext::WithinReference)?;
+                r.elem = innerty.ty;
+                Annotated::new(
+                    Type::Reference(r),
+                    innerty.types_encountered,
+                    innerty.extra_apis,
+                    TypeKind::Reference,
+                )
+            }
+            Type::Array(mut arr) => {
+                let innerty =
+                    self.convert_type(*arr.elem, ns, &TypeConversionContext::WithinReference)?;
+                arr.elem = Box::new(innerty.ty);
+                Annotated::new(
+                    Type::Array(arr),
+                    innerty.types_encountered,
+                    innerty.extra_apis,
+                    TypeKind::Regular,
+                )
+            }
+            Type::Ptr(ptr) => self.convert_ptr(ptr, ns, ctx.pointer_treatment())?,
+            _ => return Err(ConvertError::UnknownType(ty.to_token_stream().to_string())),
+        };
+        Ok(result)
+    }
+
+    fn convert_type_path(
+        &mut self,
+        mut typ: TypePath,
+        ns: &Namespace,
+    ) -> Result<Annotated<Type>, ConvertError> {
+        // First, qualify any unqualified paths.
+        if typ.path.segments.iter().next().unwrap().ident != "root" {
+            let ty = QualifiedName::from_type_path(&typ);
+            // If the type looks like it is unqualified, check we know it
+            // already, and if not, qualify it according to the current
+            // namespace. This is a bit of a shortcut compared to having a full
+            // resolution pass which can search all known namespaces.
+            if !known_types().is_known_type(&ty) {
+                let num_segments = typ.path.segments.len();
+                if num_segments > 1 {
+                    return Err(ConvertError::UnsupportedBuiltInType(ty));
+                }
+                if !self.types_found.contains(&ty) {
+                    typ.path.segments = std::iter::once(&"root".to_string())
+                        .chain(ns.iter())
+                        .map(|s| {
+                            let i = make_ident(s);
+                            parse_quote! { #i }
+                        })
+                        .chain(typ.path.segments.into_iter())
+                        .collect();
+                }
+            }
+        }
+
+        let original_tn = QualifiedName::from_type_path(&typ);
+        original_tn.validate_ok_for_cxx()?;
+        if self.config.is_on_blocklist(&original_tn.to_cpp_name()) {
+            return Err(ConvertError::Blocked(original_tn));
+        }
+        let mut deps = HashSet::new();
+
+        // Now convert this type itself.
+        deps.insert(original_tn.clone());
+        // First let's see if this is a typedef.
+        let (typ, tn) = match self.resolve_typedef(&original_tn)? {
+            None => (typ, original_tn),
+            Some(Type::Path(resolved_tp)) => {
+                let resolved_tn = QualifiedName::from_type_path(resolved_tp);
+                deps.insert(resolved_tn.clone());
+                (resolved_tp.clone(), resolved_tn)
+            }
+            Some(Type::Ptr(resolved_tp)) => {
+                return Ok(Annotated::new(
+                    Type::Ptr(resolved_tp.clone()),
+                    deps,
+                    ApiVec::new(),
+                    TypeKind::Pointer,
+                ))
+            }
+            Some(other) => {
+                return Ok(Annotated::new(
+                    other.clone(),
+                    deps,
+                    ApiVec::new(),
+                    TypeKind::Regular,
+                ))
+            }
+        };
+
+        // Now let's see if it's a known type.
+        // (We may entirely reject some types at this point too.)
+        let mut typ = match known_types().consider_substitution(&tn) {
+            Some(mut substitute_type) => {
+                if let Some(last_seg_args) =
+                    typ.path.segments.into_iter().last().map(|ps| ps.arguments)
+                {
+                    let last_seg = substitute_type.path.segments.last_mut().unwrap();
+                    last_seg.arguments = last_seg_args;
+                }
+                substitute_type
+            }
+            None => typ,
+        };
+
+        let mut extra_apis = ApiVec::new();
+        let mut kind = TypeKind::Regular;
+
+        // Finally let's see if it's generic.
+        if let Some(last_seg) = Self::get_generic_args(&mut typ) {
+            let generic_behavior = known_types().cxx_generic_behavior(&tn);
+            let forward_declarations_ok = generic_behavior == CxxGenericType::Rust;
+            if generic_behavior != CxxGenericType::Not {
+                // this is a type of generic understood by cxx (e.g. CxxVector)
+                // so let's convert any generic type arguments. This recurses.
+                if let PathArguments::AngleBracketed(ref mut ab) = last_seg.arguments {
+                    let mut innerty = self.convert_punctuated(
+                        ab.args.clone(),
+                        ns,
+                        &TypeConversionContext::WithinContainer,
+                    )?;
+                    ab.args = innerty.ty;
+                    kind = self.confirm_inner_type_is_acceptable_generic_payload(
+                        &ab.args,
+                        &tn,
+                        generic_behavior,
+                        forward_declarations_ok,
+                    )?;
+                    deps.extend(innerty.types_encountered.drain(..));
+                } else {
+                    return Err(ConvertError::TemplatedTypeContainingNonPathArg(tn.clone()));
+                }
+            } else {
+                // Oh poop. It's a generic type which cxx won't be able to handle.
+                // We'll have to come up with a concrete type in both the cxx::bridge (in Rust)
+                // and a corresponding typedef in C++.
+                // Let's first see if this is a concrete version of a templated type
+                // which we already rejected. Some, but possibly not all, of the reasons
+                // for its rejection would also apply to any concrete types we
+                // make. Err on the side of caution. In future we may be able to relax
+                // this a bit.
+                let qn = QualifiedName::from_type_path(&typ); // ignores generic params
+                if self.ignored_types.contains(&qn) {
+                    return Err(ConvertError::ConcreteVersionOfIgnoredTemplate);
+                }
+                let (new_tn, api) = self.get_templated_typename(&Type::Path(typ))?;
+                extra_apis.extend(api.into_iter());
+                deps.remove(&tn);
+                typ = new_tn.to_type_path();
+                deps.insert(new_tn);
+            }
+        }
+        Ok(Annotated::new(Type::Path(typ), deps, extra_apis, kind))
+    }
+
+    fn get_generic_args(typ: &mut TypePath) -> Option<&mut PathSegment> {
+        match typ.path.segments.last_mut() {
+            Some(s) if !s.arguments.is_empty() => Some(s),
+            _ => None,
+        }
+    }
+
+    fn convert_punctuated<P>(
+        &mut self,
+        pun: Punctuated<GenericArgument, P>,
+        ns: &Namespace,
+        ctx: &TypeConversionContext,
+    ) -> Result<Annotated<Punctuated<GenericArgument, P>>, ConvertError>
+    where
+        P: Default,
+    {
+        let mut new_pun = Punctuated::new();
+        let mut types_encountered = HashSet::new();
+        let mut extra_apis = ApiVec::new();
+        for arg in pun.into_iter() {
+            new_pun.push(match arg {
+                GenericArgument::Type(t) => {
+                    let mut innerty = self.convert_type(t, ns, ctx)?;
+                    types_encountered.extend(innerty.types_encountered.drain(..));
+                    extra_apis.append(&mut innerty.extra_apis);
+                    GenericArgument::Type(innerty.ty)
+                }
+                _ => arg,
+            });
+        }
+        Ok(Annotated::new(
+            new_pun,
+            types_encountered,
+            extra_apis,
+            TypeKind::Regular,
+        ))
+    }
+
+    fn resolve_typedef<'b>(&'b self, tn: &QualifiedName) -> Result<Option<&'b Type>, ConvertError> {
+        let mut encountered = HashSet::new();
+        let mut tn = tn.clone();
+        let mut previous_typ = None;
+        loop {
+            let r = self.typedefs.get(&tn);
+            match r {
+                Some(Type::Path(typ)) => {
+                    previous_typ = r;
+                    let new_tn = QualifiedName::from_type_path(typ);
+                    if encountered.contains(&new_tn) {
+                        return Err(ConvertError::InfinitelyRecursiveTypedef(tn.clone()));
+                    }
+                    encountered.insert(new_tn.clone());
+                    tn = new_tn;
+                }
+                None => return Ok(previous_typ),
+                _ => return Ok(r),
+            }
+        }
+    }
+
+    fn convert_ptr(
+        &mut self,
+        mut ptr: TypePtr,
+        ns: &Namespace,
+        pointer_treatment: PointerTreatment,
+    ) -> Result<Annotated<Type>, ConvertError> {
+        match pointer_treatment {
+            PointerTreatment::Pointer => {
+                crate::known_types::ensure_pointee_is_valid(&ptr)?;
+                let innerty =
+                    self.convert_boxed_type(ptr.elem, ns, &TypeConversionContext::WithinReference)?;
+                ptr.elem = innerty.ty;
+                Ok(Annotated::new(
+                    Type::Ptr(ptr),
+                    innerty.types_encountered,
+                    innerty.extra_apis,
+                    TypeKind::Pointer,
+                ))
+            }
+            PointerTreatment::Reference => {
+                let mutability = ptr.mutability;
+                let elem =
+                    self.convert_boxed_type(ptr.elem, ns, &TypeConversionContext::WithinReference)?;
+                // TODO - in the future, we should check if this is a rust::Str and throw
+                // a wobbler if not. rust::Str should only be seen _by value_ in C++
+                // headers; it manifests as &str in Rust but on the C++ side it must
+                // be a plain value. We should detect and abort.
+                let mut outer = elem.map(|elem| match mutability {
+                    Some(_) => Type::Path(parse_quote! {
+                        ::std::pin::Pin < & #mutability #elem >
+                    }),
+                    None => Type::Reference(parse_quote! {
+                        & #elem
+                    }),
+                });
+                outer.kind = if mutability.is_some() {
+                    TypeKind::MutableReference
+                } else {
+                    TypeKind::Reference
+                };
+                Ok(outer)
+            }
+            PointerTreatment::RValueReference => {
+                crate::known_types::ensure_pointee_is_valid(&ptr)?;
+                let innerty =
+                    self.convert_boxed_type(ptr.elem, ns, &TypeConversionContext::WithinReference)?;
+                ptr.elem = innerty.ty;
+                Ok(Annotated::new(
+                    Type::Ptr(ptr),
+                    innerty.types_encountered,
+                    innerty.extra_apis,
+                    TypeKind::RValueReference,
+                ))
+            }
+        }
+    }
+
+    fn get_templated_typename(
+        &mut self,
+        rs_definition: &Type,
+    ) -> Result<(QualifiedName, Option<UnanalyzedApi>), ConvertError> {
+        let count = self.concrete_templates.len();
+        // We just use this as a hash key, essentially.
+        // TODO: Once we've completed the TypeConverter refactoring (see #220),
+        // pass in an actual original_name_map here.
+        let cpp_definition = type_to_cpp(rs_definition, &HashMap::new())?;
+        let e = self.concrete_templates.get(&cpp_definition);
+        match e {
+            Some(tn) => Ok((tn.clone(), None)),
+            None => {
+                let synthetic_ident = format!(
+                    "{}_AutocxxConcrete",
+                    cpp_definition.replace(|c: char| !(c.is_ascii_alphanumeric() || c == '_'), "_")
+                );
+                // Remove runs of multiple _s. Trying to avoid a dependency on
+                // regex.
+                let synthetic_ident = synthetic_ident
+                    .split('_')
+                    .filter(|s| !s.is_empty())
+                    .join("_");
+                // Ensure we're not duplicating some existing concrete template name.
+                // If so, we'll invent a name which is guaranteed to be unique.
+                let synthetic_ident = match self
+                    .concrete_templates
+                    .values()
+                    .map(|n| n.get_final_item())
+                    .find(|s| s == &synthetic_ident)
+                {
+                    None => synthetic_ident,
+                    Some(_) => format!("AutocxxConcrete{}", count),
+                };
+                let api = UnanalyzedApi::ConcreteType {
+                    name: ApiName::new_in_root_namespace(make_ident(&synthetic_ident)),
+                    cpp_definition: cpp_definition.clone(),
+                    rs_definition: Some(Box::new(rs_definition.clone())),
+                };
+                self.concrete_templates
+                    .insert(cpp_definition, api.name().clone());
+                Ok((api.name().clone(), Some(api)))
+            }
+        }
+    }
+
+    fn confirm_inner_type_is_acceptable_generic_payload(
+        &self,
+        path_args: &Punctuated<GenericArgument, Comma>,
+        desc: &QualifiedName,
+        generic_behavior: CxxGenericType,
+        forward_declarations_ok: bool,
+    ) -> Result<TypeKind, ConvertError> {
+        for inner in path_args {
+            match inner {
+                GenericArgument::Type(Type::Path(typ)) => {
+                    let inner_qn = QualifiedName::from_type_path(typ);
+                    if !forward_declarations_ok && self.forward_declarations.contains(&inner_qn) {
+                        return Err(ConvertError::TypeContainingForwardDeclaration(inner_qn));
+                    }
+                    match generic_behavior {
+                        CxxGenericType::Rust => {
+                            if !inner_qn.get_namespace().is_empty() {
+                                return Err(ConvertError::RustTypeWithAPath(inner_qn));
+                            }
+                            if !self.config.is_rust_type(&inner_qn.get_final_ident()) {
+                                return Err(ConvertError::BoxContainingNonRustType(inner_qn));
+                            }
+                            if self
+                                .config
+                                .is_subclass_holder(&inner_qn.get_final_ident().to_string())
+                            {
+                                return Ok(TypeKind::SubclassHolder(inner_qn.get_final_ident()));
+                            } else {
+                                return Ok(TypeKind::Regular);
+                            }
+                        }
+                        CxxGenericType::CppPtr => {
+                            if !known_types().permissible_within_unique_ptr(&inner_qn) {
+                                return Err(ConvertError::InvalidTypeForCppPtr(inner_qn));
+                            }
+                        }
+                        CxxGenericType::CppVector => {
+                            if !known_types().permissible_within_vector(&inner_qn) {
+                                return Err(ConvertError::InvalidTypeForCppVector(inner_qn));
+                            }
+                            if matches!(
+                                typ.path.segments.last().map(|ps| &ps.arguments),
+                                Some(
+                                    PathArguments::Parenthesized(_)
+                                        | PathArguments::AngleBracketed(_)
+                                )
+                            ) {
+                                return Err(ConvertError::GenericsWithinVector);
+                            }
+                        }
+                        _ => {}
+                    }
+                }
+                _ => {
+                    return Err(ConvertError::TemplatedTypeContainingNonPathArg(
+                        desc.clone(),
+                    ))
+                }
+            }
+        }
+        Ok(TypeKind::Regular)
+    }
+
+    fn find_typedefs<A: AnalysisPhase>(apis: &ApiVec<A>) -> HashMap<QualifiedName, Type>
+    where
+        A::TypedefAnalysis: TypedefTarget,
+    {
+        apis.iter()
+            .filter_map(|api| match &api {
+                Api::Typedef { analysis, .. } => analysis
+                    .get_target()
+                    .cloned()
+                    .map(|ty| (api.name().clone(), ty)),
+                _ => None,
+            })
+            .collect()
+    }
+
+    fn find_concrete_templates<A: AnalysisPhase>(
+        apis: &ApiVec<A>,
+    ) -> HashMap<String, QualifiedName> {
+        apis.iter()
+            .filter_map(|api| match &api {
+                Api::ConcreteType { cpp_definition, .. } => {
+                    Some((cpp_definition.clone(), api.name().clone()))
+                }
+                _ => None,
+            })
+            .collect()
+    }
+
+    fn find_incomplete_types<A: AnalysisPhase>(apis: &ApiVec<A>) -> HashSet<QualifiedName> {
+        apis.iter()
+            .filter_map(|api| match api {
+                Api::ForwardDeclaration { .. }
+                | Api::OpaqueTypedef {
+                    forward_declaration: true,
+                    ..
+                } => Some(api.name()),
+                _ => None,
+            })
+            .cloned()
+            .collect()
+    }
+
+    fn find_ignored_types<A: AnalysisPhase>(apis: &ApiVec<A>) -> HashSet<QualifiedName> {
+        apis.iter()
+            .filter_map(|api| match api {
+                Api::IgnoredItem { .. } => Some(api.name()),
+                _ => None,
+            })
+            .cloned()
+            .collect()
+    }
+}
+
+/// Processing functions sometimes results in new types being materialized.
+/// These types haven't been through the analysis phases (chicken and egg
+/// problem) but fortunately, don't need to. We need to keep the type
+/// system happy by adding an [ApiAnalysis] but in practice, for the sorts
+/// of things that get created, it's always blank.
+pub(crate) fn add_analysis<A: AnalysisPhase>(api: UnanalyzedApi) -> Api<A> {
+    match api {
+        Api::ConcreteType {
+            name,
+            rs_definition,
+            cpp_definition,
+        } => Api::ConcreteType {
+            name,
+            rs_definition,
+            cpp_definition,
+        },
+        Api::IgnoredItem { name, err, ctx } => Api::IgnoredItem { name, err, ctx },
+        _ => panic!("Function analysis created an unexpected type of extra API"),
+    }
+}
+pub(crate) trait TypedefTarget {
+    fn get_target(&self) -> Option<&Type>;
+}
+
+impl TypedefTarget for () {
+    fn get_target(&self) -> Option<&Type> {
+        None
+    }
+}
+
+impl TypedefTarget for TypedefAnalysis {
+    fn get_target(&self) -> Option<&Type> {
+        Some(match self.kind {
+            TypedefKind::Type(ref ty) => &ty.ty,
+            TypedefKind::Use(_, ref ty) => ty,
+        })
+    }
+}
+
+pub(crate) fn find_types<A: AnalysisPhase>(apis: &ApiVec<A>) -> HashSet<QualifiedName> {
+    apis.iter()
+        .filter_map(|api| match api {
+            Api::ForwardDeclaration { .. }
+            | Api::OpaqueTypedef { .. }
+            | Api::ConcreteType { .. }
+            | Api::Typedef { .. }
+            | Api::Enum { .. }
+            | Api::Struct { .. }
+            | Api::Subclass { .. }
+            | Api::ExternCppType { .. }
+            | Api::RustType { .. } => Some(api.name()),
+            Api::StringConstructor { .. }
+            | Api::Function { .. }
+            | Api::Const { .. }
+            | Api::CType { .. }
+            | Api::RustSubclassFn { .. }
+            | Api::IgnoredItem { .. }
+            | Api::SubclassTraitItem { .. }
+            | Api::RustFn { .. } => None,
+        })
+        .cloned()
+        .collect()
+}
diff --git a/engine/src/conversion/api.rs b/engine/src/conversion/api.rs
new file mode 100644
index 0000000..3d04674
--- /dev/null
+++ b/engine/src/conversion/api.rs
@@ -0,0 +1,715 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::set::IndexSet as HashSet;
+use std::fmt::Display;
+
+use crate::types::{make_ident, Namespace, QualifiedName};
+use autocxx_parser::{ExternCppType, RustFun, RustPath};
+use itertools::Itertools;
+use quote::ToTokens;
+use syn::{
+    parse::Parse,
+    punctuated::Punctuated,
+    token::{Comma, Unsafe},
+    Attribute, FnArg, Ident, ItemConst, ItemEnum, ItemStruct, ItemType, ItemUse, LitBool, LitInt,
+    Pat, ReturnType, Type, Visibility,
+};
+
+use super::{
+    analysis::{
+        fun::{
+            function_wrapper::{CppFunction, CppFunctionBody, CppFunctionKind},
+            ReceiverMutability,
+        },
+        PointerTreatment,
+    },
+    convert_error::{ConvertErrorWithContext, ErrorContext},
+    ConvertError,
+};
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub(crate) enum TypeKind {
+    Pod,    // trivial. Can be moved and copied in Rust.
+    NonPod, // has destructor or non-trivial move constructors. Can only hold by UniquePtr
+    Abstract, // has pure virtual members - can't even generate UniquePtr.
+            // It's possible that the type itself isn't pure virtual, but it inherits from
+            // some other type which is pure virtual. Alternatively, maybe we just don't
+            // know if the base class is pure virtual because it wasn't on the allowlist,
+            // in which case we'll err on the side of caution.
+}
+
+/// C++ visibility.
+#[derive(Debug, Clone, PartialEq, Eq, Copy)]
+pub(crate) enum CppVisibility {
+    Public,
+    Protected,
+    Private,
+}
+
+/// Details about a C++ struct.
+pub(crate) struct StructDetails {
+    pub(crate) vis: CppVisibility,
+    pub(crate) item: ItemStruct,
+    pub(crate) layout: Option<Layout>,
+    pub(crate) has_rvalue_reference_fields: bool,
+}
+
+/// Layout of a type, equivalent to the same type in ir/layout.rs in bindgen
+#[derive(Clone)]
+pub(crate) struct Layout {
+    /// The size (in bytes) of this layout.
+    pub(crate) size: usize,
+    /// The alignment (in bytes) of this layout.
+    pub(crate) align: usize,
+    /// Whether this layout's members are packed or not.
+    pub(crate) packed: bool,
+}
+
+impl Parse for Layout {
+    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
+        let size: LitInt = input.parse()?;
+        input.parse::<syn::token::Comma>()?;
+        let align: LitInt = input.parse()?;
+        input.parse::<syn::token::Comma>()?;
+        let packed: LitBool = input.parse()?;
+        Ok(Layout {
+            size: size.base10_parse().unwrap(),
+            align: align.base10_parse().unwrap(),
+            packed: packed.value(),
+        })
+    }
+}
+
+#[derive(Clone)]
+pub(crate) enum Virtualness {
+    None,
+    Virtual,
+    PureVirtual,
+}
+
+#[derive(Clone, Copy)]
+pub(crate) enum CastMutability {
+    ConstToConst,
+    MutToConst,
+    MutToMut,
+}
+
+/// Indicates that this function (which is synthetic) should
+/// be a trait implementation rather than a method or free function.
+#[derive(Clone)]
+pub(crate) enum TraitSynthesis {
+    Cast {
+        to_type: QualifiedName,
+        mutable: CastMutability,
+    },
+    AllocUninitialized(QualifiedName),
+    FreeUninitialized(QualifiedName),
+}
+
+/// Details of a subclass constructor.
+/// TODO: zap this; replace with an extra API.
+#[derive(Clone)]
+pub(crate) struct SubclassConstructorDetails {
+    pub(crate) subclass: SubclassName,
+    pub(crate) is_trivial: bool,
+    /// Implementation of the constructor _itself_ as distinct
+    /// from any wrapper function we create to call it.
+    pub(crate) cpp_impl: CppFunction,
+}
+
+/// Contributions to traits representing C++ superclasses that
+/// we may implement as Rust subclasses.
+#[derive(Clone)]
+pub(crate) struct SuperclassMethod {
+    pub(crate) name: Ident,
+    pub(crate) receiver: QualifiedName,
+    pub(crate) params: Punctuated<FnArg, Comma>,
+    pub(crate) param_names: Vec<Pat>,
+    pub(crate) ret_type: ReturnType,
+    pub(crate) receiver_mutability: ReceiverMutability,
+    pub(crate) requires_unsafe: UnsafetyNeeded,
+    pub(crate) is_pure_virtual: bool,
+}
+
+/// Information about references (as opposed to pointers) to be found
+/// within the function signature. This is derived from bindgen annotations
+/// which is why it's not within `FuncToConvert::inputs`
+#[derive(Default, Clone)]
+pub(crate) struct References {
+    pub(crate) rvalue_ref_params: HashSet<Ident>,
+    pub(crate) ref_params: HashSet<Ident>,
+    pub(crate) ref_return: bool,
+    pub(crate) rvalue_ref_return: bool,
+}
+
+impl References {
+    pub(crate) fn new_with_this_and_return_as_reference() -> Self {
+        Self {
+            ref_return: true,
+            ref_params: [make_ident("this")].into_iter().collect(),
+            ..Default::default()
+        }
+    }
+    pub(crate) fn param_treatment(&self, param: &Ident) -> PointerTreatment {
+        if self.rvalue_ref_params.contains(param) {
+            PointerTreatment::RValueReference
+        } else if self.ref_params.contains(param) {
+            PointerTreatment::Reference
+        } else {
+            PointerTreatment::Pointer
+        }
+    }
+    pub(crate) fn return_treatment(&self) -> PointerTreatment {
+        if self.rvalue_ref_return {
+            PointerTreatment::RValueReference
+        } else if self.ref_return {
+            PointerTreatment::Reference
+        } else {
+            PointerTreatment::Pointer
+        }
+    }
+}
+
+#[derive(Clone)]
+pub(crate) struct TraitImplSignature {
+    pub(crate) ty: Type,
+    pub(crate) trait_signature: Type,
+    /// The trait is 'unsafe' itself
+    pub(crate) unsafety: Option<Unsafe>,
+}
+
+impl Eq for TraitImplSignature {}
+
+impl PartialEq for TraitImplSignature {
+    fn eq(&self, other: &Self) -> bool {
+        totokens_equal(&self.unsafety, &other.unsafety)
+            && totokens_equal(&self.ty, &other.ty)
+            && totokens_equal(&self.trait_signature, &other.trait_signature)
+    }
+}
+
+fn totokens_to_string<T: ToTokens>(a: &T) -> String {
+    a.to_token_stream().to_string()
+}
+
+fn totokens_equal<T: ToTokens>(a: &T, b: &T) -> bool {
+    totokens_to_string(a) == totokens_to_string(b)
+}
+
+fn hash_totokens<T: ToTokens, H: std::hash::Hasher>(a: &T, state: &mut H) {
+    use std::hash::Hash;
+    totokens_to_string(a).hash(state)
+}
+
+impl std::hash::Hash for TraitImplSignature {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        hash_totokens(&self.ty, state);
+        hash_totokens(&self.trait_signature, state);
+        hash_totokens(&self.unsafety, state);
+    }
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum SpecialMemberKind {
+    DefaultConstructor,
+    CopyConstructor,
+    MoveConstructor,
+    Destructor,
+    AssignmentOperator,
+}
+
+impl Display for SpecialMemberKind {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(
+            f,
+            "{}",
+            match self {
+                SpecialMemberKind::DefaultConstructor => "default constructor",
+                SpecialMemberKind::CopyConstructor => "copy constructor",
+                SpecialMemberKind::MoveConstructor => "move constructor",
+                SpecialMemberKind::Destructor => "destructor",
+                SpecialMemberKind::AssignmentOperator => "assignment operator",
+            }
+        )
+    }
+}
+
+#[derive(Clone)]
+pub(crate) enum Provenance {
+    Bindgen,
+    SynthesizedOther,
+    SynthesizedSubclassConstructor(Box<SubclassConstructorDetails>),
+}
+
+/// A C++ function for which we need to generate bindings, but haven't
+/// yet analyzed in depth. This is little more than a `ForeignItemFn`
+/// broken down into its constituent parts, plus some metadata from the
+/// surrounding bindgen parsing context.
+///
+/// Some parts of the code synthesize additional functions and then
+/// pass them through the same pipeline _as if_ they were discovered
+/// during normal bindgen parsing. If that happens, they'll create one
+/// of these structures, and typically fill in some of the
+/// `synthesized_*` members which are not filled in from bindgen.
+#[derive(Clone)]
+pub(crate) struct FuncToConvert {
+    pub(crate) provenance: Provenance,
+    pub(crate) ident: Ident,
+    pub(crate) doc_attrs: Vec<Attribute>,
+    pub(crate) inputs: Punctuated<FnArg, Comma>,
+    pub(crate) variadic: bool,
+    pub(crate) output: ReturnType,
+    pub(crate) vis: Visibility,
+    pub(crate) virtualness: Virtualness,
+    pub(crate) cpp_vis: CppVisibility,
+    pub(crate) special_member: Option<SpecialMemberKind>,
+    pub(crate) unused_template_param: bool,
+    pub(crate) references: References,
+    pub(crate) original_name: Option<String>,
+    /// Used for static functions only. For all other functons,
+    /// this is figured out from the receiver type in the inputs.
+    pub(crate) self_ty: Option<QualifiedName>,
+    /// If we wish to use a different 'this' type than the original
+    /// method receiver, e.g. because we're making a subclass
+    /// constructor, fill it in here.
+    pub(crate) synthesized_this_type: Option<QualifiedName>,
+    /// If this function should actually belong to a trait.
+    pub(crate) add_to_trait: Option<TraitSynthesis>,
+    /// If Some, this function didn't really exist in the original
+    /// C++ and instead we're synthesizing it.
+    pub(crate) synthetic_cpp: Option<(CppFunctionBody, CppFunctionKind)>,
+    pub(crate) is_deleted: bool,
+}
+
+/// Layers of analysis which may be applied to decorate each API.
+/// See description of the purpose of this trait within `Api`.
+pub(crate) trait AnalysisPhase {
+    type TypedefAnalysis;
+    type StructAnalysis;
+    type FunAnalysis;
+}
+
+/// No analysis has been applied to this API.
+pub(crate) struct NullPhase;
+
+impl AnalysisPhase for NullPhase {
+    type TypedefAnalysis = ();
+    type StructAnalysis = ();
+    type FunAnalysis = ();
+}
+
+#[derive(Clone)]
+pub(crate) enum TypedefKind {
+    Use(ItemUse, Box<Type>),
+    Type(ItemType),
+}
+
+/// Name information for an API. This includes the name by
+/// which we know it in Rust, and its C++ name, which may differ.
+#[derive(Clone, Hash, PartialEq, Eq)]
+pub(crate) struct ApiName {
+    pub(crate) name: QualifiedName,
+    cpp_name: Option<String>,
+}
+
+impl ApiName {
+    pub(crate) fn new(ns: &Namespace, id: Ident) -> Self {
+        Self::new_from_qualified_name(QualifiedName::new(ns, id))
+    }
+
+    pub(crate) fn new_with_cpp_name(ns: &Namespace, id: Ident, cpp_name: Option<String>) -> Self {
+        Self {
+            name: QualifiedName::new(ns, id),
+            cpp_name,
+        }
+    }
+
+    pub(crate) fn new_from_qualified_name(name: QualifiedName) -> Self {
+        Self {
+            name,
+            cpp_name: None,
+        }
+    }
+
+    pub(crate) fn new_in_root_namespace(id: Ident) -> Self {
+        Self::new(&Namespace::new(), id)
+    }
+
+    pub(crate) fn cpp_name(&self) -> String {
+        self.cpp_name
+            .as_ref()
+            .cloned()
+            .unwrap_or_else(|| self.name.get_final_item().to_string())
+    }
+
+    pub(crate) fn qualified_cpp_name(&self) -> String {
+        let cpp_name = self.cpp_name();
+        self.name
+            .ns_segment_iter()
+            .cloned()
+            .chain(std::iter::once(cpp_name))
+            .join("::")
+    }
+
+    pub(crate) fn cpp_name_if_present(&self) -> Option<&String> {
+        self.cpp_name.as_ref()
+    }
+}
+
+impl std::fmt::Debug for ApiName {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.name)?;
+        if let Some(cpp_name) = &self.cpp_name {
+            write!(f, " (cpp={})", cpp_name)?;
+        }
+        Ok(())
+    }
+}
+
+/// A name representing a subclass.
+/// This is a simple newtype wrapper which exists such that
+/// we can consistently generate the names of the various subsidiary
+/// types which are required both in C++ and Rust codegen.
+#[derive(Clone, Hash, PartialEq, Eq, Debug)]
+pub(crate) struct SubclassName(pub(crate) ApiName);
+
+impl SubclassName {
+    pub(crate) fn new(id: Ident) -> Self {
+        Self(ApiName::new_in_root_namespace(id))
+    }
+    pub(crate) fn from_holder_name(id: &Ident) -> Self {
+        Self::new(make_ident(id.to_string().strip_suffix("Holder").unwrap()))
+    }
+    pub(crate) fn id(&self) -> Ident {
+        self.0.name.get_final_ident()
+    }
+    /// Generate the name for the 'Holder' type
+    pub(crate) fn holder(&self) -> Ident {
+        self.with_suffix("Holder")
+    }
+    /// Generate the name for the 'Cpp' type
+    pub(crate) fn cpp(&self) -> QualifiedName {
+        let id = self.with_suffix("Cpp");
+        QualifiedName::new(self.0.name.get_namespace(), id)
+    }
+    pub(crate) fn cpp_remove_ownership(&self) -> Ident {
+        self.with_suffix("Cpp_remove_ownership")
+    }
+    pub(crate) fn remove_ownership(&self) -> Ident {
+        self.with_suffix("_remove_ownership")
+    }
+    fn with_suffix(&self, suffix: &str) -> Ident {
+        make_ident(format!("{}{}", self.0.name.get_final_item(), suffix))
+    }
+    pub(crate) fn get_trait_api_name(sup: &QualifiedName, method_name: &str) -> QualifiedName {
+        QualifiedName::new(
+            sup.get_namespace(),
+            make_ident(format!(
+                "{}_{}_trait_item",
+                sup.get_final_item(),
+                method_name
+            )),
+        )
+    }
+    // TODO this and the following should probably include both class name and method name
+    pub(crate) fn get_super_fn_name(superclass_namespace: &Namespace, id: &str) -> QualifiedName {
+        let id = make_ident(format!("{}_super", id));
+        QualifiedName::new(superclass_namespace, id)
+    }
+    pub(crate) fn get_methods_trait_name(superclass_name: &QualifiedName) -> QualifiedName {
+        Self::with_qualified_name_suffix(superclass_name, "methods")
+    }
+    pub(crate) fn get_supers_trait_name(superclass_name: &QualifiedName) -> QualifiedName {
+        Self::with_qualified_name_suffix(superclass_name, "supers")
+    }
+
+    fn with_qualified_name_suffix(name: &QualifiedName, suffix: &str) -> QualifiedName {
+        let id = make_ident(format!("{}_{}", name.get_final_item(), suffix));
+        QualifiedName::new(name.get_namespace(), id)
+    }
+}
+
+#[derive(strum_macros::Display)]
+/// Different types of API we might encounter.
+///
+/// This type is parameterized over an `ApiAnalysis`. This is any additional
+/// information which we wish to apply to our knowledge of our APIs later
+/// during analysis phases.
+///
+/// This is not as high-level as the equivalent types in `cxx` or `bindgen`,
+/// because sometimes we pass on the `bindgen` output directly in the
+/// Rust codegen output.
+///
+/// This derives from [strum_macros::Display] because we want to be
+/// able to debug-print the enum discriminant without worrying about
+/// the fact that their payloads may not be `Debug` or `Display`.
+/// (Specifically, allowing `syn` Types to be `Debug` requires
+/// enabling syn's `extra-traits` feature which increases compile time.)
+pub(crate) enum Api<T: AnalysisPhase> {
+    /// A forward declaration, which we mustn't store in a UniquePtr.
+    ForwardDeclaration {
+        name: ApiName,
+        /// If we found a problem parsing this forward declaration, we'll
+        /// ephemerally store the error here, as opposed to immediately
+        /// converting it to an `IgnoredItem`. That's because the
+        /// 'replace_hopeless_typedef_targets' analysis phase needs to spot
+        /// cases where there was an error which was _also_ a forward declaration.
+        /// That phase will then discard such Api::ForwardDeclarations
+        /// and replace them with normal Api::IgnoredItems.
+        err: Option<ConvertErrorWithContext>,
+    },
+    /// We found a typedef to something that we didn't fully understand.
+    /// We'll treat it as an opaque unsized type.
+    OpaqueTypedef {
+        name: ApiName,
+        /// Further store whether this was a typedef to a forward declaration.
+        /// If so we can't allow it to live in a UniquePtr, just like a regular
+        /// Api::ForwardDeclaration.
+        forward_declaration: bool,
+    },
+    /// A synthetic type we've manufactured in order to
+    /// concretize some templated C++ type.
+    ConcreteType {
+        name: ApiName,
+        rs_definition: Option<Box<Type>>,
+        cpp_definition: String,
+    },
+    /// A simple note that we want to make a constructor for
+    /// a `std::string` on the heap.
+    StringConstructor { name: ApiName },
+    /// A function. May include some analysis.
+    Function {
+        name: ApiName,
+        fun: Box<FuncToConvert>,
+        analysis: T::FunAnalysis,
+    },
+    /// A constant.
+    Const {
+        name: ApiName,
+        const_item: ItemConst,
+    },
+    /// A typedef found in the bindgen output which we wish
+    /// to pass on in our output
+    Typedef {
+        name: ApiName,
+        item: TypedefKind,
+        old_tyname: Option<QualifiedName>,
+        analysis: T::TypedefAnalysis,
+    },
+    /// An enum encountered in the
+    /// `bindgen` output.
+    Enum { name: ApiName, item: ItemEnum },
+    /// A struct encountered in the
+    /// `bindgen` output.
+    Struct {
+        name: ApiName,
+        details: Box<StructDetails>,
+        analysis: T::StructAnalysis,
+    },
+    /// A variable-length C integer type (e.g. int, unsigned long).
+    CType {
+        name: ApiName,
+        typename: QualifiedName,
+    },
+    /// Some item which couldn't be processed by autocxx for some reason.
+    /// We will have emitted a warning message about this, but we want
+    /// to mark that it's ignored so that we don't attempt to process
+    /// dependent items.
+    IgnoredItem {
+        name: ApiName,
+        err: ConvertError,
+        ctx: Option<ErrorContext>,
+    },
+    /// A Rust type which is not a C++ type.
+    RustType { name: ApiName, path: RustPath },
+    /// A function for the 'extern Rust' block which is not a C++ type.
+    RustFn {
+        name: ApiName,
+        details: RustFun,
+        receiver: Option<QualifiedName>,
+    },
+    /// Some function for the extern "Rust" block.
+    RustSubclassFn {
+        name: ApiName,
+        subclass: SubclassName,
+        details: Box<RustSubclassFnDetails>,
+    },
+    /// A Rust subclass of a C++ class.
+    Subclass {
+        name: SubclassName,
+        superclass: QualifiedName,
+    },
+    /// Contributions to the traits representing superclass methods that we might
+    /// subclass in Rust.
+    SubclassTraitItem {
+        name: ApiName,
+        details: SuperclassMethod,
+    },
+    /// A type which we shouldn't ourselves generate, but can use in functions
+    /// and so-forth by referring to some definition elsewhere.
+    ExternCppType {
+        name: ApiName,
+        details: ExternCppType,
+        pod: bool,
+    },
+}
+
+pub(crate) struct RustSubclassFnDetails {
+    pub(crate) params: Punctuated<FnArg, Comma>,
+    pub(crate) ret: ReturnType,
+    pub(crate) cpp_impl: CppFunction,
+    pub(crate) method_name: Ident,
+    pub(crate) superclass: QualifiedName,
+    pub(crate) receiver_mutability: ReceiverMutability,
+    pub(crate) dependencies: Vec<QualifiedName>,
+    pub(crate) requires_unsafe: UnsafetyNeeded,
+    pub(crate) is_pure_virtual: bool,
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum UnsafetyNeeded {
+    None,
+    JustBridge,
+    Always,
+}
+
+impl<T: AnalysisPhase> Api<T> {
+    pub(crate) fn name_info(&self) -> &ApiName {
+        match self {
+            Api::ForwardDeclaration { name, .. } => name,
+            Api::OpaqueTypedef { name, .. } => name,
+            Api::ConcreteType { name, .. } => name,
+            Api::StringConstructor { name } => name,
+            Api::Function { name, .. } => name,
+            Api::Const { name, .. } => name,
+            Api::Typedef { name, .. } => name,
+            Api::Enum { name, .. } => name,
+            Api::Struct { name, .. } => name,
+            Api::CType { name, .. } => name,
+            Api::IgnoredItem { name, .. } => name,
+            Api::RustType { name, .. } => name,
+            Api::RustFn { name, .. } => name,
+            Api::RustSubclassFn { name, .. } => name,
+            Api::Subclass { name, .. } => &name.0,
+            Api::SubclassTraitItem { name, .. } => name,
+            Api::ExternCppType { name, .. } => name,
+        }
+    }
+
+    /// The name of this API as used in Rust code.
+    /// For types, it's important that this never changes, since
+    /// functions or other types may refer to this.
+    /// Yet for functions, this may not actually be the name
+    /// used in the [cxx::bridge] mod -  see
+    /// [Api<FnAnalysis>::cxxbridge_name]
+    pub(crate) fn name(&self) -> &QualifiedName {
+        &self.name_info().name
+    }
+
+    /// The name recorded for use in C++, if and only if
+    /// it differs from Rust.
+    pub(crate) fn cpp_name(&self) -> &Option<String> {
+        &self.name_info().cpp_name
+    }
+
+    /// The name for use in C++, whether or not it differs
+    /// from Rust.
+    pub(crate) fn effective_cpp_name(&self) -> &str {
+        self.cpp_name()
+            .as_deref()
+            .unwrap_or_else(|| self.name().get_final_item())
+    }
+
+    /// If this API turns out to have the same QualifiedName as another,
+    /// whether it's OK to just discard it?
+    pub(crate) fn discard_duplicates(&self) -> bool {
+        matches!(self, Api::IgnoredItem { .. })
+    }
+
+    pub(crate) fn valid_types(&self) -> Box<dyn Iterator<Item = QualifiedName>> {
+        match self {
+            Api::Subclass { name, .. } => Box::new(
+                vec![
+                    self.name().clone(),
+                    QualifiedName::new(&Namespace::new(), name.holder()),
+                    name.cpp(),
+                ]
+                .into_iter(),
+            ),
+            _ => Box::new(std::iter::once(self.name().clone())),
+        }
+    }
+}
+
+impl<T: AnalysisPhase> std::fmt::Debug for Api<T> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?} (kind={})", self.name_info(), self)
+    }
+}
+
+pub(crate) type UnanalyzedApi = Api<NullPhase>;
+
+impl<T: AnalysisPhase> Api<T> {
+    pub(crate) fn typedef_unchanged(
+        name: ApiName,
+        item: TypedefKind,
+        old_tyname: Option<QualifiedName>,
+        analysis: T::TypedefAnalysis,
+    ) -> Result<Box<dyn Iterator<Item = Api<T>>>, ConvertErrorWithContext>
+    where
+        T: 'static,
+    {
+        Ok(Box::new(std::iter::once(Api::Typedef {
+            name,
+            item,
+            old_tyname,
+            analysis,
+        })))
+    }
+
+    pub(crate) fn struct_unchanged(
+        name: ApiName,
+        details: Box<StructDetails>,
+        analysis: T::StructAnalysis,
+    ) -> Result<Box<dyn Iterator<Item = Api<T>>>, ConvertErrorWithContext>
+    where
+        T: 'static,
+    {
+        Ok(Box::new(std::iter::once(Api::Struct {
+            name,
+            details,
+            analysis,
+        })))
+    }
+
+    pub(crate) fn fun_unchanged(
+        name: ApiName,
+        fun: Box<FuncToConvert>,
+        analysis: T::FunAnalysis,
+    ) -> Result<Box<dyn Iterator<Item = Api<T>>>, ConvertErrorWithContext>
+    where
+        T: 'static,
+    {
+        Ok(Box::new(std::iter::once(Api::Function {
+            name,
+            fun,
+            analysis,
+        })))
+    }
+
+    pub(crate) fn enum_unchanged(
+        name: ApiName,
+        item: ItemEnum,
+    ) -> Result<Box<dyn Iterator<Item = Api<T>>>, ConvertErrorWithContext>
+    where
+        T: 'static,
+    {
+        Ok(Box::new(std::iter::once(Api::Enum { name, item })))
+    }
+}
diff --git a/engine/src/conversion/apivec.rs b/engine/src/conversion/apivec.rs
new file mode 100644
index 0000000..1e440cc
--- /dev/null
+++ b/engine/src/conversion/apivec.rs
@@ -0,0 +1,137 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use indexmap::set::IndexSet as HashSet;
+
+use crate::{
+    conversion::{api::ApiName, convert_error::ErrorContext, ConvertError},
+    types::QualifiedName,
+};
+
+use super::api::{AnalysisPhase, Api};
+
+/// Newtype wrapper for a list of APIs, which enforces the invariant
+/// that each API has a unique name.
+///
+/// Specifically, each API should have a unique [`QualifiedName`] which is kept
+/// within an [`ApiName`]. The [`QualifiedName`] is used to refer to this API
+/// from others, e.g. to represent edges in the graph used for garbage collection,
+/// so that's why this uniqueness is so important.
+///
+/// At present, this type also refuses to allow mutation of an API once it
+/// has been added to a set. This is because the autocxx engine is
+/// fundamentally organized into lots of analysis phases, each one _adding_
+/// fields rather than mutating earlier fields. The idea here is that it's
+/// impossible for stupid future maintainers (i.e. me) to make errors by
+/// referring to fields before they're filled in. If a field exists, it's
+/// correct.
+///
+/// While this is currently the case, it's possible that in future we could
+/// see legitimate reasons to break this latter invariant and allow mutation
+/// of APIs within an existing `ApiVec`. But it's extremely important that
+/// the naming-uniqueness-invariant remains, so any such mutation should
+/// allow mutation only of other fields, not the name.
+pub(crate) struct ApiVec<P: AnalysisPhase> {
+    apis: Vec<Api<P>>,
+    names: HashSet<QualifiedName>,
+}
+
+impl<P: AnalysisPhase> ApiVec<P> {
+    pub(crate) fn push(&mut self, api: Api<P>) {
+        let name = api.name();
+        let already_contains = self.already_contains(name);
+        if already_contains {
+            if api.discard_duplicates() {
+                // This is already an IgnoredItem or something else where
+                // we can silently drop it.
+                log::info!("Discarding duplicate API for {}", name);
+            } else {
+                log::info!(
+                    "Duplicate API for {} - removing all of them and replacing with an IgnoredItem.",
+                    name
+                );
+                self.retain(|api| api.name() != name);
+                self.push(Api::IgnoredItem {
+                    name: ApiName::new_from_qualified_name(name.clone()),
+                    err: ConvertError::DuplicateItemsFoundInParsing,
+                    ctx: Some(ErrorContext::new_for_item(name.get_final_ident())),
+                })
+            }
+        } else {
+            self.names.insert(name.clone());
+            self.apis.push(api)
+        }
+    }
+
+    fn already_contains(&self, name: &QualifiedName) -> bool {
+        self.names.contains(name)
+    }
+
+    pub(crate) fn new() -> Self {
+        Self::default()
+    }
+
+    pub(crate) fn append(&mut self, more: &mut ApiVec<P>) {
+        self.extend(more.apis.drain(..))
+    }
+
+    pub(crate) fn extend(&mut self, it: impl Iterator<Item = Api<P>>) {
+        // Could be optimized in future
+        for api in it {
+            self.push(api)
+        }
+    }
+
+    pub(crate) fn iter(&self) -> impl Iterator<Item = &Api<P>> {
+        self.apis.iter()
+    }
+
+    pub(crate) fn into_iter(self) -> impl Iterator<Item = Api<P>> {
+        self.apis.into_iter()
+    }
+
+    pub(crate) fn is_empty(&self) -> bool {
+        self.apis.is_empty()
+    }
+
+    pub fn retain<F>(&mut self, f: F)
+    where
+        F: FnMut(&Api<P>) -> bool,
+    {
+        self.apis.retain(f);
+        self.names.clear();
+        self.names
+            .extend(self.apis.iter().map(|api| api.name()).cloned());
+    }
+}
+
+impl<P: AnalysisPhase> Default for ApiVec<P> {
+    fn default() -> Self {
+        Self {
+            apis: Default::default(),
+            names: Default::default(),
+        }
+    }
+}
+
+impl<P: AnalysisPhase> FromIterator<Api<P>> for ApiVec<P> {
+    fn from_iter<I: IntoIterator<Item = Api<P>>>(iter: I) -> Self {
+        let mut this = ApiVec::new();
+        for i in iter {
+            // Could be optimized in future
+            this.push(i);
+        }
+        this
+    }
+}
diff --git a/engine/src/conversion/codegen_cpp/function_wrapper_cpp.rs b/engine/src/conversion/codegen_cpp/function_wrapper_cpp.rs
new file mode 100644
index 0000000..b2e1ea3
--- /dev/null
+++ b/engine/src/conversion/codegen_cpp/function_wrapper_cpp.rs
@@ -0,0 +1,83 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::conversion::{
+    analysis::fun::function_wrapper::{CppConversionType, TypeConversionPolicy},
+    ConvertError,
+};
+
+use super::type_to_cpp::{type_to_cpp, CppNameMap};
+
+impl TypeConversionPolicy {
+    pub(super) fn unconverted_type(
+        &self,
+        cpp_name_map: &CppNameMap,
+    ) -> Result<String, ConvertError> {
+        match self.cpp_conversion {
+            CppConversionType::FromUniquePtrToValue => self.unique_ptr_wrapped_type(cpp_name_map),
+            CppConversionType::FromPtrToValue => {
+                Ok(format!("{}*", self.unwrapped_type_as_string(cpp_name_map)?))
+            }
+            _ => self.unwrapped_type_as_string(cpp_name_map),
+        }
+    }
+
+    pub(super) fn converted_type(&self, cpp_name_map: &CppNameMap) -> Result<String, ConvertError> {
+        match self.cpp_conversion {
+            CppConversionType::FromValueToUniquePtr => self.unique_ptr_wrapped_type(cpp_name_map),
+            _ => self.unwrapped_type_as_string(cpp_name_map),
+        }
+    }
+
+    fn unwrapped_type_as_string(&self, cpp_name_map: &CppNameMap) -> Result<String, ConvertError> {
+        type_to_cpp(&self.unwrapped_type, cpp_name_map)
+    }
+
+    fn unique_ptr_wrapped_type(
+        &self,
+        original_name_map: &CppNameMap,
+    ) -> Result<String, ConvertError> {
+        Ok(format!(
+            "std::unique_ptr<{}>",
+            self.unwrapped_type_as_string(original_name_map)?
+        ))
+    }
+
+    pub(super) fn cpp_conversion(
+        &self,
+        var_name: &str,
+        cpp_name_map: &CppNameMap,
+        is_return: bool,
+    ) -> Result<Option<String>, ConvertError> {
+        // If is_return we want to avoid unnecessary std::moves because they
+        // make RVO less effective
+        Ok(match self.cpp_conversion {
+            CppConversionType::None | CppConversionType::FromReturnValueToPlacementPtr => {
+                Some(var_name.to_string())
+            }
+            CppConversionType::Move => Some(format!("std::move({})", var_name)),
+            CppConversionType::FromUniquePtrToValue | CppConversionType::FromPtrToMove => {
+                Some(format!("std::move(*{})", var_name))
+            }
+            CppConversionType::FromValueToUniquePtr => Some(format!(
+                "std::make_unique<{}>({})",
+                self.unconverted_type(cpp_name_map)?,
+                var_name
+            )),
+            CppConversionType::FromPtrToValue => {
+                let dereference = format!("*{}", var_name);
+                Some(if is_return {
+                    dereference
+                } else {
+                    format!("std::move({})", dereference)
+                })
+            }
+            CppConversionType::IgnoredPlacementPtrParameter => None,
+        })
+    }
+}
diff --git a/engine/src/conversion/codegen_cpp/mod.rs b/engine/src/conversion/codegen_cpp/mod.rs
new file mode 100644
index 0000000..02e92b2
--- /dev/null
+++ b/engine/src/conversion/codegen_cpp/mod.rs
@@ -0,0 +1,724 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod function_wrapper_cpp;
+mod new_and_delete_prelude;
+pub(crate) mod type_to_cpp;
+
+use crate::{
+    conversion::analysis::fun::{function_wrapper::CppFunctionKind, FnAnalysis},
+    types::{make_ident, QualifiedName},
+    CppCodegenOptions, CppFilePair,
+};
+use autocxx_parser::IncludeCppConfig;
+use indexmap::map::IndexMap as HashMap;
+use indexmap::set::IndexSet as HashSet;
+use itertools::Itertools;
+use std::borrow::Cow;
+use type_to_cpp::{original_name_map_from_apis, type_to_cpp, CppNameMap};
+
+use self::type_to_cpp::{
+    final_ident_using_original_name_map, namespaced_name_using_original_name_map,
+};
+
+use super::{
+    analysis::{
+        fun::{
+            function_wrapper::{CppFunction, CppFunctionBody},
+            FnPhase, PodAndDepAnalysis,
+        },
+        pod::PodAnalysis,
+    },
+    api::{Api, Provenance, SubclassName, TypeKind},
+    apivec::ApiVec,
+    ConvertError,
+};
+
+#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash)]
+enum Header {
+    System(&'static str),
+    CxxH,
+    CxxgenH,
+    NewDeletePrelude,
+}
+
+impl Header {
+    fn include_stmt(
+        &self,
+        cpp_codegen_options: &CppCodegenOptions,
+        cxxgen_header_name: &str,
+    ) -> String {
+        let blank = "".to_string();
+        match self {
+            Self::System(name) => format!("#include <{}>", name),
+            Self::CxxH => {
+                let prefix = cpp_codegen_options.path_to_cxx_h.as_ref().unwrap_or(&blank);
+                format!("#include \"{}cxx.h\"", prefix)
+            }
+            Self::CxxgenH => {
+                let prefix = cpp_codegen_options
+                    .path_to_cxxgen_h
+                    .as_ref()
+                    .unwrap_or(&blank);
+                format!("#include \"{}{}\"", prefix, cxxgen_header_name)
+            }
+            Header::NewDeletePrelude => new_and_delete_prelude::NEW_AND_DELETE_PRELUDE.to_string(),
+        }
+    }
+
+    fn is_system(&self) -> bool {
+        matches!(self, Header::System(_) | Header::CxxH)
+    }
+}
+
+enum ConversionDirection {
+    RustCallsCpp,
+    CppCallsCpp,
+    CppCallsRust,
+}
+
+/// Some extra snippet of C++ which we (autocxx) need to generate, beyond
+/// that which cxx itself generates.
+#[derive(Default)]
+struct ExtraCpp {
+    type_definition: Option<String>, // are output before main declarations
+    declaration: Option<String>,
+    definition: Option<String>,
+    headers: Vec<Header>,
+    cpp_headers: Vec<Header>,
+}
+
+/// Generates additional C++ glue functions needed by autocxx.
+/// In some ways it would be preferable to be able to pass snippets
+/// of C++ through to `cxx` for inclusion in the C++ file which it
+/// generates, and perhaps we'll explore that in future. But for now,
+/// autocxx generates its own _additional_ C++ files which therefore
+/// need to be built and included in linking procedures.
+pub(crate) struct CppCodeGenerator<'a> {
+    additional_functions: Vec<ExtraCpp>,
+    inclusions: String,
+    original_name_map: CppNameMap,
+    config: &'a IncludeCppConfig,
+    cpp_codegen_options: &'a CppCodegenOptions<'a>,
+    cxxgen_header_name: &'a str,
+}
+
+struct SubclassFunction<'a> {
+    fun: &'a CppFunction,
+    is_pure_virtual: bool,
+}
+
+impl<'a> CppCodeGenerator<'a> {
+    pub(crate) fn generate_cpp_code(
+        inclusions: String,
+        apis: &ApiVec<FnPhase>,
+        config: &'a IncludeCppConfig,
+        cpp_codegen_options: &CppCodegenOptions,
+        cxxgen_header_name: &str,
+    ) -> Result<Option<CppFilePair>, ConvertError> {
+        let mut gen = CppCodeGenerator {
+            additional_functions: Vec::new(),
+            inclusions,
+            original_name_map: original_name_map_from_apis(apis),
+            config,
+            cpp_codegen_options,
+            cxxgen_header_name,
+        };
+        // The 'filter' on the following line is designed to ensure we don't accidentally
+        // end up out of sync with needs_cpp_codegen
+        gen.add_needs(apis.iter().filter(|api| api.needs_cpp_codegen()))?;
+        Ok(gen.generate())
+    }
+
+    // It's important to keep this in sync with Api::needs_cpp_codegen.
+    fn add_needs<'b>(
+        &mut self,
+        apis: impl Iterator<Item = &'a Api<FnPhase>>,
+    ) -> Result<(), ConvertError> {
+        let mut constructors_by_subclass: HashMap<SubclassName, Vec<&CppFunction>> = HashMap::new();
+        let mut methods_by_subclass: HashMap<SubclassName, Vec<SubclassFunction>> = HashMap::new();
+        let mut deferred_apis = Vec::new();
+        for api in apis {
+            match &api {
+                Api::StringConstructor { .. } => self.generate_string_constructor(),
+                Api::Function {
+                    analysis:
+                        FnAnalysis {
+                            cpp_wrapper: Some(cpp_wrapper),
+                            ignore_reason: Ok(_),
+                            externally_callable: true,
+                            ..
+                        },
+                    fun,
+                    ..
+                } => {
+                    if let Provenance::SynthesizedSubclassConstructor(details) = &fun.provenance {
+                        constructors_by_subclass
+                            .entry(details.subclass.clone())
+                            .or_default()
+                            .push(&details.cpp_impl);
+                    }
+                    self.generate_cpp_function(cpp_wrapper)?
+                }
+                Api::ConcreteType {
+                    rs_definition,
+                    cpp_definition,
+                    ..
+                } => {
+                    let effective_cpp_definition = match rs_definition {
+                        Some(rs_definition) => {
+                            Cow::Owned(type_to_cpp(rs_definition, &self.original_name_map)?)
+                        }
+                        None => Cow::Borrowed(cpp_definition),
+                    };
+
+                    self.generate_typedef(api.name(), &effective_cpp_definition)
+                }
+                Api::CType { typename, .. } => self.generate_ctype_typedef(typename),
+                Api::Subclass { .. } => deferred_apis.push(api),
+                Api::RustSubclassFn {
+                    subclass, details, ..
+                } => {
+                    methods_by_subclass
+                        .entry(subclass.clone())
+                        .or_default()
+                        .push(SubclassFunction {
+                            fun: &details.cpp_impl,
+                            is_pure_virtual: details.is_pure_virtual,
+                        });
+                }
+                Api::Struct {
+                    name,
+                    analysis:
+                        PodAndDepAnalysis {
+                            pod:
+                                PodAnalysis {
+                                    kind: TypeKind::Pod,
+                                    ..
+                                },
+                            ..
+                        },
+                    ..
+                } => {
+                    self.generate_pod_assertion(name.qualified_cpp_name());
+                }
+                _ => panic!("Should have filtered on needs_cpp_codegen"),
+            }
+        }
+
+        for api in deferred_apis.into_iter() {
+            match api {
+                Api::Subclass { name, superclass } => self.generate_subclass(
+                    superclass,
+                    name,
+                    constructors_by_subclass.remove(name).unwrap_or_default(),
+                    methods_by_subclass.remove(name).unwrap_or_default(),
+                )?,
+                _ => panic!("Unexpected deferred API"),
+            }
+        }
+        Ok(())
+    }
+
+    fn generate(&self) -> Option<CppFilePair> {
+        if self.additional_functions.is_empty() {
+            None
+        } else {
+            let headers = self.collect_headers(|additional_need| &additional_need.headers);
+            let cpp_headers = self.collect_headers(|additional_need| &additional_need.cpp_headers);
+            let type_definitions = self.concat_additional_items(|x| x.type_definition.as_ref());
+            let declarations = self.concat_additional_items(|x| x.declaration.as_ref());
+            let declarations = format!(
+                "#ifndef __AUTOCXXGEN_H__\n#define __AUTOCXXGEN_H__\n\n{}\n{}\n{}\n{}#endif // __AUTOCXXGEN_H__\n",
+                headers, self.inclusions, type_definitions, declarations
+            );
+            log::info!("Additional C++ decls:\n{}", declarations);
+            let header_name = self
+                .cpp_codegen_options
+                .autocxxgen_header_namer
+                .name_header(self.config.get_mod_name().to_string());
+            let implementation = if self
+                .additional_functions
+                .iter()
+                .any(|x| x.definition.is_some())
+            {
+                let definitions = self.concat_additional_items(|x| x.definition.as_ref());
+                let definitions = format!(
+                    "#include \"{}\"\n{}\n{}",
+                    header_name, cpp_headers, definitions
+                );
+                log::info!("Additional C++ defs:\n{}", definitions);
+                Some(definitions.into_bytes())
+            } else {
+                None
+            };
+            Some(CppFilePair {
+                header: declarations.into_bytes(),
+                implementation,
+                header_name,
+            })
+        }
+    }
+
+    fn collect_headers<F>(&self, filter: F) -> String
+    where
+        F: Fn(&ExtraCpp) -> &[Header],
+    {
+        let cpp_headers: HashSet<_> = self
+            .additional_functions
+            .iter()
+            .flat_map(|x| filter(x).iter())
+            .filter(|x| !self.cpp_codegen_options.suppress_system_headers || !x.is_system())
+            .collect(); // uniqify
+        cpp_headers
+            .iter()
+            .map(|x| x.include_stmt(self.cpp_codegen_options, self.cxxgen_header_name))
+            .join("\n")
+    }
+
+    fn concat_additional_items<F>(&self, field_access: F) -> String
+    where
+        F: FnMut(&ExtraCpp) -> Option<&String>,
+    {
+        let mut s = self
+            .additional_functions
+            .iter()
+            .flat_map(field_access)
+            .join("\n");
+        s.push('\n');
+        s
+    }
+
+    fn generate_pod_assertion(&mut self, name: String) {
+        // These assertions are generated by cxx for trivial ExternTypes but
+        // *only if* such types are used as trivial types in the cxx::bridge.
+        // It's possible for types which we generate to be used even without
+        // passing through the cxx::bridge, and as we generate Drop impls, that
+        // can result in destructors for nested types being called multiple times
+        // if we represent them as trivial types. So generate an extra
+        // assertion to make sure.
+        let declaration = Some(format!("static_assert(::rust::IsRelocatable<{}>::value, \"type {} should be trivially move constructible and trivially destructible to be used with generate_pod! in autocxx\");", name, name));
+        self.additional_functions.push(ExtraCpp {
+            declaration,
+            headers: vec![Header::CxxH],
+            ..Default::default()
+        })
+    }
+
+    fn generate_string_constructor(&mut self) {
+        let makestring_name = self.config.get_makestring_name();
+        let declaration = Some(format!("inline std::unique_ptr<std::string> {}(::rust::Str str) {{ return std::make_unique<std::string>(std::string(str)); }}", makestring_name));
+        self.additional_functions.push(ExtraCpp {
+            declaration,
+            headers: vec![
+                Header::System("memory"),
+                Header::System("string"),
+                Header::CxxH,
+            ],
+            ..Default::default()
+        })
+    }
+
+    fn generate_cpp_function(&mut self, details: &CppFunction) -> Result<(), ConvertError> {
+        self.additional_functions
+            .push(self.generate_cpp_function_inner(
+                details,
+                false,
+                ConversionDirection::RustCallsCpp,
+                false,
+                None,
+            )?);
+        Ok(())
+    }
+
+    fn generate_cpp_function_inner(
+        &self,
+        details: &CppFunction,
+        avoid_this: bool,
+        conversion_direction: ConversionDirection,
+        requires_rust_declarations: bool,
+        force_name: Option<&str>,
+    ) -> Result<ExtraCpp, ConvertError> {
+        // Even if the original function call is in a namespace,
+        // we generate this wrapper in the global namespace.
+        // We could easily do this the other way round, and when
+        // cxx::bridge comes to support nested namespace mods then
+        // we wil wish to do that to avoid name conflicts. However,
+        // at the moment this is simpler because it avoids us having
+        // to generate namespace blocks in the generated C++.
+        let is_a_method = !avoid_this
+            && matches!(
+                details.kind,
+                CppFunctionKind::Method
+                    | CppFunctionKind::ConstMethod
+                    | CppFunctionKind::Constructor
+            );
+        let name = match force_name {
+            Some(n) => n.to_string(),
+            None => details.wrapper_function_name.to_string(),
+        };
+        let get_arg_name = |counter: usize| -> String {
+            if is_a_method && counter == 0 {
+                // For method calls that we generate, the first
+                // argument name needs to be such that we recognize
+                // it as a method in the second invocation of
+                // bridge_converter after it's flowed again through
+                // bindgen.
+                // TODO this may not be the case any longer. We
+                // may be able to remove this.
+                "autocxx_gen_this".to_string()
+            } else {
+                format!("arg{}", counter)
+            }
+        };
+        // If this returns a non-POD value, we may instead wish to emplace
+        // it into a parameter, let's see.
+        let args: Result<Vec<_>, _> = details
+            .argument_conversion
+            .iter()
+            .enumerate()
+            .map(|(counter, ty)| {
+                Ok(format!(
+                    "{} {}",
+                    match conversion_direction {
+                        ConversionDirection::RustCallsCpp =>
+                            ty.unconverted_type(&self.original_name_map)?,
+                        ConversionDirection::CppCallsCpp =>
+                            ty.converted_type(&self.original_name_map)?,
+                        ConversionDirection::CppCallsRust =>
+                            ty.inverse().unconverted_type(&self.original_name_map)?,
+                    },
+                    get_arg_name(counter)
+                ))
+            })
+            .collect();
+        let args = args?.join(", ");
+        let default_return = match details.kind {
+            CppFunctionKind::SynthesizedConstructor => "",
+            _ => "void",
+        };
+        let ret_type = details
+            .return_conversion
+            .as_ref()
+            .and_then(|x| match conversion_direction {
+                ConversionDirection::RustCallsCpp => {
+                    if x.populate_return_value() {
+                        Some(x.converted_type(&self.original_name_map))
+                    } else {
+                        None
+                    }
+                }
+                ConversionDirection::CppCallsCpp => {
+                    Some(x.unconverted_type(&self.original_name_map))
+                }
+                ConversionDirection::CppCallsRust => {
+                    Some(x.inverse().converted_type(&self.original_name_map))
+                }
+            })
+            .unwrap_or_else(|| Ok(default_return.to_string()))?;
+        let constness = match details.kind {
+            CppFunctionKind::ConstMethod => " const",
+            _ => "",
+        };
+        let declaration = format!("{} {}({}){}", ret_type, name, args, constness);
+        let qualification = if let Some(qualification) = &details.qualification {
+            format!("{}::", qualification.to_cpp_name())
+        } else {
+            "".to_string()
+        };
+        let qualified_declaration = format!(
+            "{} {}{}({}){}",
+            ret_type, qualification, name, args, constness
+        );
+        // Whether there's a placement param in which to put the return value
+        let placement_param = details
+            .argument_conversion
+            .iter()
+            .enumerate()
+            .filter_map(|(counter, conv)| {
+                if conv.is_placement_parameter() {
+                    Some(get_arg_name(counter))
+                } else {
+                    None
+                }
+            })
+            .next();
+        // Arguments to underlying function call
+        let arg_list: Result<Vec<_>, _> = details
+            .argument_conversion
+            .iter()
+            .enumerate()
+            .map(|(counter, conv)| match conversion_direction {
+                ConversionDirection::RustCallsCpp => {
+                    conv.cpp_conversion(&get_arg_name(counter), &self.original_name_map, false)
+                }
+                ConversionDirection::CppCallsCpp => Ok(Some(get_arg_name(counter))),
+                ConversionDirection::CppCallsRust => conv.inverse().cpp_conversion(
+                    &get_arg_name(counter),
+                    &self.original_name_map,
+                    false,
+                ),
+            })
+            .collect();
+        let mut arg_list = arg_list?.into_iter().flatten();
+        let receiver = if is_a_method { arg_list.next() } else { None };
+        if matches!(&details.payload, CppFunctionBody::ConstructSuperclass(_)) {
+            arg_list.next();
+        }
+        let arg_list = if details.pass_obs_field {
+            std::iter::once("*obs".to_string())
+                .chain(arg_list)
+                .join(",")
+        } else {
+            arg_list.join(", ")
+        };
+        let (mut underlying_function_call, field_assignments, need_allocators) = match &details
+            .payload
+        {
+            CppFunctionBody::Cast => (arg_list, "".to_string(), false),
+            CppFunctionBody::PlacementNew(ns, id) => {
+                let ty_id = QualifiedName::new(ns, id.clone());
+                let ty_id = self.namespaced_name(&ty_id);
+                (
+                    format!("new ({}) {}({})", receiver.unwrap(), ty_id, arg_list),
+                    "".to_string(),
+                    false,
+                )
+            }
+            CppFunctionBody::Destructor(ns, id) => {
+                let ty_id = QualifiedName::new(ns, id.clone());
+                let ty_id = final_ident_using_original_name_map(&ty_id, &self.original_name_map);
+                (format!("{}->~{}()", arg_list, ty_id), "".to_string(), false)
+            }
+            CppFunctionBody::FunctionCall(ns, id) => match receiver {
+                Some(receiver) => (
+                    format!("{}.{}({})", receiver, id, arg_list),
+                    "".to_string(),
+                    false,
+                ),
+                None => {
+                    let underlying_function_call = ns
+                        .into_iter()
+                        .cloned()
+                        .chain(std::iter::once(id.to_string()))
+                        .join("::");
+                    (
+                        format!("{}({})", underlying_function_call, arg_list),
+                        "".to_string(),
+                        false,
+                    )
+                }
+            },
+            CppFunctionBody::StaticMethodCall(ns, ty_id, fn_id) => {
+                let underlying_function_call = ns
+                    .into_iter()
+                    .cloned()
+                    .chain([ty_id.to_string(), fn_id.to_string()].iter().cloned())
+                    .join("::");
+                (
+                    format!("{}({})", underlying_function_call, arg_list),
+                    "".to_string(),
+                    false,
+                )
+            }
+            CppFunctionBody::ConstructSuperclass(_) => ("".to_string(), arg_list, false),
+            CppFunctionBody::AllocUninitialized(ty) => {
+                let namespaced_ty = self.namespaced_name(ty);
+                (
+                    format!("new_appropriately<{}>();", namespaced_ty,),
+                    "".to_string(),
+                    true,
+                )
+            }
+            CppFunctionBody::FreeUninitialized(ty) => (
+                format!("delete_appropriately<{}>(arg0);", self.namespaced_name(ty)),
+                "".to_string(),
+                true,
+            ),
+        };
+        if let Some(ret) = &details.return_conversion {
+            let call_itself = match conversion_direction {
+                ConversionDirection::RustCallsCpp => {
+                    ret.cpp_conversion(&underlying_function_call, &self.original_name_map, true)?
+                }
+                ConversionDirection::CppCallsCpp => Some(underlying_function_call),
+                ConversionDirection::CppCallsRust => ret.inverse().cpp_conversion(
+                    &underlying_function_call,
+                    &self.original_name_map,
+                    true,
+                )?,
+            }
+            .expect(
+                "Expected some conversion type for return value which resulted in a parameter name",
+            );
+
+            underlying_function_call = match placement_param {
+                Some(placement_param) => {
+                    let tyname = type_to_cpp(&ret.unwrapped_type, &self.original_name_map)?;
+                    format!("new({}) {}({})", placement_param, tyname, call_itself)
+                }
+                None => format!("return {}", call_itself),
+            };
+        };
+        if !underlying_function_call.is_empty() {
+            underlying_function_call = format!("{};", underlying_function_call);
+        }
+        let field_assignments =
+            if let CppFunctionBody::ConstructSuperclass(superclass_name) = &details.payload {
+                let superclass_assignments = if field_assignments.is_empty() {
+                    "".to_string()
+                } else {
+                    format!("{}({}), ", superclass_name, field_assignments)
+                };
+                format!(": {}obs(std::move(arg0))", superclass_assignments)
+            } else {
+                "".into()
+            };
+        let definition_after_sig =
+            format!("{} {{ {} }}", field_assignments, underlying_function_call,);
+        let (declaration, definition) = if requires_rust_declarations {
+            (
+                Some(format!("{};", declaration)),
+                Some(format!(
+                    "{} {}",
+                    qualified_declaration, definition_after_sig
+                )),
+            )
+        } else {
+            (
+                Some(format!("inline {} {}", declaration, definition_after_sig)),
+                None,
+            )
+        };
+        let mut headers = vec![Header::System("memory")];
+        if need_allocators {
+            headers.push(Header::System("stddef.h"));
+            headers.push(Header::NewDeletePrelude);
+        }
+        Ok(ExtraCpp {
+            declaration,
+            definition,
+            headers,
+            ..Default::default()
+        })
+    }
+
+    fn namespaced_name(&self, name: &QualifiedName) -> String {
+        namespaced_name_using_original_name_map(name, &self.original_name_map)
+    }
+
+    fn generate_ctype_typedef(&mut self, tn: &QualifiedName) {
+        let cpp_name = tn.to_cpp_name();
+        self.generate_typedef(tn, &cpp_name)
+    }
+
+    fn generate_typedef(&mut self, tn: &QualifiedName, definition: &str) {
+        let our_name = tn.get_final_item();
+        self.additional_functions.push(ExtraCpp {
+            type_definition: Some(format!("typedef {} {};", definition, our_name)),
+            ..Default::default()
+        })
+    }
+
+    fn generate_subclass(
+        &mut self,
+        superclass: &QualifiedName,
+        subclass: &SubclassName,
+        constructors: Vec<&CppFunction>,
+        methods: Vec<SubclassFunction>,
+    ) -> Result<(), ConvertError> {
+        let holder = subclass.holder();
+        self.additional_functions.push(ExtraCpp {
+            type_definition: Some(format!("struct {};", holder)),
+            ..Default::default()
+        });
+        let mut method_decls = Vec::new();
+        for method in methods {
+            // First the method which calls from C++ to Rust
+            let mut fn_impl = self.generate_cpp_function_inner(
+                method.fun,
+                true,
+                ConversionDirection::CppCallsRust,
+                true,
+                Some(&method.fun.original_cpp_name),
+            )?;
+            method_decls.push(fn_impl.declaration.take().unwrap());
+            self.additional_functions.push(fn_impl);
+            // And now the function to be called from Rust for default implementation (calls superclass in C++)
+            if !method.is_pure_virtual {
+                let mut super_method = method.fun.clone();
+                super_method.pass_obs_field = false;
+                super_method.wrapper_function_name = SubclassName::get_super_fn_name(
+                    superclass.get_namespace(),
+                    &method.fun.wrapper_function_name.to_string(),
+                )
+                .get_final_ident();
+                super_method.payload = CppFunctionBody::StaticMethodCall(
+                    superclass.get_namespace().clone(),
+                    superclass.get_final_ident(),
+                    make_ident(&method.fun.original_cpp_name),
+                );
+                let mut super_fn_impl = self.generate_cpp_function_inner(
+                    &super_method,
+                    true,
+                    ConversionDirection::CppCallsCpp,
+                    false,
+                    None,
+                )?;
+                method_decls.push(super_fn_impl.declaration.take().unwrap());
+                self.additional_functions.push(super_fn_impl);
+            }
+        }
+        // In future, for each superclass..
+        let super_name = superclass.get_final_item();
+        method_decls.push(format!(
+            "const {}& As_{}() const {{ return *this; }}",
+            super_name, super_name,
+        ));
+        method_decls.push(format!(
+            "{}& As_{}_mut() {{ return *this; }}",
+            super_name, super_name
+        ));
+        // And now constructors
+        let mut constructor_decls: Vec<String> = Vec::new();
+        for constructor in constructors {
+            let mut fn_impl = self.generate_cpp_function_inner(
+                constructor,
+                false,
+                ConversionDirection::CppCallsCpp,
+                false,
+                None,
+            )?;
+            let decl = fn_impl.declaration.take().unwrap();
+            constructor_decls.push(decl);
+            self.additional_functions.push(fn_impl);
+        }
+        self.additional_functions.push(ExtraCpp {
+            type_definition: Some(format!(
+                "class {} : {}\n{{\npublic:\n{}\n{}\nvoid {}() const;\nprivate:rust::Box<{}> obs;\nvoid really_remove_ownership();\n\n}};",
+                subclass.cpp(),
+                superclass.to_cpp_name(),
+                constructor_decls.join("\n"),
+                method_decls.join("\n"),
+                subclass.cpp_remove_ownership(),
+                holder
+            )),
+            definition: Some(format!(
+                "void {}::{}() const {{\nconst_cast<{}*>(this)->really_remove_ownership();\n}}\nvoid {}::really_remove_ownership() {{\nauto new_obs = {}(std::move(obs));\nobs = std::move(new_obs);\n}}\n",
+                subclass.cpp(),
+                subclass.cpp_remove_ownership(),
+                subclass.cpp(),
+                subclass.cpp(),
+                subclass.remove_ownership()
+            )),
+            cpp_headers: vec![Header::CxxgenH],
+            ..Default::default()
+        });
+        Ok(())
+    }
+}
diff --git a/engine/src/conversion/codegen_cpp/new_and_delete_prelude.rs b/engine/src/conversion/codegen_cpp/new_and_delete_prelude.rs
new file mode 100644
index 0000000..d860789
--- /dev/null
+++ b/engine/src/conversion/codegen_cpp/new_and_delete_prelude.rs
@@ -0,0 +1,43 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indoc::indoc;
+
+/// This is logic to call either an overloaded operator new/delete
+/// or the standard one.
+/// The SFINAE magic here is: int is a better match than long,
+/// and so the versions which match class-specific operator new/delete
+/// will be used in preference to the general global ::operator new/delete.
+pub(super) static NEW_AND_DELETE_PRELUDE: &str = indoc! {"
+    #ifndef AUTOCXX_NEW_AND_DELETE_PRELUDE
+    #define AUTOCXX_NEW_AND_DELETE_PRELUDE
+    // Mechanics to call custom operator new and delete
+    template <typename T>
+    auto delete_imp(T *ptr, int) -> decltype((void)T::operator delete(ptr)) {
+      T::operator delete(ptr);
+    }
+    template <typename T> void delete_imp(T *ptr, long) { ::operator delete(ptr); }
+    template <typename T> void delete_appropriately(T *obj) {
+      // 0 is a better match for the first 'delete_imp' so will match
+      // preferentially.
+      delete_imp(obj, 0);
+    }
+    template <typename T>
+    auto new_imp(size_t count, int) -> decltype(T::operator new(count)) {
+      return T::operator new(count);
+    }
+    template <typename T> void *new_imp(size_t count, long) {
+      return ::operator new(count);
+    }
+    template <typename T> T *new_appropriately() {
+      // 0 is a better match for the first 'delete_imp' so will match
+      // preferentially.
+      return static_cast<T *>(new_imp<T>(sizeof(T), 0));
+    }
+    #endif // AUTOCXX_NEW_AND_DELETE_PRELUDE
+"};
diff --git a/engine/src/conversion/codegen_cpp/type_to_cpp.rs b/engine/src/conversion/codegen_cpp/type_to_cpp.rs
new file mode 100644
index 0000000..7febb7a
--- /dev/null
+++ b/engine/src/conversion/codegen_cpp/type_to_cpp.rs
@@ -0,0 +1,140 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::{
+    conversion::{apivec::ApiVec, AnalysisPhase, ConvertError},
+    types::QualifiedName,
+};
+use indexmap::map::IndexMap as HashMap;
+use itertools::Itertools;
+use quote::ToTokens;
+use std::iter::once;
+use syn::{Token, Type};
+
+/// Map from QualifiedName to original C++ name. Original C++ name does not
+/// include the namespace; this can be assumed to be the same as the namespace
+/// in the QualifiedName.
+pub(crate) type CppNameMap = HashMap<QualifiedName, String>;
+
+pub(crate) fn original_name_map_from_apis<T: AnalysisPhase>(apis: &ApiVec<T>) -> CppNameMap {
+    apis.iter()
+        .filter_map(|api| {
+            api.cpp_name()
+                .as_ref()
+                .map(|cpp_name| (api.name().clone(), cpp_name.clone()))
+        })
+        .collect()
+}
+
+pub(crate) fn namespaced_name_using_original_name_map(
+    qual_name: &QualifiedName,
+    original_name_map: &CppNameMap,
+) -> String {
+    if let Some(cpp_name) = original_name_map.get(qual_name) {
+        qual_name
+            .get_namespace()
+            .iter()
+            .chain(once(cpp_name))
+            .join("::")
+    } else {
+        qual_name.to_cpp_name()
+    }
+}
+
+pub(crate) fn final_ident_using_original_name_map(
+    qual_name: &QualifiedName,
+    original_name_map: &CppNameMap,
+) -> String {
+    match original_name_map.get(qual_name) {
+        Some(original_name) => {
+            // If we have an original name, this may be a nested struct
+            // (e.g. A::B). The final ident here is just 'B' so...
+            original_name
+                .rsplit_once("::")
+                .map_or(original_name.clone(), |(_, original_name)| {
+                    original_name.to_string()
+                })
+        }
+        None => qual_name.get_final_cpp_item(),
+    }
+}
+
+pub(crate) fn type_to_cpp(ty: &Type, cpp_name_map: &CppNameMap) -> Result<String, ConvertError> {
+    match ty {
+        Type::Path(typ) => {
+            // If this is a std::unique_ptr we do need to pass
+            // its argument through.
+            let qual_name = QualifiedName::from_type_path(typ);
+            let root = namespaced_name_using_original_name_map(&qual_name, cpp_name_map);
+            if root == "Pin" {
+                // Strip all Pins from type names when describing them in C++.
+                let inner_type = &typ.path.segments.last().unwrap().arguments;
+                if let syn::PathArguments::AngleBracketed(ab) = inner_type {
+                    let inner_type = ab.args.iter().next().unwrap();
+                    if let syn::GenericArgument::Type(gat) = inner_type {
+                        return type_to_cpp(gat, cpp_name_map);
+                    }
+                }
+                panic!("Pin<...> didn't contain the inner types we expected");
+            }
+            let suffix = match &typ.path.segments.last().unwrap().arguments {
+                syn::PathArguments::AngleBracketed(ab) => {
+                    let results: Result<Vec<_>, _> = ab
+                        .args
+                        .iter()
+                        .map(|x| match x {
+                            syn::GenericArgument::Type(gat) => type_to_cpp(gat, cpp_name_map),
+                            _ => Ok("".to_string()),
+                        })
+                        .collect();
+                    Some(results?.join(", "))
+                }
+                syn::PathArguments::None | syn::PathArguments::Parenthesized(_) => None,
+            };
+            match suffix {
+                None => Ok(root),
+                Some(suffix) => Ok(format!("{}<{}>", root, suffix)),
+            }
+        }
+        Type::Reference(typr) => match &*typr.elem {
+            Type::Path(typ) if typ.path.is_ident("str") => Ok("rust::Str".into()),
+            _ => Ok(format!(
+                "{}{}&",
+                get_mut_string(&typr.mutability),
+                type_to_cpp(typr.elem.as_ref(), cpp_name_map)?
+            )),
+        },
+        Type::Ptr(typp) => Ok(format!(
+            "{}{}*",
+            get_mut_string(&typp.mutability),
+            type_to_cpp(typp.elem.as_ref(), cpp_name_map)?
+        )),
+        Type::Array(_)
+        | Type::BareFn(_)
+        | Type::Group(_)
+        | Type::ImplTrait(_)
+        | Type::Infer(_)
+        | Type::Macro(_)
+        | Type::Never(_)
+        | Type::Paren(_)
+        | Type::Slice(_)
+        | Type::TraitObject(_)
+        | Type::Tuple(_)
+        | Type::Verbatim(_) => Err(ConvertError::UnsupportedType(
+            ty.to_token_stream().to_string(),
+        )),
+        _ => Err(ConvertError::UnknownType(ty.to_token_stream().to_string())),
+    }
+}
+
+fn get_mut_string(mutability: &Option<Token![mut]>) -> &'static str {
+    match mutability {
+        None => "const ",
+        Some(_) => "",
+    }
+}
diff --git a/engine/src/conversion/codegen_rs/fun_codegen.rs b/engine/src/conversion/codegen_rs/fun_codegen.rs
new file mode 100644
index 0000000..7c32b1b
--- /dev/null
+++ b/engine/src/conversion/codegen_rs/fun_codegen.rs
@@ -0,0 +1,424 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::set::IndexSet as HashSet;
+use std::borrow::Cow;
+
+use proc_macro2::TokenStream;
+use quote::{quote, ToTokens};
+use syn::{
+    parse::Parser,
+    parse_quote,
+    punctuated::Punctuated,
+    token::{Comma, Unsafe},
+    Attribute, FnArg, ForeignItem, Ident, ImplItem, Item, ReturnType,
+};
+
+use super::{
+    function_wrapper_rs::RustParamConversion,
+    maybe_unsafes_to_tokens,
+    unqualify::{unqualify_params, unqualify_ret_type},
+    ImplBlockDetails, MaybeUnsafeStmt, RsCodegenResult, TraitImplBlockDetails, Use,
+};
+use crate::{
+    conversion::{
+        analysis::fun::{
+            ArgumentAnalysis, FnAnalysis, FnKind, MethodKind, RustRenameStrategy,
+            TraitMethodDetails,
+        },
+        api::UnsafetyNeeded,
+    },
+    types::{Namespace, QualifiedName},
+};
+use crate::{
+    conversion::{api::FuncToConvert, codegen_rs::lifetime::add_explicit_lifetime_if_necessary},
+    types::make_ident,
+};
+
+impl UnsafetyNeeded {
+    pub(crate) fn bridge_token(&self) -> Option<Unsafe> {
+        match self {
+            UnsafetyNeeded::None => None,
+            _ => Some(parse_quote! { unsafe }),
+        }
+    }
+
+    pub(crate) fn wrapper_token(&self) -> Option<Unsafe> {
+        match self {
+            UnsafetyNeeded::Always => Some(parse_quote! { unsafe }),
+            _ => None,
+        }
+    }
+
+    pub(crate) fn from_param_details(params: &[ArgumentAnalysis], ignore_placements: bool) -> Self {
+        params.iter().fold(UnsafetyNeeded::None, |accumulator, pd| {
+            if matches!(accumulator, UnsafetyNeeded::Always) {
+                UnsafetyNeeded::Always
+            } else if (pd.self_type.is_some() || pd.is_placement_return_destination)
+                && ignore_placements
+            {
+                if matches!(
+                    pd.requires_unsafe,
+                    UnsafetyNeeded::Always | UnsafetyNeeded::JustBridge
+                ) {
+                    UnsafetyNeeded::JustBridge
+                } else {
+                    accumulator
+                }
+            } else if matches!(pd.requires_unsafe, UnsafetyNeeded::Always) {
+                UnsafetyNeeded::Always
+            } else if matches!(accumulator, UnsafetyNeeded::JustBridge)
+                || matches!(pd.requires_unsafe, UnsafetyNeeded::JustBridge)
+            {
+                UnsafetyNeeded::JustBridge
+            } else {
+                UnsafetyNeeded::None
+            }
+        })
+    }
+}
+
+pub(super) fn gen_function(
+    ns: &Namespace,
+    fun: FuncToConvert,
+    analysis: FnAnalysis,
+    cpp_call_name: String,
+    non_pod_types: &HashSet<QualifiedName>,
+) -> RsCodegenResult {
+    if analysis.ignore_reason.is_err() || !analysis.externally_callable {
+        return RsCodegenResult::default();
+    }
+    let cxxbridge_name = analysis.cxxbridge_name;
+    let rust_name = &analysis.rust_name;
+    let ret_type = analysis.ret_type;
+    let param_details = analysis.param_details;
+    let wrapper_function_needed = analysis.cpp_wrapper.is_some();
+    let params = analysis.params;
+    let vis = analysis.vis;
+    let kind = analysis.kind;
+    let doc_attrs = fun.doc_attrs;
+
+    let mut cpp_name_attr = Vec::new();
+    let mut impl_entry = None;
+    let mut trait_impl_entry = None;
+    let mut bindgen_mod_items = Vec::new();
+    let always_unsafe_due_to_trait_definition = match kind {
+        FnKind::TraitMethod { ref details, .. } => details.trait_call_is_unsafe,
+        _ => false,
+    };
+    let fn_generator = FnGenerator {
+        param_details: &param_details,
+        cxxbridge_name: &cxxbridge_name,
+        rust_name,
+        unsafety: &analysis.requires_unsafe,
+        always_unsafe_due_to_trait_definition,
+        doc_attrs: &doc_attrs,
+        non_pod_types,
+    };
+    // In rare occasions, we might need to give an explicit lifetime.
+    let (lifetime_tokens, params, ret_type) = add_explicit_lifetime_if_necessary(
+        &param_details,
+        params,
+        Cow::Borrowed(&ret_type),
+        non_pod_types,
+        true,
+    );
+
+    if analysis.rust_wrapper_needed {
+        match kind {
+            FnKind::Method {
+                ref impl_for,
+                method_kind: MethodKind::Constructor { .. },
+                ..
+            } => {
+                // Constructor.
+                impl_entry = Some(fn_generator.generate_constructor_impl(impl_for));
+            }
+            FnKind::Method {
+                ref impl_for,
+                ref method_kind,
+                ..
+            } => {
+                // Method, or static method.
+                impl_entry = Some(fn_generator.generate_method_impl(
+                    matches!(method_kind, MethodKind::Constructor { .. }),
+                    impl_for,
+                    &ret_type,
+                ));
+            }
+            FnKind::TraitMethod { ref details, .. } => {
+                trait_impl_entry = Some(fn_generator.generate_trait_impl(details, &ret_type));
+            }
+            _ => {
+                // Generate plain old function
+                bindgen_mod_items.push(fn_generator.generate_function_impl(&ret_type));
+            }
+        }
+    }
+
+    let materialization = match kind {
+        FnKind::Method { .. } | FnKind::TraitMethod { .. } => None,
+        FnKind::Function => match analysis.rust_rename_strategy {
+            _ if analysis.rust_wrapper_needed => {
+                Some(Use::SpecificNameFromBindgen(make_ident(rust_name)))
+            }
+            RustRenameStrategy::RenameInOutputMod(ref alias) => {
+                Some(Use::UsedFromCxxBridgeWithAlias(alias.clone()))
+            }
+            _ => Some(Use::UsedFromCxxBridge),
+        },
+    };
+    if cxxbridge_name != cpp_call_name && !wrapper_function_needed {
+        cpp_name_attr = Attribute::parse_outer
+            .parse2(quote!(
+                #[cxx_name = #cpp_call_name]
+            ))
+            .unwrap();
+    }
+
+    // Finally - namespace support. All the Types in everything
+    // above this point are fully qualified. We need to unqualify them.
+    // We need to do that _after_ the above wrapper_function_needed
+    // work, because it relies upon spotting fully qualified names like
+    // std::unique_ptr. However, after it's done its job, all such
+    // well-known types should be unqualified already (e.g. just UniquePtr)
+    // and the following code will act to unqualify only those types
+    // which the user has declared.
+    let params = unqualify_params(params);
+    let ret_type = unqualify_ret_type(ret_type.into_owned());
+    // And we need to make an attribute for the namespace that the function
+    // itself is in.
+    let namespace_attr = if ns.is_empty() || wrapper_function_needed {
+        Vec::new()
+    } else {
+        let namespace_string = ns.to_string();
+        Attribute::parse_outer
+            .parse2(quote!(
+                #[namespace = #namespace_string]
+            ))
+            .unwrap()
+    };
+    // At last, actually generate the cxx::bridge entry.
+    let bridge_unsafety = analysis.requires_unsafe.bridge_token();
+    let extern_c_mod_item = ForeignItem::Fn(parse_quote!(
+        #(#namespace_attr)*
+        #(#cpp_name_attr)*
+        #(#doc_attrs)*
+        #vis #bridge_unsafety fn #cxxbridge_name #lifetime_tokens ( #params ) #ret_type;
+    ));
+    RsCodegenResult {
+        extern_c_mod_items: vec![extern_c_mod_item],
+        bindgen_mod_items,
+        impl_entry,
+        trait_impl_entry,
+        materializations: materialization.into_iter().collect(),
+        ..Default::default()
+    }
+}
+
+/// Knows how to generate a given function.
+#[derive(Clone)]
+struct FnGenerator<'a> {
+    param_details: &'a [ArgumentAnalysis],
+    cxxbridge_name: &'a Ident,
+    rust_name: &'a str,
+    unsafety: &'a UnsafetyNeeded,
+    always_unsafe_due_to_trait_definition: bool,
+    doc_attrs: &'a Vec<Attribute>,
+    non_pod_types: &'a HashSet<QualifiedName>,
+}
+
+impl<'a> FnGenerator<'a> {
+    fn common_parts<'b>(
+        &self,
+        avoid_self: bool,
+        parameter_reordering: &Option<Vec<usize>>,
+        ret_type: &'b ReturnType,
+    ) -> (
+        Option<TokenStream>,
+        Punctuated<FnArg, Comma>,
+        std::borrow::Cow<'b, ReturnType>,
+        TokenStream,
+    ) {
+        let mut wrapper_params: Punctuated<FnArg, Comma> = Punctuated::new();
+        let mut local_variables = Vec::new();
+        let mut arg_list = Vec::new();
+        let mut ptr_arg_name = None;
+        let mut ret_type = Cow::Borrowed(ret_type);
+        let mut any_conversion_requires_unsafe = false;
+        for pd in self.param_details {
+            let wrapper_arg_name = if pd.self_type.is_some() && !avoid_self {
+                parse_quote!(self)
+            } else {
+                pd.name.clone()
+            };
+            let rust_for_param = pd.conversion.rust_conversion(wrapper_arg_name.clone());
+            match rust_for_param {
+                RustParamConversion::Param {
+                    ty,
+                    conversion,
+                    local_variables: mut these_local_variables,
+                    conversion_requires_unsafe,
+                } => {
+                    arg_list.push(conversion.clone());
+                    local_variables.append(&mut these_local_variables);
+                    if pd.is_placement_return_destination {
+                        ptr_arg_name = Some(conversion);
+                    } else {
+                        let param_mutability = pd.conversion.rust_conversion.requires_mutability();
+                        wrapper_params.push(parse_quote!(
+                            #param_mutability #wrapper_arg_name: #ty
+                        ));
+                    }
+                    any_conversion_requires_unsafe =
+                        conversion_requires_unsafe || any_conversion_requires_unsafe;
+                }
+                RustParamConversion::ReturnValue { ty } => {
+                    ptr_arg_name = Some(pd.name.to_token_stream());
+                    ret_type = Cow::Owned(parse_quote! {
+                        -> impl autocxx::moveit::new::New<Output = #ty>
+                    });
+                    arg_list.push(pd.name.to_token_stream());
+                }
+            }
+        }
+        if let Some(parameter_reordering) = &parameter_reordering {
+            wrapper_params = Self::reorder_parameters(wrapper_params, parameter_reordering);
+        }
+        let (lifetime_tokens, wrapper_params, ret_type) = add_explicit_lifetime_if_necessary(
+            self.param_details,
+            wrapper_params,
+            ret_type,
+            self.non_pod_types,
+            false,
+        );
+
+        let cxxbridge_name = self.cxxbridge_name;
+        let call_body = MaybeUnsafeStmt::maybe_unsafe(
+            quote! {
+                cxxbridge::#cxxbridge_name ( #(#arg_list),* )
+            },
+            any_conversion_requires_unsafe || matches!(self.unsafety, UnsafetyNeeded::JustBridge),
+        );
+        let call_stmts = if let Some(ptr_arg_name) = ptr_arg_name {
+            let mut closure_stmts = local_variables;
+            closure_stmts.push(MaybeUnsafeStmt::binary(
+                quote! { let #ptr_arg_name = unsafe { #ptr_arg_name.get_unchecked_mut().as_mut_ptr() };},
+                quote! { let #ptr_arg_name = #ptr_arg_name.get_unchecked_mut().as_mut_ptr();},
+            ));
+            closure_stmts.push(call_body);
+            let closure_stmts = maybe_unsafes_to_tokens(closure_stmts, true);
+            vec![MaybeUnsafeStmt::needs_unsafe(parse_quote! {
+                autocxx::moveit::new::by_raw(move |#ptr_arg_name| {
+                    #closure_stmts
+                })
+            })]
+        } else {
+            let mut call_stmts = local_variables;
+            call_stmts.push(call_body);
+            call_stmts
+        };
+        let context_is_unsafe = matches!(self.unsafety, UnsafetyNeeded::Always)
+            || self.always_unsafe_due_to_trait_definition;
+        let call_body = maybe_unsafes_to_tokens(call_stmts, context_is_unsafe);
+        (lifetime_tokens, wrapper_params, ret_type, call_body)
+    }
+
+    /// Generate an 'impl Type { methods-go-here }' item
+    fn generate_method_impl(
+        &self,
+        avoid_self: bool,
+        impl_block_type_name: &QualifiedName,
+        ret_type: &ReturnType,
+    ) -> Box<ImplBlockDetails> {
+        let (lifetime_tokens, wrapper_params, ret_type, call_body) =
+            self.common_parts(avoid_self, &None, ret_type);
+        let rust_name = make_ident(self.rust_name);
+        let unsafety = self.unsafety.wrapper_token();
+        let doc_attrs = self.doc_attrs;
+        Box::new(ImplBlockDetails {
+            item: ImplItem::Method(parse_quote! {
+                #(#doc_attrs)*
+                pub #unsafety fn #rust_name #lifetime_tokens ( #wrapper_params ) #ret_type {
+                    #call_body
+                }
+            }),
+            ty: impl_block_type_name.get_final_ident(),
+        })
+    }
+
+    /// Generate an 'impl Trait for Type { methods-go-here }' in its entrety.
+    fn generate_trait_impl(
+        &self,
+        details: &TraitMethodDetails,
+        ret_type: &ReturnType,
+    ) -> Box<TraitImplBlockDetails> {
+        let (lifetime_tokens, wrapper_params, ret_type, call_body) =
+            self.common_parts(details.avoid_self, &details.parameter_reordering, ret_type);
+        let doc_attrs = self.doc_attrs;
+        let unsafety = self.unsafety.wrapper_token();
+        let key = details.trt.clone();
+        let method_name = &details.method_name;
+        let item = parse_quote! {
+            #(#doc_attrs)*
+            #unsafety fn #method_name #lifetime_tokens ( #wrapper_params ) #ret_type {
+                #call_body
+            }
+        };
+        Box::new(TraitImplBlockDetails { item, key })
+    }
+
+    /// Generate a 'impl Type { methods-go-here }' item which is a constructor
+    /// for use with moveit traits.
+    fn generate_constructor_impl(
+        &self,
+        impl_block_type_name: &QualifiedName,
+    ) -> Box<ImplBlockDetails> {
+        let ret_type: ReturnType = parse_quote! { -> impl autocxx::moveit::new::New<Output=Self> };
+        let (lifetime_tokens, wrapper_params, ret_type, call_body) =
+            self.common_parts(true, &None, &ret_type);
+        let rust_name = make_ident(&self.rust_name);
+        let doc_attrs = self.doc_attrs;
+        let unsafety = self.unsafety.wrapper_token();
+        Box::new(ImplBlockDetails {
+            item: ImplItem::Method(parse_quote! {
+                #(#doc_attrs)*
+                pub #unsafety fn #rust_name #lifetime_tokens ( #wrapper_params ) #ret_type {
+                    #call_body
+                }
+            }),
+            ty: impl_block_type_name.get_final_ident(),
+        })
+    }
+
+    /// Generate a function call wrapper
+    fn generate_function_impl(&self, ret_type: &ReturnType) -> Item {
+        let (lifetime_tokens, wrapper_params, ret_type, call_body) =
+            self.common_parts(false, &None, ret_type);
+        let rust_name = make_ident(self.rust_name);
+        let doc_attrs = self.doc_attrs;
+        let unsafety = self.unsafety.wrapper_token();
+        Item::Fn(parse_quote! {
+            #(#doc_attrs)*
+            pub #unsafety fn #rust_name #lifetime_tokens ( #wrapper_params ) #ret_type {
+                #call_body
+            }
+        })
+    }
+
+    fn reorder_parameters(
+        params: Punctuated<FnArg, Comma>,
+        parameter_ordering: &[usize],
+    ) -> Punctuated<FnArg, Comma> {
+        let old_params = params.into_iter().collect::<Vec<_>>();
+        parameter_ordering
+            .iter()
+            .map(|n| old_params.get(*n).unwrap().clone())
+            .collect()
+    }
+}
diff --git a/engine/src/conversion/codegen_rs/function_wrapper_rs.rs b/engine/src/conversion/codegen_rs/function_wrapper_rs.rs
new file mode 100644
index 0000000..a3fc71f
--- /dev/null
+++ b/engine/src/conversion/codegen_rs/function_wrapper_rs.rs
@@ -0,0 +1,172 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use proc_macro2::TokenStream;
+use syn::{Pat, Type, TypePtr};
+
+use crate::{
+    conversion::analysis::fun::function_wrapper::{RustConversionType, TypeConversionPolicy},
+    types::make_ident,
+};
+use quote::quote;
+use syn::parse_quote;
+
+use super::MaybeUnsafeStmt;
+
+/// Output Rust snippets for how to deal with a given parameter.
+pub(super) enum RustParamConversion {
+    Param {
+        ty: Type,
+        local_variables: Vec<MaybeUnsafeStmt>,
+        conversion: TokenStream,
+        conversion_requires_unsafe: bool,
+    },
+    ReturnValue {
+        ty: Type,
+    },
+}
+
+impl TypeConversionPolicy {
+    /// If returns `None` then this parameter should be omitted entirely.
+    pub(super) fn rust_conversion(&self, var: Pat) -> RustParamConversion {
+        match self.rust_conversion {
+            RustConversionType::None => RustParamConversion::Param {
+                ty: self.converted_rust_type(),
+                local_variables: Vec::new(),
+                conversion: quote! { #var },
+                conversion_requires_unsafe: false,
+            },
+            RustConversionType::FromStr => RustParamConversion::Param {
+                ty: parse_quote! { impl ToCppString },
+                local_variables: Vec::new(),
+                conversion: quote! ( #var .into_cpp() ),
+                conversion_requires_unsafe: false,
+            },
+            RustConversionType::ToBoxedUpHolder(ref sub) => {
+                let holder_type = sub.holder();
+                let id = sub.id();
+                let ty = parse_quote! { autocxx::subclass::CppSubclassRustPeerHolder<
+                    super::super::super:: #id>
+                };
+                RustParamConversion::Param {
+                    ty,
+                    local_variables: Vec::new(),
+                    conversion: quote! {
+                        Box::new(#holder_type(#var))
+                    },
+                    conversion_requires_unsafe: false,
+                }
+            }
+            RustConversionType::FromPinMaybeUninitToPtr => {
+                let ty = match &self.unwrapped_type {
+                    Type::Ptr(TypePtr { elem, .. }) => &*elem,
+                    _ => panic!("Not a ptr"),
+                };
+                let ty = parse_quote! {
+                    ::std::pin::Pin<&mut ::std::mem::MaybeUninit< #ty >>
+                };
+                RustParamConversion::Param {
+                    ty,
+                    local_variables: Vec::new(),
+                    conversion: quote! {
+                        #var.get_unchecked_mut().as_mut_ptr()
+                    },
+                    conversion_requires_unsafe: true,
+                }
+            }
+            RustConversionType::FromPinMoveRefToPtr => {
+                let ty = match &self.unwrapped_type {
+                    Type::Ptr(TypePtr { elem, .. }) => &*elem,
+                    _ => panic!("Not a ptr"),
+                };
+                let ty = parse_quote! {
+                    ::std::pin::Pin<autocxx::moveit::MoveRef< '_, #ty >>
+                };
+                RustParamConversion::Param {
+                    ty,
+                    local_variables: Vec::new(),
+                    conversion: quote! {
+                        { let r: &mut _ = ::std::pin::Pin::into_inner_unchecked(#var.as_mut());
+                            r
+                        }
+                    },
+                    conversion_requires_unsafe: true,
+                }
+            }
+            RustConversionType::FromTypeToPtr => {
+                let ty = match &self.unwrapped_type {
+                    Type::Ptr(TypePtr { elem, .. }) => &*elem,
+                    _ => panic!("Not a ptr"),
+                };
+                let ty = parse_quote! { &mut #ty };
+                RustParamConversion::Param {
+                    ty,
+                    local_variables: Vec::new(),
+                    conversion: quote! {
+                        #var
+                    },
+                    conversion_requires_unsafe: false,
+                }
+            }
+            RustConversionType::FromValueParamToPtr | RustConversionType::FromRValueParamToPtr => {
+                let (handler_type, param_trait) = match self.rust_conversion {
+                    RustConversionType::FromValueParamToPtr => ("ValueParamHandler", "ValueParam"),
+                    RustConversionType::FromRValueParamToPtr => {
+                        ("RValueParamHandler", "RValueParam")
+                    }
+                    _ => unreachable!(),
+                };
+                let handler_type = make_ident(handler_type);
+                let param_trait = make_ident(param_trait);
+                let var_name = if let Pat::Ident(pti) = &var {
+                    &pti.ident
+                } else {
+                    panic!("Unexpected non-ident parameter name");
+                };
+                let space_var_name = make_ident(format!("{}_space", var_name));
+                let ty = &self.unwrapped_type;
+                let ty = parse_quote! { impl autocxx::#param_trait<#ty> };
+                // This is the usual trick to put something on the stack, then
+                // immediately shadow the variable name so it can't be accessed or moved.
+                RustParamConversion::Param {
+                    ty,
+                    local_variables: vec![
+                        MaybeUnsafeStmt::new(
+                            quote! { let mut #space_var_name = autocxx::#handler_type::default(); },
+                        ),
+                        MaybeUnsafeStmt::binary(
+                            quote! { let mut #space_var_name =
+                                unsafe { ::std::pin::Pin::new_unchecked(&mut #space_var_name) };
+                            },
+                            quote! { let mut #space_var_name =
+                                ::std::pin::Pin::new_unchecked(&mut #space_var_name);
+                            },
+                        ),
+                        MaybeUnsafeStmt::needs_unsafe(
+                            quote! { #space_var_name.as_mut().populate(#var_name); },
+                        ),
+                    ],
+                    conversion: quote! {
+                        #space_var_name.get_ptr()
+                    },
+                    conversion_requires_unsafe: false,
+                }
+            }
+            // This type of conversion means that this function parameter appears in the cxx::bridge
+            // but not in the arguments for the wrapper function, because instead we return an
+            // impl New which uses the cxx::bridge function's pointer parameter.
+            RustConversionType::FromPlacementParamToNewReturn => {
+                let ty = match &self.unwrapped_type {
+                    Type::Ptr(TypePtr { elem, .. }) => *(*elem).clone(),
+                    _ => panic!("Not a ptr"),
+                };
+                RustParamConversion::ReturnValue { ty }
+            }
+        }
+    }
+}
diff --git a/engine/src/conversion/codegen_rs/impl_item_creator.rs b/engine/src/conversion/codegen_rs/impl_item_creator.rs
new file mode 100644
index 0000000..89ef896
--- /dev/null
+++ b/engine/src/conversion/codegen_rs/impl_item_creator.rs
@@ -0,0 +1,41 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx_parser::IncludeCppConfig;
+use syn::{parse_quote, Ident, Item};
+
+pub(crate) fn create_impl_items(
+    id: &Ident,
+    movable: bool,
+    destroyable: bool,
+    config: &IncludeCppConfig,
+) -> Vec<Item> {
+    if config.exclude_impls {
+        return vec![];
+    }
+    let mut results = Vec::new();
+    if destroyable {
+        results.extend([
+            Item::Impl(parse_quote! {
+                impl UniquePtr<#id> {}
+            }),
+            Item::Impl(parse_quote! {
+                impl SharedPtr<#id> {}
+            }),
+            Item::Impl(parse_quote! {
+                impl WeakPtr<#id> {}
+            }),
+        ]);
+    }
+    if movable {
+        results.push(Item::Impl(parse_quote! {
+            impl CxxVector<#id> {}
+        }))
+    }
+    results
+}
diff --git a/engine/src/conversion/codegen_rs/lifetime.rs b/engine/src/conversion/codegen_rs/lifetime.rs
new file mode 100644
index 0000000..ea2c782
--- /dev/null
+++ b/engine/src/conversion/codegen_rs/lifetime.rs
@@ -0,0 +1,205 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+use crate::{
+    conversion::analysis::fun::{
+        function_wrapper::RustConversionType, ArgumentAnalysis, ReceiverMutability,
+    },
+    types::QualifiedName,
+};
+use indexmap::set::IndexSet as HashSet;
+use proc_macro2::TokenStream;
+use quote::{quote, ToTokens};
+use std::borrow::Cow;
+use syn::{
+    parse_quote, punctuated::Punctuated, token::Comma, FnArg, GenericArgument, PatType, Path,
+    PathSegment, ReturnType, Type, TypePath, TypeReference,
+};
+
+/// Function which can add explicit lifetime parameters to function signatures
+/// where necessary, based on analysis of parameters and return types.
+/// This is necessary in three cases:
+/// 1) where the parameter is a Pin<&mut T>
+///    and the return type is some kind of reference - because lifetime elision
+///    is not smart enough to see inside a Pin.
+/// 2) as a workaround for https://github.com/dtolnay/cxx/issues/1024, where the
+///    input parameter is a non-POD type but the output reference is a POD or
+///    built-in type
+/// 3) Any parameter is any form of reference, and we're returning an `impl New`
+///    3a) an 'impl ValueParam' counts as a reference.
+pub(crate) fn add_explicit_lifetime_if_necessary<'r>(
+    param_details: &[ArgumentAnalysis],
+    mut params: Punctuated<FnArg, Comma>,
+    ret_type: Cow<'r, ReturnType>,
+    non_pod_types: &HashSet<QualifiedName>,
+    assert_all_parameters_are_references: bool,
+) -> (
+    Option<TokenStream>,
+    Punctuated<FnArg, Comma>,
+    Cow<'r, ReturnType>,
+) {
+    let has_mutable_receiver = param_details.iter().any(|pd| {
+        matches!(pd.self_type, Some((_, ReceiverMutability::Mutable)))
+            && !pd.is_placement_return_destination
+    });
+
+    let any_param_is_reference = param_details.iter().any(|pd| {
+        pd.has_lifetime
+            || matches!(
+                pd.conversion.rust_conversion,
+                RustConversionType::FromValueParamToPtr
+            )
+    });
+    let return_type_is_impl = return_type_is_impl(&ret_type);
+    let non_pod_ref_param = reference_parameter_is_non_pod_reference(&params, non_pod_types);
+    let ret_type_pod = return_type_is_pod_or_known_type_reference(&ret_type, non_pod_types);
+    let returning_impl_with_a_reference_param = return_type_is_impl && any_param_is_reference;
+    let hits_1024_bug = non_pod_ref_param && ret_type_pod;
+    if !(has_mutable_receiver || hits_1024_bug || returning_impl_with_a_reference_param) {
+        return (None, params, ret_type);
+    }
+    let new_return_type = match ret_type.as_ref() {
+        ReturnType::Type(rarrow, boxed_type) => match boxed_type.as_ref() {
+            Type::Reference(rtr) => {
+                let mut new_rtr = rtr.clone();
+                new_rtr.lifetime = Some(parse_quote! { 'a });
+                Some(ReturnType::Type(
+                    *rarrow,
+                    Box::new(Type::Reference(new_rtr)),
+                ))
+            }
+            Type::Path(typ) => {
+                let mut new_path = typ.clone();
+                add_lifetime_to_pinned_reference(&mut new_path.path.segments)
+                    .ok()
+                    .map(|_| ReturnType::Type(*rarrow, Box::new(Type::Path(new_path))))
+            }
+            Type::ImplTrait(tyit) => {
+                let old_tyit = tyit.to_token_stream();
+                Some(parse_quote! {
+                    #rarrow #old_tyit + 'a
+                })
+            }
+            _ => None,
+        },
+        _ => None,
+    };
+
+    match new_return_type {
+        None => (None, params, ret_type),
+        Some(new_return_type) => {
+            for mut param in params.iter_mut() {
+                match &mut param {
+                    FnArg::Typed(PatType { ty, .. }) => match ty.as_mut() {
+                        Type::Path(TypePath {
+                            path: Path { segments, .. },
+                            ..
+                        }) => add_lifetime_to_pinned_reference(segments).unwrap_or_else(|e| {
+                            if assert_all_parameters_are_references {
+                                panic!("Expected a pinned reference: {:?}", e)
+                            }
+                        }),
+                        Type::Reference(tyr) => add_lifetime_to_reference(tyr),
+                        Type::ImplTrait(tyit) => add_lifetime_to_impl_trait(tyit),
+                        _ if assert_all_parameters_are_references => {
+                            panic!("Expected Pin<&mut T> or &T")
+                        }
+                        _ => {}
+                    },
+                    _ if assert_all_parameters_are_references => panic!("Unexpected fnarg"),
+                    _ => {}
+                }
+            }
+
+            (Some(quote! { <'a> }), params, Cow::Owned(new_return_type))
+        }
+    }
+}
+
+fn reference_parameter_is_non_pod_reference(
+    params: &Punctuated<FnArg, Comma>,
+    non_pod_types: &HashSet<QualifiedName>,
+) -> bool {
+    params.iter().any(|param| match param {
+        FnArg::Typed(PatType { ty, .. }) => match ty.as_ref() {
+            Type::Reference(TypeReference { elem, .. }) => match elem.as_ref() {
+                Type::Path(typ) => {
+                    let qn = QualifiedName::from_type_path(typ);
+                    non_pod_types.contains(&qn)
+                }
+                _ => false,
+            },
+            _ => false,
+        },
+        _ => false,
+    })
+}
+
+fn return_type_is_pod_or_known_type_reference(
+    ret_type: &ReturnType,
+    non_pod_types: &HashSet<QualifiedName>,
+) -> bool {
+    match ret_type {
+        ReturnType::Type(_, boxed_type) => match boxed_type.as_ref() {
+            Type::Reference(rtr) => match rtr.elem.as_ref() {
+                Type::Path(typ) => {
+                    let qn = QualifiedName::from_type_path(typ);
+                    !non_pod_types.contains(&qn)
+                }
+                _ => false,
+            },
+            _ => false,
+        },
+        _ => false,
+    }
+}
+
+fn return_type_is_impl(ret_type: &ReturnType) -> bool {
+    matches!(ret_type, ReturnType::Type(_, boxed_type) if matches!(boxed_type.as_ref(), Type::ImplTrait(..)))
+}
+
+#[derive(Debug)]
+enum AddLifetimeError {
+    WasNotPin,
+}
+
+fn add_lifetime_to_pinned_reference(
+    segments: &mut Punctuated<PathSegment, syn::token::Colon2>,
+) -> Result<(), AddLifetimeError> {
+    static EXPECTED_SEGMENTS: &[(&str, bool)] = &[
+        ("std", false),
+        ("pin", false),
+        ("Pin", true), // true = act on the arguments of this segment
+    ];
+
+    for (seg, (expected_name, act)) in segments.iter_mut().zip(EXPECTED_SEGMENTS.iter()) {
+        if seg.ident != expected_name {
+            return Err(AddLifetimeError::WasNotPin);
+        }
+        if *act {
+            match &mut seg.arguments {
+                syn::PathArguments::AngleBracketed(aba) => match aba.args.iter_mut().next() {
+                    Some(GenericArgument::Type(Type::Reference(tyr))) => {
+                        add_lifetime_to_reference(tyr);
+                    }
+                    _ => panic!("Expected generic args with a reference"),
+                },
+                _ => panic!("Expected angle bracketed args"),
+            }
+        }
+    }
+    Ok(())
+}
+
+fn add_lifetime_to_reference(tyr: &mut syn::TypeReference) {
+    tyr.lifetime = Some(parse_quote! { 'a })
+}
+
+fn add_lifetime_to_impl_trait(tyit: &mut syn::TypeImplTrait) {
+    tyit.bounds
+        .push(syn::TypeParamBound::Lifetime(parse_quote! { 'a }))
+}
diff --git a/engine/src/conversion/codegen_rs/mod.rs b/engine/src/conversion/codegen_rs/mod.rs
new file mode 100644
index 0000000..d488d52
--- /dev/null
+++ b/engine/src/conversion/codegen_rs/mod.rs
@@ -0,0 +1,1379 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod fun_codegen;
+mod function_wrapper_rs;
+mod impl_item_creator;
+mod lifetime;
+mod namespace_organizer;
+mod non_pod_struct;
+pub(crate) mod unqualify;
+
+use indexmap::map::IndexMap as HashMap;
+use indexmap::set::IndexSet as HashSet;
+
+use autocxx_parser::{ExternCppType, IncludeCppConfig, RustFun};
+
+use itertools::Itertools;
+use proc_macro2::{Span, TokenStream};
+use syn::{
+    parse_quote, punctuated::Punctuated, token::Comma, Attribute, Expr, FnArg, ForeignItem,
+    ForeignItemFn, Ident, ImplItem, Item, ItemForeignMod, ItemMod, TraitItem, TypePath,
+};
+
+use crate::{
+    conversion::{
+        codegen_rs::{
+            non_pod_struct::{make_non_pod, new_non_pod_struct},
+            unqualify::{unqualify_params, unqualify_ret_type},
+        },
+        doc_attr::get_doc_attrs,
+    },
+    types::{make_ident, Namespace, QualifiedName},
+};
+use impl_item_creator::create_impl_items;
+
+use self::{
+    fun_codegen::gen_function,
+    namespace_organizer::{HasNs, NamespaceEntries},
+};
+
+use super::{
+    analysis::{
+        fun::{FnPhase, PodAndDepAnalysis, ReceiverMutability},
+        pod::PodAnalysis,
+    },
+    api::{AnalysisPhase, Api, SubclassName, TypeKind, TypedefKind},
+    convert_error::ErrorContextType,
+};
+use super::{
+    api::{Layout, Provenance, RustSubclassFnDetails, SuperclassMethod, TraitImplSignature},
+    apivec::ApiVec,
+    codegen_cpp::type_to_cpp::{
+        namespaced_name_using_original_name_map, original_name_map_from_apis, CppNameMap,
+    },
+};
+use super::{convert_error::ErrorContext, ConvertError};
+use quote::quote;
+
+/// An entry which needs to go into an `impl` block for a given type.
+struct ImplBlockDetails {
+    item: ImplItem,
+    ty: Ident,
+}
+
+struct TraitImplBlockDetails {
+    item: TraitItem,
+    key: TraitImplSignature,
+}
+
+/// Whether and how this item should be exposed in the mods constructed
+/// for actual end-user use.
+#[derive(Clone)]
+enum Use {
+    /// Uses from cxx::bridge
+    UsedFromCxxBridge,
+    /// 'use' points to cxx::bridge with a different name
+    UsedFromCxxBridgeWithAlias(Ident),
+    /// 'use' directive points to bindgen
+    UsedFromBindgen,
+    /// 'use' a specific name from bindgen.
+    SpecificNameFromBindgen(Ident),
+    /// Some kind of custom item
+    Custom(Box<Item>),
+}
+
+fn get_string_items() -> Vec<Item> {
+    [
+        Item::Trait(parse_quote! {
+            pub trait ToCppString {
+                fn into_cpp(self) -> cxx::UniquePtr<cxx::CxxString>;
+            }
+        }),
+        // We can't just impl<T: AsRef<str>> ToCppString for T
+        // because the compiler says that this trait could be implemented
+        // in future for cxx::UniquePtr<cxx::CxxString>. Fair enough.
+        Item::Impl(parse_quote! {
+            impl ToCppString for &str {
+                fn into_cpp(self) -> cxx::UniquePtr<cxx::CxxString> {
+                    make_string(self)
+                }
+            }
+        }),
+        Item::Impl(parse_quote! {
+            impl ToCppString for String {
+                fn into_cpp(self) -> cxx::UniquePtr<cxx::CxxString> {
+                    make_string(&self)
+                }
+            }
+        }),
+        Item::Impl(parse_quote! {
+            impl ToCppString for &String {
+                fn into_cpp(self) -> cxx::UniquePtr<cxx::CxxString> {
+                    make_string(self)
+                }
+            }
+        }),
+        Item::Impl(parse_quote! {
+            impl ToCppString for cxx::UniquePtr<cxx::CxxString> {
+                fn into_cpp(self) -> cxx::UniquePtr<cxx::CxxString> {
+                    self
+                }
+            }
+        }),
+    ]
+    .to_vec()
+}
+
+/// Type which handles generation of Rust code.
+/// In practice, much of the "generation" involves connecting together
+/// existing lumps of code within the Api structures.
+pub(crate) struct RsCodeGenerator<'a> {
+    include_list: &'a [String],
+    bindgen_mod: ItemMod,
+    original_name_map: CppNameMap,
+    config: &'a IncludeCppConfig,
+    header_name: Option<String>,
+}
+
+impl<'a> RsCodeGenerator<'a> {
+    /// Generate code for a set of APIs that was discovered during parsing.
+    pub(crate) fn generate_rs_code(
+        all_apis: ApiVec<FnPhase>,
+        include_list: &'a [String],
+        bindgen_mod: ItemMod,
+        config: &'a IncludeCppConfig,
+        header_name: Option<String>,
+    ) -> Vec<Item> {
+        let c = Self {
+            include_list,
+            bindgen_mod,
+            original_name_map: original_name_map_from_apis(&all_apis),
+            config,
+            header_name,
+        };
+        c.rs_codegen(all_apis)
+    }
+
+    fn rs_codegen(mut self, all_apis: ApiVec<FnPhase>) -> Vec<Item> {
+        // ... and now let's start to generate the output code.
+        // First off, when we generate structs we may need to add some methods
+        // if they're superclasses.
+        let methods_by_superclass = self.accumulate_superclass_methods(&all_apis);
+        let subclasses_with_a_single_trivial_constructor =
+            find_trivially_constructed_subclasses(&all_apis);
+        let non_pod_types = find_non_pod_types(&all_apis);
+        // Now let's generate the Rust code.
+        let (rs_codegen_results_and_namespaces, additional_cpp_needs): (Vec<_>, Vec<_>) = all_apis
+            .into_iter()
+            .map(|api| {
+                let more_cpp_needed = api.needs_cpp_codegen();
+                let name = api.name().clone();
+                let gen = self.generate_rs_for_api(
+                    api,
+                    &methods_by_superclass,
+                    &subclasses_with_a_single_trivial_constructor,
+                    &non_pod_types,
+                );
+                ((name, gen), more_cpp_needed)
+            })
+            .unzip();
+        // First, the hierarchy of mods containing lots of 'use' statements
+        // which is the final API exposed as 'ffi'.
+        let mut use_statements =
+            Self::generate_final_use_statements(&rs_codegen_results_and_namespaces);
+        // And work out what we need for the bindgen mod.
+        let bindgen_root_items =
+            self.generate_final_bindgen_mods(&rs_codegen_results_and_namespaces);
+        // Both of the above ('use' hierarchy and bindgen mod) are organized into
+        // sub-mods by namespace. From here on, things are flat.
+        let (_, rs_codegen_results): (Vec<_>, Vec<_>) =
+            rs_codegen_results_and_namespaces.into_iter().unzip();
+        let (extern_c_mod_items, extern_rust_mod_items, all_items, bridge_items): (
+            Vec<_>,
+            Vec<_>,
+            Vec<_>,
+            Vec<_>,
+        ) = rs_codegen_results
+            .into_iter()
+            .map(|api| {
+                (
+                    api.extern_c_mod_items,
+                    api.extern_rust_mod_items,
+                    api.global_items,
+                    api.bridge_items,
+                )
+            })
+            .multiunzip();
+        // Items for the [cxx::bridge] mod...
+        let mut bridge_items: Vec<Item> = bridge_items.into_iter().flatten().collect();
+        // Things to include in the "extern "C"" mod passed within the cxx::bridge
+        let mut extern_c_mod_items: Vec<ForeignItem> =
+            extern_c_mod_items.into_iter().flatten().collect();
+        // The same for extern "Rust"
+        let mut extern_rust_mod_items = extern_rust_mod_items.into_iter().flatten().collect();
+        // And a list of global items to include at the top level.
+        let mut all_items: Vec<Item> = all_items.into_iter().flatten().collect();
+        // And finally any C++ we need to generate. And by "we" I mean autocxx not cxx.
+        let has_additional_cpp_needs = additional_cpp_needs.into_iter().any(std::convert::identity);
+        extern_c_mod_items.extend(self.build_include_foreign_items(has_additional_cpp_needs));
+        // We will always create an extern "C" mod even if bindgen
+        // didn't generate one, e.g. because it only generated types.
+        // We still want cxx to know about those types.
+        let mut extern_c_mod: ItemForeignMod = parse_quote!(
+            extern "C++" {}
+        );
+        extern_c_mod.items.append(&mut extern_c_mod_items);
+        bridge_items.push(Self::make_foreign_mod_unsafe(extern_c_mod));
+        let mut extern_rust_mod: ItemForeignMod = parse_quote!(
+            extern "Rust" {}
+        );
+        extern_rust_mod.items.append(&mut extern_rust_mod_items);
+        bridge_items.push(Item::ForeignMod(extern_rust_mod));
+        // The extensive use of parse_quote here could end up
+        // being a performance bottleneck. If so, we might want
+        // to set the 'contents' field of the ItemMod
+        // structures directly.
+        if !bindgen_root_items.is_empty() {
+            self.bindgen_mod.vis = parse_quote! {};
+            self.bindgen_mod.content.as_mut().unwrap().1 = vec![Item::Mod(parse_quote! {
+                pub(super) mod root {
+                    #(#bindgen_root_items)*
+                }
+            })];
+            all_items.push(Item::Mod(self.bindgen_mod));
+        }
+        all_items.push(Item::Mod(parse_quote! {
+            #[cxx::bridge]
+            mod cxxbridge {
+                #(#bridge_items)*
+            }
+        }));
+
+        all_items.push(Item::Use(parse_quote! {
+            #[allow(unused_imports)]
+            use bindgen::root;
+        }));
+        all_items.append(&mut use_statements);
+        all_items
+    }
+
+    fn accumulate_superclass_methods(
+        &self,
+        apis: &ApiVec<FnPhase>,
+    ) -> HashMap<QualifiedName, Vec<SuperclassMethod>> {
+        let mut results = HashMap::new();
+        results.extend(
+            self.config
+                .superclasses()
+                .map(|sc| (QualifiedName::new_from_cpp_name(sc), Vec::new())),
+        );
+        for api in apis.iter() {
+            if let Api::SubclassTraitItem { details, .. } = api {
+                let list = results.get_mut(&details.receiver);
+                if let Some(list) = list {
+                    list.push(details.clone());
+                }
+            }
+        }
+        results
+    }
+
+    fn make_foreign_mod_unsafe(ifm: ItemForeignMod) -> Item {
+        // At the moment syn does not support outputting 'unsafe extern "C"' except in verbatim
+        // items. See https://github.com/dtolnay/syn/pull/938
+        Item::Verbatim(quote! {
+            unsafe #ifm
+        })
+    }
+
+    fn build_include_foreign_items(&self, has_additional_cpp_needs: bool) -> Vec<ForeignItem> {
+        let extra_inclusion = if has_additional_cpp_needs {
+            Some(self.header_name.clone().unwrap())
+        } else {
+            None
+        };
+        let chained = self.include_list.iter().chain(extra_inclusion.iter());
+        chained
+            .map(|inc| {
+                ForeignItem::Macro(parse_quote! {
+                    include!(#inc);
+                })
+            })
+            .collect()
+    }
+
+    /// Generate lots of 'use' statements to pull cxxbridge items into the output
+    /// mod hierarchy according to C++ namespaces.
+    fn generate_final_use_statements(
+        input_items: &[(QualifiedName, RsCodegenResult)],
+    ) -> Vec<Item> {
+        let mut output_items = Vec::new();
+        let ns_entries = NamespaceEntries::new(input_items);
+        Self::append_child_use_namespace(&ns_entries, &mut output_items);
+        output_items
+    }
+
+    fn append_child_use_namespace(
+        ns_entries: &NamespaceEntries<(QualifiedName, RsCodegenResult)>,
+        output_items: &mut Vec<Item>,
+    ) {
+        for (name, codegen) in ns_entries.entries() {
+            output_items.extend(codegen.materializations.iter().map(|materialization| {
+                match materialization {
+                    Use::UsedFromCxxBridgeWithAlias(ref alias) => {
+                        Self::generate_cxx_use_stmt(name, Some(alias))
+                    }
+                    Use::UsedFromCxxBridge => Self::generate_cxx_use_stmt(name, None),
+                    Use::UsedFromBindgen => Self::generate_bindgen_use_stmt(name),
+                    Use::SpecificNameFromBindgen(id) => {
+                        let name = QualifiedName::new(name.get_namespace(), id.clone());
+                        Self::generate_bindgen_use_stmt(&name)
+                    }
+                    Use::Custom(item) => *item.clone(),
+                }
+            }));
+        }
+        for (child_name, child_ns_entries) in ns_entries.children() {
+            if child_ns_entries.is_empty() {
+                continue;
+            }
+            let child_id = make_ident(child_name);
+            let mut new_mod: ItemMod = parse_quote!(
+                pub mod #child_id {
+                }
+            );
+            Self::append_child_use_namespace(
+                child_ns_entries,
+                &mut new_mod.content.as_mut().unwrap().1,
+            );
+            output_items.push(Item::Mod(new_mod));
+        }
+    }
+
+    fn append_uses_for_ns(&mut self, items: &mut Vec<Item>, ns: &Namespace) {
+        let super_duper = std::iter::repeat(make_ident("super")); // I'll get my coat
+        let supers = super_duper.clone().take(ns.depth() + 2);
+        items.push(Item::Use(parse_quote! {
+            #[allow(unused_imports)]
+            use self::
+                #(#supers)::*
+            ::cxxbridge;
+        }));
+        if !self.config.exclude_utilities() {
+            let supers = super_duper.clone().take(ns.depth() + 2);
+            items.push(Item::Use(parse_quote! {
+                #[allow(unused_imports)]
+                use self::
+                    #(#supers)::*
+                ::ToCppString;
+            }));
+        }
+        let supers = super_duper.take(ns.depth() + 1);
+        items.push(Item::Use(parse_quote! {
+            #[allow(unused_imports)]
+            use self::
+                #(#supers)::*
+            ::root;
+        }));
+    }
+
+    fn append_child_bindgen_namespace(
+        &mut self,
+        ns_entries: &NamespaceEntries<(QualifiedName, RsCodegenResult)>,
+        output_items: &mut Vec<Item>,
+        ns: &Namespace,
+    ) {
+        let mut impl_entries_by_type: HashMap<_, Vec<_>> = HashMap::new();
+        let mut trait_impl_entries_by_trait_and_ty: HashMap<_, Vec<_>> = HashMap::new();
+        for item in ns_entries.entries() {
+            output_items.extend(item.1.bindgen_mod_items.iter().cloned());
+            if let Some(impl_entry) = &item.1.impl_entry {
+                impl_entries_by_type
+                    .entry(impl_entry.ty.clone())
+                    .or_default()
+                    .push(&impl_entry.item);
+            }
+            if let Some(trait_impl_entry) = &item.1.trait_impl_entry {
+                trait_impl_entries_by_trait_and_ty
+                    .entry(trait_impl_entry.key.clone())
+                    .or_default()
+                    .push(&trait_impl_entry.item);
+            }
+        }
+        for (ty, entries) in impl_entries_by_type.into_iter() {
+            output_items.push(Item::Impl(parse_quote! {
+                impl #ty {
+                    #(#entries)*
+                }
+            }))
+        }
+        for (key, entries) in trait_impl_entries_by_trait_and_ty.into_iter() {
+            let unsafety = key.unsafety;
+            let ty = key.ty;
+            let trt = key.trait_signature;
+            output_items.push(Item::Impl(parse_quote! {
+                #unsafety impl #trt for #ty {
+                    #(#entries)*
+                }
+            }))
+        }
+        for (child_name, child_ns_entries) in ns_entries.children() {
+            let new_ns = ns.push((*child_name).clone());
+            let child_id = make_ident(child_name);
+
+            let mut inner_output_items = Vec::new();
+            self.append_child_bindgen_namespace(child_ns_entries, &mut inner_output_items, &new_ns);
+            if !inner_output_items.is_empty() {
+                let mut new_mod: ItemMod = parse_quote!(
+                    pub mod #child_id {
+                    }
+                );
+                self.append_uses_for_ns(&mut inner_output_items, &new_ns);
+                new_mod.content.as_mut().unwrap().1 = inner_output_items;
+                output_items.push(Item::Mod(new_mod));
+            }
+        }
+    }
+
+    fn id_to_expr(id: &Ident) -> Expr {
+        parse_quote! { #id }
+    }
+
+    fn generate_final_bindgen_mods(
+        &mut self,
+        input_items: &[(QualifiedName, RsCodegenResult)],
+    ) -> Vec<Item> {
+        let mut output_items = Vec::new();
+        let ns = Namespace::new();
+        let ns_entries = NamespaceEntries::new(input_items);
+        self.append_child_bindgen_namespace(&ns_entries, &mut output_items, &ns);
+        self.append_uses_for_ns(&mut output_items, &ns);
+        output_items
+    }
+
+    fn generate_rs_for_api(
+        &self,
+        api: Api<FnPhase>,
+        associated_methods: &HashMap<QualifiedName, Vec<SuperclassMethod>>,
+        subclasses_with_a_single_trivial_constructor: &HashSet<QualifiedName>,
+        non_pod_types: &HashSet<QualifiedName>,
+    ) -> RsCodegenResult {
+        let name = api.name().clone();
+        let id = name.get_final_ident();
+        let cpp_call_name = api.effective_cpp_name().to_string();
+        match api {
+            Api::StringConstructor { .. } => {
+                let make_string_name = make_ident(self.config.get_makestring_name());
+                RsCodegenResult {
+                    extern_c_mod_items: vec![ForeignItem::Fn(parse_quote!(
+                        fn #make_string_name(str_: &str) -> UniquePtr<CxxString>;
+                    ))],
+                    global_items: get_string_items(),
+                    materializations: vec![Use::UsedFromCxxBridgeWithAlias(make_ident(
+                        "make_string",
+                    ))],
+                    ..Default::default()
+                }
+            }
+            Api::Function { fun, analysis, .. } => gen_function(
+                name.get_namespace(),
+                *fun,
+                analysis,
+                cpp_call_name,
+                non_pod_types,
+            ),
+            Api::Const { const_item, .. } => RsCodegenResult {
+                bindgen_mod_items: vec![Item::Const(const_item)],
+                materializations: vec![Use::UsedFromBindgen],
+                ..Default::default()
+            },
+            Api::Typedef { analysis, .. } => RsCodegenResult {
+                bindgen_mod_items: vec![match analysis.kind {
+                    TypedefKind::Type(type_item) => Item::Type(type_item),
+                    TypedefKind::Use(use_item, _) => Item::Use(use_item),
+                }],
+                materializations: vec![Use::UsedFromBindgen],
+                ..Default::default()
+            },
+            Api::Struct {
+                details,
+                analysis:
+                    PodAndDepAnalysis {
+                        pod:
+                            PodAnalysis {
+                                is_generic, kind, ..
+                            },
+                        constructors,
+                        ..
+                    },
+                ..
+            } => {
+                let doc_attrs = get_doc_attrs(&details.item.attrs);
+                let layout = details.layout.clone();
+                self.generate_type(
+                    &name,
+                    id,
+                    kind,
+                    constructors.move_constructor,
+                    constructors.destructor,
+                    || Some((Item::Struct(details.item), doc_attrs)),
+                    associated_methods,
+                    layout,
+                    is_generic,
+                )
+            }
+            Api::Enum { item, .. } => {
+                let doc_attrs = get_doc_attrs(&item.attrs);
+                self.generate_type(
+                    &name,
+                    id,
+                    TypeKind::Pod,
+                    true,
+                    true,
+                    || Some((Item::Enum(item), doc_attrs)),
+                    associated_methods,
+                    None,
+                    false,
+                )
+            }
+            Api::ForwardDeclaration { .. }
+            | Api::ConcreteType { .. }
+            | Api::OpaqueTypedef { .. } => self.generate_type(
+                &name,
+                id,
+                TypeKind::Abstract,
+                false, // assume for now that these types can't be kept in a Vector
+                true,  // assume for now that these types can be put in a smart pointer
+                || None,
+                associated_methods,
+                None,
+                false,
+            ),
+            Api::CType { .. } => RsCodegenResult {
+                extern_c_mod_items: vec![ForeignItem::Verbatim(quote! {
+                    type #id = autocxx::#id;
+                })],
+                ..Default::default()
+            },
+            Api::RustType { path, .. } => RsCodegenResult {
+                global_items: vec![parse_quote! {
+                    use super::#path;
+                }],
+                extern_rust_mod_items: vec![parse_quote! {
+                    type #id;
+                }],
+                ..Default::default()
+            },
+            Api::RustFn {
+                details:
+                    RustFun {
+                        path,
+                        sig,
+                        receiver: None,
+                        ..
+                    },
+                ..
+            } => RsCodegenResult {
+                global_items: vec![parse_quote! {
+                    use super::#path;
+                }],
+                extern_rust_mod_items: vec![parse_quote! {
+                    #sig;
+                }],
+                ..Default::default()
+            },
+            Api::RustFn {
+                details:
+                    RustFun {
+                        sig,
+                        receiver: Some(_),
+                        ..
+                    },
+                ..
+            } => RsCodegenResult {
+                extern_rust_mod_items: vec![parse_quote! {
+                    #sig;
+                }],
+                ..Default::default()
+            },
+            Api::RustSubclassFn {
+                details, subclass, ..
+            } => Self::generate_subclass_fn(id, *details, subclass),
+            Api::Subclass {
+                name, superclass, ..
+            } => {
+                let methods = associated_methods.get(&superclass);
+                let generate_peer_constructor =
+                    subclasses_with_a_single_trivial_constructor.contains(&name.0.name);
+                self.generate_subclass(name, &superclass, methods, generate_peer_constructor)
+            }
+            Api::ExternCppType {
+                details: ExternCppType { rust_path, .. },
+                ..
+            } => self.generate_extern_cpp_type(&name, rust_path, name.ns_segment_iter().count()),
+            Api::IgnoredItem {
+                err,
+                ctx: Some(ctx),
+                ..
+            } => Self::generate_error_entry(err, ctx),
+            Api::IgnoredItem { .. } | Api::SubclassTraitItem { .. } => RsCodegenResult::default(),
+        }
+    }
+
+    fn generate_subclass(
+        &self,
+        sub: SubclassName,
+        superclass: &QualifiedName,
+        methods: Option<&Vec<SuperclassMethod>>,
+        generate_peer_constructor: bool,
+    ) -> RsCodegenResult {
+        let super_name = superclass.get_final_item();
+        let super_path = superclass.to_type_path();
+        let super_cxxxbridge_id = superclass.get_final_ident();
+        let id = sub.id();
+        let holder = sub.holder();
+        let full_cpp = sub.cpp();
+        let cpp_path = full_cpp.to_type_path();
+        let cpp_id = full_cpp.get_final_ident();
+        let mut global_items = Vec::new();
+        global_items.push(parse_quote! {
+            pub use bindgen::root::#holder;
+        });
+        let relinquish_ownership_call = sub.cpp_remove_ownership();
+        let mut bindgen_mod_items = vec![
+            parse_quote! {
+                pub use cxxbridge::#cpp_id;
+            },
+            parse_quote! {
+                pub struct #holder(pub autocxx::subclass::CppSubclassRustPeerHolder<super::super::super::#id>);
+            },
+            parse_quote! {
+                impl autocxx::subclass::CppSubclassCppPeer for #cpp_id {
+                    fn relinquish_ownership(&self) {
+                        self.#relinquish_ownership_call();
+                    }
+                }
+            },
+        ];
+        let mut extern_c_mod_items = vec![
+            self.generate_cxxbridge_type(&full_cpp, false, Vec::new()),
+            parse_quote! {
+                fn #relinquish_ownership_call(self: &#cpp_id);
+            },
+        ];
+        if let Some(methods) = methods {
+            let supers = SubclassName::get_supers_trait_name(superclass).to_type_path();
+            let methods_impls: Vec<ImplItem> = methods
+                .iter()
+                .filter(|m| !m.is_pure_virtual)
+                .map(|m| {
+                    let cpp_super_method_name =
+                        SubclassName::get_super_fn_name(&Namespace::new(), &m.name.to_string())
+                            .get_final_ident();
+                    let mut params = m.params.clone();
+                    let ret = &m.ret_type.clone();
+                    let (peer_fn, first_param) = match m.receiver_mutability {
+                        ReceiverMutability::Const => ("peer", parse_quote!(&self)),
+                        ReceiverMutability::Mutable => ("peer_mut", parse_quote!(&mut self)),
+                    };
+                    let peer_fn = make_ident(peer_fn);
+                    *(params.iter_mut().next().unwrap()) = first_param;
+                    let param_names = m.param_names.iter().skip(1);
+                    let unsafe_token = m.requires_unsafe.wrapper_token();
+                    parse_quote! {
+                        #unsafe_token fn #cpp_super_method_name(#params) #ret {
+                            use autocxx::subclass::CppSubclass;
+                            self.#peer_fn().#cpp_super_method_name(#(#param_names),*)
+                        }
+                    }
+                })
+                .collect();
+            if !methods_impls.is_empty() {
+                bindgen_mod_items.push(parse_quote! {
+                    #[allow(non_snake_case)]
+                    impl #supers for super::super::super::#id {
+                        #(#methods_impls)*
+                    }
+                });
+            }
+        }
+        if generate_peer_constructor {
+            bindgen_mod_items.push(parse_quote! {
+                impl autocxx::subclass::CppPeerConstructor<#cpp_id> for super::super::super::#id {
+                    fn make_peer(&mut self, peer_holder: autocxx::subclass::CppSubclassRustPeerHolder<Self>) -> cxx::UniquePtr<#cpp_path> {
+                        use autocxx::moveit::EmplaceUnpinned;
+                        cxx::UniquePtr::emplace(#cpp_id :: new(peer_holder))
+                    }
+                }
+            })
+        };
+
+        // Once for each superclass, in future...
+        let as_id = make_ident(format!("As_{}", super_name));
+        extern_c_mod_items.push(parse_quote! {
+            fn #as_id(self: &#cpp_id) -> &#super_cxxxbridge_id;
+        });
+        let as_mut_id = make_ident(format!("As_{}_mut", super_name));
+        extern_c_mod_items.push(parse_quote! {
+            fn #as_mut_id(self: Pin<&mut #cpp_id>) -> Pin<&mut #super_cxxxbridge_id>;
+        });
+        bindgen_mod_items.push(parse_quote! {
+            impl AsRef<#super_path> for super::super::super::#id {
+                fn as_ref(&self) -> &cxxbridge::#super_cxxxbridge_id {
+                    use autocxx::subclass::CppSubclass;
+                    self.peer().#as_id()
+                }
+            }
+        });
+        // TODO it would be nice to impl AsMut here but pin prevents us
+        bindgen_mod_items.push(parse_quote! {
+            impl super::super::super::#id {
+                pub fn pin_mut(&mut self) -> ::std::pin::Pin<&mut cxxbridge::#super_cxxxbridge_id> {
+                    use autocxx::subclass::CppSubclass;
+                    self.peer_mut().#as_mut_id()
+                }
+            }
+        });
+        let remove_ownership = sub.remove_ownership();
+        global_items.push(parse_quote! {
+            #[allow(non_snake_case)]
+            pub fn #remove_ownership(me: Box<#holder>) -> Box<#holder> {
+                Box::new(#holder(me.0.relinquish_ownership()))
+            }
+        });
+        RsCodegenResult {
+            extern_c_mod_items,
+            // For now we just assume we can't keep subclasses in vectors, but we can put them in
+            // smart pointers.
+            // That's the reason for the 'false' and 'true'
+            bridge_items: create_impl_items(&cpp_id, false, true, self.config),
+            bindgen_mod_items,
+            materializations: vec![Use::Custom(Box::new(parse_quote! {
+                pub use cxxbridge::#cpp_id;
+            }))],
+            global_items,
+            extern_rust_mod_items: vec![
+                parse_quote! {
+                    pub type #holder;
+                },
+                parse_quote! {
+                    fn #remove_ownership(me: Box<#holder>) -> Box<#holder>;
+                },
+            ],
+            ..Default::default()
+        }
+    }
+
+    fn generate_subclass_fn(
+        api_name: Ident,
+        details: RustSubclassFnDetails,
+        subclass: SubclassName,
+    ) -> RsCodegenResult {
+        let params = details.params;
+        let ret = details.ret;
+        let unsafe_token = details.requires_unsafe.wrapper_token();
+        let global_def = quote! { #unsafe_token fn #api_name(#params) #ret };
+        let params = unqualify_params(params);
+        let ret = unqualify_ret_type(ret);
+        let method_name = details.method_name;
+        let cxxbridge_decl: ForeignItemFn =
+            parse_quote! { #unsafe_token fn #api_name(#params) #ret; };
+        let args: Punctuated<Expr, Comma> =
+            Self::args_from_sig(&cxxbridge_decl.sig.inputs).collect();
+        let superclass_id = details.superclass.get_final_ident();
+        let methods_trait = SubclassName::get_methods_trait_name(&details.superclass);
+        let methods_trait = methods_trait.to_type_path();
+        let (deref_ty, deref_call, borrow, mut_token) = match details.receiver_mutability {
+            ReceiverMutability::Const => ("Deref", "deref", "try_borrow", None),
+            ReceiverMutability::Mutable => (
+                "DerefMut",
+                "deref_mut",
+                "try_borrow_mut",
+                Some(syn::token::Mut(Span::call_site())),
+            ),
+        };
+        let deref_ty = make_ident(deref_ty);
+        let deref_call = make_ident(deref_call);
+        let borrow = make_ident(borrow);
+        let destroy_panic_msg = format!("Rust subclass API (method {} of subclass {} of superclass {}) called after subclass destroyed", method_name, subclass.0.name, superclass_id);
+        let reentrancy_panic_msg = format!("Rust subclass API (method {} of subclass {} of superclass {}) called whilst subclass already borrowed - likely a re-entrant call",  method_name, subclass.0.name, superclass_id);
+        RsCodegenResult {
+            global_items: vec![parse_quote! {
+                #global_def {
+                    let rc = me.0
+                        .get()
+                        .expect(#destroy_panic_msg);
+                    let #mut_token b = rc
+                        .as_ref()
+                        .#borrow()
+                        .expect(#reentrancy_panic_msg);
+                    let r = std::ops::#deref_ty::#deref_call(& #mut_token b);
+                    #methods_trait :: #method_name
+                        (r,
+                        #args)
+                }
+            }],
+            extern_rust_mod_items: vec![ForeignItem::Fn(cxxbridge_decl)],
+            ..Default::default()
+        }
+    }
+
+    fn args_from_sig(params: &Punctuated<FnArg, Comma>) -> impl Iterator<Item = Expr> + '_ {
+        params.iter().skip(1).filter_map(|fnarg| match fnarg {
+            syn::FnArg::Receiver(_) => None,
+            syn::FnArg::Typed(fnarg) => match &*fnarg.pat {
+                syn::Pat::Ident(id) => Some(Self::id_to_expr(&id.ident)),
+                _ => None,
+            },
+        })
+    }
+
+    #[allow(clippy::too_many_arguments)] // currently the least unclear way
+    fn generate_type<F>(
+        &self,
+        name: &QualifiedName,
+        id: Ident,
+        type_kind: TypeKind,
+        movable: bool,
+        destroyable: bool,
+        item_creator: F,
+        associated_methods: &HashMap<QualifiedName, Vec<SuperclassMethod>>,
+        layout: Option<Layout>,
+        is_generic: bool,
+    ) -> RsCodegenResult
+    where
+        F: FnOnce() -> Option<(Item, Vec<Attribute>)>,
+    {
+        let mut bindgen_mod_items = Vec::new();
+        let mut materializations = vec![Use::UsedFromBindgen];
+        Self::add_superclass_stuff_to_type(
+            name,
+            &mut bindgen_mod_items,
+            &mut materializations,
+            associated_methods.get(name),
+        );
+        let orig_item = item_creator();
+        let doc_attrs = orig_item
+            .as_ref()
+            .map(|maybe_item| maybe_item.1.clone())
+            .unwrap_or_default();
+        // We have a choice here to either:
+        // a) tell cxx to generate an opaque type using 'type A;'
+        // b) generate a concrete type definition, e.g. by using bindgen's
+        //    or doing our own, and then telling cxx 'type A = bindgen::A';'
+        match type_kind {
+            TypeKind::Pod | TypeKind::NonPod => {
+                // Feed cxx "type T = root::bindgen::T"
+                // For non-POD types, there might be the option of simply giving
+                // cxx a "type T;" as we do for abstract types below. There's
+                // two reasons we don't:
+                // a) we want to specify size and alignment for the sake of
+                //    moveit;
+                // b) for nested types such as 'A::B', there is no combination
+                //    of cxx-acceptable attributes which will inform cxx that
+                //    A is a class rather than a namespace.
+                let mut item = orig_item
+                    .expect("Instantiable types must provide instance")
+                    .0;
+                if matches!(type_kind, TypeKind::NonPod) {
+                    if let Item::Struct(ref mut s) = item {
+                        // Retain generics and doc attrs.
+                        make_non_pod(s, layout);
+                    } else {
+                        // enum
+                        item = Item::Struct(new_non_pod_struct(id.clone()));
+                    }
+                }
+                bindgen_mod_items.push(item);
+
+                if is_generic {
+                    // Still generate the type as emitted by bindgen,
+                    // but don't attempt to tell cxx about it
+                    RsCodegenResult {
+                        bindgen_mod_items,
+                        materializations,
+                        ..Default::default()
+                    }
+                } else {
+                    RsCodegenResult {
+                        global_items: self.generate_extern_type_impl(type_kind, name),
+                        bridge_items: create_impl_items(&id, movable, destroyable, self.config),
+                        extern_c_mod_items: vec![
+                            self.generate_cxxbridge_type(name, true, doc_attrs)
+                        ],
+                        bindgen_mod_items,
+                        materializations,
+                        ..Default::default()
+                    }
+                }
+            }
+            TypeKind::Abstract => {
+                if is_generic {
+                    RsCodegenResult::default()
+                } else {
+                    // Feed cxx "type T;"
+                    // We MUST do this because otherwise cxx assumes this can be
+                    // instantiated using UniquePtr etc.
+                    bindgen_mod_items.push(Item::Use(parse_quote! { pub use cxxbridge::#id; }));
+                    RsCodegenResult {
+                        extern_c_mod_items: vec![
+                            self.generate_cxxbridge_type(name, false, doc_attrs)
+                        ],
+                        bindgen_mod_items,
+                        materializations,
+                        ..Default::default()
+                    }
+                }
+            }
+        }
+    }
+
+    fn add_superclass_stuff_to_type(
+        name: &QualifiedName,
+        bindgen_mod_items: &mut Vec<Item>,
+        materializations: &mut Vec<Use>,
+        methods: Option<&Vec<SuperclassMethod>>,
+    ) {
+        if let Some(methods) = methods {
+            let (supers, mains): (Vec<_>, Vec<_>) = methods
+                .iter()
+                .map(|method| {
+                    let id = &method.name;
+                    let super_id =
+                        SubclassName::get_super_fn_name(&Namespace::new(), &id.to_string())
+                            .get_final_ident();
+                    let param_names: Punctuated<Expr, Comma> =
+                        Self::args_from_sig(&method.params).collect();
+                    let mut params = method.params.clone();
+                    *(params.iter_mut().next().unwrap()) = match method.receiver_mutability {
+                        ReceiverMutability::Const => parse_quote!(&self),
+                        ReceiverMutability::Mutable => parse_quote!(&mut self),
+                    };
+                    let ret_type = &method.ret_type;
+                    let unsafe_token = method.requires_unsafe.wrapper_token();
+                    if method.is_pure_virtual {
+                        (
+                            None,
+                            parse_quote!(
+                                #unsafe_token fn #id(#params) #ret_type;
+                            ),
+                        )
+                    } else {
+                        let a: Option<TraitItem> = Some(parse_quote!(
+                            #unsafe_token fn #super_id(#params) #ret_type;
+                        ));
+                        let b: TraitItem = parse_quote!(
+                            #unsafe_token fn #id(#params) #ret_type {
+                                self.#super_id(#param_names)
+                            }
+                        );
+                        (a, b)
+                    }
+                })
+                .unzip();
+            let supers: Vec<_> = supers.into_iter().flatten().collect();
+            let supers_name = SubclassName::get_supers_trait_name(name).get_final_ident();
+            let methods_name = SubclassName::get_methods_trait_name(name).get_final_ident();
+            if !supers.is_empty() {
+                bindgen_mod_items.push(parse_quote! {
+                    #[allow(non_snake_case)]
+                    pub trait #supers_name {
+                        #(#supers)*
+                    }
+                });
+                bindgen_mod_items.push(parse_quote! {
+                    #[allow(non_snake_case)]
+                    pub trait #methods_name : #supers_name {
+                        #(#mains)*
+                    }
+                });
+                materializations.push(Use::SpecificNameFromBindgen(supers_name));
+            } else {
+                bindgen_mod_items.push(parse_quote! {
+                    #[allow(non_snake_case)]
+                    pub trait #methods_name {
+                        #(#mains)*
+                    }
+                });
+            }
+            materializations.push(Use::SpecificNameFromBindgen(methods_name));
+        }
+    }
+
+    fn generate_extern_cpp_type(
+        &self,
+        name: &QualifiedName,
+        rust_path: TypePath,
+        ns_depth: usize,
+    ) -> RsCodegenResult {
+        let id = name.get_final_ident();
+        let super_duper = std::iter::repeat(make_ident("super"));
+        let supers = super_duper.take(ns_depth + 2);
+        let use_statement = parse_quote! {
+            pub use #(#supers)::* :: #id;
+        };
+        RsCodegenResult {
+            bindgen_mod_items: vec![use_statement],
+            extern_c_mod_items: vec![self.generate_cxxbridge_type(name, true, Vec::new())],
+            materializations: vec![Use::Custom(Box::new(parse_quote! { pub use #rust_path; }))],
+            ..Default::default()
+        }
+    }
+
+    /// Generates something in the output mod that will carry a docstring
+    /// explaining why a given type or function couldn't have bindings
+    /// generated.
+    fn generate_error_entry(err: ConvertError, ctx: ErrorContext) -> RsCodegenResult {
+        let err = format!("autocxx bindings couldn't be generated: {}", err);
+        let (impl_entry, bindgen_mod_item, materialization) = match ctx.into_type() {
+            ErrorContextType::Item(id) => (
+                // Populate within bindgen mod because impl blocks may attach.
+                None,
+                Some(parse_quote! {
+                    #[doc = #err]
+                    pub struct #id;
+                }),
+                Some(Use::SpecificNameFromBindgen(id)),
+            ),
+            ErrorContextType::SanitizedItem(id) => (
+                // Guaranteed to be no impl blocks - populate directly in output mod.
+                None,
+                None,
+                Some(Use::Custom(Box::new(parse_quote! {
+                    #[doc = #err]
+                    pub struct #id;
+                }))),
+            ),
+            ErrorContextType::Method { self_ty, method } => (
+                Some(Box::new(ImplBlockDetails {
+                    item: parse_quote! {
+                        #[doc = #err]
+                        fn #method(_uhoh: autocxx::BindingGenerationFailure) {
+                        }
+                    },
+                    ty: self_ty,
+                })),
+                None,
+                None,
+            ),
+        };
+        RsCodegenResult {
+            impl_entry,
+            bindgen_mod_items: bindgen_mod_item.into_iter().collect(),
+            materializations: materialization.into_iter().collect(),
+            ..Default::default()
+        }
+    }
+
+    fn generate_cxx_use_stmt(name: &QualifiedName, alias: Option<&Ident>) -> Item {
+        let segs = Self::find_output_mod_root(name.get_namespace())
+            .chain(std::iter::once(make_ident("cxxbridge")))
+            .chain(std::iter::once(name.get_final_ident()));
+        Item::Use(match alias {
+            None => parse_quote! {
+                pub use #(#segs)::*;
+            },
+            Some(alias) => parse_quote! {
+                pub use #(#segs)::* as #alias;
+            },
+        })
+    }
+
+    fn generate_bindgen_use_stmt(name: &QualifiedName) -> Item {
+        let segs =
+            Self::find_output_mod_root(name.get_namespace()).chain(name.get_bindgen_path_idents());
+        Item::Use(parse_quote! {
+            pub use #(#segs)::*;
+        })
+    }
+
+    fn generate_extern_type_impl(&self, type_kind: TypeKind, tyname: &QualifiedName) -> Vec<Item> {
+        let tynamestring = namespaced_name_using_original_name_map(tyname, &self.original_name_map);
+        let fulltypath = tyname.get_bindgen_path_idents();
+        let kind_item = match type_kind {
+            TypeKind::Pod => "Trivial",
+            _ => "Opaque",
+        };
+        let kind_item = make_ident(kind_item);
+        vec![Item::Impl(parse_quote! {
+            unsafe impl cxx::ExternType for #(#fulltypath)::* {
+                type Id = cxx::type_id!(#tynamestring);
+                type Kind = cxx::kind::#kind_item;
+            }
+        })]
+    }
+
+    fn generate_cxxbridge_type(
+        &self,
+        name: &QualifiedName,
+        references_bindgen: bool,
+        doc_attrs: Vec<Attribute>,
+    ) -> ForeignItem {
+        let ns = name.get_namespace();
+        let id = name.get_final_ident();
+        // The following lines actually Tell A Lie.
+        // If we have a nested class, B::C, within namespace A,
+        // we actually have to tell cxx that we have nested class C
+        // within namespace A.
+        let mut ns_components: Vec<_> = ns.iter().cloned().collect();
+        let mut cxx_name = None;
+        if let Some(cpp_name) = self.original_name_map.get(name) {
+            let cpp_name = QualifiedName::new_from_cpp_name(cpp_name);
+            cxx_name = Some(cpp_name.get_final_item().to_string());
+            ns_components.extend(cpp_name.ns_segment_iter().cloned());
+        };
+
+        let mut for_extern_c_ts = if !ns_components.is_empty() {
+            let ns_string = ns_components.join("::");
+            quote! {
+                #[namespace = #ns_string]
+            }
+        } else {
+            TokenStream::new()
+        };
+
+        if let Some(n) = cxx_name {
+            for_extern_c_ts.extend(quote! {
+                #[cxx_name = #n]
+            });
+        }
+
+        for_extern_c_ts.extend(quote! {
+            #(#doc_attrs)*
+        });
+
+        if references_bindgen {
+            for_extern_c_ts.extend(quote! {
+                type #id = super::bindgen::root::
+            });
+            for_extern_c_ts.extend(ns.iter().map(make_ident).map(|id| {
+                quote! {
+                    #id::
+                }
+            }));
+            for_extern_c_ts.extend(quote! {
+                #id;
+            });
+        } else {
+            for_extern_c_ts.extend(quote! {
+                type #id;
+            });
+        }
+        ForeignItem::Verbatim(for_extern_c_ts)
+    }
+
+    fn find_output_mod_root(ns: &Namespace) -> impl Iterator<Item = Ident> {
+        std::iter::repeat(make_ident("super")).take(ns.depth())
+    }
+}
+
+fn find_trivially_constructed_subclasses(apis: &ApiVec<FnPhase>) -> HashSet<QualifiedName> {
+    let (simple_constructors, complex_constructors): (Vec<_>, Vec<_>) = apis
+        .iter()
+        .filter_map(|api| match api {
+            Api::Function { fun, .. } => match &fun.provenance {
+                Provenance::SynthesizedSubclassConstructor(details) => {
+                    Some((&details.subclass.0.name, details.is_trivial))
+                }
+                _ => None,
+            },
+            _ => None,
+        })
+        .partition(|(_, trivial)| *trivial);
+    let simple_constructors: HashSet<_> =
+        simple_constructors.into_iter().map(|(qn, _)| qn).collect();
+    let complex_constructors: HashSet<_> =
+        complex_constructors.into_iter().map(|(qn, _)| qn).collect();
+    (&simple_constructors - &complex_constructors)
+        .into_iter()
+        .cloned()
+        .collect()
+}
+
+fn find_non_pod_types(apis: &ApiVec<FnPhase>) -> HashSet<QualifiedName> {
+    apis.iter()
+        .filter_map(|api| match api {
+            Api::Struct {
+                name,
+                analysis:
+                    PodAndDepAnalysis {
+                        pod:
+                            PodAnalysis {
+                                kind: TypeKind::NonPod,
+                                ..
+                            },
+                        ..
+                    },
+                ..
+            } => Some(name.name.clone()),
+            _ => None,
+        })
+        .collect()
+}
+
+impl HasNs for (QualifiedName, RsCodegenResult) {
+    fn get_namespace(&self) -> &Namespace {
+        self.0.get_namespace()
+    }
+}
+
+impl<T: AnalysisPhase> HasNs for Api<T> {
+    fn get_namespace(&self) -> &Namespace {
+        self.name().get_namespace()
+    }
+}
+
+/// Snippets of code generated from a particular API.
+/// These are then concatenated together into the final generated code.
+#[derive(Default)]
+struct RsCodegenResult {
+    extern_c_mod_items: Vec<ForeignItem>,
+    extern_rust_mod_items: Vec<ForeignItem>,
+    bridge_items: Vec<Item>,
+    global_items: Vec<Item>,
+    bindgen_mod_items: Vec<Item>,
+    impl_entry: Option<Box<ImplBlockDetails>>,
+    trait_impl_entry: Option<Box<TraitImplBlockDetails>>,
+    materializations: Vec<Use>,
+}
+
+/// An [`Item`] that always needs to be in an unsafe block.
+#[derive(Clone)]
+enum MaybeUnsafeStmt {
+    // This could almost be a syn::Stmt, but that doesn't quite work
+    // because the last stmt in a function is actually an expression
+    // thus lacking a semicolon.
+    Normal(TokenStream),
+    NeedsUnsafe(TokenStream),
+    Binary {
+        in_safe_context: TokenStream,
+        in_unsafe_context: TokenStream,
+    },
+}
+
+impl MaybeUnsafeStmt {
+    fn new(stmt: TokenStream) -> Self {
+        Self::Normal(stmt)
+    }
+
+    fn needs_unsafe(stmt: TokenStream) -> Self {
+        Self::NeedsUnsafe(stmt)
+    }
+
+    fn maybe_unsafe(stmt: TokenStream, needs_unsafe: bool) -> Self {
+        if needs_unsafe {
+            Self::NeedsUnsafe(stmt)
+        } else {
+            Self::Normal(stmt)
+        }
+    }
+
+    fn binary(in_safe_context: TokenStream, in_unsafe_context: TokenStream) -> Self {
+        Self::Binary {
+            in_safe_context,
+            in_unsafe_context,
+        }
+    }
+}
+
+fn maybe_unsafes_to_tokens(
+    items: Vec<MaybeUnsafeStmt>,
+    context_is_already_unsafe: bool,
+) -> TokenStream {
+    if context_is_already_unsafe {
+        let items = items.into_iter().map(|item| match item {
+            MaybeUnsafeStmt::Normal(stmt)
+            | MaybeUnsafeStmt::NeedsUnsafe(stmt)
+            | MaybeUnsafeStmt::Binary {
+                in_unsafe_context: stmt,
+                ..
+            } => stmt,
+        });
+        quote! {
+            #(#items)*
+        }
+    } else {
+        let mut currently_unsafe_list = None;
+        let mut output = Vec::new();
+        for item in items {
+            match item {
+                MaybeUnsafeStmt::NeedsUnsafe(stmt) => {
+                    if currently_unsafe_list.is_none() {
+                        currently_unsafe_list = Some(Vec::new());
+                    }
+                    currently_unsafe_list.as_mut().unwrap().push(stmt);
+                }
+                MaybeUnsafeStmt::Normal(stmt)
+                | MaybeUnsafeStmt::Binary {
+                    in_safe_context: stmt,
+                    ..
+                } => {
+                    if let Some(currently_unsafe_list) = currently_unsafe_list.take() {
+                        output.push(quote! {
+                            unsafe {
+                                #(#currently_unsafe_list)*
+                            }
+                        })
+                    }
+                    output.push(stmt);
+                }
+            }
+        }
+        if let Some(currently_unsafe_list) = currently_unsafe_list.take() {
+            output.push(quote! {
+                unsafe {
+                    #(#currently_unsafe_list)*
+                }
+            })
+        }
+        quote! {
+            #(#output)*
+        }
+    }
+}
+
+#[test]
+fn test_maybe_unsafes_to_tokens() {
+    let items = vec![
+        MaybeUnsafeStmt::new(quote! { use A; }),
+        MaybeUnsafeStmt::new(quote! { use B; }),
+        MaybeUnsafeStmt::needs_unsafe(quote! { use C; }),
+        MaybeUnsafeStmt::needs_unsafe(quote! { use D; }),
+        MaybeUnsafeStmt::new(quote! { use E; }),
+        MaybeUnsafeStmt::needs_unsafe(quote! { use F; }),
+    ];
+    assert_eq!(
+        maybe_unsafes_to_tokens(items.clone(), false).to_string(),
+        quote! {
+            use A;
+            use B;
+            unsafe {
+                use C;
+                use D;
+            }
+            use E;
+            unsafe {
+                use F;
+            }
+        }
+        .to_string()
+    );
+    assert_eq!(
+        maybe_unsafes_to_tokens(items, true).to_string(),
+        quote! {
+            use A;
+            use B;
+            use C;
+            use D;
+            use E;
+            use F;
+        }
+        .to_string()
+    );
+}
diff --git a/engine/src/conversion/codegen_rs/namespace_organizer.rs b/engine/src/conversion/codegen_rs/namespace_organizer.rs
new file mode 100644
index 0000000..886cb1c
--- /dev/null
+++ b/engine/src/conversion/codegen_rs/namespace_organizer.rs
@@ -0,0 +1,136 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::types::Namespace;
+use std::collections::BTreeMap;
+
+pub trait HasNs {
+    fn get_namespace(&self) -> &Namespace;
+}
+
+pub struct NamespaceEntries<'a, T: HasNs> {
+    entries: Vec<&'a T>,
+    children: BTreeMap<&'a String, NamespaceEntries<'a, T>>,
+}
+
+impl<'a, T: HasNs> NamespaceEntries<'a, T> {
+    pub(crate) fn new(apis: &'a [T]) -> Self {
+        let api_refs = apis.iter().collect::<Vec<_>>();
+        Self::sort_by_inner_namespace(api_refs, 0)
+    }
+
+    pub(crate) fn is_empty(&self) -> bool {
+        self.entries.is_empty() && self.children.iter().all(|(_, child)| child.is_empty())
+    }
+
+    pub(crate) fn entries(&self) -> &[&'a T] {
+        &self.entries
+    }
+
+    pub(crate) fn children(&self) -> impl Iterator<Item = (&&String, &NamespaceEntries<T>)> {
+        self.children.iter()
+    }
+
+    fn sort_by_inner_namespace(apis: Vec<&'a T>, depth: usize) -> Self {
+        let mut root = NamespaceEntries {
+            entries: Vec::new(),
+            children: BTreeMap::new(),
+        };
+
+        let mut kids_by_child_ns = BTreeMap::new();
+        for api in apis {
+            let first_ns_elem = api.get_namespace().iter().nth(depth);
+            if let Some(first_ns_elem) = first_ns_elem {
+                let list = kids_by_child_ns
+                    .entry(first_ns_elem)
+                    .or_insert_with(Vec::new);
+                list.push(api);
+                continue;
+            }
+            root.entries.push(api);
+        }
+
+        for (k, v) in kids_by_child_ns.into_iter() {
+            root.children
+                .insert(k, Self::sort_by_inner_namespace(v, depth + 1));
+        }
+
+        root
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{HasNs, NamespaceEntries};
+    use crate::types::Namespace;
+
+    struct TestApi(&'static str, Namespace);
+    impl HasNs for TestApi {
+        fn get_namespace(&self) -> &Namespace {
+            &self.1
+        }
+    }
+
+    #[test]
+    fn test_ns_entries_sort() {
+        let entries = vec![
+            make_api(None, "C"),
+            make_api(None, "A"),
+            make_api(Some("G"), "E"),
+            make_api(Some("D"), "F"),
+            make_api(Some("G"), "H"),
+            make_api(Some("D::K"), "L"),
+            make_api(Some("D::K"), "M"),
+            make_api(None, "B"),
+            make_api(Some("D"), "I"),
+            make_api(Some("D"), "J"),
+        ];
+        let ns = NamespaceEntries::new(&entries);
+        let root_entries = ns.entries();
+        assert_eq!(root_entries.len(), 3);
+        assert_ident(root_entries[0], "C");
+        assert_ident(root_entries[1], "A");
+        assert_ident(root_entries[2], "B");
+        let mut kids = ns.children();
+        let (d_id, d_nse) = kids.next().unwrap();
+        assert_eq!(d_id.to_string(), "D");
+        let (g_id, g_nse) = kids.next().unwrap();
+        assert_eq!(g_id.to_string(), "G");
+        assert!(kids.next().is_none());
+        let d_nse_entries = d_nse.entries();
+        assert_eq!(d_nse_entries.len(), 3);
+        assert_ident(d_nse_entries[0], "F");
+        assert_ident(d_nse_entries[1], "I");
+        assert_ident(d_nse_entries[2], "J");
+        let g_nse_entries = g_nse.entries();
+        assert_eq!(g_nse_entries.len(), 2);
+        assert_ident(g_nse_entries[0], "E");
+        assert_ident(g_nse_entries[1], "H");
+        let mut g_kids = g_nse.children();
+        assert!(g_kids.next().is_none());
+        let mut d_kids = d_nse.children();
+        let (k_id, k_nse) = d_kids.next().unwrap();
+        assert_eq!(k_id.to_string(), "K");
+        let k_nse_entries = k_nse.entries();
+        assert_eq!(k_nse_entries.len(), 2);
+        assert_ident(k_nse_entries[0], "L");
+        assert_ident(k_nse_entries[1], "M");
+    }
+
+    fn assert_ident(api: &TestApi, expected: &str) {
+        assert_eq!(api.0, expected);
+    }
+
+    fn make_api(ns: Option<&str>, id: &'static str) -> TestApi {
+        let ns = match ns {
+            Some(st) => Namespace::from_user_input(st),
+            None => Namespace::new(),
+        };
+        TestApi(id, ns)
+    }
+}
diff --git a/engine/src/conversion/codegen_rs/non_pod_struct.rs b/engine/src/conversion/codegen_rs/non_pod_struct.rs
new file mode 100644
index 0000000..e4bec2f
--- /dev/null
+++ b/engine/src/conversion/codegen_rs/non_pod_struct.rs
@@ -0,0 +1,132 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::conversion::api::Layout;
+use crate::types::make_ident;
+use proc_macro2::{Ident, Span};
+use quote::quote;
+use syn::parse::Parser;
+use syn::punctuated::Punctuated;
+use syn::{parse_quote, Field, Fields, GenericParam, ItemStruct, LitInt};
+
+pub(crate) fn new_non_pod_struct(id: Ident) -> ItemStruct {
+    let mut s = parse_quote! {
+        pub struct #id {
+        }
+    };
+    make_non_pod(&mut s, None);
+    s
+}
+
+pub(crate) fn make_non_pod(s: &mut ItemStruct, layout: Option<Layout>) {
+    // Make an opaque struct. If we have layout information, we pass
+    // that through to Rust. We keep only doc attrs, plus add a #[repr(C)]
+    // if necessary.
+    // Constraints here (thanks to dtolnay@ for this explanation of why the
+    // following is needed:)
+    // (1) If the real alignment of the C++ type is smaller and a reference
+    // is returned from C++ to Rust, mere existence of an insufficiently
+    // aligned reference in Rust causes UB even if never dereferenced
+    // by Rust code
+    // (see https://doc.rust-lang.org/1.47.0/reference/behavior-considered-undefined.html).
+    // Rustc can use least-significant bits of the reference for other storage.
+    // (if we have layout information from bindgen we use that instead)
+    // (2) We want to ensure the type is !Unpin
+    // (3) We want to ensure it's not Send or Sync
+    //
+    // For opaque types, the Rusty opaque structure could in fact be generated
+    // by three different things:
+    // a) bindgen, using its --opaque-type command line argument or the library
+    //    equivalent;
+    // b) us (autocxx), which is what this code does
+    // c) cxx, using "type B;" in an "extern "C++"" section
+    // We never use (a) because bindgen requires an allowlist of opaque types.
+    // Furthermore, it sometimes then discards struct definitions entirely
+    // and says "type A = [u8;2];" or something else which makes our life
+    // much more difficult.
+    // We use (c) for abstract types. For everything else, we do it ourselves
+    // for maximal control. See codegen_rs/mod.rs generate_type for more notes.
+    // First work out attributes.
+    let doc_attr = s
+        .attrs
+        .iter()
+        .filter(|a| a.path.get_ident().iter().any(|p| *p == "doc"))
+        .cloned();
+    let repr_attr = if let Some(layout) = &layout {
+        let align = make_lit_int(layout.align);
+        if layout.packed {
+            parse_quote! {
+                #[repr(C,align(#align),packed)]
+            }
+        } else {
+            parse_quote! {
+                #[repr(C,align(#align))]
+            }
+        }
+    } else {
+        parse_quote! {
+            #[repr(C, packed)]
+        }
+    };
+    let attrs = doc_attr.chain(std::iter::once(repr_attr));
+    s.attrs = attrs.collect();
+    // Now fill in fields. Usually, we just want a single field
+    // but if this is a generic type we need to faff a bit.
+    let generic_type_fields = s
+        .generics
+        .params
+        .iter()
+        .enumerate()
+        .filter_map(|(counter, gp)| match gp {
+            GenericParam::Type(gpt) => {
+                let id = &gpt.ident;
+                let field_name = make_ident(&format!("_phantom_{}", counter));
+                let toks = quote! {
+                    #field_name: ::std::marker::PhantomData<::std::cell::UnsafeCell< #id >>
+                };
+                Some(Field::parse_named.parse2(toks).unwrap())
+            }
+            _ => None,
+        });
+    let data_field = if let Some(layout) = layout {
+        let size = make_lit_int(layout.size);
+        Some(
+            syn::Field::parse_named
+                .parse2(quote! {
+                    _data: [u8; #size]
+                })
+                .unwrap(),
+        )
+    } else {
+        None
+    }
+    .into_iter();
+    let pin_field = syn::Field::parse_named
+        .parse2(quote! {
+            _pinned: core::marker::PhantomData<core::marker::PhantomPinned>
+        })
+        .unwrap();
+
+    let non_send_sync_field = syn::Field::parse_named
+        .parse2(quote! {
+            _non_send_sync: core::marker::PhantomData<[*const u8;0]>
+        })
+        .unwrap();
+    let all_fields: Punctuated<_, syn::token::Comma> = std::iter::once(pin_field)
+        .chain(std::iter::once(non_send_sync_field))
+        .chain(generic_type_fields)
+        .chain(data_field)
+        .collect();
+    s.fields = Fields::Named(parse_quote! { {
+        #all_fields
+    } })
+}
+
+fn make_lit_int(val: usize) -> LitInt {
+    LitInt::new(&val.to_string(), Span::call_site())
+}
diff --git a/engine/src/conversion/codegen_rs/unqualify.rs b/engine/src/conversion/codegen_rs/unqualify.rs
new file mode 100644
index 0000000..6f245c2
--- /dev/null
+++ b/engine/src/conversion/codegen_rs/unqualify.rs
@@ -0,0 +1,94 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use syn::{
+    parse_quote, punctuated::Punctuated, FnArg, GenericArgument, PathArguments, PathSegment,
+    ReturnType, Token, Type, TypePath,
+};
+
+/// Mod to handle stripping paths off the front of types.
+
+fn unqualify_type_path(typ: TypePath) -> TypePath {
+    // If we've still got more than one
+    // path segment then this is referring to a type within
+    // C++ namespaces. Strip them off for now, until cxx supports
+    // nested mods within a cxx::bridge.
+    // This is 'safe' because earlier code will already have
+    // failed with 'DuplicateType' if we had several types called
+    // the same thing.
+    let last_seg = typ.path.segments.into_iter().last().unwrap();
+    let ident = &last_seg.ident;
+    let args = match last_seg.arguments {
+        PathArguments::AngleBracketed(mut ab) => {
+            ab.args = unqualify_punctuated(ab.args);
+            PathArguments::AngleBracketed(ab)
+        }
+        _ => last_seg.arguments.clone(),
+    };
+    let last_seg: PathSegment = parse_quote!( #ident #args );
+    parse_quote!(
+        #last_seg
+    )
+}
+
+fn unqualify_punctuated<P>(pun: Punctuated<GenericArgument, P>) -> Punctuated<GenericArgument, P>
+where
+    P: Default,
+{
+    let mut new_pun = Punctuated::new();
+    for arg in pun.into_iter() {
+        new_pun.push(match arg {
+            GenericArgument::Type(t) => GenericArgument::Type(unqualify_type(t)),
+            _ => arg,
+        });
+    }
+    new_pun
+}
+
+fn unqualify_type(typ: Type) -> Type {
+    match typ {
+        Type::Path(typ) => Type::Path(unqualify_type_path(typ)),
+        Type::Reference(mut typeref) => {
+            typeref.elem = unqualify_boxed_type(typeref.elem);
+            Type::Reference(typeref)
+        }
+        Type::Ptr(mut typeptr) => {
+            typeptr.elem = unqualify_boxed_type(typeptr.elem);
+            Type::Ptr(typeptr)
+        }
+        _ => typ,
+    }
+}
+
+fn unqualify_boxed_type(typ: Box<Type>) -> Box<Type> {
+    Box::new(unqualify_type(*typ))
+}
+
+pub(crate) fn unqualify_ret_type(ret_type: ReturnType) -> ReturnType {
+    match ret_type {
+        ReturnType::Type(tok, boxed_type) => {
+            ReturnType::Type(tok, unqualify_boxed_type(boxed_type))
+        }
+        _ => ret_type,
+    }
+}
+
+pub(crate) fn unqualify_params(
+    params: Punctuated<FnArg, Token![,]>,
+) -> Punctuated<FnArg, Token![,]> {
+    params
+        .into_iter()
+        .map(|p| match p {
+            FnArg::Typed(mut pt) => {
+                pt.ty = unqualify_boxed_type(pt.ty);
+                FnArg::Typed(pt)
+            }
+            _ => p,
+        })
+        .collect()
+}
diff --git a/engine/src/conversion/conversion_tests.rs b/engine/src/conversion/conversion_tests.rs
new file mode 100644
index 0000000..b0474d6
--- /dev/null
+++ b/engine/src/conversion/conversion_tests.rs
@@ -0,0 +1,46 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx_parser::UnsafePolicy;
+#[allow(unused_imports)]
+use syn::parse_quote;
+use syn::ItemMod;
+
+use crate::CppCodegenOptions;
+
+use super::BridgeConverter;
+
+// This mod is for tests which take bindgen output directly.
+// This should be avoided where possible, since these tests will
+// become obsolete or have to change if and when we update
+// bindgen. Instead, please add tests working directly from
+// the original C++ in integration_tests.rs if possible.
+// Also, if you're pasting in code from github issues, it's
+// important to make sure that the underlying code has an
+// acceptable license. That's why this file is currently blank.
+
+#[allow(dead_code)]
+fn do_test(input: ItemMod) {
+    let tc = parse_quote! {};
+    let bc = BridgeConverter::new(&[], &tc);
+    let inclusions = "".into();
+    bc.convert(
+        input,
+        UnsafePolicy::AllFunctionsSafe,
+        inclusions,
+        &CppCodegenOptions::default(),
+    )
+    .unwrap();
+}
+
+// How to add a test here
+//
+// #[test]
+// fn test_xyz() {
+//      do_test(parse_quote!{ /* paste bindgen output here */})
+// }
diff --git a/engine/src/conversion/convert_error.rs b/engine/src/conversion/convert_error.rs
new file mode 100644
index 0000000..0de4f19
--- /dev/null
+++ b/engine/src/conversion/convert_error.rs
@@ -0,0 +1,218 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::set::IndexSet as HashSet;
+
+use itertools::Itertools;
+use syn::Ident;
+use thiserror::Error;
+
+use crate::{
+    known_types,
+    types::{make_ident, Namespace, QualifiedName},
+};
+
+#[derive(Debug, Clone, Error)]
+pub enum ConvertError {
+    #[error("The initial run of 'bindgen' did not generate any content. This might be because none of the requested items for generation could be converted.")]
+    NoContent,
+    #[error("An item was requested using 'generate_pod' which was not safe to hold by value in Rust. {0}")]
+    UnsafePodType(String),
+    #[error("Bindgen generated some unexpected code in a foreign mod section. You may have specified something in a 'generate' directive which is not currently compatible with autocxx.")]
+    UnexpectedForeignItem,
+    #[error("Bindgen generated some unexpected code in its outermost mod section. You may have specified something in a 'generate' directive which is not currently compatible with autocxx.")]
+    UnexpectedOuterItem,
+    #[error("Bindgen generated some unexpected code in an inner namespace mod. You may have specified something in a 'generate' directive which is not currently compatible with autocxx.")]
+    UnexpectedItemInMod,
+    #[error("autocxx was unable to produce a typdef pointing to the complex type {0}.")]
+    ComplexTypedefTarget(String),
+    #[error("Unexpected type for 'this' in the function {}.", .0.to_cpp_name())]
+    UnexpectedThisType(QualifiedName),
+    #[error("autocxx does not yet know how to support the built-in C++ type {} - please raise an issue on github", .0.to_cpp_name())]
+    UnsupportedBuiltInType(QualifiedName),
+    #[error("Type {} has templated arguments and so does the typedef to which it points", .0.to_cpp_name())]
+    ConflictingTemplatedArgsWithTypedef(QualifiedName),
+    #[error("Function {0} has a parameter or return type which is either on the blocklist or a forward declaration")]
+    UnacceptableParam(String),
+    #[error("Function {0} has a return reference parameter, but 0 or >1 input reference parameters, so the lifetime of the output reference cannot be deduced.")]
+    NotOneInputReference(String),
+    #[error("Encountered type not yet supported by autocxx: {0}")]
+    UnsupportedType(String),
+    #[error("Encountered type not yet known by autocxx: {0}")]
+    UnknownType(String),
+    #[error("Encountered mutable static data, not yet supported: {0}")]
+    StaticData(String),
+    #[error("Encountered typedef to itself - this is a known bindgen bug: {0}")]
+    InfinitelyRecursiveTypedef(QualifiedName),
+    #[error("Unexpected 'use' statement encountered: {}", .0.as_ref().map(|s| s.as_str()).unwrap_or("<unknown>"))]
+    UnexpectedUseStatement(Option<String>),
+    #[error("Type {} was parameterized over something complex which we don't yet support", .0.to_cpp_name())]
+    TemplatedTypeContainingNonPathArg(QualifiedName),
+    #[error("Pointer pointed to something unsupported")]
+    InvalidPointee,
+    #[error("The 'generate' or 'generate_pod' directive for '{0}' did not result in any code being generated. Perhaps this was mis-spelled or you didn't qualify the name with any namespaces? Otherwise please report a bug.")]
+    DidNotGenerateAnything(String),
+    #[error("Found an attempt at using a forward declaration ({}) inside a templated cxx type such as UniquePtr or CxxVector. If the forward declaration is a typedef, perhaps autocxx wasn't sure whether or not it involved a forward declaration. If you're sure it didn't, then you may be able to solve this by using instantiable!.", .0.to_cpp_name())]
+    TypeContainingForwardDeclaration(QualifiedName),
+    #[error("Found an attempt at using a type marked as blocked! ({})", .0.to_cpp_name())]
+    Blocked(QualifiedName),
+    #[error("This function or method uses a type where one of the template parameters was incomprehensible to bindgen/autocxx - probably because it uses template specialization.")]
+    UnusedTemplateParam,
+    #[error("Names containing __ are reserved by C++ so not acceptable to cxx")]
+    TooManyUnderscores,
+    #[error("This item relies on a type not known to autocxx ({})", .0.to_cpp_name())]
+    UnknownDependentType(QualifiedName),
+    #[error("This item depends on some other type(s) which autocxx could not generate, some of them are: {}", .0.iter().join(", "))]
+    IgnoredDependent(HashSet<QualifiedName>),
+    #[error("The item name '{0}' is a reserved word in Rust.")]
+    ReservedName(String),
+    #[error("This item name is used in multiple namespaces. At present, autocxx and cxx allow only one type of a given name. This limitation will be fixed in future. (Items found with this name: {})", .0.iter().join(", "))]
+    DuplicateCxxBridgeName(Vec<String>),
+    #[error("This is a method on a type which can't be used as the receiver in Rust (i.e. self/this). This is probably because some type involves template specialization.")]
+    UnsupportedReceiver,
+    #[error("A rust::Box<T> was encountered where T was not known to be a Rust type. Use rust_type!(T): {}", .0.to_cpp_name())]
+    BoxContainingNonRustType(QualifiedName),
+    #[error("A qualified Rust type was found (i.e. one containing ::): {}. Rust types must always be a simple identifier.", .0.to_cpp_name())]
+    RustTypeWithAPath(QualifiedName),
+    #[error("This type is nested within another struct/class, yet is abstract (or is not on the allowlist so we can't be sure). This is not yet supported by autocxx. If you don't believe this type is abstract, add it to the allowlist.")]
+    AbstractNestedType,
+    #[error("This typedef was nested within another struct/class. autocxx is unable to represent inner types if they might be abstract. Unfortunately, autocxx couldn't prove that this type isn't abstract, so it can't represent it.")]
+    NestedOpaqueTypedef,
+    #[error(
+        "This type is nested within another struct/class with protected or private visibility."
+    )]
+    NonPublicNestedType,
+    #[error("This function returns an rvalue reference (&&) which is not yet supported.")]
+    RValueReturn,
+    #[error("This method is private")]
+    PrivateMethod,
+    #[error("autocxx does not know how to generate bindings to operator=")]
+    AssignmentOperator,
+    #[error("This function was marked =delete")]
+    Deleted,
+    #[error("This structure has an rvalue reference field (&&) which is not yet supported.")]
+    RValueReferenceField,
+    #[error("This type was not on the allowlist, so we are not generating methods for it.")]
+    MethodOfNonAllowlistedType,
+    #[error("This type is templated, so we can't generate bindings. We will instead generate bindings for each instantiation.")]
+    MethodOfGenericType,
+    #[error("bindgen generated multiple different APIs (functions/types) with this name. autocxx doesn't know how to disambiguate them, so we won't generate bindings for any of them.")]
+    DuplicateItemsFoundInParsing,
+    #[error(
+        "bindgen generated a move or copy constructor with an unexpected number of parameters."
+    )]
+    ConstructorWithOnlyOneParam,
+    #[error("A copy or move constructor was found to take extra parameters. These are likely to be parameters with defaults, which are not yet supported by autocxx, so this constructor has been ignored.")]
+    ConstructorWithMultipleParams,
+    #[error("A C++ unique_ptr, shared_ptr or weak_ptr was found containing some type that cxx can't accommodate in that position ({})", .0.to_cpp_name())]
+    InvalidTypeForCppPtr(QualifiedName),
+    #[error("A C++ std::vector was found containing some type that cxx can't accommodate as a vector element ({})", .0.to_cpp_name())]
+    InvalidTypeForCppVector(QualifiedName),
+    #[error("Variadic functions are not supported by cxx or autocxx.")]
+    Variadic,
+    #[error("A type had a template inside a std::vector, which is not supported.")]
+    GenericsWithinVector,
+    #[error("This typedef takes generic parameters, not yet supported by autocxx.")]
+    TypedefTakesGenericParameters,
+    #[error("This method belonged to an item in an anonymous namespace, not currently supported.")]
+    MethodInAnonymousNamespace,
+    #[error("We're unable to make a concrete version of this template, because we found an error handling the template.")]
+    ConcreteVersionOfIgnoredTemplate,
+    #[error("bindgen decided to call this type _bindgen_ty_N because it couldn't deduce the correct name for it. That means we can't generate C++ bindings to it.")]
+    BindgenTy,
+}
+
+/// Ensures that error contexts are always created using the constructors in this
+/// mod, therefore undergoing identifier sanitation.
+#[derive(Clone)]
+struct PhantomSanitized;
+
+/// The context of an error, e.g. whether it applies to a function or a method.
+/// This is used to generate suitable rustdoc in the output codegen so that
+/// the errors can be revealed in rust-analyzer-based IDEs, etc.
+#[derive(Clone)]
+pub(crate) struct ErrorContext(ErrorContextType, PhantomSanitized);
+
+/// All idents in this structure are guaranteed to be something we can safely codegen for.
+#[derive(Clone)]
+pub(crate) enum ErrorContextType {
+    Item(Ident),
+    SanitizedItem(Ident),
+    Method { self_ty: Ident, method: Ident },
+}
+
+impl ErrorContext {
+    pub(crate) fn new_for_item(id: Ident) -> Self {
+        match Self::sanitize_error_ident(&id) {
+            None => Self(ErrorContextType::Item(id), PhantomSanitized),
+            Some(sanitized) => Self(ErrorContextType::SanitizedItem(sanitized), PhantomSanitized),
+        }
+    }
+
+    pub(crate) fn new_for_method(self_ty: Ident, method: Ident) -> Self {
+        // If this IgnoredItem relates to a method on a self_ty which we can't represent,
+        // e.g. u8, then forget about trying to attach this error text to something within
+        // an impl block.
+        match Self::sanitize_error_ident(&self_ty) {
+            None => Self(
+                ErrorContextType::Method {
+                    self_ty,
+                    method: Self::sanitize_error_ident(&method).unwrap_or(method),
+                },
+                PhantomSanitized,
+            ),
+            Some(_) => Self(
+                ErrorContextType::SanitizedItem(make_ident(format!("{}_{}", self_ty, method))),
+                PhantomSanitized,
+            ),
+        }
+    }
+
+    /// Because errors may be generated for invalid types or identifiers,
+    /// we may need to scrub the name
+    fn sanitize_error_ident(id: &Ident) -> Option<Ident> {
+        let qn = QualifiedName::new(&Namespace::new(), id.clone());
+        if known_types().conflicts_with_built_in_type(&qn) {
+            Some(make_ident(format!("{}_autocxx_error", qn.get_final_item())))
+        } else {
+            None
+        }
+    }
+
+    pub(crate) fn get_type(&self) -> &ErrorContextType {
+        &self.0
+    }
+
+    pub(crate) fn into_type(self) -> ErrorContextType {
+        self.0
+    }
+}
+
+impl std::fmt::Display for ErrorContext {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match &self.0 {
+            ErrorContextType::Item(id) | ErrorContextType::SanitizedItem(id) => write!(f, "{}", id),
+            ErrorContextType::Method { self_ty, method } => write!(f, "{}::{}", self_ty, method),
+        }
+    }
+}
+
+#[derive(Clone)]
+pub(crate) struct ConvertErrorWithContext(pub(crate) ConvertError, pub(crate) Option<ErrorContext>);
+
+impl std::fmt::Debug for ConvertErrorWithContext {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.0)
+    }
+}
+
+impl std::fmt::Display for ConvertErrorWithContext {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.0)
+    }
+}
diff --git a/engine/src/conversion/doc_attr.rs b/engine/src/conversion/doc_attr.rs
new file mode 100644
index 0000000..8fe9d0b
--- /dev/null
+++ b/engine/src/conversion/doc_attr.rs
@@ -0,0 +1,18 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use syn::Attribute;
+
+/// Returns the attribute (if any) which contains a doc comment.
+pub(super) fn get_doc_attrs(attrs: &[Attribute]) -> Vec<Attribute> {
+    attrs
+        .iter()
+        .filter(|a| a.path.get_ident().iter().any(|p| *p == "doc"))
+        .cloned()
+        .collect()
+}
diff --git a/engine/src/conversion/error_reporter.rs b/engine/src/conversion/error_reporter.rs
new file mode 100644
index 0000000..7942a32
--- /dev/null
+++ b/engine/src/conversion/error_reporter.rs
@@ -0,0 +1,225 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use syn::ItemEnum;
+
+use super::{
+    api::{AnalysisPhase, Api, ApiName, FuncToConvert, StructDetails, TypedefKind},
+    apivec::ApiVec,
+    convert_error::{ConvertErrorWithContext, ErrorContext},
+    ConvertError,
+};
+use crate::{
+    conversion::convert_error::ErrorContextType,
+    types::{Namespace, QualifiedName},
+};
+
+/// Run some code which may generate a ConvertError.
+/// If it does, try to note the problem in our output APIs
+/// such that users will see documentation of the error.
+pub(crate) fn report_any_error<F, T>(
+    ns: &Namespace,
+    apis: &mut ApiVec<impl AnalysisPhase>,
+    fun: F,
+) -> Option<T>
+where
+    F: FnOnce() -> Result<T, ConvertErrorWithContext>,
+{
+    match fun() {
+        Ok(result) => Some(result),
+        Err(ConvertErrorWithContext(err, None)) => {
+            eprintln!("Ignored item: {}", err);
+            None
+        }
+        Err(ConvertErrorWithContext(err, Some(ctx))) => {
+            let id = match ctx.get_type() {
+                ErrorContextType::Item(id) | ErrorContextType::SanitizedItem(id) => id,
+                ErrorContextType::Method { self_ty, .. } => self_ty,
+            };
+            let name = ApiName::new_from_qualified_name(QualifiedName::new(ns, id.clone()));
+            apis.push(Api::IgnoredItem {
+                name,
+                err,
+                ctx: Some(ctx),
+            });
+            None
+        }
+    }
+}
+
+/// Run some code which generates an API. Add that API, or if
+/// anything goes wrong, instead add a note of the problem in our
+/// output API such that users will see documentation for the problem.
+pub(crate) fn convert_apis<FF, SF, EF, TF, A, B: 'static>(
+    in_apis: ApiVec<A>,
+    out_apis: &mut ApiVec<B>,
+    mut func_conversion: FF,
+    mut struct_conversion: SF,
+    mut enum_conversion: EF,
+    mut typedef_conversion: TF,
+) where
+    A: AnalysisPhase,
+    B: AnalysisPhase,
+    FF: FnMut(
+        ApiName,
+        Box<FuncToConvert>,
+        A::FunAnalysis,
+    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
+    SF: FnMut(
+        ApiName,
+        Box<StructDetails>,
+        A::StructAnalysis,
+    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
+    EF: FnMut(
+        ApiName,
+        ItemEnum,
+    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
+    TF: FnMut(
+        ApiName,
+        TypedefKind,
+        Option<QualifiedName>,
+        A::TypedefAnalysis,
+    ) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext>,
+{
+    out_apis.extend(in_apis.into_iter().flat_map(|api| {
+        let fullname = api.name_info().clone();
+        let result: Result<Box<dyn Iterator<Item = Api<B>>>, ConvertErrorWithContext> = match api {
+            // No changes to any of these...
+            Api::ConcreteType {
+                name,
+                rs_definition,
+                cpp_definition,
+            } => Ok(Box::new(std::iter::once(Api::ConcreteType {
+                name,
+                rs_definition,
+                cpp_definition,
+            }))),
+            Api::ForwardDeclaration { name, err } => {
+                Ok(Box::new(std::iter::once(Api::ForwardDeclaration {
+                    name,
+                    err,
+                })))
+            }
+            Api::OpaqueTypedef {
+                name,
+                forward_declaration,
+            } => Ok(Box::new(std::iter::once(Api::OpaqueTypedef {
+                name,
+                forward_declaration,
+            }))),
+            Api::StringConstructor { name } => {
+                Ok(Box::new(std::iter::once(Api::StringConstructor { name })))
+            }
+            Api::Const { name, const_item } => {
+                Ok(Box::new(std::iter::once(Api::Const { name, const_item })))
+            }
+            Api::CType { name, typename } => {
+                Ok(Box::new(std::iter::once(Api::CType { name, typename })))
+            }
+            Api::RustType { name, path } => {
+                Ok(Box::new(std::iter::once(Api::RustType { name, path })))
+            }
+            Api::RustFn {
+                name,
+                details,
+                receiver,
+            } => Ok(Box::new(std::iter::once(Api::RustFn {
+                name,
+                details,
+                receiver,
+            }))),
+            Api::RustSubclassFn {
+                name,
+                subclass,
+                details,
+            } => Ok(Box::new(std::iter::once(Api::RustSubclassFn {
+                name,
+                subclass,
+                details,
+            }))),
+            Api::Subclass { name, superclass } => Ok(Box::new(std::iter::once(Api::Subclass {
+                name,
+                superclass,
+            }))),
+            Api::IgnoredItem { name, err, ctx } => {
+                Ok(Box::new(std::iter::once(Api::IgnoredItem {
+                    name,
+                    err,
+                    ctx,
+                })))
+            }
+            Api::SubclassTraitItem { name, details } => {
+                Ok(Box::new(std::iter::once(Api::SubclassTraitItem {
+                    name,
+                    details,
+                })))
+            }
+            Api::ExternCppType { name, details, pod } => {
+                Ok(Box::new(std::iter::once(Api::ExternCppType {
+                    name,
+                    details,
+                    pod,
+                })))
+            }
+            // Apply a mapping to the following
+            Api::Enum { name, item } => enum_conversion(name, item),
+            Api::Typedef {
+                name,
+                item,
+                old_tyname,
+                analysis,
+            } => typedef_conversion(name, item, old_tyname, analysis),
+            Api::Function {
+                name,
+                fun,
+                analysis,
+            } => func_conversion(name, fun, analysis),
+            Api::Struct {
+                name,
+                details,
+                analysis,
+            } => struct_conversion(name, details, analysis),
+        };
+        api_or_error(fullname, result)
+    }))
+}
+
+fn api_or_error<T: AnalysisPhase + 'static>(
+    name: ApiName,
+    api_or_error: Result<Box<dyn Iterator<Item = Api<T>>>, ConvertErrorWithContext>,
+) -> Box<dyn Iterator<Item = Api<T>>> {
+    match api_or_error {
+        Ok(opt) => opt,
+        Err(ConvertErrorWithContext(err, ctx)) => {
+            Box::new(std::iter::once(Api::IgnoredItem { name, err, ctx }))
+        }
+    }
+}
+
+/// Run some code which generates an API for an item (as opposed to
+/// a method). Add that API, or if
+/// anything goes wrong, instead add a note of the problem in our
+/// output API such that users will see documentation for the problem.
+pub(crate) fn convert_item_apis<F, A, B: 'static>(
+    in_apis: ApiVec<A>,
+    out_apis: &mut ApiVec<B>,
+    mut fun: F,
+) where
+    F: FnMut(Api<A>) -> Result<Box<dyn Iterator<Item = Api<B>>>, ConvertError>,
+    A: AnalysisPhase,
+    B: AnalysisPhase,
+{
+    out_apis.extend(in_apis.into_iter().flat_map(|api| {
+        let fullname = api.name_info().clone();
+        let tn = api.name().clone();
+        let result = fun(api).map_err(|e| {
+            ConvertErrorWithContext(e, Some(ErrorContext::new_for_item(tn.get_final_ident())))
+        });
+        api_or_error(fullname, result)
+    }))
+}
diff --git a/engine/src/conversion/mod.rs b/engine/src/conversion/mod.rs
new file mode 100644
index 0000000..3043dcf
--- /dev/null
+++ b/engine/src/conversion/mod.rs
@@ -0,0 +1,213 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod analysis;
+mod api;
+mod apivec;
+mod codegen_cpp;
+mod codegen_rs;
+#[cfg(test)]
+mod conversion_tests;
+mod convert_error;
+mod doc_attr;
+mod error_reporter;
+mod parse;
+mod utilities;
+
+use analysis::fun::FnAnalyzer;
+use autocxx_parser::IncludeCppConfig;
+pub(crate) use codegen_cpp::CppCodeGenerator;
+pub(crate) use convert_error::ConvertError;
+use itertools::Itertools;
+use syn::{Item, ItemMod};
+
+use crate::{
+    conversion::analysis::deps::HasDependencies, CppCodegenOptions, CppFilePair, UnsafePolicy,
+};
+
+use self::{
+    analysis::{
+        abstract_types::{discard_ignored_functions, mark_types_abstract},
+        allocators::create_alloc_and_frees,
+        casts::add_casts,
+        check_names,
+        constructor_deps::decorate_types_with_constructor_deps,
+        fun::FnPhase,
+        gc::filter_apis_by_following_edges_from_allowlist,
+        pod::analyze_pod_apis,
+        remove_ignored::filter_apis_by_ignored_dependents,
+        replace_hopeless_typedef_targets,
+        tdef::convert_typedef_targets,
+    },
+    api::AnalysisPhase,
+    apivec::ApiVec,
+    codegen_rs::RsCodeGenerator,
+    parse::ParseBindgen,
+};
+
+const LOG_APIS: bool = true;
+
+/// Converts the bindings generated by bindgen into a form suitable
+/// for use with `cxx`.
+/// In fact, most of the actual operation happens within an
+/// individual `BridgeConversion`.
+///
+/// # Flexibility in handling bindgen output
+///
+/// autocxx is inevitably tied to the details of the bindgen output;
+/// e.g. the creation of a 'root' mod when namespaces are enabled.
+/// At the moment this crate takes the view that it's OK to panic
+/// if the bindgen output is not as expected. It may be in future that
+/// we need to be a bit more graceful, but for now, that's OK.
+pub(crate) struct BridgeConverter<'a> {
+    include_list: &'a [String],
+    config: &'a IncludeCppConfig,
+}
+
+/// C++ and Rust code generation output.
+pub(crate) struct CodegenResults {
+    pub(crate) rs: Vec<Item>,
+    pub(crate) cpp: Option<CppFilePair>,
+    pub(crate) cxxgen_header_name: String,
+}
+
+impl<'a> BridgeConverter<'a> {
+    pub fn new(include_list: &'a [String], config: &'a IncludeCppConfig) -> Self {
+        Self {
+            include_list,
+            config,
+        }
+    }
+
+    fn dump_apis<T: AnalysisPhase>(label: &str, apis: &ApiVec<T>) {
+        if LOG_APIS {
+            log::info!(
+                "APIs after {}:\n{}",
+                label,
+                apis.iter()
+                    .map(|api| { format!("  {:?}", api) })
+                    .sorted()
+                    .join("\n")
+            )
+        }
+    }
+
+    fn dump_apis_with_deps(label: &str, apis: &ApiVec<FnPhase>) {
+        if LOG_APIS {
+            log::info!(
+                "APIs after {}:\n{}",
+                label,
+                apis.iter()
+                    .map(|api| { format!("  {:?}, deps={}", api, api.format_deps()) })
+                    .sorted()
+                    .join("\n")
+            )
+        }
+    }
+
+    /// Convert a TokenStream of bindgen-generated bindings to a form
+    /// suitable for cxx.
+    ///
+    /// This is really the heart of autocxx. It parses the output of `bindgen`
+    /// (although really by "parse" we mean to interpret the structures already built
+    /// up by the `syn` crate).
+    pub(crate) fn convert(
+        &self,
+        mut bindgen_mod: ItemMod,
+        unsafe_policy: UnsafePolicy,
+        inclusions: String,
+        cpp_codegen_options: &CppCodegenOptions,
+    ) -> Result<CodegenResults, ConvertError> {
+        match &mut bindgen_mod.content {
+            None => Err(ConvertError::NoContent),
+            Some((_, items)) => {
+                // Parse the bindgen mod.
+                let items_to_process = items.drain(..).collect();
+                let parser = ParseBindgen::new(self.config);
+                let apis = parser.parse_items(items_to_process)?;
+                Self::dump_apis("parsing", &apis);
+                // Inside parse_results, we now have a list of APIs.
+                // We now enter various analysis phases.
+                // Next, convert any typedefs.
+                // "Convert" means replacing bindgen-style type targets
+                // (e.g. root::std::unique_ptr) with cxx-style targets (e.g. UniquePtr).
+                let apis = convert_typedef_targets(self.config, apis);
+                Self::dump_apis("typedefs", &apis);
+                // Now analyze which of them can be POD (i.e. trivial, movable, pass-by-value
+                // versus which need to be opaque).
+                // Specifically, let's confirm that the items requested by the user to be
+                // POD really are POD, and duly mark any dependent types.
+                // This returns a new list of `Api`s, which will be parameterized with
+                // the analysis results. It also returns an object which can be used
+                // by subsequent phases to work out which objects are POD.
+                let analyzed_apis = analyze_pod_apis(apis, self.config)?;
+                Self::dump_apis("pod analysis", &analyzed_apis);
+                let analyzed_apis = replace_hopeless_typedef_targets(self.config, analyzed_apis);
+                let analyzed_apis = add_casts(analyzed_apis);
+                let analyzed_apis = create_alloc_and_frees(analyzed_apis);
+                // Next, figure out how we materialize different functions.
+                // Some will be simple entries in the cxx::bridge module; others will
+                // require C++ wrapper functions. This is probably the most complex
+                // part of `autocxx`. Again, this returns a new set of `Api`s, but
+                // parameterized by a richer set of metadata.
+                Self::dump_apis("adding casts", &analyzed_apis);
+                let analyzed_apis =
+                    FnAnalyzer::analyze_functions(analyzed_apis, unsafe_policy, self.config);
+                // If any of those functions turned out to be pure virtual, don't attempt
+                // to generate UniquePtr implementations for the type, since it can't
+                // be instantiated.
+                Self::dump_apis("analyze fns", &analyzed_apis);
+                let analyzed_apis = mark_types_abstract(analyzed_apis);
+                Self::dump_apis("marking abstract", &analyzed_apis);
+                // Annotate structs with a note of any copy/move constructors which
+                // we may want to retain to avoid garbage collecting them later.
+                let analyzed_apis = decorate_types_with_constructor_deps(analyzed_apis);
+                Self::dump_apis_with_deps("adding constructor deps", &analyzed_apis);
+                let analyzed_apis = discard_ignored_functions(analyzed_apis);
+                Self::dump_apis_with_deps("ignoring ignorable fns", &analyzed_apis);
+                // Remove any APIs whose names are not compatible with cxx.
+                let analyzed_apis = check_names(analyzed_apis);
+                // During parsing or subsequent processing we might have encountered
+                // items which we couldn't process due to as-yet-unsupported features.
+                // There might be other items depending on such things. Let's remove them
+                // too.
+                let analyzed_apis = filter_apis_by_ignored_dependents(analyzed_apis);
+                Self::dump_apis_with_deps("removing ignored dependents", &analyzed_apis);
+
+                // We now garbage collect the ones we don't need...
+                let mut analyzed_apis =
+                    filter_apis_by_following_edges_from_allowlist(analyzed_apis, self.config);
+                // Determine what variably-sized C types (e.g. int) we need to include
+                analysis::ctypes::append_ctype_information(&mut analyzed_apis);
+                Self::dump_apis_with_deps("GC", &analyzed_apis);
+                // And finally pass them to the code gen phases, which outputs
+                // code suitable for cxx to consume.
+                let cxxgen_header_name = cpp_codegen_options.cxxgen_header_namer.name_header();
+                let cpp = CppCodeGenerator::generate_cpp_code(
+                    inclusions,
+                    &analyzed_apis,
+                    self.config,
+                    cpp_codegen_options,
+                    &cxxgen_header_name,
+                )?;
+                let rs = RsCodeGenerator::generate_rs_code(
+                    analyzed_apis,
+                    self.include_list,
+                    bindgen_mod,
+                    self.config,
+                    cpp.as_ref().map(|file_pair| file_pair.header_name.clone()),
+                );
+                Ok(CodegenResults {
+                    rs,
+                    cpp,
+                    cxxgen_header_name,
+                })
+            }
+        }
+    }
+}
diff --git a/engine/src/conversion/parse/bindgen_semantic_attributes.rs b/engine/src/conversion/parse/bindgen_semantic_attributes.rs
new file mode 100644
index 0000000..8b789ae
--- /dev/null
+++ b/engine/src/conversion/parse/bindgen_semantic_attributes.rs
@@ -0,0 +1,190 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use proc_macro2::{Ident, TokenStream};
+use syn::{
+    parenthesized,
+    parse::{Parse, Parser},
+    Attribute, LitStr,
+};
+
+use crate::conversion::{
+    api::{CppVisibility, Layout, References, SpecialMemberKind, Virtualness},
+    convert_error::{ConvertErrorWithContext, ErrorContext},
+    ConvertError,
+};
+
+/// The set of all annotations that autocxx_bindgen has added
+/// for our benefit.
+#[derive(Debug)]
+pub(crate) struct BindgenSemanticAttributes(Vec<BindgenSemanticAttribute>);
+
+impl BindgenSemanticAttributes {
+    // Remove `bindgen_` attributes. They don't have a corresponding macro defined anywhere,
+    // so they will cause compilation errors if we leave them in.
+    // We may return an error if one of the bindgen attributes shows that the
+    // item can't be processed.
+    pub(crate) fn new_retaining_others(attrs: &mut Vec<Attribute>) -> Self {
+        let metadata = Self::new(attrs);
+        attrs.retain(|a| a.path.segments.last().unwrap().ident != "cpp_semantics");
+        metadata
+    }
+
+    pub(crate) fn new(attrs: &[Attribute]) -> Self {
+        Self(
+            attrs
+                .iter()
+                .filter_map(|attr| {
+                    if attr.path.segments.last().unwrap().ident == "cpp_semantics" {
+                        let r: Result<BindgenSemanticAttribute, syn::Error> = attr.parse_args();
+                        r.ok()
+                    } else {
+                        None
+                    }
+                })
+                .collect(),
+        )
+    }
+
+    /// Some attributes indicate we can never handle a given item. Check for those.
+    pub(crate) fn check_for_fatal_attrs(
+        &self,
+        id_for_context: &Ident,
+    ) -> Result<(), ConvertErrorWithContext> {
+        if self.has_attr("unused_template_param") {
+            Err(ConvertErrorWithContext(
+                ConvertError::UnusedTemplateParam,
+                Some(ErrorContext::new_for_item(id_for_context.clone())),
+            ))
+        } else {
+            Ok(())
+        }
+    }
+
+    /// Whether the given attribute is present.
+    pub(super) fn has_attr(&self, attr_name: &str) -> bool {
+        self.0.iter().any(|a| a.is_ident(attr_name))
+    }
+
+    /// The C++ visibility of the item.
+    pub(super) fn get_cpp_visibility(&self) -> CppVisibility {
+        if self.has_attr("visibility_private") {
+            CppVisibility::Private
+        } else if self.has_attr("visibility_protected") {
+            CppVisibility::Protected
+        } else {
+            CppVisibility::Public
+        }
+    }
+
+    /// Whether the item is virtual.
+    pub(super) fn get_virtualness(&self) -> Virtualness {
+        if self.has_attr("pure_virtual") {
+            Virtualness::PureVirtual
+        } else if self.has_attr("bindgen_virtual") {
+            Virtualness::Virtual
+        } else {
+            Virtualness::None
+        }
+    }
+
+    fn parse_if_present<T: Parse>(&self, annotation: &str) -> Option<T> {
+        self.0
+            .iter()
+            .find(|a| a.is_ident(annotation))
+            .map(|a| a.parse_args().unwrap())
+    }
+
+    fn string_if_present(&self, annotation: &str) -> Option<String> {
+        let ls: Option<LitStr> = self.parse_if_present(annotation);
+        ls.map(|ls| ls.value())
+    }
+
+    /// The in-memory layout of the item.
+    pub(super) fn get_layout(&self) -> Option<Layout> {
+        self.parse_if_present("layout")
+    }
+
+    /// The original C++ name, which bindgen may have changed.
+    pub(super) fn get_original_name(&self) -> Option<String> {
+        self.string_if_present("original_name")
+    }
+
+    /// Whether this is a move constructor or other special member.
+    pub(super) fn special_member_kind(&self) -> Option<SpecialMemberKind> {
+        self.string_if_present("special_member")
+            .map(|kind| match kind.as_str() {
+                "default_ctor" => SpecialMemberKind::DefaultConstructor,
+                "copy_ctor" => SpecialMemberKind::CopyConstructor,
+                "move_ctor" => SpecialMemberKind::MoveConstructor,
+                "dtor" => SpecialMemberKind::Destructor,
+                "assignment_operator" => SpecialMemberKind::AssignmentOperator,
+                _ => panic!("unexpected special_member_kind"),
+            })
+    }
+
+    /// Any reference parameters or return values.
+    pub(super) fn get_reference_parameters_and_return(&self) -> References {
+        let mut results = References::default();
+        for a in &self.0 {
+            if a.is_ident("ret_type_reference") {
+                results.ref_return = true;
+            } else if a.is_ident("ret_type_rvalue_reference") {
+                results.rvalue_ref_return = true;
+            } else if a.is_ident("arg_type_reference") {
+                let r: Result<Ident, syn::Error> = a.parse_args();
+                if let Ok(ls) = r {
+                    results.ref_params.insert(ls);
+                }
+            } else if a.is_ident("arg_type_rvalue_reference") {
+                let r: Result<Ident, syn::Error> = a.parse_args();
+                if let Ok(ls) = r {
+                    results.rvalue_ref_params.insert(ls);
+                }
+            }
+        }
+        results
+    }
+}
+
+#[derive(Debug)]
+struct BindgenSemanticAttribute {
+    annotation_name: Ident,
+    body: Option<TokenStream>,
+}
+
+impl BindgenSemanticAttribute {
+    fn is_ident(&self, name: &str) -> bool {
+        self.annotation_name == name
+    }
+
+    fn parse_args<T: Parse>(&self) -> Result<T, syn::Error> {
+        T::parse.parse2(self.body.as_ref().unwrap().clone())
+    }
+}
+
+impl Parse for BindgenSemanticAttribute {
+    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
+        let annotation_name: Ident = input.parse()?;
+        if input.peek(syn::token::Paren) {
+            let body_contents;
+            parenthesized!(body_contents in input);
+            Ok(Self {
+                annotation_name,
+                body: Some(body_contents.parse()?),
+            })
+        } else if !input.is_empty() {
+            Err(input.error("expected nothing"))
+        } else {
+            Ok(Self {
+                annotation_name,
+                body: None,
+            })
+        }
+    }
+}
diff --git a/engine/src/conversion/parse/mod.rs b/engine/src/conversion/parse/mod.rs
new file mode 100644
index 0000000..3f42ce4
--- /dev/null
+++ b/engine/src/conversion/parse/mod.rs
@@ -0,0 +1,14 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod bindgen_semantic_attributes;
+mod parse_bindgen;
+mod parse_foreign_mod;
+
+pub(crate) use bindgen_semantic_attributes::BindgenSemanticAttributes;
+pub(crate) use parse_bindgen::ParseBindgen;
diff --git a/engine/src/conversion/parse/parse_bindgen.rs b/engine/src/conversion/parse/parse_bindgen.rs
new file mode 100644
index 0000000..0818aa5
--- /dev/null
+++ b/engine/src/conversion/parse/parse_bindgen.rs
@@ -0,0 +1,388 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+use indexmap::set::IndexSet as HashSet;
+
+use crate::{
+    conversion::{
+        api::{Api, ApiName, NullPhase, StructDetails, SubclassName, TypedefKind, UnanalyzedApi},
+        apivec::ApiVec,
+        ConvertError,
+    },
+    types::Namespace,
+    types::QualifiedName,
+};
+use crate::{
+    conversion::{
+        convert_error::{ConvertErrorWithContext, ErrorContext},
+        error_reporter::report_any_error,
+    },
+    types::validate_ident_ok_for_cxx,
+};
+use autocxx_parser::{IncludeCppConfig, RustPath};
+use syn::{parse_quote, Fields, Ident, Item, Type, TypePath, UseTree};
+
+use super::{
+    super::utilities::generate_utilities, bindgen_semantic_attributes::BindgenSemanticAttributes,
+};
+
+use super::parse_foreign_mod::ParseForeignMod;
+
+/// Parses a bindgen mod in order to understand the APIs within it.
+pub(crate) struct ParseBindgen<'a> {
+    config: &'a IncludeCppConfig,
+    apis: ApiVec<NullPhase>,
+}
+
+fn api_name(ns: &Namespace, id: Ident, attrs: &BindgenSemanticAttributes) -> ApiName {
+    ApiName::new_with_cpp_name(ns, id, attrs.get_original_name())
+}
+
+pub(crate) fn api_name_qualified(
+    ns: &Namespace,
+    id: Ident,
+    attrs: &BindgenSemanticAttributes,
+) -> Result<ApiName, ConvertErrorWithContext> {
+    match validate_ident_ok_for_cxx(&id.to_string()) {
+        Err(e) => {
+            let ctx = ErrorContext::new_for_item(id);
+            Err(ConvertErrorWithContext(e, Some(ctx)))
+        }
+        Ok(..) => Ok(api_name(ns, id, attrs)),
+    }
+}
+
+impl<'a> ParseBindgen<'a> {
+    pub(crate) fn new(config: &'a IncludeCppConfig) -> Self {
+        ParseBindgen {
+            config,
+            apis: ApiVec::new(),
+        }
+    }
+
+    /// Parses items found in the `bindgen` output and returns a set of
+    /// `Api`s together with some other data.
+    pub(crate) fn parse_items(
+        mut self,
+        items: Vec<Item>,
+    ) -> Result<ApiVec<NullPhase>, ConvertError> {
+        let items = Self::find_items_in_root(items)?;
+        if !self.config.exclude_utilities() {
+            generate_utilities(&mut self.apis, self.config);
+        }
+        self.add_apis_from_config();
+        let root_ns = Namespace::new();
+        self.parse_mod_items(items, root_ns);
+        self.confirm_all_generate_directives_obeyed()?;
+        self.replace_extern_cpp_types();
+        Ok(self.apis)
+    }
+
+    /// Some API items are not populated from bindgen output, but instead
+    /// directly from items in the config.
+    fn add_apis_from_config(&mut self) {
+        self.apis
+            .extend(self.config.subclasses.iter().map(|sc| Api::Subclass {
+                name: SubclassName::new(sc.subclass.clone()),
+                superclass: QualifiedName::new_from_cpp_name(&sc.superclass),
+            }));
+        self.apis
+            .extend(self.config.extern_rust_funs.iter().map(|fun| {
+                let id = fun.sig.ident.clone();
+                Api::RustFn {
+                    name: ApiName::new_in_root_namespace(id),
+                    details: fun.clone(),
+                    receiver: fun.receiver.as_ref().map(|receiver_id| {
+                        QualifiedName::new(&Namespace::new(), receiver_id.clone())
+                    }),
+                }
+            }));
+        let unique_rust_types: HashSet<&RustPath> = self.config.rust_types.iter().collect();
+        self.apis.extend(unique_rust_types.into_iter().map(|path| {
+            let id = path.get_final_ident();
+            Api::RustType {
+                name: ApiName::new_in_root_namespace(id.clone()),
+                path: path.clone(),
+            }
+        }));
+        self.apis.extend(
+            self.config
+                .concretes
+                .0
+                .iter()
+                .map(|(cpp_definition, rust_id)| {
+                    let name = ApiName::new_in_root_namespace(rust_id.clone());
+                    Api::ConcreteType {
+                        name,
+                        cpp_definition: cpp_definition.clone(),
+                        rs_definition: None,
+                    }
+                }),
+        );
+    }
+
+    /// We do this last, _after_ we've parsed all the APIs, because we might want to actually
+    /// replace some of the existing APIs (structs/enums/etc.) with replacements.
+    fn replace_extern_cpp_types(&mut self) {
+        let pod_requests: HashSet<_> = self.config.get_pod_requests().iter().collect();
+        let replacements: HashMap<_, _> = self
+            .config
+            .externs
+            .0
+            .iter()
+            .map(|(cpp_definition, details)| {
+                let qn = QualifiedName::new_from_cpp_name(cpp_definition);
+                let pod = pod_requests.contains(&qn.to_cpp_name());
+                (
+                    qn.clone(),
+                    Api::ExternCppType {
+                        name: ApiName::new_from_qualified_name(qn),
+                        details: details.clone(),
+                        pod,
+                    },
+                )
+            })
+            .collect();
+        self.apis
+            .retain(|api| !replacements.contains_key(api.name()));
+        self.apis.extend(replacements.into_iter().map(|(_, v)| v));
+    }
+
+    fn find_items_in_root(items: Vec<Item>) -> Result<Vec<Item>, ConvertError> {
+        for item in items {
+            match item {
+                Item::Mod(root_mod) => {
+                    // With namespaces enabled, bindgen always puts everything
+                    // in a mod called 'root'. We don't want to pass that
+                    // onto cxx, so jump right into it.
+                    assert!(root_mod.ident == "root");
+                    if let Some((_, items)) = root_mod.content {
+                        return Ok(items);
+                    }
+                }
+                _ => return Err(ConvertError::UnexpectedOuterItem),
+            }
+        }
+        Ok(Vec::new())
+    }
+
+    /// Interpret the bindgen-generated .rs for a particular
+    /// mod, which corresponds to a C++ namespace.
+    fn parse_mod_items(&mut self, items: Vec<Item>, ns: Namespace) {
+        // This object maintains some state specific to this namespace, i.e.
+        // this particular mod.
+        let mut mod_converter = ParseForeignMod::new(ns.clone());
+        let mut more_apis = ApiVec::new();
+        for item in items {
+            report_any_error(&ns, &mut more_apis, || {
+                self.parse_item(item, &mut mod_converter, &ns)
+            });
+        }
+        self.apis.append(&mut more_apis);
+        mod_converter.finished(&mut self.apis);
+    }
+
+    fn parse_item(
+        &mut self,
+        item: Item,
+        mod_converter: &mut ParseForeignMod,
+        ns: &Namespace,
+    ) -> Result<(), ConvertErrorWithContext> {
+        match item {
+            Item::ForeignMod(fm) => {
+                mod_converter.convert_foreign_mod_items(fm.items);
+                Ok(())
+            }
+            Item::Struct(s) => {
+                if s.ident.to_string().ends_with("__bindgen_vtable") {
+                    return Ok(());
+                }
+                let annotations = BindgenSemanticAttributes::new(&s.attrs);
+                // cxx::bridge can't cope with type aliases to generic
+                // types at the moment.
+                let name = api_name_qualified(ns, s.ident.clone(), &annotations)?;
+                let err = annotations.check_for_fatal_attrs(&s.ident).err();
+                let api = if ns.is_empty() && self.config.is_rust_type(&s.ident) {
+                    None
+                } else if Self::spot_forward_declaration(&s.fields)
+                    || (Self::spot_zero_length_struct(&s.fields) && err.is_some())
+                {
+                    // Forward declarations are recorded especially because we can't
+                    // store them in UniquePtr or similar.
+                    // Templated forward declarations don't appear with an _unused field (which is what
+                    // we spot in the previous clause) but instead with an _address field.
+                    // So, solely in the case where we're storing up an error about such
+                    // a templated type, we'll also treat such cases as forward declarations.
+                    Some(UnanalyzedApi::ForwardDeclaration { name, err })
+                } else {
+                    let has_rvalue_reference_fields = s.fields.iter().any(|f| {
+                        BindgenSemanticAttributes::new(&f.attrs).has_attr("rvalue_reference")
+                    });
+                    Some(UnanalyzedApi::Struct {
+                        name,
+                        details: Box::new(StructDetails {
+                            vis: annotations.get_cpp_visibility(),
+                            layout: annotations.get_layout(),
+                            item: s,
+                            has_rvalue_reference_fields,
+                        }),
+                        analysis: (),
+                    })
+                };
+                if let Some(api) = api {
+                    if !self.config.is_on_blocklist(&api.name().to_cpp_name()) {
+                        self.apis.push(api);
+                    }
+                }
+                Ok(())
+            }
+            Item::Enum(e) => {
+                let annotations = BindgenSemanticAttributes::new(&e.attrs);
+                let api = UnanalyzedApi::Enum {
+                    name: api_name_qualified(ns, e.ident.clone(), &annotations)?,
+                    item: e,
+                };
+                if !self.config.is_on_blocklist(&api.name().to_cpp_name()) {
+                    self.apis.push(api);
+                }
+                Ok(())
+            }
+            Item::Impl(imp) => {
+                // We *mostly* ignore all impl blocks generated by bindgen.
+                // Methods also appear in 'extern "C"' blocks which
+                // we will convert instead. At that time we'll also construct
+                // synthetic impl blocks.
+                // We do however record which methods were spotted, since
+                // we have no other way of working out which functions are
+                // static methods vs plain functions.
+                mod_converter.convert_impl_items(imp);
+                Ok(())
+            }
+            Item::Mod(itm) => {
+                if let Some((_, items)) = itm.content {
+                    let new_ns = ns.push(itm.ident.to_string());
+                    self.parse_mod_items(items, new_ns);
+                }
+                Ok(())
+            }
+            Item::Use(use_item) => {
+                let mut segs = Vec::new();
+                let mut tree = &use_item.tree;
+                loop {
+                    match tree {
+                        UseTree::Path(up) => {
+                            segs.push(up.ident.clone());
+                            tree = &up.tree;
+                        }
+                        UseTree::Name(un) if un.ident == "root" => break, // we do not add this to any API since we generate equivalent
+                        // use statements in our codegen phase.
+                        UseTree::Rename(urn) => {
+                            let old_id = &urn.ident;
+                            let new_id = &urn.rename;
+                            let new_tyname = QualifiedName::new(ns, new_id.clone());
+                            assert!(segs.remove(0) == "self", "Path didn't start with self");
+                            assert!(
+                                segs.remove(0) == "super",
+                                "Path didn't start with self::super"
+                            );
+                            // This is similar to the path encountered within 'tree'
+                            // but without the self::super prefix which is unhelpful
+                            // in our output mod, because we prefer relative paths
+                            // (we're nested in another mod)
+                            let old_path: TypePath = parse_quote! {
+                                #(#segs)::* :: #old_id
+                            };
+                            let old_tyname = QualifiedName::from_type_path(&old_path);
+                            if new_tyname == old_tyname {
+                                return Err(ConvertErrorWithContext(
+                                    ConvertError::InfinitelyRecursiveTypedef(new_tyname),
+                                    Some(ErrorContext::new_for_item(new_id.clone())),
+                                ));
+                            }
+                            let annotations = BindgenSemanticAttributes::new(&use_item.attrs);
+                            self.apis.push(UnanalyzedApi::Typedef {
+                                name: api_name(ns, new_id.clone(), &annotations),
+                                item: TypedefKind::Use(
+                                    parse_quote! {
+                                        pub use #old_path as #new_id;
+                                    },
+                                    Box::new(Type::Path(old_path)),
+                                ),
+                                old_tyname: Some(old_tyname),
+                                analysis: (),
+                            });
+                            break;
+                        }
+                        _ => {
+                            return Err(ConvertErrorWithContext(
+                                ConvertError::UnexpectedUseStatement(
+                                    segs.into_iter().last().map(|i| i.to_string()),
+                                ),
+                                None,
+                            ))
+                        }
+                    }
+                }
+                Ok(())
+            }
+            Item::Const(const_item) => {
+                let annotations = BindgenSemanticAttributes::new(&const_item.attrs);
+                self.apis.push(UnanalyzedApi::Const {
+                    name: api_name(ns, const_item.ident.clone(), &annotations),
+                    const_item,
+                });
+                Ok(())
+            }
+            Item::Type(ity) => {
+                let annotations = BindgenSemanticAttributes::new(&ity.attrs);
+                // It's known that sometimes bindgen will give us duplicate typedefs with the
+                // same name - see test_issue_264.
+                self.apis.push(UnanalyzedApi::Typedef {
+                    name: api_name(ns, ity.ident.clone(), &annotations),
+                    item: TypedefKind::Type(ity),
+                    old_tyname: None,
+                    analysis: (),
+                });
+                Ok(())
+            }
+            _ => Err(ConvertErrorWithContext(
+                ConvertError::UnexpectedItemInMod,
+                None,
+            )),
+        }
+    }
+
+    fn spot_forward_declaration(s: &Fields) -> bool {
+        Self::spot_field(s, "_unused")
+    }
+
+    fn spot_zero_length_struct(s: &Fields) -> bool {
+        Self::spot_field(s, "_address")
+    }
+
+    fn spot_field(s: &Fields, desired_id: &str) -> bool {
+        s.iter()
+            .filter_map(|f| f.ident.as_ref())
+            .any(|id| id == desired_id)
+    }
+
+    fn confirm_all_generate_directives_obeyed(&self) -> Result<(), ConvertError> {
+        let api_names: HashSet<_> = self
+            .apis
+            .iter()
+            .map(|api| api.name().to_cpp_name())
+            .collect();
+        for generate_directive in self.config.must_generate_list() {
+            if !api_names.contains(&generate_directive) {
+                return Err(ConvertError::DidNotGenerateAnything(generate_directive));
+            }
+        }
+        Ok(())
+    }
+}
diff --git a/engine/src/conversion/parse/parse_foreign_mod.rs b/engine/src/conversion/parse/parse_foreign_mod.rs
new file mode 100644
index 0000000..08c1fd8
--- /dev/null
+++ b/engine/src/conversion/parse/parse_foreign_mod.rs
@@ -0,0 +1,177 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::conversion::api::{ApiName, NullPhase, Provenance};
+use crate::conversion::apivec::ApiVec;
+use crate::conversion::doc_attr::get_doc_attrs;
+use crate::conversion::error_reporter::report_any_error;
+use crate::conversion::{
+    api::{FuncToConvert, UnanalyzedApi},
+    convert_error::ConvertErrorWithContext,
+    convert_error::ErrorContext,
+};
+use crate::{
+    conversion::ConvertError,
+    types::{Namespace, QualifiedName},
+};
+use std::collections::HashMap;
+use syn::{Block, Expr, ExprCall, ForeignItem, Ident, ImplItem, ItemImpl, Stmt, Type};
+
+use super::bindgen_semantic_attributes::BindgenSemanticAttributes;
+
+/// Parses a given bindgen-generated 'mod' into suitable
+/// [Api]s. In bindgen output, a given mod concerns
+/// a specific C++ namespace.
+pub(crate) struct ParseForeignMod {
+    ns: Namespace,
+    // We mostly act upon the functions we see within the 'extern "C"'
+    // block of bindgen output, but we can't actually do this until
+    // we've seen the (possibly subsequent) 'impl' blocks so we can
+    // deduce which functions are actually static methods. Hence
+    // store them.
+    funcs_to_convert: Vec<FuncToConvert>,
+    // Evidence from 'impl' blocks about which of these items
+    // may actually be methods (static or otherwise). Mapping from
+    // function name to type name.
+    method_receivers: HashMap<Ident, QualifiedName>,
+    ignored_apis: ApiVec<NullPhase>,
+}
+
+impl ParseForeignMod {
+    pub(crate) fn new(ns: Namespace) -> Self {
+        Self {
+            ns,
+            funcs_to_convert: Vec::new(),
+            method_receivers: HashMap::new(),
+            ignored_apis: ApiVec::new(),
+        }
+    }
+
+    /// Record information from foreign mod items encountered
+    /// in bindgen output.
+    pub(crate) fn convert_foreign_mod_items(&mut self, foreign_mod_items: Vec<ForeignItem>) {
+        let mut extra_apis = ApiVec::new();
+        for i in foreign_mod_items {
+            report_any_error(&self.ns.clone(), &mut extra_apis, || {
+                self.parse_foreign_item(i)
+            });
+        }
+        self.ignored_apis.append(&mut extra_apis);
+    }
+
+    fn parse_foreign_item(&mut self, i: ForeignItem) -> Result<(), ConvertErrorWithContext> {
+        match i {
+            ForeignItem::Fn(item) => {
+                let annotations = BindgenSemanticAttributes::new(&item.attrs);
+                let doc_attrs = get_doc_attrs(&item.attrs);
+                self.funcs_to_convert.push(FuncToConvert {
+                    provenance: Provenance::Bindgen,
+                    self_ty: None,
+                    ident: item.sig.ident,
+                    doc_attrs,
+                    inputs: item.sig.inputs,
+                    output: item.sig.output,
+                    vis: item.vis,
+                    virtualness: annotations.get_virtualness(),
+                    cpp_vis: annotations.get_cpp_visibility(),
+                    special_member: annotations.special_member_kind(),
+                    unused_template_param: annotations
+                        .has_attr("incomprehensible_param_in_arg_or_return"),
+                    references: annotations.get_reference_parameters_and_return(),
+                    original_name: annotations.get_original_name(),
+                    synthesized_this_type: None,
+                    add_to_trait: None,
+                    is_deleted: annotations.has_attr("deleted"),
+                    synthetic_cpp: None,
+                    variadic: item.sig.variadic.is_some(),
+                });
+                Ok(())
+            }
+            ForeignItem::Static(item) => Err(ConvertErrorWithContext(
+                ConvertError::StaticData(item.ident.to_string()),
+                Some(ErrorContext::new_for_item(item.ident)),
+            )),
+            _ => Err(ConvertErrorWithContext(
+                ConvertError::UnexpectedForeignItem,
+                None,
+            )),
+        }
+    }
+
+    /// Record information from impl blocks encountered in bindgen
+    /// output.
+    pub(crate) fn convert_impl_items(&mut self, imp: ItemImpl) {
+        let ty_id = match *imp.self_ty {
+            Type::Path(typ) => typ.path.segments.last().unwrap().ident.clone(),
+            _ => return,
+        };
+        for i in imp.items {
+            if let ImplItem::Method(itm) = i {
+                let effective_fun_name = match get_called_function(&itm.block) {
+                    Some(id) => id.clone(),
+                    None => itm.sig.ident,
+                };
+                self.method_receivers.insert(
+                    effective_fun_name,
+                    QualifiedName::new(&self.ns, ty_id.clone()),
+                );
+            }
+        }
+    }
+
+    /// Indicate that all foreign mods and all impl blocks have been
+    /// fed into us, and we should process that information to generate
+    /// the resulting APIs.
+    pub(crate) fn finished(mut self, apis: &mut ApiVec<NullPhase>) {
+        apis.append(&mut self.ignored_apis);
+        while !self.funcs_to_convert.is_empty() {
+            let mut fun = self.funcs_to_convert.remove(0);
+            fun.self_ty = self.method_receivers.get(&fun.ident).cloned();
+            apis.push(UnanalyzedApi::Function {
+                name: ApiName::new_with_cpp_name(
+                    &self.ns,
+                    fun.ident.clone(),
+                    fun.original_name.clone(),
+                ),
+                fun: Box::new(fun),
+                analysis: (),
+            })
+        }
+    }
+}
+
+/// bindgen sometimes generates an impl fn called a which calls
+/// a function called a1(), if it's dealing with conflicting names.
+/// We actually care about the name a1, so we have to parse the
+/// name of the actual function call inside the block's body.
+fn get_called_function(block: &Block) -> Option<&Ident> {
+    match block.stmts.first() {
+        Some(Stmt::Expr(Expr::Call(ExprCall { func, .. }))) => match **func {
+            Expr::Path(ref exp) => exp.path.segments.first().map(|ps| &ps.ident),
+            _ => None,
+        },
+        _ => None,
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::get_called_function;
+    use syn::parse_quote;
+    use syn::Block;
+
+    #[test]
+    fn test_get_called_function() {
+        let b: Block = parse_quote! {
+            {
+                call_foo()
+            }
+        };
+        assert_eq!(get_called_function(&b).unwrap().to_string(), "call_foo");
+    }
+}
diff --git a/engine/src/conversion/utilities.rs b/engine/src/conversion/utilities.rs
new file mode 100644
index 0000000..b90b365
--- /dev/null
+++ b/engine/src/conversion/utilities.rs
@@ -0,0 +1,30 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx_parser::IncludeCppConfig;
+
+use super::{
+    api::{ApiName, NullPhase, UnanalyzedApi},
+    apivec::ApiVec,
+};
+use crate::types::{make_ident, Namespace};
+
+/// Adds items which we always add, cos they're useful.
+/// Any APIs or techniques which do not involve actual C++ interop
+/// shouldn't go here, but instead should go into the main autocxx
+/// src/lib.rs.
+pub(crate) fn generate_utilities(apis: &mut ApiVec<NullPhase>, config: &IncludeCppConfig) {
+    // Unless we've been specifically asked not to do so, we always
+    // generate a 'make_string' function. That pretty much *always* means
+    // we run two passes through bindgen. i.e. the next 'if' is always true,
+    // and we always generate an additional C++ file for our bindings additions,
+    // unless the include_cpp macro has specified ExcludeUtilities.
+    apis.push(UnanalyzedApi::StringConstructor {
+        name: ApiName::new(&Namespace::new(), make_ident(config.get_makestring_name())),
+    });
+}
diff --git a/engine/src/cxxbridge.rs b/engine/src/cxxbridge.rs
new file mode 100644
index 0000000..28163af
--- /dev/null
+++ b/engine/src/cxxbridge.rs
@@ -0,0 +1,45 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use proc_macro2::TokenStream;
+use quote::{ToTokens, TokenStreamExt};
+use syn::ItemMod;
+
+use crate::{do_cxx_cpp_generation, parse_file::CppBuildable, CppCodegenOptions, GeneratedCpp};
+
+/// A struct to represent a cxx::bridge (i.e. some manual bindings)
+/// found in a file. autocxx knows about them so that we can generate C++
+/// for both manual and automatic bindings using the same tooling.
+pub struct CxxBridge {
+    tokens: TokenStream,
+}
+
+impl From<ItemMod> for CxxBridge {
+    fn from(itm: ItemMod) -> Self {
+        Self {
+            tokens: itm.to_token_stream(),
+        }
+    }
+}
+
+impl ToTokens for CxxBridge {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.append_all(self.tokens.clone());
+    }
+}
+
+impl CppBuildable for CxxBridge {
+    fn generate_h_and_cxx(
+        &self,
+        cpp_codegen_options: &CppCodegenOptions,
+    ) -> Result<GeneratedCpp, cxx_gen::Error> {
+        let header_name = cpp_codegen_options.cxxgen_header_namer.name_header();
+        let fp = do_cxx_cpp_generation(self.tokens.clone(), cpp_codegen_options, header_name)?;
+        Ok(GeneratedCpp(vec![fp]))
+    }
+}
diff --git a/engine/src/known_types.rs b/engine/src/known_types.rs
new file mode 100644
index 0000000..377101a
--- /dev/null
+++ b/engine/src/known_types.rs
@@ -0,0 +1,562 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::{
+    conversion::ConvertError,
+    types::{make_ident, QualifiedName},
+};
+use indexmap::map::IndexMap as HashMap;
+use indoc::indoc;
+use once_cell::sync::OnceCell;
+use syn::{parse_quote, Type, TypePath, TypePtr};
+
+//// The behavior of the type.
+#[derive(Debug)]
+enum Behavior {
+    CxxContainerPtr,
+    CxxContainerVector,
+    CxxString,
+    RustStr,
+    RustString,
+    RustByValue,
+    CByValue,
+    CByValueVecSafe,
+    CVariableLengthByValue,
+    CVoid,
+    CChar16,
+    RustContainerByValueSafe,
+}
+
+/// Details about known special types, mostly primitives.
+#[derive(Debug)]
+struct TypeDetails {
+    /// The name used by cxx (in Rust code) for this type.
+    rs_name: String,
+    /// C++ equivalent name for a Rust type.
+    cpp_name: String,
+    /// The behavior of the type.
+    behavior: Behavior,
+    /// Any extra non-canonical names
+    extra_non_canonical_name: Option<String>,
+    has_const_copy_constructor: bool,
+    has_move_constructor: bool,
+}
+
+impl TypeDetails {
+    fn new(
+        rs_name: impl Into<String>,
+        cpp_name: impl Into<String>,
+        behavior: Behavior,
+        extra_non_canonical_name: Option<String>,
+        has_const_copy_constructor: bool,
+        has_move_constructor: bool,
+    ) -> Self {
+        TypeDetails {
+            rs_name: rs_name.into(),
+            cpp_name: cpp_name.into(),
+            behavior,
+            extra_non_canonical_name,
+            has_const_copy_constructor,
+            has_move_constructor,
+        }
+    }
+
+    /// Whether and how to include this in the prelude given to bindgen.
+    fn get_prelude_entry(&self) -> Option<String> {
+        match self.behavior {
+            Behavior::RustString
+            | Behavior::RustStr
+            | Behavior::CxxString
+            | Behavior::CxxContainerPtr
+            | Behavior::CxxContainerVector
+            | Behavior::RustContainerByValueSafe => {
+                let tn = QualifiedName::new_from_cpp_name(&self.rs_name);
+                let cxx_name = tn.get_final_item();
+                let (templating, payload) = match self.behavior {
+                    Behavior::CxxContainerPtr
+                    | Behavior::CxxContainerVector
+                    | Behavior::RustContainerByValueSafe => ("template<typename T> ", "T* ptr"),
+                    _ => ("", "char* ptr"),
+                };
+                Some(format!(
+                    indoc! {"
+                    /**
+                    * <div rustbindgen=\"true\" replaces=\"{}\">
+                    */
+                    {}class {} {{
+                        {};
+                    }};
+                    "},
+                    self.cpp_name, templating, cxx_name, payload
+                ))
+            }
+            _ => None,
+        }
+    }
+
+    fn to_type_path(&self) -> TypePath {
+        let mut segs = self.rs_name.split("::").peekable();
+        if segs.peek().map(|seg| seg.is_empty()).unwrap_or_default() {
+            segs.next();
+            let segs = segs.into_iter().map(make_ident);
+            parse_quote! {
+                ::#(#segs)::*
+            }
+        } else {
+            let segs = segs.into_iter().map(make_ident);
+            parse_quote! {
+                #(#segs)::*
+            }
+        }
+    }
+
+    fn to_typename(&self) -> QualifiedName {
+        QualifiedName::new_from_cpp_name(&self.rs_name)
+    }
+
+    fn get_generic_behavior(&self) -> CxxGenericType {
+        match self.behavior {
+            Behavior::CxxContainerPtr => CxxGenericType::CppPtr,
+            Behavior::CxxContainerVector => CxxGenericType::CppVector,
+            Behavior::RustContainerByValueSafe => CxxGenericType::Rust,
+            _ => CxxGenericType::Not,
+        }
+    }
+}
+
+/// Database of known types.
+#[derive(Default)]
+pub(crate) struct TypeDatabase {
+    by_rs_name: HashMap<QualifiedName, TypeDetails>,
+    canonical_names: HashMap<QualifiedName, QualifiedName>,
+}
+
+/// Returns a database of known types.
+pub(crate) fn known_types() -> &'static TypeDatabase {
+    static KNOWN_TYPES: OnceCell<TypeDatabase> = OnceCell::new();
+    KNOWN_TYPES.get_or_init(create_type_database)
+}
+
+/// The type of payload that a cxx generic can contain.
+#[derive(PartialEq, Clone, Copy)]
+pub enum CxxGenericType {
+    /// Not a generic at all
+    Not,
+    /// Some generic like cxx::UniquePtr where the contents must be a
+    /// complete type.
+    CppPtr,
+    /// Some generic like cxx::Vector where the contents must be a
+    /// complete type, and some types of int are allowed too.
+    CppVector,
+    /// Some generic like rust::Box where forward declarations are OK
+    Rust,
+}
+
+pub struct KnownTypeConstructorDetails {
+    pub has_move_constructor: bool,
+    pub has_const_copy_constructor: bool,
+}
+
+impl TypeDatabase {
+    fn get(&self, ty: &QualifiedName) -> Option<&TypeDetails> {
+        // The following line is important. It says that
+        // when we encounter something like 'std::unique_ptr'
+        // in the bindgen-generated bindings, we'll immediately
+        // start to refer to that as 'UniquePtr' henceforth.
+        let canonical_name = self.canonical_names.get(ty).unwrap_or(ty);
+        self.by_rs_name.get(canonical_name)
+    }
+
+    /// Prelude of C++ for squirting into bindgen. This configures
+    /// bindgen to output simpler types to replace some STL types
+    /// that bindgen just can't cope with. Although we then replace
+    /// those types with cxx types (e.g. UniquePtr), this intermediate
+    /// step is still necessary because bindgen can't otherwise
+    /// give us the templated types (e.g. when faced with the STL
+    /// unique_ptr, bindgen would normally give us std_unique_ptr
+    /// as opposed to std_unique_ptr<T>.)
+    pub(crate) fn get_prelude(&self) -> String {
+        itertools::join(
+            self.by_rs_name
+                .values()
+                .filter_map(|t| t.get_prelude_entry()),
+            "",
+        )
+    }
+
+    /// Returns all known types.
+    pub(crate) fn all_names(&self) -> impl Iterator<Item = &QualifiedName> {
+        self.canonical_names.keys().chain(self.by_rs_name.keys())
+    }
+
+    /// Types which are known to be safe (or unsafe) to hold and pass by
+    /// value in Rust.
+    pub(crate) fn get_pod_safe_types(&self) -> impl Iterator<Item = (QualifiedName, bool)> {
+        let pod_safety = self
+            .all_names()
+            .map(|tn| {
+                (
+                    tn.clone(),
+                    match self.get(tn).unwrap().behavior {
+                        Behavior::CxxContainerPtr
+                        | Behavior::RustStr
+                        | Behavior::RustString
+                        | Behavior::RustByValue
+                        | Behavior::CByValueVecSafe
+                        | Behavior::CByValue
+                        | Behavior::CVariableLengthByValue
+                        | Behavior::CChar16
+                        | Behavior::RustContainerByValueSafe => true,
+                        Behavior::CxxString | Behavior::CxxContainerVector | Behavior::CVoid => {
+                            false
+                        }
+                    },
+                )
+            })
+            .collect::<HashMap<_, _>>();
+        pod_safety.into_iter()
+    }
+
+    pub(crate) fn get_constructor_details(
+        &self,
+        qn: &QualifiedName,
+    ) -> Option<KnownTypeConstructorDetails> {
+        self.get(qn).map(|x| KnownTypeConstructorDetails {
+            has_move_constructor: x.has_move_constructor,
+            has_const_copy_constructor: x.has_const_copy_constructor,
+        })
+    }
+
+    /// Whether this TypePath should be treated as a value in C++
+    /// but a reference in Rust. This only applies to rust::Str
+    /// (C++ name) which is &str in Rust.
+    pub(crate) fn should_dereference_in_cpp(&self, tn: &QualifiedName) -> bool {
+        self.get(tn)
+            .map(|td| matches!(td.behavior, Behavior::RustStr))
+            .unwrap_or(false)
+    }
+
+    /// Whether this can only be passed around using `std::move`
+    pub(crate) fn lacks_copy_constructor(&self, tn: &QualifiedName) -> bool {
+        self.get(tn)
+            .map(|td| {
+                matches!(
+                    td.behavior,
+                    Behavior::CxxContainerPtr | Behavior::CxxContainerVector
+                )
+            })
+            .unwrap_or(false)
+    }
+
+    /// Here we substitute any names which we know are Special from
+    /// our type database, e.g. std::unique_ptr -> UniquePtr.
+    /// We strip off and ignore
+    /// any PathArguments within this TypePath - callers should
+    /// put them back again if needs be.
+    pub(crate) fn consider_substitution(&self, tn: &QualifiedName) -> Option<TypePath> {
+        self.get(tn).map(|td| td.to_type_path())
+    }
+
+    pub(crate) fn special_cpp_name(&self, rs: &QualifiedName) -> Option<String> {
+        self.get(rs).map(|x| x.cpp_name.to_string())
+    }
+
+    pub(crate) fn is_known_type(&self, ty: &QualifiedName) -> bool {
+        self.get(ty).is_some()
+    }
+
+    pub(crate) fn known_type_type_path(&self, ty: &QualifiedName) -> Option<TypePath> {
+        self.get(ty).map(|td| td.to_type_path())
+    }
+
+    /// Get the list of types to give to bindgen to ask it _not_ to
+    /// generate code for.
+    pub(crate) fn get_initial_blocklist(&self) -> impl Iterator<Item = &str> + '_ {
+        self.by_rs_name
+            .iter()
+            .filter_map(|(_, td)| td.get_prelude_entry().map(|_| td.cpp_name.as_str()))
+    }
+
+    /// Whether this is one of the ctypes (mostly variable length integers)
+    /// which we need to wrap.
+    pub(crate) fn is_ctype(&self, ty: &QualifiedName) -> bool {
+        self.get(ty)
+            .map(|td| {
+                matches!(
+                    td.behavior,
+                    Behavior::CVariableLengthByValue | Behavior::CVoid | Behavior::CChar16
+                )
+            })
+            .unwrap_or(false)
+    }
+
+    /// Whether this is a generic type acceptable to cxx. Otherwise,
+    /// if we encounter a generic, we'll replace it with a synthesized concrete
+    /// type.
+    pub(crate) fn cxx_generic_behavior(&self, ty: &QualifiedName) -> CxxGenericType {
+        self.get(ty)
+            .map(|x| x.get_generic_behavior())
+            .unwrap_or(CxxGenericType::Not)
+    }
+
+    pub(crate) fn is_cxx_acceptable_receiver(&self, ty: &QualifiedName) -> bool {
+        self.get(ty).is_none() // at present, none of our known types can have
+                               // methods attached.
+    }
+
+    pub(crate) fn permissible_within_vector(&self, ty: &QualifiedName) -> bool {
+        self.get(ty)
+            .map(|x| matches!(x.behavior, Behavior::CxxString | Behavior::CByValueVecSafe))
+            .unwrap_or(true)
+    }
+
+    pub(crate) fn permissible_within_unique_ptr(&self, ty: &QualifiedName) -> bool {
+        self.get(ty)
+            .map(|x| {
+                matches!(
+                    x.behavior,
+                    Behavior::CxxString | Behavior::CxxContainerVector
+                )
+            })
+            .unwrap_or(true)
+    }
+
+    pub(crate) fn conflicts_with_built_in_type(&self, ty: &QualifiedName) -> bool {
+        self.get(ty).is_some()
+    }
+
+    pub(crate) fn convertible_from_strs(&self, ty: &QualifiedName) -> bool {
+        self.get(ty)
+            .map(|x| matches!(x.behavior, Behavior::CxxString))
+            .unwrap_or(false)
+    }
+
+    fn insert(&mut self, td: TypeDetails) {
+        let rs_name = td.to_typename();
+        if let Some(extra_non_canonical_name) = &td.extra_non_canonical_name {
+            self.canonical_names.insert(
+                QualifiedName::new_from_cpp_name(extra_non_canonical_name),
+                rs_name.clone(),
+            );
+        }
+        self.canonical_names.insert(
+            QualifiedName::new_from_cpp_name(&td.cpp_name),
+            rs_name.clone(),
+        );
+        self.by_rs_name.insert(rs_name, td);
+    }
+
+    pub(crate) fn get_moveit_safe_types(&self) -> impl Iterator<Item = QualifiedName> + '_ {
+        self.all_names()
+            .filter(|tn| {
+                !matches!(
+                    self.get(tn).unwrap().behavior,
+                    Behavior::CxxString | Behavior::CxxContainerVector
+                )
+            })
+            .cloned()
+    }
+}
+
+fn create_type_database() -> TypeDatabase {
+    let mut db = TypeDatabase::default();
+    db.insert(TypeDetails::new(
+        "cxx::UniquePtr",
+        "std::unique_ptr",
+        Behavior::CxxContainerPtr,
+        None,
+        false,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "cxx::CxxVector",
+        "std::vector",
+        Behavior::CxxContainerVector,
+        None,
+        false,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "cxx::SharedPtr",
+        "std::shared_ptr",
+        Behavior::CxxContainerPtr,
+        None,
+        true,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "cxx::WeakPtr",
+        "std::weak_ptr",
+        Behavior::CxxContainerPtr,
+        None,
+        true,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "cxx::CxxString",
+        "std::string",
+        Behavior::CxxString,
+        None,
+        true,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "str",
+        "rust::Str",
+        Behavior::RustStr,
+        None,
+        true,
+        false,
+    ));
+    db.insert(TypeDetails::new(
+        "String",
+        "rust::String",
+        Behavior::RustString,
+        None,
+        true,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "std::boxed::Box",
+        "rust::Box",
+        Behavior::RustContainerByValueSafe,
+        None,
+        false,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "i8",
+        "int8_t",
+        Behavior::CByValueVecSafe,
+        Some("std::os::raw::c_schar".into()),
+        true,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "u8",
+        "uint8_t",
+        Behavior::CByValueVecSafe,
+        Some("std::os::raw::c_uchar".into()),
+        true,
+        true,
+    ));
+    for (cpp_type, rust_type) in (4..7).map(|x| 2i32.pow(x)).flat_map(|x| {
+        vec![
+            (format!("uint{}_t", x), format!("u{}", x)),
+            (format!("int{}_t", x), format!("i{}", x)),
+        ]
+    }) {
+        db.insert(TypeDetails::new(
+            rust_type,
+            cpp_type,
+            Behavior::CByValueVecSafe,
+            None,
+            true,
+            true,
+        ));
+    }
+    db.insert(TypeDetails::new(
+        "bool",
+        "bool",
+        Behavior::CByValue,
+        None,
+        true,
+        true,
+    ));
+
+    db.insert(TypeDetails::new(
+        "std::pin::Pin",
+        "Pin",
+        Behavior::RustByValue, // because this is actually Pin<&something>
+        None,
+        true,
+        false,
+    ));
+
+    let mut insert_ctype = |cname: &str| {
+        let concatenated_name = cname.replace(' ', "");
+        db.insert(TypeDetails::new(
+            format!("autocxx::c_{}", concatenated_name),
+            cname,
+            Behavior::CVariableLengthByValue,
+            Some(format!("std::os::raw::c_{}", concatenated_name)),
+            true,
+            true,
+        ));
+        db.insert(TypeDetails::new(
+            format!("autocxx::c_u{}", concatenated_name),
+            format!("unsigned {}", cname),
+            Behavior::CVariableLengthByValue,
+            Some(format!("std::os::raw::c_u{}", concatenated_name)),
+            true,
+            true,
+        ));
+    };
+
+    insert_ctype("long");
+    insert_ctype("int");
+    insert_ctype("short");
+    insert_ctype("long long");
+
+    db.insert(TypeDetails::new(
+        "f32",
+        "float",
+        Behavior::CByValueVecSafe,
+        None,
+        true,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "f64",
+        "double",
+        Behavior::CByValueVecSafe,
+        None,
+        true,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "::std::os::raw::c_char",
+        "char",
+        Behavior::CByValue,
+        None,
+        true,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "usize",
+        "size_t",
+        Behavior::CByValueVecSafe,
+        None,
+        true,
+        true,
+    ));
+    db.insert(TypeDetails::new(
+        "autocxx::c_void",
+        "void",
+        Behavior::CVoid,
+        Some("std::os::raw::c_void".into()),
+        false,
+        false,
+    ));
+    db.insert(TypeDetails::new(
+        "autocxx::c_char16_t",
+        "char16_t",
+        Behavior::CChar16,
+        Some("c_char16_t".into()),
+        false,
+        false,
+    ));
+    db
+}
+
+pub(crate) fn ensure_pointee_is_valid(ptr: &TypePtr) -> Result<(), ConvertError> {
+    match *ptr.elem {
+        Type::Path(..) => Ok(()),
+        _ => Err(ConvertError::InvalidPointee),
+    }
+}
diff --git a/engine/src/lib.rs b/engine/src/lib.rs
new file mode 100644
index 0000000..4edc4a4
--- /dev/null
+++ b/engine/src/lib.rs
@@ -0,0 +1,735 @@
+//! The core of the `autocxx` engine, used by both the
+//! `autocxx_macro` and also code generators (e.g. `autocxx_build`).
+//! See [IncludeCppEngine] for general description of how this engine works.
+
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This feature=nightly could be set by build.rs, but since we only care
+// about it for docs, we ask docs.rs to set it in the Cargo.toml.
+#![cfg_attr(feature = "nightly", feature(doc_cfg))]
+#![forbid(unsafe_code)]
+
+mod ast_discoverer;
+mod conversion;
+mod cxxbridge;
+mod known_types;
+mod output_generators;
+mod parse_callbacks;
+mod parse_file;
+mod rust_pretty_printer;
+mod types;
+
+#[cfg(any(test, feature = "build"))]
+mod builder;
+
+use autocxx_parser::{IncludeCppConfig, UnsafePolicy};
+use conversion::BridgeConverter;
+use miette::{SourceOffset, SourceSpan};
+use parse_callbacks::AutocxxParseCallbacks;
+use parse_file::CppBuildable;
+use proc_macro2::TokenStream as TokenStream2;
+use regex::Regex;
+use std::path::PathBuf;
+use std::{
+    fs::File,
+    io::prelude::*,
+    path::Path,
+    process::{Command, Stdio},
+};
+use tempfile::NamedTempFile;
+
+use quote::ToTokens;
+use syn::Result as ParseResult;
+use syn::{
+    parse::{Parse, ParseStream},
+    parse_quote, ItemMod, Macro,
+};
+use thiserror::Error;
+
+use itertools::{join, Itertools};
+use known_types::known_types;
+use log::info;
+use miette::Diagnostic;
+
+/// We use a forked version of bindgen - for now.
+/// We hope to unfork.
+use autocxx_bindgen as bindgen;
+
+#[cfg(any(test, feature = "build"))]
+pub use builder::{
+    Builder, BuilderBuild, BuilderContext, BuilderError, BuilderResult, BuilderSuccess,
+};
+pub use output_generators::{generate_rs_archive, generate_rs_single, RsOutput};
+pub use parse_file::{parse_file, ParseError, ParsedFile};
+
+pub use cxx_gen::HEADER;
+
+#[derive(Clone)]
+/// Some C++ content which should be written to disk and built.
+pub struct CppFilePair {
+    /// Declarations to go into a header file.
+    pub header: Vec<u8>,
+    /// Implementations to go into a .cpp file.
+    pub implementation: Option<Vec<u8>>,
+    /// The name which should be used for the header file
+    /// (important as it may be `#include`d elsewhere)
+    pub header_name: String,
+}
+
+/// All generated C++ content which should be written to disk.
+pub struct GeneratedCpp(pub Vec<CppFilePair>);
+
+/// A [`syn::Error`] which also implements [`miette::Diagnostic`] so can be pretty-printed
+/// to show the affected span of code.
+#[derive(Error, Debug, Diagnostic)]
+#[error("{err}")]
+pub struct LocatedSynError {
+    err: syn::Error,
+    #[source_code]
+    file: String,
+    #[label("error here")]
+    span: SourceSpan,
+}
+
+impl LocatedSynError {
+    fn new(err: syn::Error, file: &str) -> Self {
+        let span = proc_macro_span_to_miette_span(&err.span());
+        Self {
+            err,
+            file: file.to_string(),
+            span,
+        }
+    }
+}
+
+/// Errors which may occur in generating bindings for these C++
+/// functions.
+#[derive(Debug, Error, Diagnostic)]
+pub enum Error {
+    #[error("Bindgen was unable to generate the initial .rs bindings for this file. This may indicate a parsing problem with the C++ headers.")]
+    Bindgen(()),
+    #[error(transparent)]
+    #[diagnostic(transparent)]
+    MacroParsing(LocatedSynError),
+    #[error(transparent)]
+    #[diagnostic(transparent)]
+    BindingsParsing(LocatedSynError),
+    #[error("no C++ include directory was provided.")]
+    NoAutoCxxInc,
+    #[error(transparent)]
+    Conversion(conversion::ConvertError),
+}
+
+/// Result type.
+pub type Result<T, E = Error> = std::result::Result<T, E>;
+
+struct GenerationResults {
+    item_mod: ItemMod,
+    cpp: Option<CppFilePair>,
+    #[allow(dead_code)]
+    inc_dirs: Vec<PathBuf>,
+    cxxgen_header_name: String,
+}
+enum State {
+    NotGenerated,
+    ParseOnly,
+    Generated(Box<GenerationResults>),
+}
+
+const AUTOCXX_CLANG_ARGS: &[&str; 4] = &["-x", "c++", "-std=c++14", "-DBINDGEN"];
+
+/// Implement to learn of header files which get included
+/// by this build process, such that your build system can choose
+/// to rerun the build process if any such file changes in future.
+pub trait RebuildDependencyRecorder: std::fmt::Debug {
+    /// Records that this autocxx build depends on the given
+    /// header file. Full paths will be provided.
+    fn record_header_file_dependency(&self, filename: &str);
+}
+
+#[cfg_attr(doc, aquamarine::aquamarine)]
+/// Core of the autocxx engine.
+///
+/// The basic idea is this. We will run `bindgen` which will spit
+/// out a ton of Rust code corresponding to all the types and functions
+/// defined in C++. We'll then post-process that bindgen output
+/// into a form suitable for ingestion by `cxx`.
+/// (It's the `BridgeConverter` mod which does that.)
+/// Along the way, the `bridge_converter` might tell us of additional
+/// C++ code which we should generate, e.g. wrappers to move things
+/// into and out of `UniquePtr`s.
+///
+/// ```mermaid
+/// flowchart TB
+///     s[(C++ headers)]
+///     s --> lc
+///     rss[(.rs input)]
+///     rss --> parser
+///     parser --> include_cpp_conf
+///     cpp_output[(C++ output)]
+///     rs_output[(.rs output)]
+///     subgraph autocxx[autocxx_engine]
+///     parser[File parser]
+///     subgraph bindgen[autocxx_bindgen]
+///     lc[libclang parse]
+///     bir(bindgen IR)
+///     lc --> bir
+///     end
+///     bgo(bindgen generated bindings)
+///     bir --> bgo
+///     include_cpp_conf(Config from include_cpp)
+///     syn[Parse with syn]
+///     bgo --> syn
+///     conv[['conversion' mod: see below]]
+///     syn --> conv
+///     rsgen(Generated .rs TokenStream)
+///     conv --> rsgen
+///     subgraph cxx_gen
+///     cxx_codegen[cxx_gen C++ codegen]
+///     end
+///     rsgen --> cxx_codegen
+///     end
+///     conv -- autocxx C++ codegen --> cpp_output
+///     rsgen -- autocxx .rs codegen --> rs_output
+///     cxx_codegen -- cxx C++ codegen --> cpp_output
+///     subgraph rustc [rustc build]
+///     subgraph autocxx_macro
+///     include_cpp[autocxx include_cpp macro]
+///     end
+///     subgraph cxx
+///     cxxm[cxx procedural macro]
+///     end
+///     comprs(Fully expanded Rust code)
+///     end
+///     rs_output-. included .->include_cpp
+///     include_cpp --> cxxm
+///     cxxm --> comprs
+///     rss --> rustc
+///     include_cpp_conf -. used to configure .-> bindgen
+///     include_cpp_conf --> conv
+///     link[linker]
+///     cpp_output --> link
+///     comprs --> link
+/// ```
+///
+/// Here's a zoomed-in view of the "conversion" part:
+///
+/// ```mermaid
+/// flowchart TB
+///     syn[(syn parse)]
+///     apis(Unanalyzed APIs)
+///     subgraph parse
+///     syn ==> parse_bindgen
+///     end
+///     parse_bindgen ==> apis
+///     subgraph analysis
+///     typedef[typedef analysis]
+///     pod[POD analysis]
+///     apis ==> typedef
+///     typedef ==> pod
+///     podapis(APIs with POD analysis)
+///     pod ==> podapis
+///     fun[Function materialization analysis]
+///     podapis ==> fun
+///     funapis(APIs with function analysis)
+///     fun ==> funapis
+///     gc[Garbage collection]
+///     funapis ==> gc
+///     ctypes[C int analysis]
+///     gc ==> ctypes
+///     ctypes ==> finalapis
+///     end
+///     finalapis(Analyzed APIs)
+///     codegenrs(.rs codegen)
+///     codegencpp(.cpp codegen)
+///     finalapis ==> codegenrs
+///     finalapis ==> codegencpp
+/// ```
+pub struct IncludeCppEngine {
+    config: IncludeCppConfig,
+    state: State,
+}
+
+impl Parse for IncludeCppEngine {
+    fn parse(input: ParseStream) -> ParseResult<Self> {
+        let config = input.parse::<IncludeCppConfig>()?;
+        let state = if config.parse_only {
+            State::ParseOnly
+        } else {
+            State::NotGenerated
+        };
+        Ok(Self { config, state })
+    }
+}
+
+impl IncludeCppEngine {
+    pub fn new_from_syn(mac: Macro, file_contents: &str) -> Result<Self> {
+        mac.parse_body::<IncludeCppEngine>()
+            .map_err(|e| Error::MacroParsing(LocatedSynError::new(e, file_contents)))
+    }
+
+    pub fn config_mut(&mut self) -> &mut IncludeCppConfig {
+        assert!(
+            matches!(self.state, State::NotGenerated),
+            "Can't alter config after generation commenced"
+        );
+        &mut self.config
+    }
+
+    fn build_header(&self) -> String {
+        join(
+            self.config
+                .inclusions
+                .iter()
+                .map(|path| format!("#include \"{}\"\n", path)),
+            "",
+        )
+    }
+
+    fn make_bindgen_builder(
+        &self,
+        inc_dirs: &[PathBuf],
+        extra_clang_args: &[&str],
+    ) -> bindgen::Builder {
+        let mut builder = bindgen::builder()
+            .clang_args(make_clang_args(inc_dirs, extra_clang_args))
+            .derive_copy(false)
+            .derive_debug(false)
+            .default_enum_style(bindgen::EnumVariation::Rust {
+                non_exhaustive: false,
+            })
+            .size_t_is_usize(true)
+            .enable_cxx_namespaces()
+            .generate_inline_functions(true)
+            .respect_cxx_access_specs(true)
+            .use_specific_virtual_function_receiver(true)
+            .cpp_semantic_attributes(true)
+            .represent_cxx_operators(true)
+            .use_distinct_char16_t(true)
+            .layout_tests(false); // TODO revisit later
+        for item in known_types().get_initial_blocklist() {
+            builder = builder.blocklist_item(item);
+        }
+
+        // 3. Passes allowlist and other options to the bindgen::Builder equivalent
+        //    to --output-style=cxx --allowlist=<as passed in>
+        if let Some(allowlist) = self.config.bindgen_allowlist() {
+            for a in allowlist {
+                // TODO - allowlist type/functions/separately
+                builder = builder
+                    .allowlist_type(&a)
+                    .allowlist_function(&a)
+                    .allowlist_var(&a);
+            }
+        }
+
+        log::info!(
+            "Bindgen flags would be: {}",
+            builder
+                .command_line_flags()
+                .into_iter()
+                .map(|f| format!("\"{}\"", f))
+                .join(" ")
+        );
+        builder
+    }
+
+    pub fn get_rs_filename(&self) -> String {
+        self.config.get_rs_filename()
+    }
+
+    /// Generate the Rust bindings. Call `generate` first.
+    pub fn get_rs_output(&self) -> RsOutput {
+        RsOutput {
+            config: &self.config,
+            rs: match &self.state {
+                State::NotGenerated => panic!("Generate first"),
+                State::Generated(gen_results) => gen_results.item_mod.to_token_stream(),
+                State::ParseOnly => TokenStream2::new(),
+            },
+        }
+    }
+
+    /// Returns the name of the mod which this `include_cpp!` will generate.
+    /// Can and should be used to ensure multiple mods in a file don't conflict.
+    pub fn get_mod_name(&self) -> String {
+        self.config.get_mod_name().to_string()
+    }
+
+    fn parse_bindings(&self, bindings: bindgen::Bindings) -> Result<ItemMod> {
+        // This bindings object is actually a TokenStream internally and we're wasting
+        // effort converting to and from string. We could enhance the bindgen API
+        // in future.
+        let bindings = bindings.to_string();
+        // Manually add the mod ffi {} so that we can ask syn to parse
+        // into a single construct.
+        let bindings = format!("mod bindgen {{ {} }}", bindings);
+        info!("Bindings: {}", bindings);
+        syn::parse_str::<ItemMod>(&bindings)
+            .map_err(|e| Error::BindingsParsing(LocatedSynError::new(e, &bindings)))
+    }
+
+    /// Actually examine the headers to find out what needs generating.
+    /// Most errors occur at this stage as we fail to interpret the C++
+    /// headers properly.
+    ///
+    /// See documentation for this type for flow diagrams and more details.
+    pub fn generate(
+        &mut self,
+        inc_dirs: Vec<PathBuf>,
+        extra_clang_args: &[&str],
+        dep_recorder: Option<Box<dyn RebuildDependencyRecorder>>,
+        cpp_codegen_options: &CppCodegenOptions,
+    ) -> Result<()> {
+        // If we are in parse only mode, do nothing. This is used for
+        // doc tests to ensure the parsing is valid, but we can't expect
+        // valid C++ header files or linkers to allow a complete build.
+        match self.state {
+            State::ParseOnly => return Ok(()),
+            State::NotGenerated => {}
+            State::Generated(_) => panic!("Only call generate once"),
+        }
+
+        let mod_name = self.config.get_mod_name();
+        let mut builder = self.make_bindgen_builder(&inc_dirs, extra_clang_args);
+        if let Some(dep_recorder) = dep_recorder {
+            builder = builder.parse_callbacks(Box::new(AutocxxParseCallbacks(dep_recorder)));
+        }
+        let header_contents = self.build_header();
+        self.dump_header_if_so_configured(&header_contents, &inc_dirs, extra_clang_args);
+        let header_and_prelude = format!("{}\n\n{}", known_types().get_prelude(), header_contents);
+        log::info!("Header and prelude for bindgen:\n{}", header_and_prelude);
+        builder = builder.header_contents("example.hpp", &header_and_prelude);
+
+        let bindings = builder.generate().map_err(Error::Bindgen)?;
+        let bindings = self.parse_bindings(bindings)?;
+
+        let converter = BridgeConverter::new(&self.config.inclusions, &self.config);
+
+        let conversion = converter
+            .convert(
+                bindings,
+                self.config.unsafe_policy.clone(),
+                header_contents,
+                cpp_codegen_options,
+            )
+            .map_err(Error::Conversion)?;
+        let mut items = conversion.rs;
+        let mut new_bindings: ItemMod = parse_quote! {
+            #[allow(non_snake_case)]
+            #[allow(dead_code)]
+            #[allow(non_upper_case_globals)]
+            #[allow(non_camel_case_types)]
+            mod #mod_name {
+            }
+        };
+        new_bindings.content.as_mut().unwrap().1.append(&mut items);
+        info!(
+            "New bindings:\n{}",
+            rust_pretty_printer::pretty_print(&new_bindings.to_token_stream())
+        );
+        self.state = State::Generated(Box::new(GenerationResults {
+            item_mod: new_bindings,
+            cpp: conversion.cpp,
+            inc_dirs,
+            cxxgen_header_name: conversion.cxxgen_header_name,
+        }));
+        Ok(())
+    }
+
+    /// Return the include directories used for this include_cpp invocation.
+    #[cfg(any(test, feature = "build"))]
+    fn include_dirs(&self) -> impl Iterator<Item = &PathBuf> {
+        match &self.state {
+            State::Generated(gen_results) => gen_results.inc_dirs.iter(),
+            _ => panic!("Must call generate() before include_dirs()"),
+        }
+    }
+
+    fn dump_header_if_so_configured(
+        &self,
+        header: &str,
+        inc_dirs: &[PathBuf],
+        extra_clang_args: &[&str],
+    ) {
+        if let Ok(output_path) = std::env::var("AUTOCXX_PREPROCESS") {
+            self.make_preprocessed_file(
+                &PathBuf::from(output_path),
+                header,
+                inc_dirs,
+                extra_clang_args,
+            );
+        }
+        #[cfg(feature = "reproduction_case")]
+        if let Ok(output_path) = std::env::var("AUTOCXX_REPRO_CASE") {
+            let tf = NamedTempFile::new().unwrap();
+            self.make_preprocessed_file(
+                &PathBuf::from(tf.path()),
+                header,
+                inc_dirs,
+                extra_clang_args,
+            );
+            let header = std::fs::read(tf.path()).unwrap();
+            let header = String::from_utf8_lossy(&header);
+            let output_path = PathBuf::from(output_path);
+            let config = self.config.to_token_stream().to_string();
+            let json = serde_json::json!({
+                "header": header,
+                "config": config
+            });
+            let f = File::create(&output_path).unwrap();
+            serde_json::to_writer(f, &json).unwrap();
+        }
+    }
+
+    fn make_preprocessed_file(
+        &self,
+        output_path: &Path,
+        header: &str,
+        inc_dirs: &[PathBuf],
+        extra_clang_args: &[&str],
+    ) {
+        // Include a load of system headers at the end of the preprocessed output,
+        // because we would like to be able to generate bindings from the
+        // preprocessed header, and then build those bindings. The C++ parts
+        // of those bindings might need things inside these various headers;
+        // we make sure all these definitions and declarations are inside
+        // this one header file so that the reduction process does not have
+        // to refer to local headers on the reduction machine too.
+        let suffix = ALL_KNOWN_SYSTEM_HEADERS
+            .iter()
+            .map(|hdr| format!("#include <{}>\n", hdr))
+            .join("\n");
+        let input = format!("/*\nautocxx config:\n\n{:?}\n\nend autocxx config.\nautocxx preprocessed input:\n*/\n\n{}\n\n/* autocxx: extra headers added below for completeness. */\n\n{}\n{}\n",
+            self.config, header, suffix, cxx_gen::HEADER);
+        let mut tf = NamedTempFile::new().unwrap();
+        write!(tf, "{}", input).unwrap();
+        let tp = tf.into_temp_path();
+        preprocess(&tp, &PathBuf::from(output_path), inc_dirs, extra_clang_args).unwrap();
+    }
+}
+
+/// This is a list of all the headers known to be included in generated
+/// C++ by cxx. We only use this when `AUTOCXX_PERPROCESS` is set to true,
+/// in an attempt to make the resulting preprocessed header more hermetic.
+/// We clearly should _not_ use this in any other circumstance; obviously
+/// we'd then want to add an API to cxx_gen such that we could retrieve
+/// that information from source.
+static ALL_KNOWN_SYSTEM_HEADERS: &[&str] = &[
+    "memory",
+    "string",
+    "algorithm",
+    "array",
+    "cassert",
+    "cstddef",
+    "cstdint",
+    "cstring",
+    "exception",
+    "functional",
+    "initializer_list",
+    "iterator",
+    "memory",
+    "new",
+    "stdexcept",
+    "type_traits",
+    "utility",
+    "vector",
+    "sys/types.h",
+];
+
+pub fn do_cxx_cpp_generation(
+    rs: TokenStream2,
+    cpp_codegen_options: &CppCodegenOptions,
+    cxxgen_header_name: String,
+) -> Result<CppFilePair, cxx_gen::Error> {
+    let mut opt = cxx_gen::Opt::default();
+    opt.cxx_impl_annotations = cpp_codegen_options.cxx_impl_annotations.clone();
+    let cxx_generated = cxx_gen::generate_header_and_cc(rs, &opt)?;
+    Ok(CppFilePair {
+        header: strip_system_headers(
+            cxx_generated.header,
+            cpp_codegen_options.suppress_system_headers,
+        ),
+        header_name: cxxgen_header_name,
+        implementation: Some(strip_system_headers(
+            cxx_generated.implementation,
+            cpp_codegen_options.suppress_system_headers,
+        )),
+    })
+}
+
+pub(crate) fn strip_system_headers(input: Vec<u8>, suppress_system_headers: bool) -> Vec<u8> {
+    if suppress_system_headers {
+        std::str::from_utf8(&input)
+            .unwrap()
+            .lines()
+            .filter(|l| !l.starts_with("#include <"))
+            .join("\n")
+            .as_bytes()
+            .to_vec()
+    } else {
+        input
+    }
+}
+
+impl CppBuildable for IncludeCppEngine {
+    /// Generate C++-side bindings for these APIs. Call `generate` first.
+    fn generate_h_and_cxx(
+        &self,
+        cpp_codegen_options: &CppCodegenOptions,
+    ) -> Result<GeneratedCpp, cxx_gen::Error> {
+        let mut files = Vec::new();
+        match &self.state {
+            State::ParseOnly => panic!("Cannot generate C++ in parse-only mode"),
+            State::NotGenerated => panic!("Call generate() first"),
+            State::Generated(gen_results) => {
+                let rs = gen_results.item_mod.to_token_stream();
+                files.push(do_cxx_cpp_generation(
+                    rs,
+                    cpp_codegen_options,
+                    gen_results.cxxgen_header_name.clone(),
+                )?);
+                if let Some(cpp_file_pair) = &gen_results.cpp {
+                    files.push(cpp_file_pair.clone());
+                }
+            }
+        };
+        Ok(GeneratedCpp(files))
+    }
+}
+
+/// Get clang args as if we were operating clang the same way as we operate
+/// bindgen.
+pub fn make_clang_args<'a>(
+    incs: &'a [PathBuf],
+    extra_args: &'a [&str],
+) -> impl Iterator<Item = String> + 'a {
+    // AUTOCXX_CLANG_ARGS come first so that any defaults defined there(e.g. for the `-std`
+    // argument) can be overridden by extra_args.
+    AUTOCXX_CLANG_ARGS
+        .iter()
+        .map(|s| s.to_string())
+        .chain(incs.iter().map(|i| format!("-I{}", i.to_str().unwrap())))
+        .chain(extra_args.iter().map(|s| s.to_string()))
+}
+
+/// Preprocess a file using the same options
+/// as is used by autocxx. Input: listing_path, output: preprocess_path.
+pub fn preprocess(
+    listing_path: &Path,
+    preprocess_path: &Path,
+    incs: &[PathBuf],
+    extra_clang_args: &[&str],
+) -> Result<(), std::io::Error> {
+    let mut cmd = Command::new(get_clang_path());
+    cmd.arg("-E");
+    cmd.arg("-C");
+    cmd.args(make_clang_args(incs, extra_clang_args));
+    cmd.arg(listing_path.to_str().unwrap());
+    cmd.stderr(Stdio::inherit());
+    let result = cmd.output().expect("failed to execute clang++");
+    assert!(result.status.success(), "failed to preprocess");
+    let mut file = File::create(preprocess_path)?;
+    file.write_all(&result.stdout)?;
+    Ok(())
+}
+
+/// Get the path to clang which is effective for any preprocessing
+/// operations done by autocxx.
+pub fn get_clang_path() -> String {
+    // `CLANG_PATH` is the environment variable that clang-sys uses to specify
+    // the path to Clang, so in most cases where someone is using a compiler
+    // that's not on the path, things should just work. We also check `CXX`,
+    // since some users may have set that.
+    std::env::var("CLANG_PATH")
+        .or_else(|_| std::env::var("CXX"))
+        .unwrap_or_else(|_| "clang++".to_string())
+}
+
+/// Function to generate the desired name of the header containing autocxx's
+/// extra generated C++.
+/// Newtype wrapper so we can give it a [`Default`].
+pub struct AutocxxgenHeaderNamer<'a>(pub Box<dyn 'a + Fn(String) -> String>);
+
+impl Default for AutocxxgenHeaderNamer<'static> {
+    fn default() -> Self {
+        Self(Box::new(|mod_name| format!("autocxxgen_{}.h", mod_name)))
+    }
+}
+
+impl AutocxxgenHeaderNamer<'_> {
+    fn name_header(&self, mod_name: String) -> String {
+        self.0(mod_name)
+    }
+}
+
+/// Function to generate the desired name of the header containing cxx's
+/// declarations.
+/// Newtype wrapper so we can give it a [`Default`].
+pub struct CxxgenHeaderNamer<'a>(pub Box<dyn 'a + Fn() -> String>);
+
+impl Default for CxxgenHeaderNamer<'static> {
+    fn default() -> Self {
+        Self(Box::new(|| "cxxgen.h".into()))
+    }
+}
+
+impl CxxgenHeaderNamer<'_> {
+    fn name_header(&self) -> String {
+        self.0()
+    }
+}
+
+/// Options for C++ codegen
+#[derive(Default)]
+pub struct CppCodegenOptions<'a> {
+    /// Whether to avoid generating `#include <some-system-header>`.
+    /// You may wish to do this to make a hermetic test case with no
+    /// external dependencies.
+    pub suppress_system_headers: bool,
+    /// Optionally, a prefix to go at `#include "<here>cxx.h". This is a header file from the `cxx`
+    /// crate.
+    pub path_to_cxx_h: Option<String>,
+    /// Optionally, a prefix to go at `#include "<here>cxxgen.h". This is a header file which we
+    /// generate.
+    pub path_to_cxxgen_h: Option<String>,
+    /// Optionally, a function called to determine the name that will be used
+    /// for the autocxxgen.h file.
+    /// The function is passed the name of the module generated by each `include_cpp`,
+    /// configured via `name`. These will be unique.
+    pub autocxxgen_header_namer: AutocxxgenHeaderNamer<'a>,
+    /// A function to generate the name of the cxxgen.h header that should be output.
+    pub cxxgen_header_namer: CxxgenHeaderNamer<'a>,
+    /// An annotation optionally to include on each C++ function.
+    /// For example to export the symbol from a library.
+    pub cxx_impl_annotations: Option<String>,
+}
+
+fn proc_macro_span_to_miette_span(span: &proc_macro2::Span) -> SourceSpan {
+    // A proc_macro2::Span stores its location as a byte offset. But there are
+    // no APIs to get that offset out.
+    // We could use `.start()` and `.end()` to get the line + column numbers, but it appears
+    // they're a little buggy. Hence we do this, to get the offsets directly across into
+    // miette.
+    struct Err;
+    let r: Result<(usize, usize), Err> = (|| {
+        let span_desc = format!("{:?}", span);
+        let re = Regex::new(r"(\d+)..(\d+)").unwrap();
+        let captures = re.captures(&span_desc).ok_or(Err)?;
+        let start = captures.get(1).ok_or(Err)?;
+        let start: usize = start.as_str().parse().map_err(|_| Err)?;
+        let start = start.saturating_sub(1); // proc_macro::Span offsets seem to be off-by-one
+        let end = captures.get(2).ok_or(Err)?;
+        let end: usize = end.as_str().parse().map_err(|_| Err)?;
+        let end = end.saturating_sub(1); // proc_macro::Span offsets seem to be off-by-one
+        Ok((start, end.saturating_sub(start)))
+    })();
+    let (start, end) = r.unwrap_or((0, 0));
+    SourceSpan::new(SourceOffset::from(start), SourceOffset::from(end))
+}
diff --git a/engine/src/output_generators.rs b/engine/src/output_generators.rs
new file mode 100644
index 0000000..a862558
--- /dev/null
+++ b/engine/src/output_generators.rs
@@ -0,0 +1,46 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx_parser::{IncludeCppConfig, MultiBindings};
+use proc_macro2::TokenStream;
+
+/// Opaque structure representing the Rust which needs to be generated
+/// for a given `include_cpp!` macro. You will want to pass this into
+/// either [`generate_rs_single`] or [`generate_rs_archive`].
+pub struct RsOutput<'a> {
+    pub(crate) config: &'a IncludeCppConfig,
+    pub(crate) rs: TokenStream,
+}
+
+/// Creates an on-disk archive (actually a JSON file) of the Rust side of the bindings
+/// for multiple `include_cpp` macros. If you use this, you will want to tell
+/// `autocxx_macro` how to find this file using the `AUTOCXX_RS_ARCHIVE`
+/// environment variable.
+pub fn generate_rs_archive<'a>(rs_outputs: impl Iterator<Item = RsOutput<'a>>) -> String {
+    let mut multi_bindings = MultiBindings::default();
+    for rs in rs_outputs {
+        multi_bindings.insert(rs.config, rs.rs);
+    }
+    serde_json::to_string(&multi_bindings).expect("Unable to encode JSON archive")
+}
+
+/// A single Rust file to be written to disk.
+pub struct RsInclude {
+    pub code: String,
+    pub filename: String,
+}
+
+/// Gets the Rust code corresponding to a single [`RsOutput`]. You can write this
+/// to a file which can simply be `include!`ed by `autocxx_macro` when you give
+/// it the `AUTOCXX_RS_FILE` environment variable.
+pub fn generate_rs_single(rs_output: RsOutput) -> RsInclude {
+    RsInclude {
+        code: rs_output.rs.to_string(),
+        filename: rs_output.config.get_rs_filename(),
+    }
+}
diff --git a/engine/src/parse_callbacks.rs b/engine/src/parse_callbacks.rs
new file mode 100644
index 0000000..61098c0
--- /dev/null
+++ b/engine/src/parse_callbacks.rs
@@ -0,0 +1,23 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::panic::UnwindSafe;
+
+use crate::RebuildDependencyRecorder;
+use autocxx_bindgen::callbacks::ParseCallbacks;
+
+#[derive(Debug)]
+pub(crate) struct AutocxxParseCallbacks(pub(crate) Box<dyn RebuildDependencyRecorder>);
+
+impl UnwindSafe for AutocxxParseCallbacks {}
+
+impl ParseCallbacks for AutocxxParseCallbacks {
+    fn include_file(&self, filename: &str) {
+        self.0.record_header_file_dependency(filename);
+    }
+}
diff --git a/engine/src/parse_file.rs b/engine/src/parse_file.rs
new file mode 100644
index 0000000..3571d19
--- /dev/null
+++ b/engine/src/parse_file.rs
@@ -0,0 +1,414 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::ast_discoverer::{Discoveries, DiscoveryErr};
+use crate::output_generators::RsOutput;
+use crate::{
+    cxxbridge::CxxBridge, Error as EngineError, GeneratedCpp, IncludeCppEngine,
+    RebuildDependencyRecorder,
+};
+use crate::{CppCodegenOptions, LocatedSynError};
+use autocxx_parser::directive_names::SUBCLASS;
+use autocxx_parser::{AllowlistEntry, RustPath, Subclass, SubclassAttrs};
+use indexmap::set::IndexSet as HashSet;
+use miette::Diagnostic;
+use quote::ToTokens;
+use std::{io::Read, path::PathBuf};
+use std::{panic::UnwindSafe, path::Path, rc::Rc};
+use syn::{token::Brace, Item, ItemMod};
+use thiserror::Error;
+
+/// Errors which may occur when parsing a Rust source file to discover
+/// and interpret include_cxx macros.
+#[derive(Error, Diagnostic, Debug)]
+pub enum ParseError {
+    #[error("unable to open the source file: {0}")]
+    FileOpen(std::io::Error),
+    #[error("the .rs file couldn't be read: {0}")]
+    FileRead(std::io::Error),
+    #[error("syntax error interpreting Rust code: {0}")]
+    #[diagnostic(transparent)]
+    Syntax(LocatedSynError),
+    #[error("generate!/generate_ns! was used at the same time as generate_all!")]
+    ConflictingAllowlist,
+    #[error("the subclass attribute couldn't be parsed: {0}")]
+    #[diagnostic(transparent)]
+    SubclassSyntax(LocatedSynError),
+    /// The include CPP macro could not be expanded into
+    /// Rust bindings to C++, because of some problem during the conversion
+    /// process. This could be anything from a C++ parsing error to some
+    /// C++ feature that autocxx can't yet handle and isn't able to skip
+    /// over. It could also cover errors in your syntax of the `include_cpp`
+    /// macro or the directives inside.
+    #[error("the include_cpp! macro couldn't be expanded into Rust bindings to C++: {0}")]
+    #[diagnostic(transparent)]
+    AutocxxCodegenError(EngineError),
+    /// There are two or more `include_cpp` macros with the same
+    /// mod name.
+    #[error("there are two or more include_cpp! mods with the same mod name")]
+    ConflictingModNames,
+    #[error("dynamic discovery was enabled but no mod was found")]
+    ZeroModsForDynamicDiscovery,
+    #[error("dynamic discovery was enabled but multiple mods were found")]
+    MultipleModsForDynamicDiscovery,
+    #[error("a problem occurred while discovering C++ APIs used within the Rust: {0}")]
+    Discovery(DiscoveryErr),
+}
+
+/// Parse a Rust file, and spot any include_cpp macros within it.
+pub fn parse_file<P1: AsRef<Path>>(
+    rs_file: P1,
+    auto_allowlist: bool,
+) -> Result<ParsedFile, ParseError> {
+    let mut source_code = String::new();
+    let mut file = std::fs::File::open(rs_file).map_err(ParseError::FileOpen)?;
+    file.read_to_string(&mut source_code)
+        .map_err(ParseError::FileRead)?;
+    proc_macro2::fallback::force();
+    let source = syn::parse_file(&source_code)
+        .map_err(|e| ParseError::Syntax(LocatedSynError::new(e, &source_code)))?;
+    parse_file_contents(source, auto_allowlist, &source_code)
+}
+
+fn parse_file_contents(
+    source: syn::File,
+    auto_allowlist: bool,
+    file_contents: &str,
+) -> Result<ParsedFile, ParseError> {
+    #[derive(Default)]
+    struct State {
+        auto_allowlist: bool,
+        results: Vec<Segment>,
+        extra_superclasses: Vec<Subclass>,
+        discoveries: Discoveries,
+    }
+    impl State {
+        fn parse_item(
+            &mut self,
+            item: Item,
+            mod_path: Option<RustPath>,
+            file_contents: &str,
+        ) -> Result<(), ParseError> {
+            let result = match item {
+                Item::Macro(mac)
+                    if mac
+                        .mac
+                        .path
+                        .segments
+                        .last()
+                        .map(|s| s.ident == "include_cpp")
+                        .unwrap_or(false) =>
+                {
+                    Segment::Autocxx(
+                        crate::IncludeCppEngine::new_from_syn(mac.mac, file_contents)
+                            .map_err(ParseError::AutocxxCodegenError)?,
+                    )
+                }
+                Item::Mod(itm)
+                    if itm
+                        .attrs
+                        .iter()
+                        .any(|attr| attr.path.to_token_stream().to_string() == "cxx :: bridge") =>
+                {
+                    Segment::Cxx(CxxBridge::from(itm))
+                }
+                Item::Mod(itm) => {
+                    if let Some((brace, items)) = itm.content {
+                        let mut mod_state = State {
+                            auto_allowlist: self.auto_allowlist,
+                            ..Default::default()
+                        };
+                        let mod_path = match &mod_path {
+                            None => RustPath::new_from_ident(itm.ident.clone()),
+                            Some(mod_path) => mod_path.append(itm.ident.clone()),
+                        };
+                        for item in items {
+                            mod_state.parse_item(item, Some(mod_path.clone()), file_contents)?
+                        }
+                        self.extra_superclasses.extend(mod_state.extra_superclasses);
+                        self.discoveries.extend(mod_state.discoveries);
+                        Segment::Mod(
+                            mod_state.results,
+                            (
+                                brace,
+                                ItemMod {
+                                    content: None,
+                                    ..itm
+                                },
+                            ),
+                        )
+                    } else {
+                        Segment::Other(Item::Mod(itm))
+                    }
+                }
+                Item::Struct(ref its) if self.auto_allowlist => {
+                    let attrs = &its.attrs;
+                    let is_superclass_attr = attrs.iter().find(|attr| {
+                        attr.path
+                            .segments
+                            .last()
+                            .map(|seg| seg.ident == "is_subclass" || seg.ident == SUBCLASS)
+                            .unwrap_or(false)
+                    });
+                    if let Some(is_superclass_attr) = is_superclass_attr {
+                        if !is_superclass_attr.tokens.is_empty() {
+                            let subclass = its.ident.clone();
+                            let args: SubclassAttrs =
+                                is_superclass_attr.parse_args().map_err(|e| {
+                                    ParseError::SubclassSyntax(LocatedSynError::new(
+                                        e,
+                                        file_contents,
+                                    ))
+                                })?;
+                            if let Some(superclass) = args.superclass {
+                                self.extra_superclasses.push(Subclass {
+                                    superclass,
+                                    subclass,
+                                })
+                            }
+                        }
+                    }
+                    self.discoveries
+                        .search_item(&item, mod_path)
+                        .map_err(ParseError::Discovery)?;
+                    Segment::Other(item)
+                }
+                _ => {
+                    self.discoveries
+                        .search_item(&item, mod_path)
+                        .map_err(ParseError::Discovery)?;
+                    Segment::Other(item)
+                }
+            };
+            self.results.push(result);
+            Ok(())
+        }
+    }
+    let mut state = State {
+        auto_allowlist,
+        ..Default::default()
+    };
+    for item in source.items {
+        state.parse_item(item, None, file_contents)?
+    }
+    let State {
+        auto_allowlist,
+        mut results,
+        mut extra_superclasses,
+        mut discoveries,
+    } = state;
+
+    let must_handle_discovered_things = discoveries.found_rust()
+        || !extra_superclasses.is_empty()
+        || (auto_allowlist && discoveries.found_allowlist());
+
+    // We do not want to enter this 'if' block unless the above conditions are true,
+    // since we may emit errors.
+    if must_handle_discovered_things {
+        let mut autocxx_seg_iterator = results.iter_mut().filter_map(|seg| match seg {
+            Segment::Autocxx(engine) => Some(engine),
+            _ => None,
+        });
+        let our_seg = autocxx_seg_iterator.next();
+        match our_seg {
+            None => return Err(ParseError::ZeroModsForDynamicDiscovery),
+            Some(engine) => {
+                engine
+                    .config_mut()
+                    .subclasses
+                    .append(&mut extra_superclasses);
+                if auto_allowlist {
+                    for cpp in discoveries.cpp_list {
+                        engine
+                            .config_mut()
+                            .allowlist
+                            .push(AllowlistEntry::Item(cpp))
+                            .map_err(|_| ParseError::ConflictingAllowlist)?;
+                    }
+                }
+                engine
+                    .config_mut()
+                    .extern_rust_funs
+                    .append(&mut discoveries.extern_rust_funs);
+                engine
+                    .config_mut()
+                    .rust_types
+                    .append(&mut discoveries.extern_rust_types);
+            }
+        }
+        if autocxx_seg_iterator.next().is_some() {
+            return Err(ParseError::MultipleModsForDynamicDiscovery);
+        }
+    }
+    let autocxx_seg_iterator = results.iter_mut().filter_map(|seg| match seg {
+        Segment::Autocxx(engine) => Some(engine),
+        _ => None,
+    });
+    for seg in autocxx_seg_iterator {
+        seg.config.confirm_complete();
+    }
+    Ok(ParsedFile(results))
+}
+
+/// A Rust file parsed by autocxx. May contain zero or more autocxx 'engines',
+/// i.e. the `IncludeCpp` class, corresponding to zero or more include_cpp
+/// macros within this file. Also contains `syn::Item` structures for all
+/// the rest of the Rust code, such that it can be reconstituted if necessary.
+pub struct ParsedFile(Vec<Segment>);
+
+#[allow(clippy::large_enum_variant)]
+enum Segment {
+    Autocxx(IncludeCppEngine),
+    Cxx(CxxBridge),
+    Mod(Vec<Segment>, (Brace, ItemMod)),
+    Other(Item),
+}
+
+pub trait CppBuildable {
+    fn generate_h_and_cxx(
+        &self,
+        cpp_codegen_options: &CppCodegenOptions,
+    ) -> Result<GeneratedCpp, cxx_gen::Error>;
+}
+
+impl ParsedFile {
+    /// Get all the autocxx `include_cpp` macros found in this file.
+    pub fn get_autocxxes(&self) -> impl Iterator<Item = &IncludeCppEngine> {
+        fn do_get_autocxxes(segments: &[Segment]) -> impl Iterator<Item = &IncludeCppEngine> {
+            segments
+                .iter()
+                .flat_map(|s| -> Box<dyn Iterator<Item = &IncludeCppEngine>> {
+                    match s {
+                        Segment::Autocxx(includecpp) => Box::new(std::iter::once(includecpp)),
+                        Segment::Mod(segments, _) => Box::new(do_get_autocxxes(segments)),
+                        _ => Box::new(std::iter::empty()),
+                    }
+                })
+        }
+
+        do_get_autocxxes(&self.0)
+    }
+
+    /// Get all the areas of Rust code which need to be built for these bindings.
+    /// A shortcut for `get_autocxxes()` then calling `get_rs_output` on each.
+    pub fn get_rs_outputs(&self) -> impl Iterator<Item = RsOutput> {
+        self.get_autocxxes().map(|autocxx| autocxx.get_rs_output())
+    }
+
+    /// Get all items which can result in C++ code
+    pub fn get_cpp_buildables(&self) -> impl Iterator<Item = &dyn CppBuildable> {
+        fn do_get_cpp_buildables(segments: &[Segment]) -> impl Iterator<Item = &dyn CppBuildable> {
+            segments
+                .iter()
+                .flat_map(|s| -> Box<dyn Iterator<Item = &dyn CppBuildable>> {
+                    match s {
+                        Segment::Autocxx(includecpp) => {
+                            Box::new(std::iter::once(includecpp as &dyn CppBuildable))
+                        }
+                        Segment::Cxx(cxxbridge) => {
+                            Box::new(std::iter::once(cxxbridge as &dyn CppBuildable))
+                        }
+                        Segment::Mod(segments, _) => Box::new(do_get_cpp_buildables(segments)),
+                        _ => Box::new(std::iter::empty()),
+                    }
+                })
+        }
+
+        do_get_cpp_buildables(&self.0)
+    }
+
+    fn get_autocxxes_mut(&mut self) -> impl Iterator<Item = &mut IncludeCppEngine> {
+        fn do_get_autocxxes_mut(
+            segments: &mut [Segment],
+        ) -> impl Iterator<Item = &mut IncludeCppEngine> {
+            segments
+                .iter_mut()
+                .flat_map(|s| -> Box<dyn Iterator<Item = &mut IncludeCppEngine>> {
+                    match s {
+                        Segment::Autocxx(includecpp) => Box::new(std::iter::once(includecpp)),
+                        Segment::Mod(segments, _) => Box::new(do_get_autocxxes_mut(segments)),
+                        _ => Box::new(std::iter::empty()),
+                    }
+                })
+        }
+
+        do_get_autocxxes_mut(&mut self.0)
+    }
+
+    /// Determines the include dirs that were set for each include_cpp, so they can be
+    /// used as input to a `cc::Build`.
+    #[cfg(any(test, feature = "build"))]
+    pub(crate) fn include_dirs(&self) -> impl Iterator<Item = &PathBuf> {
+        fn do_get_include_dirs(segments: &[Segment]) -> impl Iterator<Item = &PathBuf> {
+            segments
+                .iter()
+                .flat_map(|s| -> Box<dyn Iterator<Item = &PathBuf>> {
+                    match s {
+                        Segment::Autocxx(includecpp) => Box::new(includecpp.include_dirs()),
+                        Segment::Mod(segments, _) => Box::new(do_get_include_dirs(segments)),
+                        _ => Box::new(std::iter::empty()),
+                    }
+                })
+        }
+
+        do_get_include_dirs(&self.0)
+    }
+
+    pub fn resolve_all(
+        &mut self,
+        autocxx_inc: Vec<PathBuf>,
+        extra_clang_args: &[&str],
+        dep_recorder: Option<Box<dyn RebuildDependencyRecorder>>,
+        cpp_codegen_options: &CppCodegenOptions,
+    ) -> Result<(), ParseError> {
+        let mut mods_found = HashSet::new();
+        let inner_dep_recorder: Option<Rc<dyn RebuildDependencyRecorder>> =
+            dep_recorder.map(Rc::from);
+        for include_cpp in self.get_autocxxes_mut() {
+            #[allow(clippy::manual_map)] // because of dyn shenanigans
+            let dep_recorder: Option<Box<dyn RebuildDependencyRecorder>> = match &inner_dep_recorder
+            {
+                None => None,
+                Some(inner_dep_recorder) => Some(Box::new(CompositeDepRecorder::new(
+                    inner_dep_recorder.clone(),
+                ))),
+            };
+            if !mods_found.insert(include_cpp.get_mod_name()) {
+                return Err(ParseError::ConflictingModNames);
+            }
+            include_cpp
+                .generate(
+                    autocxx_inc.clone(),
+                    extra_clang_args,
+                    dep_recorder,
+                    cpp_codegen_options,
+                )
+                .map_err(ParseError::AutocxxCodegenError)?
+        }
+        Ok(())
+    }
+}
+
+/// Shenanigans required to share the same RebuildDependencyRecorder
+/// with all of the include_cpp instances in this one file.
+#[derive(Debug, Clone)]
+struct CompositeDepRecorder(Rc<dyn RebuildDependencyRecorder>);
+
+impl CompositeDepRecorder {
+    fn new(inner: Rc<dyn RebuildDependencyRecorder>) -> Self {
+        CompositeDepRecorder(inner)
+    }
+}
+
+impl UnwindSafe for CompositeDepRecorder {}
+
+impl RebuildDependencyRecorder for CompositeDepRecorder {
+    fn record_header_file_dependency(&self, filename: &str) {
+        self.0.record_header_file_dependency(filename);
+    }
+}
diff --git a/engine/src/rust_pretty_printer.rs b/engine/src/rust_pretty_printer.rs
new file mode 100644
index 0000000..9c23cbc
--- /dev/null
+++ b/engine/src/rust_pretty_printer.rs
@@ -0,0 +1,40 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use proc_macro2::TokenStream;
+use std::io::Write;
+use std::process::{Command, Stdio};
+
+enum Error {
+    Run(std::io::Error),
+    Write(std::io::Error),
+    Utf8(std::string::FromUtf8Error),
+    Wait(std::io::Error),
+}
+
+pub(crate) fn pretty_print(ts: &TokenStream) -> String {
+    reformat_or_else(ts.to_string())
+}
+
+fn reformat_or_else(text: impl std::fmt::Display) -> String {
+    match reformat(&text) {
+        Ok(s) => s,
+        Err(_) => text.to_string(),
+    }
+}
+
+fn reformat(text: impl std::fmt::Display) -> Result<String, Error> {
+    let mut rustfmt = Command::new("rustfmt")
+        .stdin(Stdio::piped())
+        .stdout(Stdio::piped())
+        .spawn()
+        .map_err(Error::Run)?;
+    write!(rustfmt.stdin.take().unwrap(), "{}", text).map_err(Error::Write)?;
+    let output = rustfmt.wait_with_output().map_err(Error::Wait)?;
+    String::from_utf8(output.stdout).map_err(Error::Utf8)
+}
diff --git a/engine/src/types.rs b/engine/src/types.rs
new file mode 100644
index 0000000..0d11895
--- /dev/null
+++ b/engine/src/types.rs
@@ -0,0 +1,259 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use itertools::Itertools;
+use proc_macro2::Span;
+use quote::ToTokens;
+use std::iter::Peekable;
+use std::{fmt::Display, sync::Arc};
+use syn::{parse_quote, Ident, PathSegment, TypePath};
+
+use crate::{conversion::ConvertError, known_types::known_types};
+
+pub(crate) fn make_ident<S: AsRef<str>>(id: S) -> Ident {
+    Ident::new(id.as_ref(), Span::call_site())
+}
+
+/// Newtype wrapper for a C++ namespace.
+#[derive(Debug, PartialEq, PartialOrd, Eq, Hash, Clone)]
+#[allow(clippy::rc_buffer)]
+pub struct Namespace(Arc<Vec<String>>);
+
+impl Namespace {
+    pub(crate) fn new() -> Self {
+        Self(Arc::new(Vec::new()))
+    }
+
+    #[must_use]
+    pub(crate) fn push(&self, segment: String) -> Self {
+        let mut bigger = (*self.0).clone();
+        bigger.push(segment);
+        Namespace(Arc::new(bigger))
+    }
+
+    pub(crate) fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+
+    pub(crate) fn iter(&self) -> impl Iterator<Item = &String> {
+        self.0.iter()
+    }
+
+    #[cfg(test)]
+    pub(crate) fn from_user_input(input: &str) -> Self {
+        Self(Arc::new(input.split("::").map(|x| x.to_string()).collect()))
+    }
+
+    pub(crate) fn depth(&self) -> usize {
+        self.0.len()
+    }
+}
+
+impl Display for Namespace {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.write_str(&self.0.join("::"))
+    }
+}
+
+impl<'a> IntoIterator for &'a Namespace {
+    type Item = &'a String;
+
+    type IntoIter = std::slice::Iter<'a, String>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.0.iter()
+    }
+}
+
+/// Any time we store a qualified name, we should use this. Stores the type
+/// and its namespace. Namespaces should be stored without any
+/// 'bindgen::root' prefix; that means a type not in any C++
+/// namespace should have an empty namespace segment list.
+/// Some types have names that change as they flow through the
+/// autocxx pipeline. e.g. you start with std::string
+/// and end up with CxxString. This TypeName type can store
+/// either. It doesn't directly have functionality to convert
+/// from one to the other; `replace_type_path_without_arguments`
+/// does that.
+#[derive(Debug, PartialEq, PartialOrd, Eq, Hash, Clone)]
+pub struct QualifiedName(Namespace, String);
+
+impl QualifiedName {
+    /// From a TypePath which starts with 'root'
+    pub(crate) fn from_type_path(typ: &TypePath) -> Self {
+        let mut seg_iter = typ.path.segments.iter().peekable();
+        let first_seg = seg_iter.next().unwrap().ident.clone();
+        if first_seg == "root" {
+            // This is a C++ type prefixed with a namespace,
+            // e.g. std::string or something the user has defined.
+            Self::from_segments(seg_iter) // all but 'root'
+        } else {
+            // This is actually a Rust type e.g.
+            // std::os::raw::c_ulong. Start iterating from the beginning again.
+            Self::from_segments(typ.path.segments.iter().peekable())
+        }
+    }
+
+    fn from_segments<'a, T: Iterator<Item = &'a PathSegment>>(mut seg_iter: Peekable<T>) -> Self {
+        let mut ns = Namespace::new();
+        while let Some(seg) = seg_iter.next() {
+            if seg_iter.peek().is_some() {
+                ns = ns.push(seg.ident.to_string());
+            } else {
+                return Self(ns, seg.ident.to_string());
+            }
+        }
+        unreachable!()
+    }
+
+    /// Create from a type encountered in the code.
+    pub(crate) fn new(ns: &Namespace, id: Ident) -> Self {
+        Self(ns.clone(), id.to_string())
+    }
+
+    /// Create from user input, e.g. a name in an AllowPOD directive.
+    pub(crate) fn new_from_cpp_name(id: &str) -> Self {
+        let mut seg_iter = id.split("::").peekable();
+        let mut ns = Namespace::new();
+        while let Some(seg) = seg_iter.next() {
+            if seg_iter.peek().is_some() {
+                if !seg.to_string().is_empty() {
+                    ns = ns.push(seg.to_string());
+                }
+            } else {
+                return Self(ns, seg.to_string());
+            }
+        }
+        unreachable!()
+    }
+
+    /// Return the actual type name, without any namespace
+    /// qualification. Avoid unless you have a good reason.
+    pub(crate) fn get_final_item(&self) -> &str {
+        &self.1
+    }
+
+    /// cxx doesn't accept names containing double underscores,
+    /// but these are OK elsewhere in our output mod.
+    pub(crate) fn validate_ok_for_cxx(&self) -> Result<(), ConvertError> {
+        validate_ident_ok_for_cxx(self.get_final_item())
+    }
+
+    /// Return the actual type name as an [Ident], without any namespace
+    /// qualification. Avoid unless you have a good reason.
+    pub(crate) fn get_final_ident(&self) -> Ident {
+        make_ident(self.get_final_item())
+    }
+
+    pub(crate) fn get_namespace(&self) -> &Namespace {
+        &self.0
+    }
+
+    pub(crate) fn get_bindgen_path_idents(&self) -> Vec<Ident> {
+        ["bindgen", "root"]
+            .iter()
+            .map(make_ident)
+            .chain(self.ns_segment_iter().map(make_ident))
+            .chain(std::iter::once(self.get_final_ident()))
+            .collect()
+    }
+
+    /// Output the fully-qualified C++ name of this type.
+    pub(crate) fn to_cpp_name(&self) -> String {
+        let special_cpp_name = known_types().special_cpp_name(self);
+        match special_cpp_name {
+            Some(name) => name,
+            None => self.0.iter().chain(std::iter::once(&self.1)).join("::"),
+        }
+    }
+
+    pub(crate) fn get_final_cpp_item(&self) -> String {
+        let special_cpp_name = known_types().special_cpp_name(self);
+        match special_cpp_name {
+            Some(name) => name,
+            None => self.1.to_string(),
+        }
+    }
+
+    pub(crate) fn to_type_path(&self) -> TypePath {
+        if let Some(known_type_path) = known_types().known_type_type_path(self) {
+            known_type_path
+        } else {
+            let root = "root".to_string();
+            let segs = std::iter::once(&root)
+                .chain(self.ns_segment_iter())
+                .chain(std::iter::once(&self.1))
+                .map(make_ident);
+            parse_quote! {
+                #(#segs)::*
+            }
+        }
+    }
+
+    /// Iterator over segments in the namespace of this name.
+    pub(crate) fn ns_segment_iter(&self) -> impl Iterator<Item = &String> {
+        self.0.iter()
+    }
+
+    /// Iterate over all segments of this name.
+    pub(crate) fn segment_iter(&self) -> impl Iterator<Item = String> + '_ {
+        self.ns_segment_iter()
+            .cloned()
+            .chain(std::iter::once(self.get_final_item().to_string()))
+    }
+}
+
+impl Display for QualifiedName {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        for seg in &self.0 {
+            f.write_str(seg)?;
+            f.write_str("::")?;
+        }
+        f.write_str(&self.1)
+    }
+}
+
+/// cxx doesn't allow identifiers containing __. These are OK elsewhere
+/// in our output mod. It would be nice in future to think of a way we
+/// can enforce this using the Rust type system, e.g. a newtype
+/// wrapper for a CxxCompatibleIdent which is used in any context
+/// where code will be output as part of the `#[cxx::bridge]` mod.
+pub fn validate_ident_ok_for_cxx(id: &str) -> Result<(), ConvertError> {
+    validate_ident_ok_for_rust(id)?;
+    if id.contains("__") {
+        Err(ConvertError::TooManyUnderscores)
+    } else if id.starts_with("_bindgen_ty_") {
+        Err(ConvertError::BindgenTy)
+    } else {
+        Ok(())
+    }
+}
+
+pub fn validate_ident_ok_for_rust(label: &str) -> Result<(), ConvertError> {
+    let id = make_ident(label);
+    syn::parse2::<syn::Ident>(id.into_token_stream())
+        .map_err(|_| ConvertError::ReservedName(label.to_string()))
+        .map(|_| ())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::QualifiedName;
+
+    #[test]
+    fn test_ints() {
+        assert_eq!(
+            QualifiedName::new_from_cpp_name("i8").to_cpp_name(),
+            "int8_t"
+        );
+        assert_eq!(
+            QualifiedName::new_from_cpp_name("u64").to_cpp_name(),
+            "uint64_t"
+        );
+    }
+}
diff --git a/examples/chromium-fake-render-frame-host/Cargo.toml b/examples/chromium-fake-render-frame-host/Cargo.toml
new file mode 100644
index 0000000..a961708
--- /dev/null
+++ b/examples/chromium-fake-render-frame-host/Cargo.toml
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-chromium-fake-render-frame-host-example"
+version = "0.1.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+[dependencies]
+cxx = "1.0.54"
+autocxx = { path = "../..", version="0.22.0" }
+
+[build-dependencies]
+autocxx-build = { path = "../../gen/build", version="0.22.0" }
+miette = { version="4.3", features = [ "fancy" ] }
diff --git a/examples/chromium-fake-render-frame-host/build.rs b/examples/chromium-fake-render-frame-host/build.rs
new file mode 100644
index 0000000..b533af4
--- /dev/null
+++ b/examples/chromium-fake-render-frame-host/build.rs
@@ -0,0 +1,20 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() -> miette::Result<()> {
+    let path = std::path::PathBuf::from("src");
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path]).build()?;
+    b.flag_if_supported("-std=c++17")       // clang
+        .flag_if_supported("/std:c++17")    // msvc
+        .file("src/fake-chromium-src.cc")
+        .compile("autocxx-fake-render-frame-host-example");
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/fake-chromium-src.cc");
+    println!("cargo:rerun-if-changed=src/fake-chromium-header.h");
+    Ok(())
+}
diff --git a/examples/chromium-fake-render-frame-host/src/fake-chromium-header.h b/examples/chromium-fake-render-frame-host/src/fake-chromium-header.h
new file mode 100644
index 0000000..8f1c532
--- /dev/null
+++ b/examples/chromium-fake-render-frame-host/src/fake-chromium-header.h
@@ -0,0 +1,78 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#pragma once
+#include <memory>
+#include <string>
+#include <vector>
+
+// This is supposed to be a _fairly_ faithful representation of a few
+// Chromium codebase APIs. Just enough that we can start to experiment
+// with ownership patterns.
+
+namespace content {
+
+class RenderFrameHost {
+public:
+  static RenderFrameHost *FromId(int process_id, int frame_id);
+  virtual int GetRoutingID() = 0;
+
+  /// Returns the assigned name of the frame, the name of the iframe tag
+  /// declaring it. For example, <iframe name="framename">[...]</iframe>. It is
+  /// quite possible for a frame to have no name, in which case GetFrameName
+  /// will return an empty string.
+  virtual std::string GetFrameName() = 0;
+  virtual ~RenderFrameHost() {}
+};
+
+class CreateParams {
+public:
+  CreateParams(const std::string &);
+  std::string main_frame_name_;
+};
+
+class WebContentsObserver;
+
+class WebContents {
+public:
+  static std::unique_ptr<WebContents> Create(const CreateParams &params);
+
+  static WebContents *FromFrameTreeNodeId(int frame_tree_node_id);
+
+  // TODO - should not be in WebContents, just WebContentsImpl
+  virtual void AddObserver(WebContentsObserver *) {}
+  virtual void RemoveObserver(WebContentsObserver *) {}
+
+  virtual ~WebContents(){};
+
+  virtual const std::string &GetTitle() = 0;
+};
+
+class WebContentsObserver {
+public:
+  virtual void RenderFrameCreated(RenderFrameHost *) {}
+  virtual void RenderFrameDeleted(RenderFrameHost *) {}
+  virtual ~WebContentsObserver() {}
+};
+
+class WebContentsImpl : public WebContents {
+public:
+  void AddObserver(WebContentsObserver *);
+  void RemoveObserver(WebContentsObserver *);
+  const std::string &GetTitle();
+  WebContentsImpl(const CreateParams &);
+  void DeleteRFH();
+
+private:
+  std::string title_;
+  std::vector<WebContentsObserver *> observers_;
+  std::vector<std::unique_ptr<RenderFrameHost>> rfhs_;
+};
+} // namespace content
+
+void SimulateRendererShutdown(int frame_id);
\ No newline at end of file
diff --git a/examples/chromium-fake-render-frame-host/src/fake-chromium-src.cc b/examples/chromium-fake-render-frame-host/src/fake-chromium-src.cc
new file mode 100644
index 0000000..2f9a9d4
--- /dev/null
+++ b/examples/chromium-fake-render-frame-host/src/fake-chromium-src.cc
@@ -0,0 +1,81 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#include "fake-chromium-header.h"
+#include <map>
+#include <algorithm>
+
+using namespace content;
+
+// This is all appalling. None of this is real Chromium code.
+// It's just designed to be the bare minimum required
+// to knock together a quick Rust-side demo. In some future realities, all
+// this is replaced with real Chromium code.
+
+int latest_rfh_id = 0;
+std::map<int, RenderFrameHost *> render_frame_hosts;
+WebContentsImpl *the_only_web_contents; // for this daft demo
+
+CreateParams::CreateParams(const std::string &main_frame_name)
+    : main_frame_name_(main_frame_name) {}
+
+RenderFrameHost *RenderFrameHost::FromId(int, int frame_id) {
+  return render_frame_hosts.at(frame_id);
+}
+
+class RenderFrameHostImpl : public RenderFrameHost {
+public:
+  RenderFrameHostImpl(const std::string name, int routing_id)
+      : routing_id_(routing_id), name_(name) {}
+  virtual int GetRoutingID() { return routing_id_; }
+  virtual std::string GetFrameName() { return name_; }
+
+private:
+  int routing_id_;
+  std::string name_;
+};
+
+std::unique_ptr<WebContents> WebContents::Create(const CreateParams &params) {
+  auto wc = std::make_unique<WebContentsImpl>(params);
+  the_only_web_contents = wc.get();
+  return wc;
+}
+
+WebContentsImpl::WebContentsImpl(const CreateParams &params)
+    : title_(params.main_frame_name_) {
+  int id = latest_rfh_id++;
+  std::unique_ptr<RenderFrameHost> new_rfh(
+      new RenderFrameHostImpl(params.main_frame_name_, id));
+  render_frame_hosts.insert(
+      std::pair<int, RenderFrameHost *>(id, new_rfh.get()));
+  for (auto obs : observers_) {
+    obs->RenderFrameCreated(new_rfh.get());
+  }
+  rfhs_.push_back(std::move(new_rfh));
+}
+
+void WebContentsImpl::AddObserver(WebContentsObserver *observer) {
+  observers_.push_back(observer);
+}
+void WebContentsImpl::RemoveObserver(WebContentsObserver *observer) {
+  std::remove(std::begin(observers_), std::end(observers_), observer);
+}
+
+void WebContentsImpl::DeleteRFH() {
+  for (auto obs : observers_) {
+    obs->RenderFrameDeleted(rfhs_[0].get());
+  }
+  rfhs_.clear();
+}
+
+const std::string &WebContentsImpl::GetTitle() { return title_; }
+
+void SimulateRendererShutdown(int frame_id) {
+  render_frame_hosts.erase(frame_id);
+  the_only_web_contents->DeleteRFH();
+}
diff --git a/examples/chromium-fake-render-frame-host/src/main.rs b/examples/chromium-fake-render-frame-host/src/main.rs
new file mode 100644
index 0000000..d2504dc
--- /dev/null
+++ b/examples/chromium-fake-render-frame-host/src/main.rs
@@ -0,0 +1,73 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*;
+mod render_frame_host;
+use render_frame_host::RenderFrameHostForWebContents;
+use render_frame_host::RenderFrameHostHandle;
+
+include_cpp! {
+    #include "fake-chromium-header.h"
+    safety!(unsafe) // unsafety policy; see docs
+    generate!("content::WebContents")
+    generate!("content::RenderFrameHost")
+    generate!("content::CreateParams")
+    generate!("SimulateRendererShutdown")
+    subclass!("content::WebContentsObserver",RenderFrameHostForWebContents)
+}
+
+use ffi::ToCppString;
+
+fn main() {
+    // Create some fake toy WebContents.
+    let create_params = ffi::content::CreateParams::new(&"silly-frame".into_cpp()).within_unique_ptr();
+    let mut frame = ffi::content::WebContents::Create(&create_params);
+
+    // This object is a memory-safe handle to a RenderFrameHost.
+    // On creation, we pass it the WebContents, such that it can register
+    // to be informed of the destruction of the RenderFrameHost.
+    // It also happens to store a reference to that WebContents,
+    // so the compiler will prove that this RenderFrameHostHandle
+    // can't outlive the WebContents. That's nice. But currently
+    // it stores an exclusive (a.k.a. mutable) reference, and we may
+    // well want to relax that in future.
+    // (This relates to https://github.com/google/autocxx/issues/622)
+    let mut rfh_handle = RenderFrameHostHandle::from_id(c_int(3), c_int(0), frame.pin_mut());
+
+    // We can directly call methods on the RFH.
+    // (If this were a 'const' method, the `.pin_mut()` wouldn't be necessary).
+    let frame_name = rfh_handle.pin_mut().GetFrameName();
+    println!("Frame name is {}", frame_name.to_str().unwrap());
+
+    {
+        // We can also borrow the RFH and use Rust's borrow checker to ensure
+        // no other code can do so. This also gives us a chance to explicitly
+        // handle the case where the RFH was already destroyed, in case
+        // we want to do something smarter than panicking.
+        let mut rfh_borrowed = rfh_handle
+            .try_borrow_mut()
+            .expect("Oh! The RFH was already destroyed!");
+        // Nobody else can borrow it during this time...
+        //   let mut rfh_borrowed_again = rfh_handle.try_borrow_mut().unwrap();
+        // Gives compile-time error "second mutable borrow occurs here..."
+        let frame_name = rfh_borrowed.pin_mut().GetFrameName();
+        println!("Frame name is {}", frame_name.to_str().unwrap());
+        let frame_name = rfh_borrowed.pin_mut().GetFrameName();
+        println!("Frame name is {}", frame_name.to_str().unwrap());
+
+        // Supposing we end up calling some code deep in the Chrome C++
+        // stack which destroys the RFH whilst it's still borrowed.
+        // That will result in a runtime panic...
+        //  ffi::SimulateRendererShutdown(c_int(0)); // would panic
+    }
+
+    // But let's assume we've now returned to the event loop.
+    // None of the previous borrows still exist. It's perfectly OK to now
+    // delete the RFH.
+    ffi::SimulateRendererShutdown(c_int(0));
+}
diff --git a/examples/chromium-fake-render-frame-host/src/render_frame_host.rs b/examples/chromium-fake-render-frame-host/src/render_frame_host.rs
new file mode 100644
index 0000000..9c2bf51
--- /dev/null
+++ b/examples/chromium-fake-render-frame-host/src/render_frame_host.rs
@@ -0,0 +1,242 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::subclass::prelude::*;
+use autocxx::{c_int, PinMut};
+use std::cell::{Ref, RefCell, RefMut};
+use std::ops::Deref;
+use std::pin::Pin;
+use std::rc::Rc;
+
+use crate::ffi;
+
+/// A memory-safe handle to a C++ RenderFrameHost.
+///
+/// This is a toy, hypothetical, example.
+///
+/// Creation: in this sample, the only option is to use [`RenderFrameHostHandle::from_id`]
+/// which corresponds to the equivalent method in C++ `RenderFrameHost`. Unlike
+/// the C++ version, you must pass a WebContents so that Rust wrappers can listen for
+/// destruction events.
+///
+/// The returned handle is memory safe and can be used to access the methods
+/// of [`ffi::content::RenderFrameHost`]. To use such a method, you have three options:
+/// * If you believe there is no chance that the `RenderFrameHost` has been
+///   destroyed, and if the method is const, you can just go ahead and call methods
+///   on this object. As it implements [`std::ops::Deref`], that will just work -
+///   but your code will panic if the `RenderFrameHost` was already destroyed.
+/// * If the method is non-const, you'll have to call `.pin_mut().method()` instead
+//    but otherwise this is functionally identical.
+/// * If you believe that there is a chance that the `RenderFrameHost` was already
+///   destroyed, use [`RenderFrameHostHandle::try_borrow`] or
+///   [`RenderFrameHostHandle::try_borrow_mut`]. This will return
+///   a guard object which guarantees the existence of the `RenderFrameHost`
+///   during its lifetime.
+///
+/// # Performance characteristics
+///
+/// The existence of this object registers an observer with the `WebContents`
+/// and deregisters it on destruction. That is, of course, an overhead, but
+/// that's necessary to keep track of liveness. (A more efficient
+/// implementation would use a single observer for multiple such handles - but
+/// this is a toy implementation).
+///
+/// In addition, each time you extract the value from this
+/// `RenderFrameHostHandle`, a liveness check is performed. This involves
+/// not just a null check but also some reference count manipulation.
+/// If you're going to access the `RenderFrameHost` multiple times, it's
+/// advised that you call [`RenderFrameHostHandle::try_borrow`] or
+/// [`RenderFrameHostHandle::try_borrow_mut`] and then use
+/// the result multiple times. The liveness check for the `RenderFrameHost`
+/// will be performed only once at runtime.
+///
+/// # Destruction of RenderFrameHosts while borrowed
+///
+/// If you have called [`RenderFrameHostHandle::try_borrow`] (or its mutable
+/// equivalent) and still have an outstanding borrow, any code path - via C++
+/// - which results it the destruction of the `RenderFrameHost` will result in
+/// a runtime panic.
+pub struct RenderFrameHostHandle<'wc> {
+    obs: Rc<RefCell<RenderFrameHostForWebContents>>,
+    web_contents: Pin<&'wc mut ffi::content::WebContents>,
+}
+
+impl<'wc> RenderFrameHostHandle<'wc> {
+    /// Create a memory-safe handle to a RenderFrameHost using its
+    /// process ID and frame ID.
+    pub fn from_id(
+        render_process_id: c_int,
+        render_frame_id: c_int,
+        mut web_contents: Pin<&'wc mut ffi::content::WebContents>,
+    ) -> Self {
+        // Instantiate our WebContentsObserver subclass.
+        let obs = RenderFrameHostForWebContents::new_rust_owned(RenderFrameHostForWebContents {
+            rfh: ffi::content::RenderFrameHost::FromId(render_process_id, render_frame_id),
+            cpp_peer: Default::default(),
+        });
+
+        // And now register it.
+        // This nasty line will go away when autocxx is a bit more sophisticated.
+        let superclass_ptr = cast_to_superclass(obs.as_ref().borrow_mut().peer_mut());
+
+        // But this will remain unsafe. cxx policy is that any raw pointer
+        // passed into a C++ function requires an unsafe {} block and that
+        // is sensible. We may of course provide an ergonomic Rust wrapper
+        // around WebContents which provides safe Rust equivalents
+        // (using references or similar rather than pointers) in which case
+        // this unsafe block would go away.
+        unsafe { web_contents.as_mut().AddObserver(superclass_ptr) };
+
+        Self { obs, web_contents }
+    }
+
+    /// Tries to return a mutable reference to the RenderFrameHost.
+    /// Because this requires `self` to be `&mut`, and that lifetime is
+    /// applied to the returned `RenderFrameHost`, the compiler will prevent
+    /// multiple such references existing in Rust at the same time.
+    /// This will return `None` if the RenderFrameHost were already destroyed.
+    pub fn try_borrow_mut<'a>(
+        &'a mut self,
+    ) -> Option<impl PinMut<ffi::content::RenderFrameHost> + 'a> {
+        let ref_mut = self.obs.as_ref().borrow_mut();
+        if ref_mut.rfh.is_null() {
+            None
+        } else {
+            Some(RenderFrameHostRefMut(ref_mut))
+        }
+    }
+
+    /// Tries to return a reference to the RenderFrameHost.
+    /// The compiler will prevent calls to this if anyone has an outstanding
+    /// mutable reference from [`RenderFrameHostHandle::try_borrow_mut`].
+    /// This will return `None` if the RenderFrameHost were already destroyed.
+    #[allow(dead_code)]
+    pub fn try_borrow<'a>(&'a self) -> Option<impl AsRef<ffi::content::RenderFrameHost> + 'a> {
+        let ref_non_mut = self.obs.as_ref().borrow();
+        if ref_non_mut.rfh.is_null() {
+            None
+        } else {
+            Some(RenderFrameHostRef(ref_non_mut))
+        }
+    }
+}
+
+impl<'wc> Drop for RenderFrameHostHandle<'wc> {
+    fn drop(&mut self) {
+        // Unregister our observer.
+        let superclass_ptr = cast_to_superclass(self.obs.as_ref().borrow_mut().peer_mut());
+        unsafe { self.web_contents.as_mut().RemoveObserver(superclass_ptr) };
+    }
+}
+
+impl<'wc> AsRef<ffi::content::RenderFrameHost> for RenderFrameHostHandle<'wc> {
+    fn as_ref(&self) -> &ffi::content::RenderFrameHost {
+        let ref_non_mut = self.obs.as_ref().borrow();
+        // Safety: the .rfh field is guaranteed to be a RenderFrameHost
+        // and we are observing its lifetime so it will be reset to null
+        // if destroyed.
+        unsafe { ref_non_mut.rfh.as_ref() }.expect("This RenderFrameHost was already destroyed")
+    }
+}
+
+impl<'wc> PinMut<ffi::content::RenderFrameHost> for RenderFrameHostHandle<'wc> {
+    fn pin_mut(&mut self) -> Pin<&mut ffi::content::RenderFrameHost> {
+        let ref_mut = self.obs.as_ref().borrow_mut();
+        // Safety: the .rfh field is guaranteed to be a RenderFrameHost
+        // and we are observing its lifetime so it will be reset to null
+        // if destroyed.
+        unsafe { ref_mut.rfh.as_mut().map(|p| Pin::new_unchecked(p)) }
+            .expect("This RenderFrameHost was already destroyed")
+    }
+}
+
+impl<'wc> Deref for RenderFrameHostHandle<'wc> {
+    type Target = ffi::content::RenderFrameHost;
+    fn deref(&self) -> &Self::Target {
+        self.as_ref()
+    }
+}
+
+#[doc(hidden)]
+struct RenderFrameHostRefMut<'a>(RefMut<'a, RenderFrameHostForWebContents>);
+
+#[doc(hidden)]
+struct RenderFrameHostRef<'a>(Ref<'a, RenderFrameHostForWebContents>);
+
+impl<'a> AsRef<ffi::content::RenderFrameHost> for RenderFrameHostRef<'a> {
+    fn as_ref(&self) -> &ffi::content::RenderFrameHost {
+        // Safety:
+        // Creation precondition is that self.0.rfh is not null
+        // and it can't be destroyed whilst this borrow exists.
+        unsafe { self.0.rfh.as_ref().unwrap() }
+    }
+}
+
+impl<'a> PinMut<ffi::content::RenderFrameHost> for RenderFrameHostRefMut<'a> {
+    fn pin_mut(&mut self) -> Pin<&mut ffi::content::RenderFrameHost> {
+        // Safety:
+        // Creation precondition is that self.0.rfh is not null
+        // and it can't be destroyed whilst this borrow exists.
+        unsafe { Pin::new_unchecked(self.0.rfh.as_mut().unwrap()) }
+    }
+}
+
+impl<'a> AsRef<ffi::content::RenderFrameHost> for RenderFrameHostRefMut<'a> {
+    fn as_ref(&self) -> &ffi::content::RenderFrameHost {
+        // Safety:
+        // Creation precondition is that self.0.rfh is not null
+        // and it can't be destroyed whilst this borrow exists.
+        unsafe { self.0.rfh.as_ref().unwrap() }
+    }
+}
+
+impl<'a> Deref for RenderFrameHostRef<'a> {
+    type Target = ffi::content::RenderFrameHost;
+    fn deref(&self) -> &Self::Target {
+        self.as_ref()
+    }
+}
+
+impl<'a> Deref for RenderFrameHostRefMut<'a> {
+    type Target = ffi::content::RenderFrameHost;
+    fn deref(&self) -> &Self::Target {
+        self.as_ref()
+    }
+}
+
+#[is_subclass(superclass("content::WebContentsObserver"))]
+#[doc(hidden)]
+pub struct RenderFrameHostForWebContents {
+    rfh: *mut ffi::content::RenderFrameHost,
+}
+
+impl ffi::content::WebContentsObserver_methods for RenderFrameHostForWebContents {
+    unsafe fn RenderFrameDeleted(&mut self, destroyed_rfh: *mut ffi::content::RenderFrameHost) {
+        if self.rfh == destroyed_rfh {
+            self.rfh = std::ptr::null_mut()
+        }
+    }
+}
+
+fn cast_to_superclass(
+    obs: Pin<&mut ffi::RenderFrameHostForWebContentsCpp>,
+) -> *mut ffi::content::WebContentsObserver {
+    // This horrid code will all go away once we implement
+    // https://github.com/google/autocxx/issues/592; safe wrappers will
+    // be automatically generated to allow upcasting to superclasses.
+    // NB this code is probably actually _wrong_ too meanwhile; we need to cast
+    // on the C++ side.
+    let subclass_obs_ptr =
+        unsafe { Pin::into_inner_unchecked(obs) } as *mut ffi::RenderFrameHostForWebContentsCpp;
+    unsafe {
+        std::mem::transmute::<
+            *mut ffi::RenderFrameHostForWebContentsCpp,
+            *mut ffi::content::WebContentsObserver,
+        >(subclass_obs_ptr)
+    }
+}
diff --git a/examples/llvm/Cargo.toml b/examples/llvm/Cargo.toml
new file mode 100644
index 0000000..d8806c8
--- /dev/null
+++ b/examples/llvm/Cargo.toml
@@ -0,0 +1,21 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-llvm-example"
+version = "0.1.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+[dependencies]
+cxx = "1.0.54"
+autocxx = { path = "../..", version="0.17.2" }
+
+[build-dependencies]
+autocxx-build = { path = "../../gen/build", version="0.17.2" }
+miette = { version="4.3", features = [ "fancy" ] }
diff --git a/examples/llvm/build.rs b/examples/llvm/build.rs
new file mode 100644
index 0000000..1bb82ce
--- /dev/null
+++ b/examples/llvm/build.rs
@@ -0,0 +1,23 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::path::PathBuf;
+fn main() -> miette::Result<()> {
+    let mut b = autocxx_build::Builder::new(
+        "src/lib.rs",
+        &[
+            PathBuf::from("/usr/include/llvm-13"),
+            PathBuf::from("/usr/include/llvm-c-13"),
+        ],
+    )
+    .build()?;
+
+    b.flag_if_supported("-std=c++14").compile("llvm");
+    println!("cargo:rerun-if-changed=src/lib.rs");
+    Ok(())
+}
diff --git a/examples/llvm/src/lib.rs b/examples/llvm/src/lib.rs
new file mode 100644
index 0000000..bd18880
--- /dev/null
+++ b/examples/llvm/src/lib.rs
@@ -0,0 +1,23 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*; // use all the main autocxx functions
+
+include_cpp! {
+    #include "llvm/Support/MemoryBuffer.h"
+    safety!(unsafe)
+    generate!("llvm::MemoryBuffer")
+}
+
+// Simply re-export the MemoryBuffer API to users of this library.
+// Generally speaking, the APIs generated by autocxx (or similar tools)
+// still contain C++-isms, and it's wise to consider making idiomatic
+// Rust wrappers instead of doing this.
+pub use ffi::llvm::MemoryBuffer;
+
+// It would be advisable to add tests here.
diff --git a/examples/non-trivial-type-on-stack/Cargo.toml b/examples/non-trivial-type-on-stack/Cargo.toml
new file mode 100644
index 0000000..ff227d4
--- /dev/null
+++ b/examples/non-trivial-type-on-stack/Cargo.toml
@@ -0,0 +1,21 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-non-trivial-type-on-stack-example"
+version = "0.1.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+[dependencies]
+cxx = "1.0.54"
+autocxx = { path = "../..", version="0.22.0" }
+
+[build-dependencies]
+autocxx-build = { path = "../../gen/build", version="0.22.0" }
+miette = { version="4.3", features = [ "fancy" ] }
diff --git a/examples/non-trivial-type-on-stack/build.rs b/examples/non-trivial-type-on-stack/build.rs
new file mode 100644
index 0000000..f83a228
--- /dev/null
+++ b/examples/non-trivial-type-on-stack/build.rs
@@ -0,0 +1,17 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() -> miette::Result<()> {
+    let path = std::path::PathBuf::from("src");
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path]).build()?;
+    b.flag_if_supported("-std=c++14")
+        .compile("autocxx-non-trivial-type-on-stack-example");
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/cpp.h");
+    Ok(())
+}
diff --git a/examples/non-trivial-type-on-stack/src/cpp.h b/examples/non-trivial-type-on-stack/src/cpp.h
new file mode 100644
index 0000000..9cb6502
--- /dev/null
+++ b/examples/non-trivial-type-on-stack/src/cpp.h
@@ -0,0 +1,24 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#pragma once
+#include <iostream>
+
+class MessageBuffer {
+public:
+  // std::string is not a trivial type because in some STL implementations
+  // it may contain a self-referential pointer.
+  void add_blurb(std::string blurb) {
+    message += blurb;
+  }
+  std::string get() const {
+    return message;
+  }
+private:
+  std::string message;
+};
diff --git a/examples/non-trivial-type-on-stack/src/main.rs b/examples/non-trivial-type-on-stack/src/main.rs
new file mode 100644
index 0000000..32dcdd7
--- /dev/null
+++ b/examples/non-trivial-type-on-stack/src/main.rs
@@ -0,0 +1,30 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*;
+
+include_cpp! {
+    // C++ headers we want to include.
+    #include "cpp.h"
+    safety!(unsafe)
+    // A non-trivial C++ type
+    generate!("MessageBuffer")
+}
+
+fn main() {
+    // Put the non-trivial C++ type on the Rust stack.
+    moveit! { let mut msg = ffi::MessageBuffer::new(); }
+    // Call methods on it.
+    msg.as_mut().add_blurb("Hello");
+    msg.as_mut().add_blurb(" world!");
+
+    assert_eq!(
+        msg.get().as_ref().unwrap().to_string_lossy(),
+        "Hello world!"
+    );
+}
diff --git a/examples/pod/Cargo.toml b/examples/pod/Cargo.toml
new file mode 100644
index 0000000..71bd5a0
--- /dev/null
+++ b/examples/pod/Cargo.toml
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-pod-example"
+version = "0.1.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+[dependencies]
+cxx = "1.0.54"
+autocxx = { path = "../..", version="0.22.0" }
+
+[build-dependencies]
+autocxx-build = { path = "../../gen/build", version="0.22.0" }
+miette = { version="4.3", features = [ "fancy" ] }
diff --git a/examples/pod/build.rs b/examples/pod/build.rs
new file mode 100644
index 0000000..a6bd95c
--- /dev/null
+++ b/examples/pod/build.rs
@@ -0,0 +1,17 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() -> miette::Result<()> {
+    let path = std::path::PathBuf::from("src");
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path]).build()?;
+    b.flag_if_supported("-std=c++14")
+        .compile("autocxx-pod-example");
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/cpp.h");
+    Ok(())
+}
diff --git a/examples/pod/src/cpp.h b/examples/pod/src/cpp.h
new file mode 100644
index 0000000..94d1466
--- /dev/null
+++ b/examples/pod/src/cpp.h
@@ -0,0 +1,27 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#pragma once
+#include <iostream>
+
+struct Point {
+  int x;
+  int y;
+};
+
+class Rect {
+public:
+  Point top_left;
+  Point bottom_right;
+  int width() const { return bottom_right.x - top_left.x; }
+  int height() const { return bottom_right.y - top_left.y; }
+};
+
+inline void print_point(Point p) {
+  std::cout << "(" << p.x << ", " << p.y << ")\n";
+}
diff --git a/examples/pod/src/main.rs b/examples/pod/src/main.rs
new file mode 100644
index 0000000..7a8b659
--- /dev/null
+++ b/examples/pod/src/main.rs
@@ -0,0 +1,40 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*;
+
+include_cpp! {
+    // C++ headers we want to include.
+    #include "cpp.h"
+    // Safety policy. We are marking that this whole C++ inclusion is unsafe
+    // which means the functions themselves do not need to be marked
+    // as unsafe. Other policies are possible.
+    safety!(unsafe)
+    // What types and functions we want to generate
+    generate_pod!("Rect")
+    generate!("print_point")
+}
+
+use ffi::{Point, Rect};
+
+// A simple example dealing with plain-old-data types.
+
+fn main() {
+    let r = Rect {
+        top_left: Point { x: 3, y: 3 },
+        bottom_right: Point { x: 12, y: 15 },
+    };
+    // r.width() and r.height() return an autocxx::c_int
+    // which we need to unpackage. It is hoped that one day cxx will
+    // natively support 'int' and friends, and that won't be necessary.
+    let center = Point {
+        x: r.top_left.x + r.width().0 / 2,
+        y: r.top_left.y + r.height().0 / 2,
+    };
+    ffi::print_point(center);
+}
diff --git a/examples/s2/Cargo.toml b/examples/s2/Cargo.toml
new file mode 100644
index 0000000..994a381
--- /dev/null
+++ b/examples/s2/Cargo.toml
@@ -0,0 +1,23 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-s2-example"
+version = "0.1.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cxx = "1.0.54"
+autocxx = { path = "../..", version="0.22.0" }
+
+[build-dependencies]
+autocxx-build = { path = "../../gen/build", version="0.22.0" }
+miette = { version="4.3", features = [ "fancy" ] }
diff --git a/examples/s2/README.md b/examples/s2/README.md
new file mode 100644
index 0000000..36a56ca
--- /dev/null
+++ b/examples/s2/README.md
@@ -0,0 +1,5 @@
+To build this example:
+* `git submodule update --init --recursive s2geometry`
+* `cargo run`
+
+Thanks to @nside for inspiring this example.
diff --git a/examples/s2/build.rs b/examples/s2/build.rs
new file mode 100644
index 0000000..e61c1af
--- /dev/null
+++ b/examples/s2/build.rs
@@ -0,0 +1,20 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() -> miette::Result<()> {
+    // It's necessary to use an absolute path here because the
+    // C++ codegen and the macro codegen appears to be run from different
+    // working directories.
+    let path = std::path::PathBuf::from("s2geometry/src");
+    let path2 = std::path::PathBuf::from("src");
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path, &path2]).build()?;
+    b.flag_if_supported("-std=c++14")
+        .compile("autocxx-s2-example");
+    println!("cargo:rerun-if-changed=src/main.rs");
+    Ok(())
+}
diff --git a/examples/s2/s2geometry b/examples/s2/s2geometry
new file mode 160000
index 0000000..0c4c460
--- /dev/null
+++ b/examples/s2/s2geometry
@@ -0,0 +1 @@
+Subproject commit 0c4c460bdfe696da303641771f9def900b3e440f
diff --git a/examples/s2/src/extras.h b/examples/s2/src/extras.h
new file mode 100644
index 0000000..927a30d
--- /dev/null
+++ b/examples/s2/src/extras.h
@@ -0,0 +1,27 @@
+// Copyright 2020 Google LLC
+//  
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//  
+//    https://www.apache.org/licenses/LICENSE-2.0 
+//  
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include "s2/r2.h"
+#include <sstream>
+
+// autocxx isn't yet smart enough to do anything with the R2Point
+// structure, so here we've manually made a cheeky little API to
+// do something useful with it.
+inline std::string describe_point(R2Point pt) {
+    std::ostringstream oss;
+    oss << pt.x() << ", " << pt.y();
+    return oss.str();
+}
diff --git a/examples/s2/src/main.rs b/examples/s2/src/main.rs
new file mode 100644
index 0000000..141b80e
--- /dev/null
+++ b/examples/s2/src/main.rs
@@ -0,0 +1,53 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*;
+
+include_cpp! {
+    // C++ headers we want to include.
+    #include "s2/r2rect.h"
+    #include "extras.h"
+    // Safety policy. We are marking that this whole C++ inclusion is unsafe
+    // which means the functions themselves do not need to be marked
+    // as unsafe. Other policies are possible.
+    safety!(unsafe)
+    // What types and functions we want to generate
+    generate!("R1Interval")
+    generate!("R2Rect")
+    generate!("describe_point")
+}
+
+// Everything that we care about is inlined, so we don't have to do
+// anything fancy to build or link any external code.
+fn main() {
+    // Create a couple of R1Intervals using their pre-existing C++
+    // constructors. Actually these will be cxx::UniquePtr<R1Interval>s.
+    let i1 = ffi::R1Interval::new(1.0f64, 2.0f64).within_unique_ptr();
+    let i2 = ffi::R1Interval::new(5.0f64, 6.0f64).within_unique_ptr();
+    // Create a rect, passing references to the intervals.
+    // Note this is 'new1' because R2Rect has multiple
+    // overloaded constructors. 'cargo expand', `cargo doc`
+    // or a rust-analyzer IDE is useful here.
+    let r = ffi::R2Rect::new1(&i1, &i2).within_unique_ptr();
+    // Call a method on one of these objects. As it happens,
+    // this returns a
+    // UniquePtr< ... opaque object representing a point ...>.
+    let center = r.GetCenter();
+    // As the object is too complex for autocxx to understand,
+    // we can't do much with it except to send it into other
+    // C++ APIs. We'll make our own which describes the point.
+    // This will return a std::string, which autocxx will
+    // convert to a UniquePtr<CxxString>. We can convert that
+    // back to a Rust string and print it, so long as we
+    // take care to decide how to deal with non-UTF8
+    // characters (hence the unwrap).
+    println!(
+        "Center of rectangle is {}",
+        ffi::describe_point(center).to_str().unwrap()
+    );
+}
diff --git a/examples/steam-mini/Cargo.toml b/examples/steam-mini/Cargo.toml
new file mode 100644
index 0000000..b292f25
--- /dev/null
+++ b/examples/steam-mini/Cargo.toml
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-steam-example"
+version = "0.1.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cxx = "1.0.54"
+autocxx = { path = "../..", version="0.22.0" }
+
+[build-dependencies]
+autocxx-build = { path = "../../gen/build", version="0.22.0" }
+miette = { version="4.3", features = [ "fancy" ] }
diff --git a/examples/steam-mini/README.md b/examples/steam-mini/README.md
new file mode 100644
index 0000000..325c899
--- /dev/null
+++ b/examples/steam-mini/README.md
@@ -0,0 +1,2 @@
+This example is supposed to simulate something a bit like the Steam API,
+where you're given a pointer to a collection of virtual methods.
diff --git a/examples/steam-mini/build.rs b/examples/steam-mini/build.rs
new file mode 100644
index 0000000..d9b3c68
--- /dev/null
+++ b/examples/steam-mini/build.rs
@@ -0,0 +1,17 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() -> miette::Result<()> {
+    let path = std::path::PathBuf::from("steam/src");
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path]).build()?;
+    b.flag_if_supported("-std=c++14")
+        .file("steam/src/steam.cc")
+        .compile("autocxx-steam-example");
+    println!("cargo:rerun-if-changed=src/main.rs");
+    Ok(())
+}
diff --git a/examples/steam-mini/src/main.rs b/examples/steam-mini/src/main.rs
new file mode 100644
index 0000000..e5d6e64
--- /dev/null
+++ b/examples/steam-mini/src/main.rs
@@ -0,0 +1,65 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*;
+
+include_cpp! {
+    // C++ headers we want to include.
+    #include "steam.h"
+    // Safety policy. We are marking that this whole C++ inclusion is unsafe
+    // which means the functions themselves do not need to be marked
+    // as unsafe. Other policies are possible.
+    safety!(unsafe)
+    // What types and functions we want to generate
+    generate!("GetSteamEngine")
+    generate!("IEngine")
+}
+
+fn main() {
+    // The "Steam" API gives us a void* on which we call virtual functions.
+    // This is a void*.
+    let steam_engine = ffi::GetSteamEngine();
+    // We need to know three things about this void*:
+    // 1. What is it? We know from the (fake) Steam documentation that it's
+    //    an IEngine*
+    // 2. Do we gain ownership of it? i.e. is it our responsibility to
+    //    destroy it?
+    // 3. If not, C++ presumably continues to own it. Does C++ ever destroy
+    //    it?
+    // None of these things are really encoded in the nature of a void*
+    // so you have to figure them out from the documentation.
+    //
+    // In this case, the first is easy:
+    let steam_engine = steam_engine as *mut ffi::IEngine;
+    //
+    // You then need to figure out how to expose it in Rust. Ideally, any
+    // such lifetime invariants would be handled by the compiler.
+    // If C++ is passing ownership of this object to us, and we have the
+    // prerogative to destroy it whenever we wish, then
+    // simply use [`cxx::UniquePtr::from_raw`]. If it goes out of scope in
+    // Rust the underlying C++ object will be deleted.
+    //
+    // Let's assume life is more complicated, and we must never destroy this
+    // object (because it's owned by C++). In that case, we ideally want
+    // to convert the pointer into a Rust reference with the lifetime of
+    // the program.
+    //
+    // We also have to promise to Rust that it'll never move in memory.
+    // C++ doesn't do that, so that's OK.
+    let mut steam_engine = unsafe { std::pin::Pin::new_unchecked(&mut *steam_engine) };
+    // Now we have steam_engine which is a Pin<&mut SteamEngine>
+    // Each time we call a method we need to add `as_mut()`
+    // as per the pattern explained in
+    // https://doc.rust-lang.org/std/pin/struct.Pin.html#method.as_mut
+    steam_engine
+        .as_mut()
+        .ConnectToGlobalUser(autocxx::c_int(12));
+    steam_engine
+        .as_mut()
+        .DisconnectGlobalUser(autocxx::c_int(12));
+}
diff --git a/examples/steam-mini/steam/src/steam.cc b/examples/steam-mini/steam/src/steam.cc
new file mode 100644
index 0000000..2c45488
--- /dev/null
+++ b/examples/steam-mini/steam/src/steam.cc
@@ -0,0 +1,28 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#include <iostream>
+#include "steam.h"
+
+// This is a simulation of _something like_ the way the steam API works.
+// None of this code is really from Steam.
+
+class SteamEngine : public IEngine {
+    int ConnectToGlobalUser(int user_id) {
+        std::cout << "ConnectToGlobalUser, passed " << user_id << std::endl;
+        return 42;
+    }
+    void DisconnectGlobalUser(int user_id) {
+        std::cout << "DisconnectGlobalUser, passed " << user_id << std::endl;
+    }
+};
+
+void* GetSteamEngine() {
+    return new SteamEngine();
+}
+
diff --git a/examples/steam-mini/steam/src/steam.h b/examples/steam-mini/steam/src/steam.h
new file mode 100644
index 0000000..f07aee3
--- /dev/null
+++ b/examples/steam-mini/steam/src/steam.h
@@ -0,0 +1,19 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#pragma once
+
+// This is a simulation of _something like_ the way the steam API works.
+
+class IEngine {
+public:
+	virtual int ConnectToGlobalUser(int) = 0;
+    virtual void DisconnectGlobalUser(int user_id) = 0;
+};
+
+void* GetSteamEngine(); // return an IEngine*
diff --git a/examples/subclass/Cargo.toml b/examples/subclass/Cargo.toml
new file mode 100644
index 0000000..8a01205
--- /dev/null
+++ b/examples/subclass/Cargo.toml
@@ -0,0 +1,27 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-subclass-example"
+version = "0.1.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cxx = "1.0.54"
+autocxx = { path = "../..", version="0.22.0" }
+uwuify = "0.2.2"
+textwrap = "0.14"
+fastrand = "1.5.0"
+
+[build-dependencies]
+autocxx-build = { path = "../../gen/build", version="0.22.0" }
+regex = "1.5.4"
+miette = { version="4.3", features = [ "fancy" ] }
diff --git a/examples/subclass/README.md b/examples/subclass/README.md
new file mode 100644
index 0000000..b46d001
--- /dev/null
+++ b/examples/subclass/README.md
@@ -0,0 +1 @@
+This example shows Rust types 'inheriting' from C++ subclasses.
diff --git a/examples/subclass/build.rs b/examples/subclass/build.rs
new file mode 100644
index 0000000..b41e924
--- /dev/null
+++ b/examples/subclass/build.rs
@@ -0,0 +1,93 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() -> miette::Result<()> {
+    let path = std::path::PathBuf::from("src");
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path])
+        .auto_allowlist(true)
+        .build()?;
+    b.flag_if_supported("-std=c++17")
+        .file("src/messages.cc")
+        .compile("autocxx-subclass-example");
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/messages.cc");
+    println!("cargo:rerun-if-changed=src/messages.h");
+
+    // The following line is *unrelated* to autocxx builds and is
+    // just designed to ensure that example code doesn't get out of sync
+    // from copies in comments.
+    ensure_comments_match_real_code(&std::path::PathBuf::from("src/main.rs"));
+    Ok(())
+}
+
+use std::fs::File;
+use std::io::BufRead;
+use std::io::BufReader;
+use std::io::Lines;
+use std::path::Path;
+
+enum CommentMatcherState {
+    Searching,
+    EatingBacktickLine(Lines<BufReader<File>>),
+    SearchingForFirstLine(Lines<BufReader<File>>),
+    Found(Lines<BufReader<File>>),
+}
+
+fn ensure_comments_match_real_code(rs_file: &Path) {
+    use regex::Regex;
+    let start_re = Regex::new(r"// .*from ([\w/]+\.\w+).*").unwrap();
+    let strip_comment_re = Regex::new(r"// (.*)").unwrap();
+    let file = File::open(rs_file).unwrap();
+    let lines = BufReader::new(file).lines();
+    let mut state = CommentMatcherState::Searching;
+    for line in lines {
+        let line = line.unwrap();
+        state = match state {
+            CommentMatcherState::Searching => match start_re.captures(&line) {
+                Some(captures) => {
+                    let fname = captures.get(1).unwrap().as_str();
+                    let srcfile = File::open(fname).unwrap();
+                    let srclines = BufReader::new(srcfile).lines();
+                    CommentMatcherState::EatingBacktickLine(srclines)
+                }
+                None => CommentMatcherState::Searching,
+            },
+            CommentMatcherState::EatingBacktickLine(srclines) => {
+                CommentMatcherState::SearchingForFirstLine(srclines)
+            }
+            CommentMatcherState::SearchingForFirstLine(mut srclines) => {
+                match strip_comment_re.captures(&line) {
+                    Some(captures) => {
+                        let mut found = false;
+                        while !found {
+                            let srcline = srclines.next().unwrap().unwrap();
+                            found = captures.get(1).unwrap().as_str() == srcline;
+                        }
+                        CommentMatcherState::Found(srclines)
+                    }
+                    None => CommentMatcherState::Searching,
+                }
+            }
+            CommentMatcherState::Found(mut srclines) => {
+                if line == "// ```" {
+                    CommentMatcherState::Searching
+                } else {
+                    match strip_comment_re.captures(&line) {
+                        Some(captures) => {
+                            let actual = captures.get(1).unwrap().as_str();
+                            let expected = srclines.next().unwrap().unwrap();
+                            assert_eq!(expected, actual);
+                            CommentMatcherState::Found(srclines)
+                        }
+                        None => CommentMatcherState::Searching,
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/examples/subclass/src/billy.rs b/examples/subclass/src/billy.rs
new file mode 100644
index 0000000..5defe1b
--- /dev/null
+++ b/examples/subclass/src/billy.rs
@@ -0,0 +1,20 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub(crate) static SHAKESPEARE_QUOTES: [&str; 10] = [
+    "All that glitters is not gold",
+    "Hell is empty and all the devils are here.",
+    "Good night, good night! parting is such sweet sorrow, That I shall say good night till it be morrow.",
+    "These violent delights have violent ends...",
+    "Something is rotten in the state of Denmark.",
+    "Love all, trust a few, do wrong to none.",
+    "The lady doth protest too much, methinks.",
+    "Brevity is the soul of wit.",
+    "Uneasy lies the head that wears a crown.",
+    "Now is the winter of our discontent.",
+];
diff --git a/examples/subclass/src/main.rs b/examples/subclass/src/main.rs
new file mode 100644
index 0000000..2841598
--- /dev/null
+++ b/examples/subclass/src/main.rs
@@ -0,0 +1,145 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This example shows some Rust subclasses of C++ classes.
+
+mod billy;
+mod uwu;
+
+use autocxx::prelude::*;
+use autocxx::subclass::prelude::*;
+use cxx::CxxString;
+use std::cell::RefCell;
+use std::rc::Rc;
+
+include_cpp! {
+    #include "messages.h"
+    safety!(unsafe) // unsafety policy; see docs
+}
+
+// Here's the definition of MessageDisplayer from src/messages.h:
+// ```cpp
+// class MessageDisplayer {
+// public:
+//     virtual void display_message(const std::string& message) const = 0;
+//     virtual ~MessageDisplayer() {};
+// };
+// ```
+// The following lines define a subclass of MessageDisplayer.
+// See the main function at the bottom for how this subclass
+// is instantiated.
+
+#[is_subclass(superclass("MessageDisplayer"))]
+#[derive(Default)]
+pub struct UwuDisplayer {}
+
+impl ffi::MessageDisplayer_methods for UwuDisplayer {
+    fn display_message(&self, msg: &CxxString) {
+        let uwu = uwu::uwu(msg.to_str().unwrap());
+        println!("{}", uwu);
+    }
+}
+
+// And here's a different pure virtual class.
+// Here's its definition from src/messages.h:
+// ```cpp
+// class MessageProducer {
+// public:
+//     virtual std::string get_message() const = 0;
+//     virtual ~MessageProducer() {};
+// };
+// ```
+// This one is notable only in that the interface of the C++ class
+// involves std::string, yet in Rust the subclass uses
+// std::unique_ptr<std::string> (for all the normal reasons in autocxx -
+// for now, at least, we can't hold non-trivial C++ objects on the Rust stack.)
+// All the boxing and unboxing is done automatically by autocxx layers.
+
+#[is_subclass(superclass("MessageProducer"))]
+#[derive(Default)]
+pub struct QuoteProducer;
+
+// Here we've chosen to have an explicit constructor instead rather than deriving
+// from CppSubclassDefault. It's functionally the same.
+impl QuoteProducer {
+    fn new() -> Rc<RefCell<Self>> {
+        Self::new_rust_owned(Self::default())
+    }
+}
+
+impl ffi::MessageProducer_methods for QuoteProducer {
+    fn get_message(&self) -> cxx::UniquePtr<CxxString> {
+        use ffi::ToCppString;
+        billy::SHAKESPEARE_QUOTES[fastrand::usize(0..billy::SHAKESPEARE_QUOTES.len())].into_cpp()
+    }
+}
+
+// Here's another subclass of the same 'displayer' class.
+// This one is more complex in two ways.
+//
+// First, we actually want to store some data here in our subclass.
+// That means we can't just allocate ourselves with Default::default().
+// And that means we need to be aware of the cpp_peer field which is
+// added by the #[subclass] macro.
+//
+// Second, we're going to simulate the observer/listener type pattern
+// in C++ where a const* is used to send messages around a codebase yet
+// recipients need to react by mutating themselves or otherwise actively
+// doing stuff. In C++ you'd probably need a const_cast. Here we use
+// interior mutability.
+
+#[is_subclass(superclass("MessageDisplayer"))]
+pub struct BoxDisplayer {
+    message_count: RefCell<usize>,
+}
+
+impl BoxDisplayer {
+    fn new() -> Rc<RefCell<Self>> {
+        Self::new_rust_owned(Self {
+            // As we're allocating this class ourselves instead of using [`Default`]
+            // we need to initialize the `cpp_peer` member ourselves. This member is
+            // inserted by the `#[is_subclass]` annotation. autocxx will
+            // later use this to store a pointer back to the C++ peer.
+            cpp_peer: Default::default(),
+            message_count: RefCell::new(1usize),
+        })
+    }
+}
+
+impl ffi::MessageDisplayer_methods for BoxDisplayer {
+    fn display_message(&self, msg: &CxxString) {
+        let msg = textwrap::fill(msg.to_str().unwrap(), 70);
+        let horz_line = std::iter::repeat("#").take(74).collect::<String>();
+        println!("{}", horz_line);
+        let msgmsg = format!("Message {}", self.message_count.borrow());
+        self.message_count.replace_with(|old| *old + 1usize);
+        println!("# {:^70} #", msgmsg);
+        println!("{}", horz_line);
+        for l in msg.lines() {
+            println!("# {:^70} #", l);
+        }
+        println!("{}", horz_line);
+    }
+}
+
+fn main() {
+    ffi::register_cpp_thingies();
+    // Construct a Rust-owned UwuDisplayer. We can also construct
+    // a C++-owned or self-owned subclass - see docs for `CppSubclass`.
+    let uwu = UwuDisplayer::default_rust_owned();
+    // The next line casts the &UwuDisplayerCpp to a &MessageDisplayer.
+    ffi::register_displayer(uwu.as_ref().borrow().as_ref());
+    // Constructs in just the same way as the first one, but using
+    // our explicit constructor.
+    let boxd = BoxDisplayer::new();
+    ffi::register_displayer(boxd.as_ref().borrow().as_ref());
+    let shakespeare = QuoteProducer::new();
+    ffi::register_producer(shakespeare.as_ref().borrow().as_ref());
+    ffi::run_demo();
+    ffi::run_demo();
+}
diff --git a/examples/subclass/src/messages.cc b/examples/subclass/src/messages.cc
new file mode 100644
index 0000000..4d24aab
--- /dev/null
+++ b/examples/subclass/src/messages.cc
@@ -0,0 +1,70 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This example shows Rust subclasses of C++ classes.
+// See messages.h and main.rs for most of the interesting code.
+
+#include "messages.h"
+#include <ctime>
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <functional>
+ 
+class CppExampleProducer : public MessageProducer {
+public:
+    CppExampleProducer() {}
+    std::string get_message() const {
+        std::time_t result = std::time(nullptr);
+        std::ostringstream st;
+        st << std::asctime(std::localtime(&result))
+           << result << " seconds since the Epoch";
+        return st.str();
+    }
+};
+
+class CppExampleDisplayer : public MessageDisplayer {
+public:
+    CppExampleDisplayer() {}
+    void display_message(const std::string& msg) const {
+        std::cout << "Message: " << msg << std::endl;
+    }
+};
+
+std::vector<std::reference_wrapper<const MessageProducer>> producers;
+std::vector<std::reference_wrapper<const MessageDisplayer>> displayers;
+CppExampleProducer cpp_producer;
+CppExampleDisplayer cpp_displayer;
+
+
+// Maybe we should use a language which tracks lifetimes
+// better than this. If only such a language existed.
+void register_displayer(const MessageDisplayer& displayer) {
+    displayers.push_back(displayer);
+}
+
+void register_producer(const MessageProducer& producer) {
+    producers.push_back(producer);
+}
+
+void register_cpp_thingies() {
+    register_producer(cpp_producer);
+    register_displayer(cpp_displayer);
+}
+
+void run_demo() {
+    for (auto& producer: producers) {
+        auto msg = producer.get().get_message();
+        for (auto& displayer: displayers) {
+            displayer.get().display_message(msg);
+            std::cout << std::endl;
+        }
+        std::cout << std::endl;
+    }
+}
+
diff --git a/examples/subclass/src/messages.h b/examples/subclass/src/messages.h
new file mode 100644
index 0000000..02ff248
--- /dev/null
+++ b/examples/subclass/src/messages.h
@@ -0,0 +1,33 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This example shows Rust subclasses of C++ classes.
+// Here are the C++ classes which we're subclassing.
+
+#pragma once
+
+#include <string>
+#include <memory>
+
+class MessageProducer {
+public:
+    virtual std::string get_message() const = 0;
+    virtual ~MessageProducer() {};
+};
+
+class MessageDisplayer {
+public:
+    virtual void display_message(const std::string& message) const = 0;
+    virtual ~MessageDisplayer() {};
+};
+
+void register_cpp_thingies();
+void register_producer(const MessageProducer& producer);
+void register_displayer(const MessageDisplayer& displayer);
+
+void run_demo();
diff --git a/examples/subclass/src/uwu.rs b/examples/subclass/src/uwu.rs
new file mode 100644
index 0000000..ce02510
--- /dev/null
+++ b/examples/subclass/src/uwu.rs
@@ -0,0 +1,17 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub(crate) fn uwu(msg: &str) -> String {
+    uwuifier::uwuify_str_sse(msg)
+}
+
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+pub(crate) fn uwu(_msg: &str) -> String {
+    "uwuification is unavailable for this pwatform :(".to_string()
+}
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
new file mode 100644
index 0000000..2895526
--- /dev/null
+++ b/gen/build/Cargo.toml
@@ -0,0 +1,31 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-build"
+version = "0.22.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+license = "MIT OR Apache-2.0"
+description = "Safe autogenerated interop between Rust and C++"
+repository = "https://github.com/google/autocxx"
+keywords = ["ffi"]
+categories = ["development-tools::ffi", "api-bindings"]
+
+[features]
+runtime = [ "autocxx-engine/runtime" ]
+static = [ "autocxx-engine/static" ]
+
+[dependencies]
+autocxx-engine = { version="=0.22.0", path="../../engine", features = ["build"] }
+env_logger = "0.9.0"
+indexmap = "1.8"
+
+[dependencies.syn]
+version = "1.0"
+features = [ "full" ]
diff --git a/gen/build/README.md b/gen/build/README.md
new file mode 100644
index 0000000..9b91d4a
--- /dev/null
+++ b/gen/build/README.md
@@ -0,0 +1 @@
+This crate is a [component of autocxx](https://google.github.io/autocxx/).
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
new file mode 100644
index 0000000..c1df580
--- /dev/null
+++ b/gen/build/src/lib.rs
@@ -0,0 +1,51 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![forbid(unsafe_code)]
+
+use autocxx_engine::{BuilderContext, RebuildDependencyRecorder};
+use indexmap::set::IndexSet as HashSet;
+use std::{io::Write, sync::Mutex};
+
+pub type Builder = autocxx_engine::Builder<'static, CargoBuilderContext>;
+
+#[doc(hidden)]
+pub struct CargoBuilderContext;
+
+impl BuilderContext for CargoBuilderContext {
+    fn setup() {
+        env_logger::builder()
+            .format(|buf, record| writeln!(buf, "cargo:warning=MESSAGE:{}", record.args()))
+            .init();
+    }
+    fn get_dependency_recorder() -> Option<Box<dyn RebuildDependencyRecorder>> {
+        Some(Box::new(CargoRebuildDependencyRecorder::new()))
+    }
+}
+
+#[derive(Debug)]
+struct CargoRebuildDependencyRecorder {
+    printed_already: Mutex<HashSet<String>>,
+}
+
+impl CargoRebuildDependencyRecorder {
+    fn new() -> Self {
+        Self {
+            printed_already: Mutex::new(HashSet::new()),
+        }
+    }
+}
+
+impl RebuildDependencyRecorder for CargoRebuildDependencyRecorder {
+    fn record_header_file_dependency(&self, filename: &str) {
+        let mut already = self.printed_already.lock().unwrap();
+        if already.insert(filename.into()) {
+            println!("cargo:rerun-if-changed={}", filename);
+        }
+    }
+}
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
new file mode 100644
index 0000000..744d29a
--- /dev/null
+++ b/gen/cmd/Cargo.toml
@@ -0,0 +1,41 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-gen"
+version = "0.22.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+license = "MIT OR Apache-2.0"
+description = "Safe autogenerated interop between Rust and C++"
+repository = "https://github.com/google/autocxx"
+keywords = ["ffi"]
+categories = ["development-tools::ffi", "api-bindings"]
+
+[features]
+runtime = [ "autocxx-engine/runtime" ]
+static = [ "autocxx-engine/static" ]
+
+[dependencies]
+autocxx-engine = { version="=0.22.0", path="../../engine" }
+clap = { version = "3.1.2", features = ["cargo"] }
+proc-macro2 = "1.0"
+env_logger = "0.9.0"
+miette = { version="4.3", features=["fancy"]}
+pathdiff = "0.2.1"
+indexmap = "1.8"
+
+[dev-dependencies]
+assert_cmd = "1.0.3"
+tempdir = "0.3.7"
+autocxx-integration-tests = { path = "../../integration-tests", version="=0.22.0" }
+# This is necessary for building the projects created
+# by the trybuild test system...
+autocxx = { path="../.." }
+cxx = "1.0.54"
+itertools = "0.10.3"
\ No newline at end of file
diff --git a/gen/cmd/README.md b/gen/cmd/README.md
new file mode 100644
index 0000000..9b91d4a
--- /dev/null
+++ b/gen/cmd/README.md
@@ -0,0 +1 @@
+This crate is a [component of autocxx](https://google.github.io/autocxx/).
diff --git a/gen/cmd/src/depfile.rs b/gen/cmd/src/depfile.rs
new file mode 100644
index 0000000..5bb7a66
--- /dev/null
+++ b/gen/cmd/src/depfile.rs
@@ -0,0 +1,102 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{
+    fs::File,
+    io::Write,
+    path::{Path, PathBuf},
+};
+
+/// Type which knows how to write a .d file. All outputs depend on all
+/// dependencies.
+pub(crate) struct Depfile {
+    file: File,
+    outputs: Vec<String>,
+    dependencies: Vec<String>,
+    depfile_dir: PathBuf,
+}
+
+impl Depfile {
+    pub(crate) fn new(depfile: &Path) -> std::io::Result<Self> {
+        let file = File::create(depfile)?;
+        Ok(Self {
+            file,
+            outputs: Vec::new(),
+            dependencies: Vec::new(),
+            depfile_dir: depfile.parent().unwrap().to_path_buf(),
+        })
+    }
+
+    pub(crate) fn add_dependency(&mut self, dependency: &Path) {
+        self.dependencies.push(self.relativize(dependency))
+    }
+
+    pub(crate) fn add_output(&mut self, output: &Path) {
+        self.outputs.push(self.relativize(output))
+    }
+
+    pub(crate) fn write(&mut self) -> std::io::Result<()> {
+        let dependency_list = self.dependencies.join(" \\\n  ");
+        for output in &self.outputs {
+            self.file
+                .write_all(format!("{}: {}\n\n", output, dependency_list).as_bytes())?
+        }
+        Ok(())
+    }
+
+    /// Return a string giving a relative path from the depfile.
+    fn relativize(&self, path: &Path) -> String {
+        pathdiff::diff_paths(path, &self.depfile_dir)
+            .expect("Unable to make a relative path from the depfile's directory to the dependency")
+            .to_str()
+            .expect("Unable to represent the file path in a UTF8 encoding")
+            .into()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::{fs::File, io::Read};
+
+    use tempdir::TempDir;
+
+    use super::Depfile;
+
+    #[test]
+    fn test_simple_depfile() {
+        let tmp_dir = TempDir::new("depfile-test").unwrap();
+        let f = tmp_dir.path().join("depfile.d");
+        let mut df = Depfile::new(&f).unwrap();
+        df.add_output(&tmp_dir.path().join("a/b"));
+        df.add_dependency(&tmp_dir.path().join("c/d"));
+        df.add_dependency(&tmp_dir.path().join("e/f"));
+        df.write().unwrap();
+
+        let mut f = File::open(&f).unwrap();
+        let mut contents = String::new();
+        f.read_to_string(&mut contents).unwrap();
+        assert_eq!(contents, "a/b: c/d \\\n  e/f\n\n");
+    }
+
+    #[test]
+    fn test_multiple_outputs() {
+        let tmp_dir = TempDir::new("depfile-test").unwrap();
+        let f = tmp_dir.path().join("depfile.d");
+        let mut df = Depfile::new(&f).unwrap();
+        df.add_output(&tmp_dir.path().join("a/b"));
+        df.add_output(&tmp_dir.path().join("z"));
+        df.add_dependency(&tmp_dir.path().join("c/d"));
+        df.add_dependency(&tmp_dir.path().join("e/f"));
+        df.write().unwrap();
+
+        let mut f = File::open(&f).unwrap();
+        let mut contents = String::new();
+        f.read_to_string(&mut contents).unwrap();
+        assert_eq!(contents, "a/b: c/d \\\n  e/f\n\nz: c/d \\\n  e/f\n\n");
+    }
+}
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
new file mode 100644
index 0000000..20f278b
--- /dev/null
+++ b/gen/cmd/src/main.rs
@@ -0,0 +1,428 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![forbid(unsafe_code)]
+
+mod depfile;
+
+use autocxx_engine::{
+    generate_rs_archive, generate_rs_single, parse_file, AutocxxgenHeaderNamer, CxxgenHeaderNamer,
+    RebuildDependencyRecorder,
+};
+use clap::{crate_authors, crate_version, Arg, ArgGroup, Command};
+use depfile::Depfile;
+use indexmap::IndexSet;
+use miette::IntoDiagnostic;
+use std::cell::RefCell;
+use std::io::{Read, Write};
+use std::path::PathBuf;
+use std::rc::Rc;
+use std::{cell::Cell, fs::File, path::Path};
+
+pub(crate) static BLANK: &str = "// Blank autocxx placeholder";
+
+static LONG_HELP: &str = "
+Command line utility to expand the Rust 'autocxx' include_cpp! directive.
+
+This tool can generate both the C++ and Rust side binding code for
+a Rust file containing an include_cpp! directive.
+
+If you're using cargo, don't use this: use autocxx_build instead,
+which is much easier to include in build.rs build scripts. You'd likely
+use this tool only if you're using some non-Cargo build system. If
+that's you, read on.
+
+This tool has three modes: generate the C++; or generate
+a Rust file which can be included by the autocxx_macro; or generate an archive
+containing multiple Rust files to be expanded by different autocxx macros.
+You may specify multiple modes, or of course, invoke the tool multiple times.
+
+In any mode, you'll need to pass the source Rust file name and the C++
+include path. You may pass multiple Rust files, each of which may contain
+multiple include_cpp! or cxx::bridge macros.
+
+There are three basic ways to use this tool, depending on the flexibility
+of your build system.
+
+Does your build system require fixed output filenames, or can it enumerate
+whatever files are generated?
+
+If it's flexible, then use
+  --gen-rs-include --gen-cpp
+An arbitrary number of .h, .cc and .rs files will be generated, depending
+on how many cxx::bridge and include_cpp macros are encountered and their contents.
+When building the rust code, simply ensure that AUTOCXX_RS or OUT_DIR is set to
+teach rustc where to find these .rs files.
+
+If your build system needs to be told exactly what C++ files are generated,
+additionally use --generate-exact <N> You are then guaranteed to get
+exactly 'n' files as follows:
+  gen<n>.h
+  autocxxgen<n>.h
+  gen<n>.cc
+Some of them may be blank. If the tool finds too many include_cpp or cxx::bridge
+macros to fit within that allowance, the build will fail.
+
+If your build system additionally requires that Rust files have fixed
+filenames, then you should use
+  --gen-rs-archive
+instead of
+  --gen-rs-include
+and you will need to give AUTOCXX_RS_JSON_ARCHIVE when building the Rust code.
+The output filename is named gen.rs.json.
+
+This teaches rustc (and the autocxx macro) that all the different Rust bindings
+for multiple different autocxx macros have been archived into this single file.
+";
+
+fn main() -> miette::Result<()> {
+    let matches = Command::new("autocxx-gen")
+        .version(crate_version!())
+        .author(crate_authors!())
+        .about("Generates bindings files from Rust files that contain include_cpp! macros")
+        .long_about(LONG_HELP)
+        .arg(
+            Arg::new("INPUT")
+                .help("Sets the input .rs files to use")
+                .required(true)
+                .multiple_occurrences(true)
+        )
+        .arg(
+            Arg::new("outdir")
+                .short('o')
+                .long("outdir")
+                .allow_invalid_utf8(true)
+                .value_name("PATH")
+                .help("output directory path")
+                .takes_value(true)
+                .required(true),
+        )
+        .arg(
+            Arg::new("inc")
+                .short('I')
+                .long("inc")
+                .multiple_occurrences(true)
+                .number_of_values(1)
+                .value_name("INCLUDE DIRS")
+                .help("include path")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("cpp-extension")
+                .long("cpp-extension")
+                .value_name("EXTENSION")
+                .default_value("cc")
+                .help("C++ filename extension")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("gen-cpp")
+                .long("gen-cpp")
+                .help("whether to generate C++ implementation and header files")
+        )
+        .arg(
+            Arg::new("gen-rs-include")
+                .long("gen-rs-include")
+                .help("whether to generate Rust files for inclusion using autocxx_macro (suffix will be .include.rs)")
+        )
+        .arg(
+            Arg::new("gen-rs-archive")
+                .long("gen-rs-archive")
+                .help("whether to generate an archive of multiple sets of Rust bindings for use by autocxx_macro (suffix will be .rs.json)")
+        )
+        .group(ArgGroup::new("mode")
+            .required(true)
+            .multiple(true)
+            .arg("gen-cpp")
+            .arg("gen-rs-include")
+            .arg("gen-rs-archive")
+        )
+        .arg(
+            Arg::new("generate-exact")
+                .long("generate-exact")
+                .value_name("NUM")
+                .help("assume and ensure there are exactly NUM bridge blocks in the file. Only applies for --gen-cpp or --gen-rs-include")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("fix-rs-include-name")
+                .long("fix-rs-include-name")
+                .help("Make the name of the .rs file predictable. You must set AUTOCXX_RS_FILE during Rust build time to educate autocxx_macro about your choice.")
+                .requires("gen-rs-include")
+        )
+        .arg(
+            Arg::new("auto-allowlist")
+                .long("auto-allowlist")
+                .help("Dynamically construct allowlist from real uses of APIs.")
+        )
+        .arg(
+            Arg::new("suppress-system-headers")
+                .long("suppress-system-headers")
+                .help("Do not refer to any system headers from generated code. May be useful for minimization.")
+        )
+        .arg(
+            Arg::new("cxx-impl-annotations")
+                .long("cxx-impl-annotations")
+                .value_name("ANNOTATION")
+                .help("prefix for symbols to be exported from C++ bindings, e.g. __attribute__ ((visibility (\"default\")))")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("cxx-h-path")
+                .long("cxx-h-path")
+                .value_name("PREFIX")
+                .help("prefix for path to cxx.h (from the cxx crate) within #include statements. Must end in /")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("cxxgen-h-path")
+                .long("cxxgen-h-path")
+                .value_name("PREFIX")
+                .help("prefix for path to cxxgen.h (which we generate into the output directory) within #include statements. Must end in /")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("depfile")
+                .long("depfile")
+                .value_name("DEPFILE")
+                .help("A .d file to write")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("clang-args")
+                .last(true)
+                .multiple_occurrences(true)
+                .help("Extra arguments to pass to Clang"),
+        )
+        .get_matches();
+
+    env_logger::builder().init();
+    let incs = matches
+        .values_of("inc")
+        .unwrap_or_default()
+        .map(PathBuf::from)
+        .collect::<Vec<_>>();
+    let extra_clang_args: Vec<_> = matches
+        .values_of("clang-args")
+        .unwrap_or_default()
+        .collect();
+    let suppress_system_headers = matches.is_present("suppress-system-headers");
+    let desired_number = matches
+        .value_of("generate-exact")
+        .map(|s| s.parse::<usize>().unwrap());
+    let autocxxgen_header_counter = Cell::new(0);
+    let autocxxgen_header_namer = if desired_number.is_some() {
+        AutocxxgenHeaderNamer(Box::new(|_| {
+            let r = name_autocxxgen_h(autocxxgen_header_counter.get());
+            autocxxgen_header_counter.set(autocxxgen_header_counter.get() + 1);
+            r
+        }))
+    } else {
+        Default::default()
+    };
+    let cxxgen_header_counter = Cell::new(0);
+    let cxxgen_header_namer = if desired_number.is_some() {
+        CxxgenHeaderNamer(Box::new(|| {
+            let r = name_cxxgen_h(cxxgen_header_counter.get());
+            cxxgen_header_counter.set(cxxgen_header_counter.get() + 1);
+            r
+        }))
+    } else {
+        Default::default()
+    };
+    let cpp_codegen_options = autocxx_engine::CppCodegenOptions {
+        suppress_system_headers,
+        cxx_impl_annotations: get_option_string("cxx-impl-annotations", &matches),
+        path_to_cxx_h: get_option_string("cxx-h-path", &matches),
+        path_to_cxxgen_h: get_option_string("cxxgen-h-path", &matches),
+        autocxxgen_header_namer,
+        cxxgen_header_namer,
+    };
+    let depfile = match matches.value_of("depfile") {
+        None => None,
+        Some(depfile_path) => {
+            let depfile_path = PathBuf::from(depfile_path);
+            Some(Rc::new(RefCell::new(
+                Depfile::new(&depfile_path).into_diagnostic()?,
+            )))
+        }
+    };
+    let auto_allowlist = matches.is_present("auto-allowlist");
+
+    let mut parsed_files = Vec::new();
+    for input in matches.values_of("INPUT").expect("No INPUT was provided") {
+        // Parse all the .rs files we're asked to process, first.
+        // Spot any fundamental parsing or command line problems before we start
+        // to do the complex processing.
+        let parsed_file = parse_file(input, auto_allowlist)?;
+        parsed_files.push(parsed_file);
+    }
+
+    for parsed_file in parsed_files.iter_mut() {
+        // Now actually handle all the include_cpp directives we found,
+        // which is the complex bit where we interpret all the C+.
+        let dep_recorder: Option<Box<dyn RebuildDependencyRecorder>> = depfile
+            .as_ref()
+            .map(|rc| get_dependency_recorder(rc.clone()));
+        parsed_file.resolve_all(
+            incs.clone(),
+            &extra_clang_args,
+            dep_recorder,
+            &cpp_codegen_options,
+        )?;
+    }
+
+    // Finally start to write the C++ and Rust out.
+    let outdir: PathBuf = matches.value_of_os("outdir").unwrap().into();
+    let mut writer = FileWriter {
+        depfile: &depfile,
+        outdir: &outdir,
+        written: IndexSet::new(),
+    };
+    if matches.is_present("gen-cpp") {
+        let cpp = matches.value_of("cpp-extension").unwrap();
+        let name_cc_file = |counter| format!("gen{}.{}", counter, cpp);
+        let mut counter = 0usize;
+        for include_cxx in parsed_files
+            .iter()
+            .flat_map(|file| file.get_cpp_buildables())
+        {
+            let generations = include_cxx
+                .generate_h_and_cxx(&cpp_codegen_options)
+                .expect("Unable to generate header and C++ code");
+            for pair in generations.0 {
+                let cppname = name_cc_file(counter);
+                writer.write_to_file(cppname, &pair.implementation.unwrap_or_default())?;
+                writer.write_to_file(pair.header_name, &pair.header)?;
+                counter += 1;
+            }
+        }
+        drop(cpp_codegen_options);
+        // Write placeholders to ensure we always make exactly 'n' of each file type.
+        writer.write_placeholders(counter, desired_number, name_cc_file)?;
+        writer.write_placeholders(
+            cxxgen_header_counter.into_inner(),
+            desired_number,
+            name_cxxgen_h,
+        )?;
+        writer.write_placeholders(
+            autocxxgen_header_counter.into_inner(),
+            desired_number,
+            name_autocxxgen_h,
+        )?;
+    }
+    //writer.write_placeholders(header_counter.into_inner(), desired_number, "h")?;
+    if matches.is_present("gen-rs-include") {
+        let rust_buildables = parsed_files
+            .iter()
+            .flat_map(|parsed_file| parsed_file.get_rs_outputs());
+        for (counter, include_cxx) in rust_buildables.enumerate() {
+            let rs_code = generate_rs_single(include_cxx);
+            let fname = if matches.is_present("fix-rs-include-name") {
+                format!("gen{}.include.rs", counter)
+            } else {
+                rs_code.filename
+            };
+            writer.write_to_file(fname, rs_code.code.as_bytes())?;
+        }
+    }
+    if matches.is_present("gen-rs-archive") {
+        let rust_buildables = parsed_files
+            .iter()
+            .flat_map(|parsed_file| parsed_file.get_rs_outputs());
+        let json = generate_rs_archive(rust_buildables);
+        eprintln!("Writing to gen.rs.json in {:?}", outdir);
+        writer.write_to_file("gen.rs.json".into(), json.as_bytes())?;
+    }
+    if let Some(depfile) = depfile {
+        depfile.borrow_mut().write().into_diagnostic()?;
+    }
+    Ok(())
+}
+
+fn name_autocxxgen_h(counter: usize) -> String {
+    format!("autocxxgen{}.h", counter)
+}
+
+fn name_cxxgen_h(counter: usize) -> String {
+    format!("gen{}.h", counter)
+}
+
+fn get_dependency_recorder(depfile: Rc<RefCell<Depfile>>) -> Box<dyn RebuildDependencyRecorder> {
+    Box::new(RecordIntoDepfile(depfile))
+}
+
+fn get_option_string(option: &str, matches: &clap::ArgMatches) -> Option<String> {
+    let cxx_impl_annotations = matches.value_of(option).map(|s| s.to_string());
+    cxx_impl_annotations
+}
+
+struct FileWriter<'a> {
+    depfile: &'a Option<Rc<RefCell<Depfile>>>,
+    outdir: &'a Path,
+    written: IndexSet<String>,
+}
+
+impl<'a> FileWriter<'a> {
+    fn write_placeholders<F: FnOnce(usize) -> String + Copy>(
+        &mut self,
+        mut counter: usize,
+        desired_number: Option<usize>,
+        filename: F,
+    ) -> miette::Result<()> {
+        if let Some(desired_number) = desired_number {
+            if counter > desired_number {
+                return Err(miette::Report::msg("More files were generated than expected. Increase the value passed to --generate-exact or reduce the number of include_cpp! sections."));
+            }
+            while counter < desired_number {
+                let fname = filename(counter);
+                self.write_to_file(fname, BLANK.as_bytes())?;
+                counter += 1;
+            }
+        }
+        Ok(())
+    }
+
+    fn write_to_file(&mut self, filename: String, content: &[u8]) -> miette::Result<()> {
+        let path = self.outdir.join(&filename);
+        if let Some(depfile) = self.depfile {
+            depfile.borrow_mut().add_output(&path);
+        }
+        {
+            let f = File::open(&path);
+            if let Ok(mut f) = f {
+                let mut existing_content = Vec::new();
+                let r = f.read_to_end(&mut existing_content);
+                if r.is_ok() && existing_content == content {
+                    return Ok(()); // don't change timestamp on existing file unnecessarily
+                }
+            }
+        }
+        let mut f = File::create(&path).into_diagnostic()?;
+        f.write_all(content).into_diagnostic()?;
+        if self.written.contains(&filename) {
+            return Err(miette::Report::msg(format!("autocxx_gen would write two files entitled '{}' which would have conflicting contents. Consider using --generate-exact.", filename)));
+        }
+        self.written.insert(filename);
+        Ok(())
+    }
+}
+
+struct RecordIntoDepfile(Rc<RefCell<Depfile>>);
+
+impl RebuildDependencyRecorder for RecordIntoDepfile {
+    fn record_header_file_dependency(&self, filename: &str) {
+        self.0.borrow_mut().add_dependency(&PathBuf::from(filename))
+    }
+}
+
+impl std::fmt::Debug for RecordIntoDepfile {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "<depfile>")
+    }
+}
diff --git a/gen/cmd/tests/cmd_test.rs b/gen/cmd/tests/cmd_test.rs
new file mode 100644
index 0000000..d0e671e
--- /dev/null
+++ b/gen/cmd/tests/cmd_test.rs
@@ -0,0 +1,302 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{convert::TryInto, fs::File, io::Write, path::Path};
+
+use indexmap::map::IndexMap as HashMap;
+
+use assert_cmd::Command;
+use autocxx_integration_tests::{build_from_folder, RsFindMode};
+use itertools::Itertools;
+use tempdir::TempDir;
+
+static MAIN_RS: &str = concat!(
+    include_str!("../../../demo/src/main.rs"),
+    "#[link(name = \"autocxx-demo\")]\nextern \"C\" {}"
+);
+static INPUT_H: &str = include_str!("../../../demo/src/input.h");
+static BLANK: &str = "// Blank autocxx placeholder";
+
+static MAIN2_RS: &str = concat!(
+    include_str!("data/main2.rs"),
+    "#[link(name = \"autocxx-demo\")]\nextern \"C\" {}"
+);
+static DIRECTIVE1_RS: &str = include_str!("data/directive1.rs");
+static DIRECTIVE2_RS: &str = include_str!("data/directive2.rs");
+static INPUT2_H: &str = include_str!("data/input2.h");
+static INPUT3_H: &str = include_str!("data/input3.h");
+
+const KEEP_TEMPDIRS: bool = false;
+
+#[test]
+fn test_help() -> Result<(), Box<dyn std::error::Error>> {
+    let mut cmd = Command::cargo_bin("autocxx-gen")?;
+    cmd.arg("-h").assert().success();
+    Ok(())
+}
+
+enum RsGenMode {
+    Single,
+    Archive,
+}
+
+fn base_test<F>(
+    tmp_dir: &TempDir,
+    rs_gen_mode: RsGenMode,
+    arg_modifier: F,
+) -> Result<(), Box<dyn std::error::Error>>
+where
+    F: FnOnce(&mut Command),
+{
+    let mut standard_files = HashMap::new();
+    standard_files.insert("input.h", INPUT_H.as_bytes());
+    standard_files.insert("main.rs", MAIN_RS.as_bytes());
+    let result = base_test_ex(
+        tmp_dir,
+        rs_gen_mode,
+        arg_modifier,
+        standard_files,
+        vec!["main.rs"],
+    );
+    assert_contentful(tmp_dir, "gen0.cc");
+    result
+}
+
+fn base_test_ex<F>(
+    tmp_dir: &TempDir,
+    rs_gen_mode: RsGenMode,
+    arg_modifier: F,
+    files_to_write: HashMap<&str, &[u8]>,
+    files_to_process: Vec<&str>,
+) -> Result<(), Box<dyn std::error::Error>>
+where
+    F: FnOnce(&mut Command),
+{
+    let demo_code_dir = tmp_dir.path().join("demo");
+    std::fs::create_dir(&demo_code_dir).unwrap();
+    for (filename, content) in files_to_write {
+        write_to_file(&demo_code_dir, filename, content);
+    }
+    let mut cmd = Command::cargo_bin("autocxx-gen")?;
+    arg_modifier(&mut cmd);
+    cmd.arg("--inc")
+        .arg(demo_code_dir.to_str().unwrap())
+        .arg("--outdir")
+        .arg(tmp_dir.path().to_str().unwrap())
+        .arg("--gen-cpp");
+    cmd.arg(match rs_gen_mode {
+        RsGenMode::Single => "--gen-rs-include",
+        RsGenMode::Archive => "--gen-rs-archive",
+    });
+    for file in files_to_process {
+        cmd.arg(demo_code_dir.join(file));
+    }
+    let output = cmd.output();
+    if let Ok(output) = output {
+        eprintln!("Cmd stdout: {:?}", std::str::from_utf8(&output.stdout));
+        eprintln!("Cmd stderr: {:?}", std::str::from_utf8(&output.stderr));
+    }
+    cmd.assert().success();
+    Ok(())
+}
+
+#[test]
+fn test_gen() -> Result<(), Box<dyn std::error::Error>> {
+    let tmp_dir = TempDir::new("example")?;
+    base_test(&tmp_dir, RsGenMode::Single, |_| {})?;
+    File::create(tmp_dir.path().join("cxx.h"))
+        .and_then(|mut cxx_h| cxx_h.write_all(autocxx_engine::HEADER.as_bytes()))?;
+    std::env::set_var("OUT_DIR", tmp_dir.path().to_str().unwrap());
+    let r = build_from_folder(
+        tmp_dir.path(),
+        &tmp_dir.path().join("demo/main.rs"),
+        vec![tmp_dir.path().join("autocxx-ffi-default-gen.rs")],
+        &["gen0.cc"],
+        RsFindMode::AutocxxRs,
+    );
+    if KEEP_TEMPDIRS {
+        println!("Tempdir: {:?}", tmp_dir.into_path().to_str());
+    }
+    r.unwrap();
+    Ok(())
+}
+
+#[test]
+fn test_gen_archive() -> Result<(), Box<dyn std::error::Error>> {
+    let tmp_dir = TempDir::new("example")?;
+    base_test(&tmp_dir, RsGenMode::Archive, |_| {})?;
+    File::create(tmp_dir.path().join("cxx.h"))
+        .and_then(|mut cxx_h| cxx_h.write_all(autocxx_engine::HEADER.as_bytes()))?;
+    let r = build_from_folder(
+        tmp_dir.path(),
+        &tmp_dir.path().join("demo/main.rs"),
+        vec![tmp_dir.path().join("gen.rs.json")],
+        &["gen0.cc"],
+        RsFindMode::AutocxxRsArchive,
+    );
+    if KEEP_TEMPDIRS {
+        println!("Tempdir: {:?}", tmp_dir.into_path().to_str());
+    }
+    r.unwrap();
+    Ok(())
+}
+
+#[test]
+fn test_gen_multiple_in_archive() -> Result<(), Box<dyn std::error::Error>> {
+    let tmp_dir = TempDir::new("example")?;
+
+    let mut files = HashMap::new();
+    files.insert("input2.h", INPUT2_H.as_bytes());
+    files.insert("input3.h", INPUT3_H.as_bytes());
+    files.insert("main.rs", MAIN2_RS.as_bytes());
+    files.insert("directive1.rs", DIRECTIVE1_RS.as_bytes());
+    files.insert("directive2.rs", DIRECTIVE2_RS.as_bytes());
+    base_test_ex(
+        &tmp_dir,
+        RsGenMode::Archive,
+        |cmd| {
+            cmd.arg("--generate-exact").arg("8");
+        },
+        files,
+        vec!["directive1.rs", "directive2.rs"],
+    )?;
+    File::create(tmp_dir.path().join("cxx.h"))
+        .and_then(|mut cxx_h| cxx_h.write_all(autocxx_engine::HEADER.as_bytes()))?;
+    // We've asked to create 8 C++ files, mostly blank. Build 'em all.
+    let cpp_files = (0..7).map(|id| format!("gen{}.cc", id)).collect_vec();
+    let cpp_files = cpp_files.iter().map(|s| s.as_str()).collect_vec();
+    let r = build_from_folder(
+        tmp_dir.path(),
+        &tmp_dir.path().join("demo/main.rs"),
+        vec![tmp_dir.path().join("gen.rs.json")],
+        &cpp_files,
+        RsFindMode::AutocxxRsArchive,
+    );
+    if KEEP_TEMPDIRS {
+        println!("Tempdir: {:?}", tmp_dir.into_path().to_str());
+    }
+    r.unwrap();
+    Ok(())
+}
+
+#[test]
+fn test_include_prefixes() -> Result<(), Box<dyn std::error::Error>> {
+    let tmp_dir = TempDir::new("example")?;
+    base_test(&tmp_dir, RsGenMode::Single, |cmd| {
+        cmd.arg("--cxx-h-path")
+            .arg("foo/")
+            .arg("--cxxgen-h-path")
+            .arg("bar/")
+            .arg("--generate-exact")
+            .arg("3");
+    })?;
+    assert_contains(&tmp_dir, "autocxxgen0.h", "foo/cxx.h");
+    // Currently we don't test cxxgen-h-path because we build the demo code
+    // which doesn't refer to generated cxx header code.
+    Ok(())
+}
+
+#[test]
+fn test_gen_fixed_num() -> Result<(), Box<dyn std::error::Error>> {
+    let tmp_dir = TempDir::new("example")?;
+    let depfile = tmp_dir.path().join("test.d");
+    base_test(&tmp_dir, RsGenMode::Single, |cmd| {
+        cmd.arg("--generate-exact")
+            .arg("2")
+            .arg("--depfile")
+            .arg(depfile);
+    })?;
+    assert_contentful(&tmp_dir, "gen0.cc");
+    assert_contentful(&tmp_dir, "gen0.h");
+    assert_not_contentful(&tmp_dir, "gen1.cc");
+    assert_contentful(&tmp_dir, "autocxxgen0.h");
+    assert_not_contentful(&tmp_dir, "gen1.h");
+    assert_not_contentful(&tmp_dir, "autocxxgen1.h");
+    assert_contentful(&tmp_dir, "autocxx-ffi-default-gen.rs");
+    assert_contentful(&tmp_dir, "test.d");
+    File::create(tmp_dir.path().join("cxx.h"))
+        .and_then(|mut cxx_h| cxx_h.write_all(autocxx_engine::HEADER.as_bytes()))?;
+    let r = build_from_folder(
+        tmp_dir.path(),
+        &tmp_dir.path().join("demo/main.rs"),
+        vec![tmp_dir.path().join("autocxx-ffi-default-gen.rs")],
+        &["gen0.cc"],
+        RsFindMode::AutocxxRs,
+    );
+    if KEEP_TEMPDIRS {
+        println!("Tempdir: {:?}", tmp_dir.into_path().to_str());
+    }
+    r.unwrap();
+    Ok(())
+}
+
+#[test]
+fn test_gen_preprocess() -> Result<(), Box<dyn std::error::Error>> {
+    let tmp_dir = TempDir::new("example")?;
+    let prepro_path = tmp_dir.path().join("preprocessed.h");
+    base_test(&tmp_dir, RsGenMode::Single, |cmd| {
+        cmd.env("AUTOCXX_PREPROCESS", prepro_path.to_str().unwrap());
+    })?;
+    assert_contentful(&tmp_dir, "preprocessed.h");
+    // Check that a random thing from one of the headers in
+    // `ALL_KNOWN_SYSTEM_HEADERS` is included.
+    assert!(std::fs::read_to_string(prepro_path)?.contains("integer_sequence"));
+    Ok(())
+}
+
+#[test]
+fn test_gen_repro() -> Result<(), Box<dyn std::error::Error>> {
+    let tmp_dir = TempDir::new("example")?;
+    let repro_path = tmp_dir.path().join("repro.json");
+    base_test(&tmp_dir, RsGenMode::Single, |cmd| {
+        cmd.env("AUTOCXX_REPRO_CASE", repro_path.to_str().unwrap());
+    })?;
+    assert_contentful(&tmp_dir, "repro.json");
+    // Check that a random thing from one of the headers in
+    // `ALL_KNOWN_SYSTEM_HEADERS` is included.
+    assert!(std::fs::read_to_string(repro_path)?.contains("integer_sequence"));
+    Ok(())
+}
+
+fn write_to_file(dir: &Path, filename: &str, content: &[u8]) {
+    let path = dir.join(filename);
+    let mut f = File::create(&path).expect("Unable to create file");
+    f.write_all(content).expect("Unable to write file");
+}
+
+fn assert_contentful(outdir: &TempDir, fname: &str) {
+    let p = outdir.path().join(fname);
+    if !p.exists() {
+        panic!("File {} didn't exist", p.to_string_lossy());
+    }
+    assert!(
+        p.metadata().unwrap().len() > BLANK.len().try_into().unwrap(),
+        "File {} is empty",
+        fname
+    );
+}
+
+fn assert_not_contentful(outdir: &TempDir, fname: &str) {
+    let p = outdir.path().join(fname);
+    if !p.exists() {
+        panic!("File {} didn't exist", p.to_string_lossy());
+    }
+    assert!(
+        p.metadata().unwrap().len() <= BLANK.len().try_into().unwrap(),
+        "File {} is not empty; it contains {}",
+        fname,
+        std::fs::read_to_string(&p).unwrap_or_default()
+    );
+}
+
+fn assert_contains(outdir: &TempDir, fname: &str, pattern: &str) {
+    let p = outdir.path().join(fname);
+    let content = std::fs::read_to_string(&p).expect(fname);
+    eprintln!("content = {}", content);
+    assert!(content.contains(pattern));
+}
diff --git a/gen/cmd/tests/data/directive1.rs b/gen/cmd/tests/data/directive1.rs
new file mode 100644
index 0000000..792ab06
--- /dev/null
+++ b/gen/cmd/tests/data/directive1.rs
@@ -0,0 +1,16 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*;
+include_cpp! {
+    #include "input2.h"
+    safety!(unsafe_ffi)
+    generate!("get_hello")
+}
+
+pub use ffi::get_hello;
\ No newline at end of file
diff --git a/gen/cmd/tests/data/directive2.rs b/gen/cmd/tests/data/directive2.rs
new file mode 100644
index 0000000..eaa451b
--- /dev/null
+++ b/gen/cmd/tests/data/directive2.rs
@@ -0,0 +1,16 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*;
+include_cpp! {
+    #include "input3.h"
+    safety!(unsafe_ffi)
+    generate!("get_goodbye")
+}
+
+pub use ffi::get_goodbye;
diff --git a/gen/cmd/tests/data/input2.h b/gen/cmd/tests/data/input2.h
new file mode 100644
index 0000000..715b8ec
--- /dev/null
+++ b/gen/cmd/tests/data/input2.h
@@ -0,0 +1,15 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#pragma once
+
+#include <string>
+
+inline std::string get_hello() {
+    return "hello!";
+}
\ No newline at end of file
diff --git a/gen/cmd/tests/data/input3.h b/gen/cmd/tests/data/input3.h
new file mode 100644
index 0000000..d5d2c87
--- /dev/null
+++ b/gen/cmd/tests/data/input3.h
@@ -0,0 +1,15 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#pragma once
+
+#include <string>
+
+inline std::string get_goodbye() {
+    return "goodbye!";
+}
\ No newline at end of file
diff --git a/gen/cmd/tests/data/main2.rs b/gen/cmd/tests/data/main2.rs
new file mode 100644
index 0000000..1509843
--- /dev/null
+++ b/gen/cmd/tests/data/main2.rs
@@ -0,0 +1,15 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod directive1;
+mod directive2;
+
+fn main() {
+    println!("C++ says {} then {}", directive1::get_hello().as_ref().unwrap().to_string_lossy(),
+        directive2::get_goodbye().as_ref().unwrap().to_string_lossy());
+}
diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml
new file mode 100644
index 0000000..c139479
--- /dev/null
+++ b/integration-tests/Cargo.toml
@@ -0,0 +1,49 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-integration-tests"
+version = "0.22.0"
+autotests = false
+edition = "2021"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+license = "MIT OR Apache-2.0"
+description = "Safe autogenerated interop between Rust and C++"
+repository = "https://github.com/google/autocxx"
+keywords = ["ffi"]
+categories = ["development-tools::ffi", "api-bindings"]
+
+[dependencies]
+proc-macro2 = "1.0.11"
+trybuild = "1.0.53"
+test-log = "0.2.2"
+env_logger = "0.9.0"
+rust_info = "0.3.1"
+cc = "1.0"
+quote = "1.0"
+once_cell = "1.7"
+autocxx-engine = { version="=0.22.0", path="../engine", features = ["build"] }
+# This is necessary for building the projects created
+# by the trybuild test system...
+autocxx = { path="..", version="=0.22.0" }
+link-cplusplus = "1.0"
+tempfile = "3.1"
+indoc = "1.0"
+log = "0.4"
+cxx = "1.0.54"
+itertools = "0.10"
+
+[dependencies.syn]
+version = "1.0.39"
+features = [ "full" ]
+#features = [ "full", "extra-traits" ]
+
+[[test]]
+name = "integration_tests"
+path = "tests/lib.rs"
+harness = true
diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs
new file mode 100644
index 0000000..3499af8
--- /dev/null
+++ b/integration-tests/src/lib.rs
@@ -0,0 +1,481 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{
+    ffi::OsStr,
+    fs::File,
+    io::{Read, Write},
+    panic::RefUnwindSafe,
+    path::{Path, PathBuf},
+    sync::Mutex,
+};
+
+use autocxx_engine::{
+    Builder, BuilderBuild, BuilderContext, BuilderError, RebuildDependencyRecorder, HEADER,
+};
+use log::info;
+use once_cell::sync::OnceCell;
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, TokenStreamExt};
+use syn::Token;
+use tempfile::{tempdir, TempDir};
+
+const KEEP_TEMPDIRS: bool = false;
+
+/// API to run a documentation test. Panics if the test fails.
+/// Guarantees not to emit anything to stdout and so can be run in an mdbook context.
+pub fn doctest(
+    cxx_code: &str,
+    header_code: &str,
+    rust_code: TokenStream,
+    manifest_dir: &OsStr,
+) -> Result<(), TestError> {
+    std::env::set_var("CARGO_PKG_NAME", "autocxx-integration-tests");
+    std::env::set_var("CARGO_MANIFEST_DIR", manifest_dir);
+    do_run_test_manual(cxx_code, header_code, rust_code, None, None)
+}
+
+fn configure_builder(b: &mut BuilderBuild) -> &mut BuilderBuild {
+    let target = rust_info::get().target_triple.unwrap();
+    b.host(&target)
+        .target(&target)
+        .opt_level(1)
+        .flag("-std=c++14") // For clang
+        .flag_if_supported("/GX") // Enable C++ exceptions for msvc
+        .flag_if_supported("-Wall")
+        .flag_if_supported("-Werror")
+}
+
+/// What environment variables we should set in order to tell rustc how to find
+/// the Rust code.
+pub enum RsFindMode {
+    AutocxxRs,
+    AutocxxRsArchive,
+}
+
+/// API to test building pre-generated files.
+pub fn build_from_folder(
+    folder: &Path,
+    main_rs_file: &Path,
+    generated_rs_files: Vec<PathBuf>,
+    cpp_files: &[&str],
+    rs_find_mode: RsFindMode,
+) -> Result<(), TestError> {
+    let target_dir = folder.join("target");
+    std::fs::create_dir(&target_dir).unwrap();
+    let mut b = BuilderBuild::new();
+    for cpp_file in cpp_files.iter() {
+        b.file(folder.join(cpp_file));
+    }
+    configure_builder(&mut b)
+        .out_dir(&target_dir)
+        .include(folder)
+        .include(folder.join("demo"))
+        .try_compile("autocxx-demo")
+        .map_err(TestError::CppBuild)?;
+    // use the trybuild crate to build the Rust file.
+    let r = get_builder().lock().unwrap().build(
+        &target_dir,
+        "autocxx-demo",
+        &folder,
+        &["input.h", "cxx.h"],
+        &main_rs_file,
+        generated_rs_files,
+        rs_find_mode,
+    );
+    if r.is_err() {
+        return Err(TestError::RsBuild); // details of Rust panic are a bit messy to include, and
+                                        // not important at the moment.
+    }
+    Ok(())
+}
+
+fn get_builder() -> &'static Mutex<LinkableTryBuilder> {
+    static INSTANCE: OnceCell<Mutex<LinkableTryBuilder>> = OnceCell::new();
+    INSTANCE.get_or_init(|| Mutex::new(LinkableTryBuilder::new()))
+}
+
+/// TryBuild which maintains a directory of libraries to link.
+/// This is desirable because otherwise, if we alter the RUSTFLAGS
+/// then trybuild rebuilds *everything* including all the dev-dependencies.
+/// This object exists purely so that we use the same RUSTFLAGS for every
+/// test case.
+struct LinkableTryBuilder {
+    /// Directory in which we'll keep any linkable libraries
+    temp_dir: TempDir,
+}
+
+impl LinkableTryBuilder {
+    fn new() -> Self {
+        LinkableTryBuilder {
+            temp_dir: tempdir().unwrap(),
+        }
+    }
+
+    fn move_items_into_temp_dir<P1: AsRef<Path>>(&self, src_path: &P1, pattern: &str) {
+        for item in std::fs::read_dir(src_path).unwrap() {
+            let item = item.unwrap();
+            if item.file_name().into_string().unwrap().contains(pattern) {
+                let dest = self.temp_dir.path().join(item.file_name());
+                if dest.exists() {
+                    std::fs::remove_file(&dest).unwrap();
+                }
+                if KEEP_TEMPDIRS {
+                    std::fs::copy(item.path(), dest).unwrap();
+                } else {
+                    std::fs::rename(item.path(), dest).unwrap();
+                }
+            }
+        }
+    }
+
+    #[allow(clippy::too_many_arguments)]
+    fn build<P1: AsRef<Path>, P2: AsRef<Path>, P3: AsRef<Path> + RefUnwindSafe>(
+        &self,
+        library_path: &P1,
+        library_name: &str,
+        header_path: &P2,
+        header_names: &[&str],
+        rs_path: &P3,
+        generated_rs_files: Vec<PathBuf>,
+        rs_find_mode: RsFindMode,
+    ) -> std::thread::Result<()> {
+        // Copy all items from the source dir into our temporary dir if their name matches
+        // the pattern given in `library_name`.
+        self.move_items_into_temp_dir(library_path, library_name);
+        for header_name in header_names {
+            self.move_items_into_temp_dir(header_path, header_name);
+        }
+        for generated_rs in generated_rs_files {
+            self.move_items_into_temp_dir(
+                &generated_rs.parent().unwrap(),
+                generated_rs.file_name().unwrap().to_str().unwrap(),
+            );
+        }
+        let temp_path = self.temp_dir.path().to_str().unwrap();
+        let mut rustflags = format!("-L {}", temp_path);
+        if std::env::var_os("AUTOCXX_ASAN").is_some() {
+            rustflags.push_str(" -Z sanitizer=address -Clinker=clang++ -Clink-arg=-fuse-ld=lld");
+        }
+        std::env::set_var("RUSTFLAGS", rustflags);
+        match rs_find_mode {
+            RsFindMode::AutocxxRs => std::env::set_var("AUTOCXX_RS", temp_path),
+            RsFindMode::AutocxxRsArchive => std::env::set_var(
+                "AUTOCXX_RS_JSON_ARCHIVE",
+                self.temp_dir.path().join("gen.rs.json"),
+            ),
+        };
+        std::panic::catch_unwind(|| {
+            let test_cases = trybuild::TestCases::new();
+            test_cases.pass(rs_path)
+        })
+    }
+}
+
+fn write_to_file(tdir: &TempDir, filename: &str, content: &str) -> PathBuf {
+    let path = tdir.path().join(filename);
+    let mut f = File::create(&path).unwrap();
+    f.write_all(content.as_bytes()).unwrap();
+    path
+}
+
+/// A positive test, we expect to pass.
+pub fn run_test(
+    cxx_code: &str,
+    header_code: &str,
+    rust_code: TokenStream,
+    generate: &[&str],
+    generate_pods: &[&str],
+) {
+    do_run_test(
+        cxx_code,
+        header_code,
+        rust_code,
+        directives_from_lists(generate, generate_pods, None),
+        None,
+        None,
+        None,
+    )
+    .unwrap()
+}
+
+// A trait for objects which can check the output of the code creation
+// process.
+pub trait CodeCheckerFns {
+    fn check_rust(&self, _rs: syn::File) -> Result<(), TestError> {
+        Ok(())
+    }
+    fn check_cpp(&self, _cpp: &[PathBuf]) -> Result<(), TestError> {
+        Ok(())
+    }
+    fn skip_build(&self) -> bool {
+        false
+    }
+}
+
+// A function applied to the resultant generated Rust code
+// which can be used to inspect that code.
+pub type CodeChecker = Box<dyn CodeCheckerFns>;
+
+// A trait for objects which can modify builders for testing purposes.
+pub trait BuilderModifierFns {
+    fn modify_autocxx_builder<'a>(
+        &self,
+        builder: Builder<'a, TestBuilderContext>,
+    ) -> Builder<'a, TestBuilderContext>;
+    fn modify_cc_builder<'a>(&self, builder: &'a mut cc::Build) -> &'a mut cc::Build {
+        builder
+    }
+}
+
+pub type BuilderModifier = Box<dyn BuilderModifierFns>;
+
+/// A positive test, we expect to pass.
+#[allow(clippy::too_many_arguments)] // least typing for each test
+pub fn run_test_ex(
+    cxx_code: &str,
+    header_code: &str,
+    rust_code: TokenStream,
+    directives: TokenStream,
+    builder_modifier: Option<BuilderModifier>,
+    code_checker: Option<CodeChecker>,
+    extra_rust: Option<TokenStream>,
+) {
+    do_run_test(
+        cxx_code,
+        header_code,
+        rust_code,
+        directives,
+        builder_modifier,
+        code_checker,
+        extra_rust,
+    )
+    .unwrap()
+}
+
+pub fn run_test_expect_fail(
+    cxx_code: &str,
+    header_code: &str,
+    rust_code: TokenStream,
+    generate: &[&str],
+    generate_pods: &[&str],
+) {
+    do_run_test(
+        cxx_code,
+        header_code,
+        rust_code,
+        directives_from_lists(generate, generate_pods, None),
+        None,
+        None,
+        None,
+    )
+    .expect_err("Unexpected success");
+}
+
+pub fn run_test_expect_fail_ex(
+    cxx_code: &str,
+    header_code: &str,
+    rust_code: TokenStream,
+    directives: TokenStream,
+    builder_modifier: Option<BuilderModifier>,
+    code_checker: Option<CodeChecker>,
+    extra_rust: Option<TokenStream>,
+) {
+    do_run_test(
+        cxx_code,
+        header_code,
+        rust_code,
+        directives,
+        builder_modifier,
+        code_checker,
+        extra_rust,
+    )
+    .expect_err("Unexpected success");
+}
+
+/// In the future maybe the tests will distinguish the exact type of failure expected.
+#[derive(Debug)]
+pub enum TestError {
+    AutoCxx(BuilderError),
+    CppBuild(cc::Error),
+    RsBuild,
+    NoRs,
+    RsFileOpen(std::io::Error),
+    RsFileRead(std::io::Error),
+    RsFileParse(syn::Error),
+    RsCodeExaminationFail(String),
+    CppCodeExaminationFail,
+}
+
+pub fn directives_from_lists(
+    generate: &[&str],
+    generate_pods: &[&str],
+    extra_directives: Option<TokenStream>,
+) -> TokenStream {
+    let generate = generate.iter().map(|s| {
+        quote! {
+            generate!(#s)
+        }
+    });
+    let generate_pods = generate_pods.iter().map(|s| {
+        quote! {
+            generate_pod!(#s)
+        }
+    });
+    quote! {
+        #(#generate)*
+        #(#generate_pods)*
+        #extra_directives
+    }
+}
+
+#[allow(clippy::too_many_arguments)] // least typing for each test
+pub fn do_run_test(
+    cxx_code: &str,
+    header_code: &str,
+    rust_code: TokenStream,
+    directives: TokenStream,
+    builder_modifier: Option<BuilderModifier>,
+    rust_code_checker: Option<CodeChecker>,
+    extra_rust: Option<TokenStream>,
+) -> Result<(), TestError> {
+    let hexathorpe = Token![#](Span::call_site());
+    let unexpanded_rust = quote! {
+            use autocxx::prelude::*;
+
+            include_cpp!(
+                #hexathorpe include "input.h"
+                safety!(unsafe_ffi)
+                #directives
+            );
+
+            #extra_rust
+
+            fn main() {
+                #rust_code
+            }
+
+    };
+    do_run_test_manual(
+        cxx_code,
+        header_code,
+        unexpanded_rust,
+        builder_modifier,
+        rust_code_checker,
+    )
+}
+
+/// The [`BuilderContext`] used in autocxx's integration tests.
+pub struct TestBuilderContext;
+
+impl BuilderContext for TestBuilderContext {
+    fn get_dependency_recorder() -> Option<Box<dyn RebuildDependencyRecorder>> {
+        None
+    }
+}
+
+pub fn do_run_test_manual(
+    cxx_code: &str,
+    header_code: &str,
+    mut rust_code: TokenStream,
+    builder_modifier: Option<BuilderModifier>,
+    rust_code_checker: Option<CodeChecker>,
+) -> Result<(), TestError> {
+    const HEADER_NAME: &str = "input.h";
+    // Step 2: Write the C++ header snippet to a temp file
+    let tdir = tempdir().unwrap();
+    write_to_file(
+        &tdir,
+        HEADER_NAME,
+        &format!("#pragma once\n{}", header_code),
+    );
+    write_to_file(&tdir, "cxx.h", HEADER);
+
+    rust_code.append_all(quote! {
+        #[link(name="autocxx-demo")]
+        extern {}
+    });
+    info!("Unexpanded Rust: {}", rust_code);
+
+    let write_rust_to_file = |ts: &TokenStream| -> PathBuf {
+        // Step 3: Write the Rust code to a temp file
+        let rs_code = format!("{}", ts);
+        write_to_file(&tdir, "input.rs", &rs_code)
+    };
+
+    let target_dir = tdir.path().join("target");
+    std::fs::create_dir(&target_dir).unwrap();
+
+    let rs_path = write_rust_to_file(&rust_code);
+
+    info!("Path is {:?}", tdir.path());
+    let builder = Builder::<TestBuilderContext>::new(&rs_path, &[tdir.path()])
+        .custom_gendir(target_dir.clone());
+    let builder = if let Some(builder_modifier) = &builder_modifier {
+        builder_modifier.modify_autocxx_builder(builder)
+    } else {
+        builder
+    };
+    let build_results = builder.build_listing_files().map_err(TestError::AutoCxx)?;
+    let mut b = build_results.0;
+    let generated_rs_files = build_results.1;
+
+    if let Some(code_checker) = &rust_code_checker {
+        let mut file = File::open(generated_rs_files.get(0).ok_or(TestError::NoRs)?)
+            .map_err(TestError::RsFileOpen)?;
+        let mut content = String::new();
+        file.read_to_string(&mut content)
+            .map_err(TestError::RsFileRead)?;
+
+        let ast = syn::parse_file(&content).map_err(TestError::RsFileParse)?;
+        code_checker.check_rust(ast)?;
+        code_checker.check_cpp(&build_results.2)?;
+        if code_checker.skip_build() {
+            return Ok(());
+        }
+    }
+
+    if !cxx_code.is_empty() {
+        // Step 4: Write the C++ code snippet to a .cc file, along with a #include
+        //         of the header emitted in step 5.
+        let cxx_code = format!("#include \"input.h\"\n#include \"cxxgen.h\"\n{}", cxx_code);
+        let cxx_path = write_to_file(&tdir, "input.cxx", &cxx_code);
+        b.file(cxx_path);
+    }
+
+    let b = configure_builder(&mut b).out_dir(&target_dir);
+    let b = if let Some(builder_modifier) = builder_modifier {
+        builder_modifier.modify_cc_builder(b)
+    } else {
+        b
+    };
+    b.include(tdir.path())
+        .try_compile("autocxx-demo")
+        .map_err(TestError::CppBuild)?;
+    if KEEP_TEMPDIRS {
+        println!("Generated .rs files: {:?}", generated_rs_files);
+    }
+    // Step 8: use the trybuild crate to build the Rust file.
+    let r = get_builder().lock().unwrap().build(
+        &target_dir,
+        "autocxx-demo",
+        &tdir.path(),
+        &["input.h", "cxx.h"],
+        &rs_path,
+        generated_rs_files,
+        RsFindMode::AutocxxRs,
+    );
+    if KEEP_TEMPDIRS {
+        println!("Tempdir: {:?}", tdir.into_path().to_str());
+    }
+    if r.is_err() {
+        return Err(TestError::RsBuild); // details of Rust panic are a bit messy to include, and
+                                        // not important at the moment.
+    }
+    Ok(())
+}
diff --git a/integration-tests/tests/builder_modifiers.rs b/integration-tests/tests/builder_modifiers.rs
new file mode 100644
index 0000000..0cf763e
--- /dev/null
+++ b/integration-tests/tests/builder_modifiers.rs
@@ -0,0 +1,61 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx_engine::Builder;
+
+use autocxx_integration_tests::{BuilderModifier, BuilderModifierFns, TestBuilderContext};
+
+pub(crate) fn make_cpp17_adder() -> Option<BuilderModifier> {
+    make_clang_arg_adder(&["-std=c++17"])
+}
+
+struct ClangArgAdder(Vec<String>);
+
+pub(crate) fn make_clang_arg_adder(args: &[&str]) -> Option<BuilderModifier> {
+    let args: Vec<_> = args.iter().map(|a| a.to_string()).collect();
+    Some(Box::new(ClangArgAdder(args)))
+}
+
+impl BuilderModifierFns for ClangArgAdder {
+    fn modify_autocxx_builder<'a>(
+        &self,
+        builder: Builder<'a, TestBuilderContext>,
+    ) -> Builder<'a, TestBuilderContext> {
+        let refs: Vec<_> = self.0.iter().map(|s| s.as_str()).collect();
+        builder.extra_clang_args(&refs)
+    }
+
+    fn modify_cc_builder<'a>(&self, mut builder: &'a mut cc::Build) -> &'a mut cc::Build {
+        for f in &self.0 {
+            builder = builder.flag(f);
+        }
+        builder
+    }
+}
+
+pub(crate) struct SetSuppressSystemHeaders;
+
+impl BuilderModifierFns for SetSuppressSystemHeaders {
+    fn modify_autocxx_builder<'a>(
+        &self,
+        builder: Builder<'a, TestBuilderContext>,
+    ) -> Builder<'a, TestBuilderContext> {
+        builder.suppress_system_headers(true)
+    }
+}
+
+pub(crate) struct EnableAutodiscover;
+
+impl BuilderModifierFns for EnableAutodiscover {
+    fn modify_autocxx_builder<'a>(
+        &self,
+        builder: Builder<'a, TestBuilderContext>,
+    ) -> Builder<'a, TestBuilderContext> {
+        builder.auto_allowlist(true)
+    }
+}
diff --git a/integration-tests/tests/code_checkers.rs b/integration-tests/tests/code_checkers.rs
new file mode 100644
index 0000000..619c79c
--- /dev/null
+++ b/integration-tests/tests/code_checkers.rs
@@ -0,0 +1,182 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{
+    fs::File,
+    io::{BufRead, BufReader},
+    path::PathBuf,
+};
+
+use itertools::{Either, Itertools};
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::Item;
+
+use autocxx_integration_tests::{CodeChecker, CodeCheckerFns, TestError};
+
+/// Generates a closure which can be used to ensure that the given symbol
+/// is mentioned in the output and has documentation attached.
+/// The idea is that this is what we do in cases where we can't generate code properly.
+pub(crate) fn make_error_finder(error_symbol: &'static str) -> CodeChecker {
+    Box::new(ErrorFinder(error_symbol))
+}
+struct ErrorFinder(&'static str);
+
+impl CodeCheckerFns for ErrorFinder {
+    fn check_rust(&self, rs: syn::File) -> Result<(), TestError> {
+        let ffi_items = find_ffi_items(rs)?;
+        // Ensure there's some kind of struct entry for this symbol
+        let error_item = ffi_items
+            .into_iter()
+            .filter_map(|i| match i {
+                Item::Struct(its) if its.ident == self.0 => Some(its),
+                _ => None,
+            })
+            .next()
+            .ok_or_else(|| TestError::RsCodeExaminationFail("Couldn't find item".into()))?;
+        // Ensure doc attribute
+        error_item
+            .attrs
+            .into_iter()
+            .find(|a| a.path.get_ident().filter(|p| *p == "doc").is_some())
+            .ok_or_else(|| TestError::RsCodeExaminationFail("Item had no docs".into()))?;
+        Ok(())
+    }
+}
+
+fn find_ffi_items(f: syn::File) -> Result<Vec<Item>, TestError> {
+    let md = f
+        .items
+        .into_iter()
+        .filter_map(|i| match i {
+            Item::Mod(itm) => Some(itm),
+            _ => None,
+        })
+        .next()
+        .ok_or_else(|| TestError::RsCodeExaminationFail("No mods in file".into()))?;
+    let mut items = Vec::new();
+    find_all_non_mod_items(md, &mut items);
+    Ok(items)
+}
+
+fn find_all_non_mod_items(md: syn::ItemMod, items: &mut Vec<Item>) {
+    let (more_mods, mut these_items): (Vec<_>, Vec<_>) = md
+        .content
+        .into_iter()
+        .flat_map(|(_, more_items)| more_items.into_iter())
+        .partition_map(|i| match i {
+            Item::Mod(itm) => Either::Left(itm),
+            _ => Either::Right(i),
+        });
+    items.append(&mut these_items);
+    for md in more_mods.into_iter() {
+        find_all_non_mod_items(md, items);
+    }
+}
+
+struct StringFinder(Vec<String>);
+
+impl CodeCheckerFns for StringFinder {
+    fn check_rust(&self, rs: syn::File) -> Result<(), TestError> {
+        let toks = rs.to_token_stream().to_string();
+        for msg in &self.0 {
+            if !toks.contains(msg) {
+                return Err(TestError::RsCodeExaminationFail(format!(
+                    "Couldn't find string '{}'",
+                    msg
+                )));
+            };
+        }
+        Ok(())
+    }
+}
+
+/// Returns a code checker which simply hunts for a given string in the results
+pub(crate) fn make_string_finder(error_texts: Vec<String>) -> CodeChecker {
+    Box::new(StringFinder(error_texts))
+}
+
+struct RustCodeFinder(Vec<TokenStream>);
+
+impl CodeCheckerFns for RustCodeFinder {
+    fn check_rust(&self, rs: syn::File) -> Result<(), TestError> {
+        let haystack = rs.to_token_stream().to_string();
+        for msg in &self.0 {
+            let needle = msg.to_string();
+            if !haystack.contains(&needle) {
+                return Err(TestError::RsCodeExaminationFail(format!(
+                    "Couldn't find tokens '{}'",
+                    needle
+                )));
+            };
+        }
+        Ok(())
+    }
+}
+
+/// Returns a code checker which hunts for the given Rust tokens in the output
+pub(crate) fn make_rust_code_finder(code: Vec<TokenStream>) -> CodeChecker {
+    Box::new(RustCodeFinder(code))
+}
+
+/// Searches generated C++ for strings we want to find, or want _not_ to find,
+/// or both.
+pub(crate) struct CppMatcher<'a> {
+    positive_matches: &'a [&'a str],
+    negative_matches: &'a [&'a str],
+}
+
+impl<'a> CppMatcher<'a> {
+    pub(crate) fn new(positive_matches: &'a [&'a str], negative_matches: &'a [&'a str]) -> Self {
+        Self {
+            positive_matches,
+            negative_matches,
+        }
+    }
+}
+
+impl<'a> CodeCheckerFns for CppMatcher<'a> {
+    fn check_cpp(&self, cpp: &[PathBuf]) -> Result<(), TestError> {
+        let mut positives_needed = self.positive_matches.to_vec();
+        for filename in cpp {
+            let file = File::open(filename).unwrap();
+            let lines = BufReader::new(file).lines();
+            for l in lines.filter_map(|l| l.ok()) {
+                if self.negative_matches.iter().any(|neg| l.contains(neg)) {
+                    return Err(TestError::CppCodeExaminationFail);
+                }
+                positives_needed.retain(|pos| !l.contains(pos));
+            }
+        }
+        if positives_needed.is_empty() {
+            Ok(())
+        } else {
+            Err(TestError::CppCodeExaminationFail)
+        }
+    }
+}
+
+pub(crate) struct NoSystemHeadersChecker;
+
+impl CodeCheckerFns for NoSystemHeadersChecker {
+    fn check_cpp(&self, cpp: &[PathBuf]) -> Result<(), TestError> {
+        for filename in cpp {
+            let file = File::open(filename).unwrap();
+            if BufReader::new(file)
+                .lines()
+                .any(|l| l.as_ref().unwrap().starts_with("#include <"))
+            {
+                return Err(TestError::CppCodeExaminationFail);
+            }
+        }
+        Ok(())
+    }
+    fn skip_build(&self) -> bool {
+        true
+    }
+}
diff --git a/integration-tests/tests/integration_test.rs b/integration-tests/tests/integration_test.rs
new file mode 100644
index 0000000..2a3340a
--- /dev/null
+++ b/integration-tests/tests/integration_test.rs
@@ -0,0 +1,11195 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::{
+    builder_modifiers::{
+        make_clang_arg_adder, make_cpp17_adder, EnableAutodiscover, SetSuppressSystemHeaders,
+    },
+    code_checkers::{
+        make_error_finder, make_rust_code_finder, make_string_finder, CppMatcher,
+        NoSystemHeadersChecker,
+    },
+};
+use autocxx_integration_tests::{
+    directives_from_lists, do_run_test, do_run_test_manual, run_test, run_test_ex,
+    run_test_expect_fail, run_test_expect_fail_ex, TestError,
+};
+use indoc::indoc;
+use itertools::Itertools;
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{parse_quote, Token};
+use test_log::test;
+
+#[test]
+fn test_return_void() {
+    let cxx = indoc! {"
+        void do_nothing() {
+        }
+    "};
+    let hdr = indoc! {"
+        void do_nothing();
+    "};
+    let rs = quote! {
+        ffi::do_nothing();
+    };
+    run_test(cxx, hdr, rs, &["do_nothing"], &[]);
+}
+
+#[test]
+fn test_two_funcs() {
+    let cxx = indoc! {"
+        void do_nothing1() {
+        }
+        void do_nothing2() {
+        }
+    "};
+    let hdr = indoc! {"
+        void do_nothing1();
+        void do_nothing2();
+    "};
+    let rs = quote! {
+        ffi::do_nothing1();
+        ffi::do_nothing2();
+    };
+    run_test(cxx, hdr, rs, &["do_nothing1", "do_nothing2"], &[]);
+}
+
+#[test]
+fn test_two_funcs_with_definition() {
+    // Test to ensure C++ header isn't included twice
+    let cxx = indoc! {"
+        void do_nothing1() {
+        }
+        void do_nothing2() {
+        }
+    "};
+    let hdr = indoc! {"
+        struct Bob {
+            int a;
+        };
+        void do_nothing1();
+        void do_nothing2();
+    "};
+    let rs = quote! {
+        ffi::do_nothing1();
+        ffi::do_nothing2();
+    };
+    run_test(cxx, hdr, rs, &["do_nothing1", "do_nothing2"], &[]);
+}
+
+#[test]
+fn test_return_i32() {
+    let cxx = indoc! {"
+        uint32_t give_int() {
+            return 5;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        uint32_t give_int();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_int(), 5);
+    };
+    run_test(cxx, hdr, rs, &["give_int"], &[]);
+}
+
+#[test]
+fn test_take_i32() {
+    let cxx = indoc! {"
+        uint32_t take_int(uint32_t a) {
+            return a + 3;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        uint32_t take_int(uint32_t a);
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::take_int(3), 6);
+    };
+    run_test(cxx, hdr, rs, &["take_int"], &[]);
+}
+
+#[test]
+fn test_nested_module() {
+    let cxx = indoc! {"
+        void do_nothing() {
+        }
+    "};
+    let hdr = indoc! {"
+        void do_nothing();
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let unexpanded_rust = quote! {
+        mod a {
+            use autocxx::prelude::*;
+
+            include_cpp!(
+                #hexathorpe include "input.h"
+                generate!("do_nothing")
+                safety!(unsafe)
+            );
+
+            pub use ffi::*;
+        }
+
+        fn main() {
+            a::do_nothing();
+        }
+    };
+
+    do_run_test_manual(cxx, hdr, unexpanded_rust, None, None).unwrap();
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/681
+#[cfg(target_pointer_width = "64")]
+fn test_return_big_ints() {
+    let cxx = indoc! {"
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        inline uint32_t give_u32() {
+            return 5;
+        }
+        inline uint64_t give_u64() {
+            return 5;
+        }
+        inline int32_t give_i32() {
+            return 5;
+        }
+        inline int64_t give_i64() {
+            return 5;
+        }
+        inline __int128 give_i128() {
+            return 5;
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_u32(), 5);
+        assert_eq!(ffi::give_u64(), 5);
+        assert_eq!(ffi::give_i32(), 5);
+        assert_eq!(ffi::give_i64(), 5);
+        assert_eq!(ffi::give_i128(), 5);
+    };
+    run_test(
+        cxx,
+        hdr,
+        rs,
+        &["give_u32", "give_u64", "give_i32", "give_i64", "give_i128"],
+        &[],
+    );
+}
+
+#[test]
+#[ignore] // because cxx doesn't support unique_ptrs to primitives.
+fn test_give_up_int() {
+    let cxx = indoc! {"
+        std::unique_ptr<uint32_t> give_up() {
+            return std::make_unique<uint32_t>(12);
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        std::unique_ptr<uint32_t> give_up();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_up().as_ref().unwrap(), 12);
+    };
+    run_test(cxx, hdr, rs, &["give_up"], &[]);
+}
+
+#[test]
+#[ignore] // because we don't yet implement UniquePtr etc. for autocxx::c_int and friends
+fn test_give_up_ctype() {
+    let cxx = indoc! {"
+        std::unique_ptr<int> give_up() {
+            return std::make_unique<int>(12);
+        }
+    "};
+    let hdr = indoc! {"
+        #include <memory>
+        std::unique_ptr<int> give_up();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_up().as_ref().unwrap(), autocxx::c_int(12));
+    };
+    run_test(cxx, hdr, rs, &["give_up"], &[]);
+}
+
+#[test]
+fn test_give_string_up() {
+    let cxx = indoc! {"
+        std::unique_ptr<std::string> give_str_up() {
+            return std::make_unique<std::string>(\"Bob\");
+        }
+    "};
+    let hdr = indoc! {"
+        #include <memory>
+        #include <string>
+        std::unique_ptr<std::string> give_str_up();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_str_up().as_ref().unwrap().to_str().unwrap(), "Bob");
+    };
+    run_test(cxx, hdr, rs, &["give_str_up"], &[]);
+}
+
+#[test]
+fn test_give_string_plain() {
+    let cxx = indoc! {"
+        std::string give_str() {
+            return std::string(\"Bob\");
+        }
+    "};
+    let hdr = indoc! {"
+        #include <string>
+        std::string give_str();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_str().as_ref().unwrap(), "Bob");
+    };
+    run_test(cxx, hdr, rs, &["give_str"], &[]);
+}
+
+#[test]
+fn test_cycle_string_up() {
+    let cxx = indoc! {"
+        std::unique_ptr<std::string> give_str_up() {
+            return std::make_unique<std::string>(\"Bob\");
+        }
+        uint32_t take_str_up(std::unique_ptr<std::string> a) {
+            return a->length();
+        }
+    "};
+    let hdr = indoc! {"
+        #include <memory>
+        #include <string>
+        #include <cstdint>
+        std::unique_ptr<std::string> give_str_up();
+        uint32_t take_str_up(std::unique_ptr<std::string> a);
+    "};
+    let rs = quote! {
+        let s = ffi::give_str_up();
+        assert_eq!(ffi::take_str_up(s), 3);
+    };
+    run_test(cxx, hdr, rs, &["give_str_up", "take_str_up"], &[]);
+}
+
+#[test]
+fn test_cycle_string() {
+    let cxx = indoc! {"
+        std::string give_str() {
+            return std::string(\"Bob\");
+        }
+        uint32_t take_str(std::string a) {
+            return a.length();
+        }
+    "};
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+        std::string give_str();
+        uint32_t take_str(std::string a);
+    "};
+    let rs = quote! {
+        let s = ffi::give_str();
+        assert_eq!(ffi::take_str(s), 3);
+    };
+    let generate = &["give_str", "take_str"];
+    run_test(cxx, hdr, rs, generate, &[]);
+}
+
+#[test]
+fn test_cycle_string_by_ref() {
+    let cxx = indoc! {"
+        std::unique_ptr<std::string> give_str() {
+            return std::make_unique<std::string>(\"Bob\");
+        }
+        uint32_t take_str(const std::string& a) {
+            return a.length();
+        }
+    "};
+    let hdr = indoc! {"
+        #include <string>
+        #include <memory>
+        #include <cstdint>
+        std::unique_ptr<std::string> give_str();
+        uint32_t take_str(const std::string& a);
+    "};
+    let rs = quote! {
+        let s = ffi::give_str();
+        assert_eq!(ffi::take_str(s.as_ref().unwrap()), 3);
+    };
+    let generate = &["give_str", "take_str"];
+    run_test(cxx, hdr, rs, generate, &[]);
+}
+
+#[test]
+fn test_cycle_string_by_mut_ref() {
+    let cxx = indoc! {"
+        std::unique_ptr<std::string> give_str() {
+            return std::make_unique<std::string>(\"Bob\");
+        }
+        uint32_t take_str(std::string& a) {
+            return a.length();
+        }
+    "};
+    let hdr = indoc! {"
+        #include <string>
+        #include <memory>
+        #include <cstdint>
+        std::unique_ptr<std::string> give_str();
+        uint32_t take_str(std::string& a);
+    "};
+    let rs = quote! {
+        let mut s = ffi::give_str();
+        assert_eq!(ffi::take_str(s.as_mut().unwrap()), 3);
+    };
+    let generate = &["give_str", "take_str"];
+    run_test(cxx, hdr, rs, generate, &[]);
+}
+
+#[test]
+fn test_give_pod_by_value() {
+    let cxx = indoc! {"
+        Bob give_bob() {
+            Bob a;
+            a.a = 3;
+            a.b = 4;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        Bob give_bob();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_bob().b, 4);
+    };
+    run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_give_pod_class_by_value() {
+    let cxx = indoc! {"
+        Bob give_bob() {
+            Bob a;
+            a.a = 3;
+            a.b = 4;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        class Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+        };
+        Bob give_bob();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_bob().b, 4);
+    };
+    run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_give_pod_by_up() {
+    let cxx = indoc! {"
+        std::unique_ptr<Bob> give_bob() {
+            auto a = std::make_unique<Bob>();
+            a->a = 3;
+            a->b = 4;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        std::unique_ptr<Bob> give_bob();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_bob().as_ref().unwrap().b, 4);
+    };
+    run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_take_pod_by_value() {
+    let cxx = indoc! {"
+        uint32_t take_bob(Bob a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        uint32_t take_bob(Bob a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(ffi::take_bob(a), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_negative_take_as_pod_with_destructor() {
+    let cxx = indoc! {"
+        uint32_t take_bob(Bob a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+            inline ~Bob() {}
+        };
+        uint32_t take_bob(Bob a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(ffi::take_bob(a), 12);
+    };
+    run_test_expect_fail(cxx, hdr, rs, &["take_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_negative_take_as_pod_with_move_constructor() {
+    let cxx = indoc! {"
+        uint32_t take_bob(Bob a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <type_traits>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+            inline Bob(Bob&& other_bob) {}
+        };
+        uint32_t take_bob(Bob a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(ffi::take_bob(a), 12);
+    };
+    run_test_expect_fail(cxx, hdr, rs, &["take_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_take_as_pod_with_is_relocatable() {
+    let cxx = indoc! {"
+        uint32_t take_bob(Bob a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <type_traits>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+            inline Bob() {}
+            inline ~Bob() {}
+            inline Bob(Bob&& other_bob) { a = other_bob.a; b = other_bob.b; }
+            using IsRelocatable = std::true_type;
+        };
+        uint32_t take_bob(Bob a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(ffi::take_bob(a), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_take_pod_by_ref() {
+    let cxx = indoc! {"
+        uint32_t take_bob(const Bob& a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        uint32_t take_bob(const Bob& a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(ffi::take_bob(&a), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_take_pod_by_ref_and_ptr() {
+    let cxx = indoc! {"
+        uint32_t take_bob_ref(const Bob& a) {
+            return a.a;
+        }
+        uint32_t take_bob_ptr(const Bob* a) {
+            return a->a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        uint32_t take_bob_ref(const Bob& a);
+        uint32_t take_bob_ptr(const Bob* a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(ffi::take_bob_ref(&a), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob_ref", "take_bob_ptr"], &["Bob"]);
+}
+
+#[test]
+fn test_return_pod_by_ref_and_ptr() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct B {
+            uint32_t a;
+        };
+        struct A {
+            B b;
+        };
+        inline const B& return_b_ref(const A& a) {
+            return a.b;
+        }
+        inline const B* return_b_ptr(const A& a) {
+            return &a.b;
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A { b: ffi::B { a: 3 } };
+        assert_eq!(ffi::return_b_ref(&a).a, 3);
+        let b_ptr = ffi::return_b_ptr(&a);
+        assert_eq!(unsafe { b_ptr.as_ref() }.unwrap().a, 3);
+    };
+    run_test("", hdr, rs, &["return_b_ref", "return_b_ptr"], &["A", "B"]);
+}
+
+#[test]
+fn test_take_pod_by_mut_ref() {
+    let cxx = indoc! {"
+        uint32_t take_bob(Bob& a) {
+            a.b = 14;
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        uint32_t take_bob(Bob& a);
+    "};
+    let rs = quote! {
+        let mut a = Box::pin(ffi::Bob { a: 12, b: 13 });
+        assert_eq!(ffi::take_bob(a.as_mut()), 12);
+        assert_eq!(a.b, 14);
+    };
+    run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_take_nested_pod_by_value() {
+    let cxx = indoc! {"
+        uint32_t take_bob(Bob a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Phil {
+            uint32_t d;
+        };
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+            Phil c;
+        };
+        uint32_t take_bob(Bob a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12, b: 13, c: ffi::Phil { d: 4 } };
+        assert_eq!(ffi::take_bob(a), 12);
+    };
+    // Should be no need to allowlist Phil below
+    run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_take_nonpod_by_value() {
+    let cxx = indoc! {"
+        Bob::Bob(uint32_t a0, uint32_t b0)
+           : a(a0), b(b0) {}
+        uint32_t take_bob(Bob a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Bob {
+            Bob(uint32_t a, uint32_t b);
+            uint32_t a;
+            uint32_t b;
+            std::string reason_why_this_is_nonpod;
+        };
+        uint32_t take_bob(Bob a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::new(12, 13).within_unique_ptr();
+        assert_eq!(ffi::take_bob(a), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob", "Bob"], &[]);
+}
+
+#[test]
+fn test_take_nonpod_by_ref() {
+    let cxx = indoc! {"
+        uint32_t take_bob(const Bob& a) {
+            return a.a;
+        }
+        std::unique_ptr<Bob> make_bob(uint32_t a) {
+            auto b = std::make_unique<Bob>();
+            b->a = a;
+            return b;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        std::unique_ptr<Bob> make_bob(uint32_t a);
+        uint32_t take_bob(const Bob& a);
+    "};
+    let rs = quote! {
+        let a = ffi::make_bob(12);
+        assert_eq!(ffi::take_bob(&a), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
+}
+
+#[test]
+fn test_take_nonpod_by_up() {
+    let cxx = indoc! {"
+        uint32_t take_bob(std::unique_ptr<Bob> a) {
+            return a->a;
+        }
+        std::unique_ptr<Bob> make_bob(uint32_t a) {
+            auto b = std::make_unique<Bob>();
+            b->a = a;
+            return b;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+
+        struct NOP { inline void take_bob(); };
+        std::unique_ptr<Bob> make_bob(uint32_t a);
+        uint32_t take_bob(std::unique_ptr<Bob> a);
+    "};
+    let rs = quote! {
+        let a = ffi::make_bob(12);
+        assert_eq!(ffi::take_bob(a), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob", "NOP"], &[]);
+}
+
+#[test]
+fn test_take_nonpod_by_ptr_simple() {
+    let cxx = indoc! {"
+        uint32_t take_bob(const Bob* a) {
+            return a->a;
+        }
+        std::unique_ptr<Bob> make_bob(uint32_t a) {
+            auto b = std::make_unique<Bob>();
+            b->a = a;
+            return b;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        std::unique_ptr<Bob> make_bob(uint32_t a);
+        uint32_t take_bob(const Bob* a);
+    "};
+    let rs = quote! {
+        let a = ffi::make_bob(12);
+        let a_ptr = a.into_raw();
+        assert_eq!(unsafe { ffi::take_bob(a_ptr) }, 12);
+        unsafe { cxx::UniquePtr::from_raw(a_ptr) }; // so we drop
+    };
+    run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
+}
+
+#[test]
+fn test_take_nonpod_by_ptr_in_method() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        #include <cstdint>
+        class A {
+        public:
+            A() {};
+            uint32_t take_bob(const Bob* a) const {
+                return a->a;
+            }
+            std::unique_ptr<Bob> make_bob(uint32_t a) const {
+                auto b = std::make_unique<Bob>();
+                b->a = a;
+                return b;
+            }
+            uint16_t a;
+        };
+
+    "};
+    let rs = quote! {
+        let a = ffi::A::new().within_unique_ptr();
+        let b = a.as_ref().unwrap().make_bob(12);
+        let b_ptr = b.into_raw();
+        assert_eq!(unsafe { a.as_ref().unwrap().take_bob(b_ptr) }, 12);
+        unsafe { cxx::UniquePtr::from_raw(b_ptr) }; // so we drop
+    };
+    run_test("", hdr, rs, &["A", "Bob"], &[]);
+}
+
+#[test]
+fn test_take_nonpod_by_ptr_in_wrapped_method() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct C {
+            C() {}
+            uint32_t a;
+        };
+        struct Bob {
+            uint32_t a;
+        };
+        class A {
+        public:
+            A() {};
+            uint32_t take_bob(const Bob* a, C) const {
+                return a->a;
+            }
+            std::unique_ptr<Bob> make_bob(uint32_t a) const {
+                auto b = std::make_unique<Bob>();
+                b->a = a;
+                return b;
+            }
+            uint16_t a;
+        };
+
+    "};
+    let rs = quote! {
+        let a = ffi::A::new().within_unique_ptr();
+        let c = ffi::C::new().within_unique_ptr();
+        let b = a.as_ref().unwrap().make_bob(12);
+        let b_ptr = b.into_raw();
+        assert_eq!(unsafe { a.as_ref().unwrap().take_bob(b_ptr, c) }, 12);
+        unsafe { cxx::UniquePtr::from_raw(b_ptr) }; // so we drop
+    };
+    run_test("", hdr, rs, &["A", "Bob", "C"], &[]);
+}
+
+#[test]
+fn test_take_char_by_ptr_in_wrapped_method() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct C {
+            C() { test = \"hi\"; }
+            uint32_t a;
+            const char* test;
+        };
+        class A {
+        public:
+            A() {};
+            uint32_t take_char(const char* a, C) const {
+                return a[0];
+            }
+            const char* make_char(C extra) const {
+                return extra.test;
+            }
+            uint16_t a;
+        };
+
+    "};
+    let rs = quote! {
+        let a = ffi::A::new().within_unique_ptr();
+        let c1 = ffi::C::new().within_unique_ptr();
+        let c2 = ffi::C::new().within_unique_ptr();
+        let ch = a.as_ref().unwrap().make_char(c1);
+        assert_eq!(unsafe { ch.as_ref()}.unwrap(), &104i8);
+        assert_eq!(unsafe { a.as_ref().unwrap().take_char(ch, c2) }, 104);
+    };
+    run_test("", hdr, rs, &["A", "C"], &[]);
+}
+
+#[test]
+fn test_take_nonpod_by_mut_ref() {
+    let cxx = indoc! {"
+        uint32_t take_bob(Bob& a) {
+            return a.a;
+        }
+        std::unique_ptr<Bob> make_bob(uint32_t a) {
+            auto b = std::make_unique<Bob>();
+            b->a = a;
+            return b;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        std::unique_ptr<Bob> make_bob(uint32_t a);
+        uint32_t take_bob(Bob& a);
+    "};
+    let rs = quote! {
+        let mut a = ffi::make_bob(12);
+        assert_eq!(ffi::take_bob(a.pin_mut()), 12);
+    };
+    // TODO confirm that the object really was mutated by C++ in this
+    // and similar tests.
+    run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
+}
+
+#[test]
+fn test_return_nonpod_by_value() {
+    let cxx = indoc! {"
+        Bob::Bob(uint32_t a0, uint32_t b0)
+           : a(a0), b(b0) {}
+        Bob give_bob(uint32_t a) {
+            Bob c(a, 44);
+            return c;
+        }
+        uint32_t take_bob(std::unique_ptr<Bob> a) {
+            return a->a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            Bob(uint32_t a, uint32_t b);
+            uint32_t a;
+            uint32_t b;
+        };
+        Bob give_bob(uint32_t a);
+        uint32_t take_bob(std::unique_ptr<Bob> a);
+    "};
+    let rs = quote! {
+        let a = ffi::give_bob(13).within_unique_ptr();
+        assert_eq!(ffi::take_bob(a), 13);
+    };
+    run_test(cxx, hdr, rs, &["take_bob", "give_bob", "Bob"], &[]);
+}
+
+#[test]
+fn test_get_str_by_up() {
+    let cxx = indoc! {"
+    std::unique_ptr<std::string> get_str() {
+            return std::make_unique<std::string>(\"hello\");
+        }
+    "};
+    let hdr = indoc! {"
+        #include <string>
+        #include <memory>
+        std::unique_ptr<std::string> get_str();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::get_str().as_ref().unwrap(), "hello");
+    };
+    run_test(cxx, hdr, rs, &["get_str"], &[]);
+}
+
+#[test]
+fn test_get_str_by_value() {
+    let cxx = indoc! {"
+        std::string get_str() {
+            return \"hello\";
+        }
+    "};
+    let hdr = indoc! {"
+        #include <string>
+        std::string get_str();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::get_str().as_ref().unwrap(), "hello");
+    };
+    run_test(cxx, hdr, rs, &["get_str"], &[]);
+}
+
+#[test]
+fn test_cycle_nonpod_with_str_by_ref() {
+    let cxx = indoc! {"
+        uint32_t take_bob(const Bob& a) {
+            return a.a;
+        }
+        std::unique_ptr<Bob> make_bob() {
+            auto a = std::make_unique<Bob>();
+            a->a = 32;
+            a->b = \"hello\";
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+            std::string b;
+        };
+        uint32_t take_bob(const Bob& a);
+        std::unique_ptr<Bob> make_bob();
+    "};
+    let rs = quote! {
+        let a = ffi::make_bob();
+        assert_eq!(ffi::take_bob(a.as_ref().unwrap()), 32);
+    };
+    run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
+}
+
+#[test]
+fn test_make_up() {
+    let cxx = indoc! {"
+        Bob::Bob() : a(3) {
+        }
+        uint32_t take_bob(const Bob& a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        class Bob {
+        public:
+            Bob();
+            uint32_t a;
+        };
+        uint32_t take_bob(const Bob& a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::new().within_unique_ptr(); // TODO test with all sorts of arguments.
+        assert_eq!(ffi::take_bob(a.as_ref().unwrap()), 3);
+    };
+    run_test(cxx, hdr, rs, &["Bob", "take_bob"], &[]);
+}
+
+#[test]
+fn test_make_up_with_args() {
+    let cxx = indoc! {"
+        Bob::Bob(uint32_t a0, uint32_t b0)
+           : a(a0), b(b0) {}
+        uint32_t take_bob(const Bob& a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            Bob(uint32_t a, uint32_t b);
+            uint32_t a;
+            uint32_t b;
+        };
+        uint32_t take_bob(const Bob& a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::new(12, 13).within_unique_ptr();
+        assert_eq!(ffi::take_bob(a.as_ref().unwrap()), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob", "Bob"], &[]);
+}
+
+#[test]
+#[ignore] // because we don't support unique_ptrs to primitives
+fn test_make_up_int() {
+    let cxx = indoc! {"
+        Bob::Bob(uint32_t a) : b(a) {
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        class Bob {
+        public:
+            Bob(uint32_t a);
+            uint32_t b;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::new(3).within_unique_ptr();
+        assert_eq!(a.as_ref().unwrap().b, 3);
+    };
+    run_test(cxx, hdr, rs, &["Bob"], &[]);
+}
+
+#[test]
+fn test_enum_with_funcs() {
+    let cxx = indoc! {"
+        Bob give_bob() {
+            return Bob::BOB_VALUE_2;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        enum Bob {
+            BOB_VALUE_1,
+            BOB_VALUE_2,
+        };
+        Bob give_bob();
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::BOB_VALUE_2;
+        let b = ffi::give_bob();
+        assert!(a == b);
+    };
+    run_test(cxx, hdr, rs, &["Bob", "give_bob"], &[]);
+}
+
+#[test]
+fn test_re_export() {
+    let cxx = indoc! {"
+        Bob give_bob() {
+            return Bob::BOB_VALUE_2;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        enum Bob {
+            BOB_VALUE_1,
+            BOB_VALUE_2,
+        };
+        Bob give_bob();
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::BOB_VALUE_2;
+        let b = ffi::give_bob();
+        assert!(a == b);
+    };
+    run_test_ex(
+        cxx,
+        hdr,
+        rs,
+        directives_from_lists(&["Bob", "give_bob"], &[], None),
+        None,
+        None,
+        Some(quote! { pub use ffi::Bob; }),
+    );
+}
+
+#[test]
+fn test_enum_no_funcs() {
+    let cxx = indoc! {"
+    "};
+    let hdr = indoc! {"
+        enum Bob {
+            BOB_VALUE_1,
+            BOB_VALUE_2,
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::BOB_VALUE_1;
+        let b = ffi::Bob::BOB_VALUE_2;
+        assert!(a != b);
+    };
+    run_test(cxx, hdr, rs, &["Bob"], &[]);
+}
+
+#[test]
+fn test_enum_with_funcs_as_pod() {
+    let cxx = indoc! {"
+        Bob give_bob() {
+            return Bob::BOB_VALUE_2;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        enum Bob {
+            BOB_VALUE_1,
+            BOB_VALUE_2,
+        };
+        Bob give_bob();
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::BOB_VALUE_2;
+        let b = ffi::give_bob();
+        assert!(a == b);
+    };
+    run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
+}
+
+#[test] // works, but causes compile warnings
+fn test_take_pod_class_by_value() {
+    let cxx = indoc! {"
+        uint32_t take_bob(Bob a) {
+            return a.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        class Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+        };
+        uint32_t take_bob(Bob a);
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(ffi::take_bob(a), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_pod_method() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob() const {
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob() const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(a.get_bob(), 12);
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob"]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/723
+fn test_constructors_for_specialized_types() {
+    // bindgen sometimes makes such opaque types as type Bob = u32[2];
+    let hdr = indoc! {"
+        #include <cstdint>
+        template<typename T>
+        class A {
+            uint32_t foo() { return 12; };
+        private:
+            T a[2];
+        };
+
+        typedef A<uint32_t> B;
+        typedef B C;
+    "};
+    let rs = quote! {
+        let a = ffi::C::new().within_unique_ptr();
+        assert_eq!(a.foo(), 12);
+    };
+    run_test("", hdr, rs, &["C"], &[]);
+}
+
+#[test]
+fn test_pod_mut_method() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob() {
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob();
+        };
+    "};
+    let rs = quote! {
+        let mut a = Box::pin(ffi::Bob { a: 12, b: 13 });
+        assert_eq!(a.as_mut().get_bob(), 12);
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob"]);
+}
+
+#[test]
+fn test_define_int() {
+    let cxx = indoc! {"
+    "};
+    let hdr = indoc! {"
+        #define BOB 3
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::BOB, 3);
+    };
+    run_test(cxx, hdr, rs, &["BOB"], &[]);
+}
+
+#[test]
+fn test_define_str() {
+    let cxx = indoc! {"
+    "};
+    let hdr = indoc! {"
+        #define BOB \"foo\"
+    "};
+    let rs = quote! {
+        assert_eq!(std::str::from_utf8(ffi::BOB).unwrap().trim_end_matches(char::from(0)), "foo");
+    };
+    run_test(cxx, hdr, rs, &["BOB"], &[]);
+}
+
+#[test]
+fn test_i32_const() {
+    let cxx = indoc! {"
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        const uint32_t BOB = 3;
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::BOB, 3);
+    };
+    run_test(cxx, hdr, rs, &["BOB"], &[]);
+}
+
+#[test]
+fn test_negative_rs_nonsense() {
+    // Really just testing the test infrastructure.
+    let cxx = indoc! {"
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        const uint32_t BOB = 3;
+    "};
+    let rs = quote! {
+        foo bar
+    };
+    run_test_expect_fail(cxx, hdr, rs, &["BOB"], &[]);
+}
+
+#[test]
+fn test_negative_cpp_nonsense() {
+    // Really just testing the test infrastructure.
+    let cxx = indoc! {"
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        const uint32_t BOB = CAT;
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::BOB, 3);
+    };
+    run_test_expect_fail(cxx, hdr, rs, &["BOB"], &[]);
+}
+
+#[test]
+fn test_negative_make_nonpod() {
+    let cxx = indoc! {"
+        uint32_t take_bob(const Bob& a) {
+            return a.a;
+        }
+        std::unique_ptr<Bob> make_bob(uint32_t a) {
+            auto b = std::make_unique<Bob>();
+            b->a = a;
+            return b;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        std::unique_ptr<Bob> make_bob(uint32_t a);
+        uint32_t take_bob(const Bob& a);
+    "};
+    let rs = quote! {
+        ffi::Bob {};
+    };
+    let rs2 = quote! {
+        ffi::Bob { a: 12 };
+    };
+    let rs3 = quote! {
+        ffi::Bob { do_not_attempt_to_allocate_nonpod_types: [] };
+    };
+    run_test_expect_fail(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]);
+    run_test_expect_fail(cxx, hdr, rs2, &["take_bob", "Bob", "make_bob"], &[]);
+    run_test_expect_fail(cxx, hdr, rs3, &["take_bob", "Bob", "make_bob"], &[]);
+}
+
+#[test]
+fn test_method_pass_pod_by_value() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob(Anna) const {
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Anna {
+            uint32_t a;
+        };
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(Anna a) const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::Anna { a: 14 };
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(a), 12);
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]);
+}
+
+fn perform_asan_doom_test(into_raw: TokenStream, box_type: TokenStream) {
+    if std::env::var_os("AUTOCXX_ASAN").is_none() {
+        return;
+    }
+    // Testing that we get an asan fail when it's enabled.
+    // Really just testing our CI is working to spot ASAN mistakes.
+    let hdr = indoc! {"
+        #include <cstddef>
+        struct A {
+            int a;
+        };
+        inline size_t how_big_is_a() {
+            return sizeof(A);
+        }
+    "};
+    let rs = quote! {
+        let a = #box_type::emplace(ffi::A::new());
+        unsafe {
+            let a_raw = #into_raw;
+            // Intentional memory unsafety. Don't @ me.
+            let a_offset_into_doom = a_raw.offset(ffi::how_big_is_a().try_into().unwrap());
+            a_offset_into_doom.write_bytes(0x69, 1);
+            #box_type::from_raw(a_raw); // to delete. If we haven't yet crashed.
+        }
+    };
+    run_test_expect_fail("", hdr, rs, &["A", "how_big_is_a"], &[]);
+}
+
+#[test]
+fn test_asan_working_as_expected_for_cpp_allocations() {
+    perform_asan_doom_test(quote! { a.into_raw() }, quote! { UniquePtr })
+}
+
+#[test]
+fn test_asan_working_as_expected_for_rust_allocations() {
+    perform_asan_doom_test(
+        quote! { Box::into_raw(std::pin::Pin::into_inner_unchecked(a)) },
+        quote! { Box },
+    )
+}
+
+#[test]
+fn test_inline_method() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Anna {
+            uint32_t a;
+        };
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(Anna) const {
+                return a;
+            }
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::Anna { a: 14 };
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(a), 12);
+    };
+    run_test("", hdr, rs, &[], &["Bob", "Anna"]);
+}
+
+#[test]
+fn test_method_pass_pod_by_reference() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob(const Anna&) const {
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Anna {
+            uint32_t a;
+        };
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(const Anna& a) const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::Anna { a: 14 };
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(&a), 12);
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]);
+}
+
+#[test]
+fn test_method_pass_pod_by_mut_reference() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob(Anna&) const {
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Anna {
+            uint32_t a;
+        };
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(Anna& a) const;
+        };
+    "};
+    let rs = quote! {
+        let mut a = Box::pin(ffi::Anna { a: 14 });
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(a.as_mut()), 12);
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]);
+}
+
+#[test]
+fn test_method_pass_pod_by_up() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob(std::unique_ptr<Anna>) const {
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Anna {
+            uint32_t a;
+        };
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(std::unique_ptr<Anna> z) const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::Anna { a: 14 };
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(cxx::UniquePtr::new(a)), 12);
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]);
+}
+
+#[test]
+fn test_method_pass_nonpod_by_value() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob(Anna) const {
+            return a;
+        }
+        Anna give_anna() {
+            Anna a;
+            a.a = 10;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Anna {
+            uint32_t a;
+            std::string b;
+        };
+        Anna give_anna();
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(Anna a) const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::give_anna().within_box();
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(a), 12);
+    };
+    run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]);
+}
+
+#[test]
+fn test_pass_two_nonpod_by_value() {
+    let cxx = indoc! {"
+        void take_a(A, A) {
+        }
+    "};
+    let hdr = indoc! {"
+        #include <string>
+        struct A {
+            std::string b;
+        };
+        void take_a(A, A);
+    "};
+    let rs = quote! {
+        let a = ffi::A::new().within_unique_ptr();
+        let a2 = ffi::A::new().within_unique_ptr();
+        ffi::take_a(a, a2);
+    };
+    run_test(cxx, hdr, rs, &["A", "take_a"], &[]);
+}
+
+#[test]
+fn test_issue_931() {
+    let cxx = "";
+    let hdr = indoc! {"
+    namespace a {
+        struct __cow_string {
+          __cow_string();
+        };
+        class b {
+        public:
+          __cow_string c;
+        };
+        class j {
+        public:
+          b d;
+        };
+        template <typename> class e;
+        } // namespace a
+        template <typename> struct f {};
+        namespace llvm {
+        template <class> class g {
+          union {
+            f<a::j> h;
+          };
+        };
+        class MemoryBuffer {
+        public:
+          g<a::e<MemoryBuffer>> i;
+        };
+        } // namespace llvm
+    "};
+    let rs = quote! {};
+    run_test(cxx, hdr, rs, &["llvm::MemoryBuffer"], &[]);
+}
+
+#[test]
+fn test_issue_936() {
+    let cxx = "";
+    let hdr = indoc! {"
+    struct a;
+    class B {
+    public:
+        B(a &, bool);
+    };
+    "};
+    let rs = quote! {};
+    run_test(cxx, hdr, rs, &["B"], &[]);
+}
+
+#[test]
+fn test_method_pass_nonpod_by_value_with_up() {
+    // Checks that existing UniquePtr params are not wrecked
+    // by the conversion we do here.
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob(Anna, std::unique_ptr<Anna>) const {
+            return a;
+        }
+        Anna give_anna() {
+            Anna a;
+            a.a = 10;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        #include <memory>
+        struct Anna {
+            uint32_t a;
+            std::string b;
+        };
+        Anna give_anna();
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(Anna a, std::unique_ptr<Anna>) const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::give_anna().within_unique_ptr();
+        let a2 = ffi::give_anna().within_unique_ptr();
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(a, a2), 12);
+    };
+    run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]);
+}
+
+#[test]
+fn test_issue_940() {
+    let cxx = "";
+    let hdr = indoc! {"
+    template <class> class b;
+    template <class = void> struct c;
+    struct identity;
+    template <class, class, class e, class> class f {
+    using g = e;
+    g h;
+    };
+    template <class i, class k = c<>, class l = b<i>>
+    using j = f<i, identity, k, l>;
+    class n;
+    class RenderFrameHost {
+    public:
+    virtual void o(const j<n> &);
+    virtual ~RenderFrameHost() {}
+    };
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        cxx,
+        hdr,
+        rs,
+        directives_from_lists(&["RenderFrameHost"], &[], None),
+        make_cpp17_adder(),
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_method_pass_nonpod_by_reference() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob(const Anna&) const {
+            return a;
+        }
+        Anna give_anna() {
+            Anna a;
+            a.a = 10;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Anna {
+            uint32_t a;
+            std::string b;
+        };
+        Anna give_anna();
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(const Anna& a) const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::give_anna().within_box();
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(a.as_ref().get_ref()), 12);
+    };
+    run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]);
+}
+
+#[test]
+fn test_method_pass_nonpod_by_mut_reference() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob(Anna&) const {
+            return a;
+        }
+        Anna give_anna() {
+            Anna a;
+            a.a = 10;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Anna {
+            uint32_t a;
+            std::string b;
+        };
+        Anna give_anna();
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(Anna& a) const;
+        };
+    "};
+    let rs = quote! {
+        let mut a = ffi::give_anna().within_unique_ptr();
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(a.as_mut().unwrap()), 12);
+    };
+    run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]);
+}
+
+#[test]
+fn test_method_pass_nonpod_by_up() {
+    let cxx = indoc! {"
+        uint32_t Bob::get_bob(std::unique_ptr<Anna>) const {
+            return a;
+        }
+        Anna give_anna() {
+            Anna a;
+            a.a = 10;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        #include <string>
+        struct Anna {
+            uint32_t a;
+            std::string b;
+        };
+        Anna give_anna();
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t get_bob(std::unique_ptr<Anna> z) const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::give_anna().within_unique_ptr();
+        let b = ffi::Bob { a: 12, b: 13 };
+        assert_eq!(b.get_bob(a), 12);
+    };
+    run_test(cxx, hdr, rs, &["give_anna"], &["Bob"]);
+}
+
+#[test]
+fn test_method_return_nonpod_by_value() {
+    let cxx = indoc! {"
+        Anna Bob::get_anna() const {
+            Anna a;
+            a.a = 12;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Anna {
+            uint32_t a;
+            std::string b;
+        };
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            Anna get_anna() const;
+        };
+    "};
+    let rs = quote! {
+        let b = ffi::Bob { a: 12, b: 13 };
+        let a = b.get_anna().within_unique_ptr();
+        assert!(!a.is_null());
+    };
+    run_test(cxx, hdr, rs, &["Anna"], &["Bob"]);
+}
+
+#[test]
+fn test_pass_string_by_value() {
+    let cxx = indoc! {"
+        uint32_t measure_string(std::string z) {
+            return z.length();
+        }
+        std::unique_ptr<std::string> get_msg() {
+            return std::make_unique<std::string>(\"hello\");
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        #include <memory>
+        uint32_t measure_string(std::string a);
+        std::unique_ptr<std::string> get_msg();
+    "};
+    let rs = quote! {
+        let a = ffi::get_msg();
+        let c = ffi::measure_string(a);
+        assert_eq!(c, 5);
+    };
+    run_test(cxx, hdr, rs, &["measure_string", "get_msg"], &[]);
+}
+
+#[test]
+fn test_return_string_by_value() {
+    let cxx = indoc! {"
+        std::string get_msg() {
+            return \"hello\";
+        }
+    "};
+    let hdr = indoc! {"
+        #include <string>
+        std::string get_msg();
+    "};
+    let rs = quote! {
+        let a = ffi::get_msg();
+        assert!(a.as_ref().unwrap() == "hello");
+    };
+    run_test(cxx, hdr, rs, &["get_msg"], &[]);
+}
+
+#[test]
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+fn test_method_pass_string_by_value() {
+    let cxx = indoc! {"
+        uint32_t Bob::measure_string(std::string z) const {
+            return z.length();
+        }
+        std::unique_ptr<std::string> get_msg() {
+            return std::make_unique<std::string>(\"hello\");
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        #include <memory>
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            uint32_t measure_string(std::string a) const;
+        };
+        std::unique_ptr<std::string> get_msg();
+    "};
+    let rs = quote! {
+        let a = ffi::get_msg();
+        let b = ffi::Bob { a: 12, b: 13 };
+        let c = b.measure_string(a);
+        assert_eq!(c, 5);
+    };
+    run_test(cxx, hdr, rs, &["Bob", "get_msg"], &["Bob"]);
+}
+
+#[test]
+fn test_method_return_string_by_value() {
+    let cxx = indoc! {"
+        std::string Bob::get_msg() const {
+            return \"hello\";
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Bob {
+        public:
+            uint32_t a;
+            uint32_t b;
+            std::string get_msg() const;
+        };
+    "};
+    let rs = quote! {
+        let b = ffi::Bob { a: 12, b: 13 };
+        let a = b.get_msg();
+        assert!(a.as_ref().unwrap() == "hello");
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob"]);
+}
+
+#[test]
+fn test_pass_rust_string_by_ref() {
+    let cxx = indoc! {"
+        uint32_t measure_string(const rust::String& z) {
+            return std::string(z).length();
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <cxx.h>
+        uint32_t measure_string(const rust::String& z);
+    "};
+    let rs = quote! {
+        let c = ffi::measure_string(&"hello".to_string());
+        assert_eq!(c, 5);
+    };
+    run_test(cxx, hdr, rs, &["measure_string"], &[]);
+}
+
+#[test]
+fn test_pass_rust_string_by_value() {
+    let cxx = indoc! {"
+        uint32_t measure_string(rust::String z) {
+            return std::string(z).length();
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <cxx.h>
+        uint32_t measure_string(rust::String z);
+    "};
+    let rs = quote! {
+        let c = ffi::measure_string("hello".into());
+        assert_eq!(c, 5);
+    };
+    run_test(cxx, hdr, rs, &["measure_string"], &[]);
+}
+
+#[test]
+fn test_pass_rust_str() {
+    // passing by value is the only legal option
+    let cxx = indoc! {"
+        uint32_t measure_string(rust::Str z) {
+            return std::string(z).length();
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <cxx.h>
+        uint32_t measure_string(rust::Str z);
+    "};
+    let rs = quote! {
+        let c = ffi::measure_string("hello");
+        assert_eq!(c, 5);
+    };
+    run_test(cxx, hdr, rs, &["measure_string"], &[]);
+}
+
+#[test]
+fn test_multiple_classes_with_methods() {
+    let hdr = indoc! {"
+        #include <cstdint>
+
+        struct TrivialStruct {
+            uint32_t val = 0;
+
+            uint32_t get() const;
+            uint32_t inc();
+        };
+        TrivialStruct make_trivial_struct();
+
+        class TrivialClass {
+          public:
+            uint32_t get() const;
+            uint32_t inc();
+
+          private:
+            uint32_t val_ = 1;
+        };
+        TrivialClass make_trivial_class();
+
+        struct OpaqueStruct {
+            // ~OpaqueStruct();
+            uint32_t val = 2;
+
+            uint32_t get() const;
+            uint32_t inc();
+        };
+        OpaqueStruct make_opaque_struct();
+
+        class OpaqueClass {
+          public:
+            // ~OpaqueClass();
+            uint32_t get() const;
+            uint32_t inc();
+
+          private:
+            uint32_t val_ = 3;
+        };
+        OpaqueClass make_opaque_class();
+    "};
+    let cxx = indoc! {"
+        TrivialStruct make_trivial_struct() { return {}; }
+        TrivialClass make_trivial_class() { return {}; }
+        OpaqueStruct make_opaque_struct() { return {}; }
+        OpaqueClass make_opaque_class() { return {}; }
+
+        uint32_t TrivialStruct::get() const { return val;}
+        uint32_t TrivialClass::get() const { return val_; }
+        uint32_t OpaqueStruct::get() const { return val;}
+        uint32_t OpaqueClass::get() const { return val_; }
+
+        uint32_t TrivialStruct::inc() { return ++val; }
+        uint32_t TrivialClass::inc() { return ++val_; }
+        uint32_t OpaqueStruct::inc() { return ++val; }
+        uint32_t OpaqueClass::inc() { return ++val_; }
+    "};
+    let rs = quote! {
+        use ffi::*;
+
+        let mut ts = Box::pin(make_trivial_struct());
+        assert_eq!(ts.get(), 0);
+        assert_eq!(ts.as_mut().inc(), 1);
+        assert_eq!(ts.as_mut().inc(), 2);
+
+        let mut tc = Box::pin(make_trivial_class());
+        assert_eq!(tc.get(), 1);
+        assert_eq!(tc.as_mut().inc(), 2);
+        assert_eq!(tc.as_mut().inc(), 3);
+
+        let mut os= make_opaque_struct().within_unique_ptr();
+        assert_eq!(os.get(), 2);
+        assert_eq!(os.pin_mut().inc(), 3);
+        assert_eq!(os.pin_mut().inc(), 4);
+
+        let mut oc = make_opaque_class().within_unique_ptr();
+        assert_eq!(oc.get(), 3);
+        assert_eq!(oc.pin_mut().inc(), 4);
+        assert_eq!(oc.pin_mut().inc(), 5);
+    };
+    run_test(
+        cxx,
+        hdr,
+        rs,
+        &[
+            "make_trivial_struct",
+            "make_trivial_class",
+            "make_opaque_struct",
+            "make_opaque_class",
+            "OpaqueStruct",
+            "OpaqueClass",
+        ],
+        &["TrivialStruct", "TrivialClass"],
+    );
+}
+
+#[test]
+fn test_ns_return_struct() {
+    let cxx = indoc! {"
+        A::B::Bob give_bob() {
+            A::B::Bob a;
+            a.a = 3;
+            a.b = 4;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            namespace B {
+                struct Bob {
+                    uint32_t a;
+                    uint32_t b;
+                };
+            }
+        }
+        A::B::Bob give_bob();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_bob().b, 4);
+    };
+    run_test(cxx, hdr, rs, &["give_bob"], &["A::B::Bob"]);
+}
+
+#[test]
+fn test_ns_take_struct() {
+    let cxx = indoc! {"
+    uint32_t take_bob(A::B::Bob a) {
+        return a.a;
+    }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            namespace B {
+                struct Bob {
+                    uint32_t a;
+                    uint32_t b;
+                };
+            }
+        }
+        uint32_t take_bob(A::B::Bob a);
+    "};
+    let rs = quote! {
+        let a = ffi::A::B::Bob { a: 12, b: 13 };
+        assert_eq!(ffi::take_bob(a), 12);
+    };
+    run_test(cxx, hdr, rs, &["take_bob"], &["A::B::Bob"]);
+}
+
+#[test]
+fn test_ns_func() {
+    let cxx = indoc! {"
+        using namespace C;
+        A::B::Bob C::give_bob() {
+            A::B::Bob a;
+            a.a = 3;
+            a.b = 4;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            namespace B {
+                struct Bob {
+                    uint32_t a;
+                    uint32_t b;
+                };
+            }
+        }
+        namespace C {
+            ::A::B::Bob give_bob();
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::C::give_bob().b, 4);
+    };
+    run_test(cxx, hdr, rs, &["C::give_bob"], &["A::B::Bob"]);
+}
+
+#[test]
+fn test_overload_constructors() {
+    let cxx = indoc! {"
+        Bob::Bob() {}
+        Bob::Bob(uint32_t _a) :a(_a) {}
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            Bob();
+            Bob(uint32_t a);
+            uint32_t a;
+            uint32_t b;
+        };
+    "};
+    let rs = quote! {
+        ffi::Bob::new().within_unique_ptr();
+        ffi::Bob::new1(32).within_unique_ptr();
+    };
+    run_test(cxx, hdr, rs, &["Bob"], &[]);
+}
+
+#[test]
+fn test_overload_functions() {
+    let cxx = indoc! {"
+        void daft(uint32_t) {}
+        void daft(uint8_t) {}
+        void daft(std::string) {}
+        void daft(Fred) {}
+        void daft(Norma) {}
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Fred {
+            uint32_t a;
+        };
+        struct Norma {
+            Norma() {}
+            uint32_t a;
+        };
+        void daft(uint32_t);
+        void daft(uint8_t);
+        void daft(std::string);
+        void daft(Fred);
+        void daft(Norma);
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        ffi::daft(32);
+        ffi::daft1(8);
+        ffi::daft2("hello".into_cpp());
+        let b = ffi::Fred { a: 3 };
+        ffi::daft3(b);
+        let c = ffi::Norma::new().within_unique_ptr();
+        ffi::daft4(c);
+    };
+    run_test(
+        cxx,
+        hdr,
+        rs,
+        &["Norma", "daft", "daft1", "daft2", "daft3", "daft4"],
+        &["Fred"],
+    );
+}
+
+#[test]
+#[ignore] // At present, bindgen generates two separate 'daft1'
+          // functions here, and there's not much we can do about that.
+fn test_overload_numeric_functions() {
+    // Because bindgen deals with conflicting overloaded functions by
+    // appending a numeric suffix, let's see if we can cope.
+    let cxx = indoc! {"
+        void daft1(uint32_t) {}
+        void daft2(uint8_t) {}
+        void daft(std::string) {}
+        void daft(Fred) {}
+        void daft(Norma) {}
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Fred {
+            uint32_t a;
+        };
+        struct Norma {
+            uint32_t a;
+        };
+        void daft1(uint32_t a);
+        void daft2(uint8_t a);
+        void daft(std::string a);
+        void daft(Fred a);
+        void daft(Norma a);
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        ffi::daft(32);
+        ffi::daft1(8);
+        ffi::daft2("hello".into_cpp());
+        let b = ffi::Fred { a: 3 };
+        ffi::daft3(b);
+        let c = ffi::Norma::new().within_unique_ptr();
+        ffi::daft4(c);
+    };
+    run_test(
+        cxx,
+        hdr,
+        rs,
+        &["Norma", "daft", "daft1", "daft2", "daft3", "daft4"],
+        &["Fred"],
+    );
+}
+
+#[test]
+fn test_overload_methods() {
+    let cxx = indoc! {"
+        void Bob::daft(uint32_t) const {}
+        void Bob::daft(uint8_t) const {}
+        void Bob::daft(std::string) const {}
+        void Bob::daft(Fred) const {}
+        void Bob::daft(Norma) const {}
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Fred {
+            uint32_t a;
+        };
+        struct Norma {
+            Norma() {}
+            uint32_t a;
+        };
+        struct Bob {
+            uint32_t a;
+            void daft(uint32_t) const;
+            void daft(uint8_t) const;
+            void daft(std::string) const;
+            void daft(Fred) const;
+            void daft(Norma) const;
+        };
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        let a = ffi::Bob { a: 12 };
+        a.daft(32);
+        a.daft1(8);
+        a.daft2("hello".into_cpp());
+        let b = ffi::Fred { a: 3 };
+        a.daft3(b);
+        let c = ffi::Norma::new().within_unique_ptr();
+        a.daft4(c);
+    };
+    run_test(cxx, hdr, rs, &["Norma"], &["Fred", "Bob"]);
+}
+
+#[test]
+fn test_ns_constructor() {
+    let cxx = indoc! {"
+        A::Bob::Bob() {}
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                Bob();
+                uint32_t a;
+                uint32_t b;
+            };
+        }
+    "};
+    let rs = quote! {
+        ffi::A::Bob::new().within_unique_ptr();
+    };
+    run_test(cxx, hdr, rs, &["A::Bob"], &[]);
+}
+
+#[test]
+fn test_ns_up_direct() {
+    let cxx = indoc! {"
+        std::unique_ptr<A::Bob> A::get_bob() {
+            A::Bob b;
+            b.a = 2;
+            b.b = 3;
+            return std::make_unique<A::Bob>(b);
+        }
+        uint32_t give_bob(A::Bob bob) {
+            return bob.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+                uint32_t b;
+            };
+            std::unique_ptr<Bob> get_bob();
+        }
+        uint32_t give_bob(A::Bob bob);
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_bob(ffi::A::get_bob()), 2);
+    };
+    run_test(cxx, hdr, rs, &["give_bob", "A::get_bob"], &[]);
+}
+
+#[test]
+fn test_ns_up_wrappers() {
+    let cxx = indoc! {"
+        A::Bob get_bob() {
+            A::Bob b;
+            b.a = 2;
+            b.b = 3;
+            return b;
+        }
+        uint32_t give_bob(A::Bob bob) {
+            return bob.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+                uint32_t b;
+            };
+        }
+        A::Bob get_bob();
+        uint32_t give_bob(A::Bob bob);
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_bob(as_new(ffi::get_bob())), 2);
+    };
+    run_test(cxx, hdr, rs, &["give_bob", "get_bob"], &[]);
+}
+
+#[test]
+fn test_ns_up_wrappers_in_up() {
+    let cxx = indoc! {"
+        A::Bob A::get_bob() {
+            A::Bob b;
+            b.a = 2;
+            b.b = 3;
+            return b;
+        }
+        uint32_t give_bob(A::Bob bob) {
+            return bob.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+                uint32_t b;
+            };
+            Bob get_bob();
+        }
+        uint32_t give_bob(A::Bob bob);
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_bob(as_new(ffi::A::get_bob())), 2);
+    };
+    run_test(cxx, hdr, rs, &["give_bob", "A::get_bob"], &[]);
+}
+
+#[test]
+fn test_return_reference() {
+    let cxx = indoc! {"
+        const Bob& give_bob(const Bob& input_bob) {
+            return input_bob;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        const Bob& give_bob(const Bob& input_bob);
+    "};
+    let rs = quote! {
+        let b = ffi::Bob { a: 3, b: 4 };
+        assert_eq!(ffi::give_bob(&b).b, 4);
+    };
+    run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
+}
+
+#[test]
+fn test_return_reference_non_pod() {
+    let cxx = indoc! {"
+        const Bob& give_bob(const Bob& input_bob) {
+            return input_bob;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        namespace A {
+            void give_bob(); // force wrapper generation
+        }
+        const Bob& give_bob(const Bob& input_bob);
+    "};
+    let rs = quote! {};
+    run_test(cxx, hdr, rs, &["give_bob", "Bob", "A::give_bob"], &[]);
+}
+
+#[test]
+fn test_return_reference_non_pod_string() {
+    let cxx = indoc! {"
+        const std::string& give_bob(const Bob& input_bob) {
+            return input_bob.a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <string>
+        struct Bob {
+            std::string a;
+        };
+       // namespace A {
+       //     void give_bob(); // force wrapper generation
+       // }
+        const std::string& give_bob(const Bob& input_bob);
+    "};
+    let rs = quote! {};
+    run_test(cxx, hdr, rs, &["give_bob", "Bob"], &[]);
+}
+
+#[test]
+fn test_member_return_reference() {
+    let hdr = indoc! {"
+        #include <string>
+        class A {
+        public:
+            virtual const std::string& get_str() { return a; }
+            virtual ~A() {}
+            std::string a;
+        };
+    "};
+    let rs = quote! {
+        let mut b = ffi::A::new().within_unique_ptr();
+        b.pin_mut().get_str();
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_destructor() {
+    let hdr = indoc! {"
+        struct WithDtor {
+            ~WithDtor();
+        };
+        WithDtor make_with_dtor();
+    "};
+    let cxx = indoc! {"
+        WithDtor::~WithDtor() {}
+        WithDtor make_with_dtor() {
+            return {};
+        }
+    "};
+    let rs = quote! {
+        use ffi::*;
+        let with_dtor: cxx::UniquePtr<WithDtor> = make_with_dtor().within_unique_ptr();
+        drop(with_dtor);
+    };
+    run_test(cxx, hdr, rs, &["WithDtor", "make_with_dtor"], &[]);
+}
+
+#[test]
+fn test_nested_with_destructor() {
+    // Regression test, naming the destructor in the generated C++ is a bit tricky.
+    let hdr = indoc! {"
+        struct A {
+            struct B {
+                B() = default;
+                ~B() = default;
+            };
+        };
+    "};
+    let rs = quote! {
+        ffi::A_B::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["A", "A_B"], &[]);
+}
+
+// Even without a `safety!`, we still need to generate a safe `fn drop`.
+#[test]
+fn test_destructor_no_safety() {
+    let hdr = indoc! {"
+        struct WithDtor {
+            ~WithDtor();
+        };
+    "};
+    let cxx = indoc! {"
+        WithDtor::~WithDtor() {}
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let unexpanded_rust = quote! {
+        use autocxx::prelude::*;
+
+        include_cpp!(
+            #hexathorpe include "input.h"
+            generate!("WithDtor")
+        );
+
+        fn main() {}
+    };
+
+    do_run_test_manual(cxx, hdr, unexpanded_rust, None, None).unwrap();
+}
+
+#[test]
+fn test_static_func() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct WithStaticMethod {
+            static uint32_t call();
+        };
+    "};
+    let cxx = indoc! {"
+        uint32_t WithStaticMethod::call() {
+            return 42;
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::WithStaticMethod::call(), 42);
+    };
+    run_test(cxx, hdr, rs, &["WithStaticMethod"], &[]);
+}
+
+#[test]
+fn test_static_func_wrapper() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct A {
+            std::string a;
+            static A CreateA(std::string a, std::string) {
+                A c;
+                c.a = a;
+                return c;
+            }
+        };
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        ffi::A::CreateA("a".into_cpp(), "b".into_cpp());
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_give_pod_typedef_by_value() {
+    let cxx = indoc! {"
+        Horace give_bob() {
+            Horace a;
+            a.a = 3;
+            a.b = 4;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        using Horace = Bob;
+        Horace give_bob();
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_bob().b, 4);
+    };
+    run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]);
+}
+
+#[ignore] // because we need to put some aliases in the output ffi mod.
+#[test]
+fn test_use_pod_typedef() {
+    let cxx = indoc! {"
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        using Horace = Bob;
+    "};
+    let rs = quote! {
+        let h = Horace { a: 3, b: 4 };
+        assert_eq!(h.b, 4);
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob"]);
+}
+
+#[test]
+fn test_typedef_to_ns() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            template<typename T>
+            struct C {
+                T* t;
+            };
+            typedef C<char> B;
+        }
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A::B"], &[]);
+}
+
+#[ignore] // we don't yet allow typedefs to be listed in allow_pod
+#[test]
+fn test_use_pod_typedef_with_allowpod() {
+    let cxx = indoc! {"
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        using Horace = Bob;
+    "};
+    let rs = quote! {
+        let h = Horace { a: 3, b: 4 };
+        assert_eq!(h.b, 4);
+    };
+    run_test(cxx, hdr, rs, &[], &["Horace"]);
+}
+
+#[test]
+fn test_give_nonpod_typedef_by_value() {
+    let cxx = indoc! {"
+        Horace give_bob() {
+            Horace a;
+            a.a = 3;
+            a.b = 4;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t b;
+        };
+        using Horace = Bob;
+        Horace give_bob();
+        inline uint32_t take_horace(const Horace& horace) { return horace.b; }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::take_horace(&moveit!(ffi::give_bob())), 4);
+    };
+    run_test(cxx, hdr, rs, &["give_bob", "take_horace"], &[]);
+}
+
+#[test]
+fn test_conflicting_static_functions() {
+    let cxx = indoc! {"
+        Bob Bob::create() { Bob a; return a; }
+        Fred Fred::create() { Fred b; return b; }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            Bob() : a(0) {}
+            uint32_t a;
+            static Bob create();
+        };
+        struct Fred {
+            Fred() : b(0) {}
+            uint32_t b;
+            static Fred create();
+        };
+    "};
+    let rs = quote! {
+        ffi::Bob::create();
+        ffi::Fred::create();
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob", "Fred"]);
+}
+
+#[test]
+fn test_conflicting_ns_up_functions() {
+    let cxx = indoc! {"
+        uint32_t A::create(C) { return 3; }
+        uint32_t B::create(C) { return 4; }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct C {
+            C() {}
+            uint32_t a;
+        };
+        namespace A {
+            uint32_t create(C c);
+        };
+        namespace B {
+            uint32_t create(C c);
+        };
+    "};
+    let rs = quote! {
+        let c = ffi::C::new().within_unique_ptr();
+        let c2 = ffi::C::new().within_unique_ptr();
+        assert_eq!(ffi::A::create(c), 3);
+        assert_eq!(ffi::B::create(c2), 4);
+    };
+    run_test(cxx, hdr, rs, &["A::create", "B::create", "C"], &[]);
+}
+
+#[test]
+fn test_conflicting_methods() {
+    let cxx = indoc! {"
+        uint32_t Bob::get() const { return a; }
+        uint32_t Fred::get() const { return b; }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+            uint32_t get() const;
+        };
+        struct Fred {
+            uint32_t b;
+            uint32_t get() const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 10 };
+        let b = ffi::Fred { b: 20 };
+        assert_eq!(a.get(), 10);
+        assert_eq!(b.get(), 20);
+    };
+    run_test(cxx, hdr, rs, &[], &["Bob", "Fred"]);
+}
+
+#[test]
+// There's a bindgen bug here. bindgen generates
+// functions called 'get' and 'get1' but then generates impl
+// blocks which call 'get' and 'get'. By luck, we currently
+// should not be broken by this, but at some point we should take
+// the time to create a minimal bindgen test case and submit it
+// as a bindgen bug.
+fn test_conflicting_up_wrapper_methods_not_in_ns() {
+    // Ensures the two names 'get' do not conflict in the flat
+    // cxx::bridge mod namespace.
+    let cxx = indoc! {"
+        Bob::Bob() : a(\"hello\") {}
+        Fred::Fred() : b(\"goodbye\") {}
+        std::string Bob::get() const { return a; }
+        std::string Fred::get() const { return b; }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Bob {
+            Bob();
+            std::string a;
+            std::string get() const;
+        };
+        struct Fred {
+            Fred();
+            std::string b;
+            std::string get() const;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::new().within_unique_ptr();
+        let b = ffi::Fred::new().within_unique_ptr();
+        assert_eq!(a.get().as_ref().unwrap().to_str().unwrap(), "hello");
+        assert_eq!(b.get().as_ref().unwrap().to_str().unwrap(), "goodbye");
+    };
+    run_test(cxx, hdr, rs, &["Bob", "Fred"], &[]);
+}
+
+#[test]
+fn test_conflicting_methods_in_ns() {
+    let cxx = indoc! {"
+        uint32_t A::Bob::get() const { return a; }
+        uint32_t B::Fred::get() const { return b; }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+                uint32_t get() const;
+            };
+        }
+        namespace B {
+            struct Fred {
+                uint32_t b;
+                uint32_t get() const;
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A::Bob { a: 10 };
+        let b = ffi::B::Fred { b: 20 };
+        assert_eq!(a.get(), 10);
+        assert_eq!(b.get(), 20);
+    };
+    run_test(cxx, hdr, rs, &[], &["A::Bob", "B::Fred"]);
+}
+
+#[test]
+fn test_conflicting_up_wrapper_methods_in_ns() {
+    let cxx = indoc! {"
+        A::Bob::Bob() : a(\"hello\") {}
+        B::Fred::Fred() : b(\"goodbye\") {}
+        std::string A::Bob::get() const { return a; }
+        std::string B::Fred::get() const { return b; }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        namespace A {
+            struct Bob {
+                Bob();
+                std::string a;
+                std::string get() const;
+            };
+        }
+        namespace B {
+            struct Fred {
+                Fred();
+                std::string b;
+                std::string get() const;
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A::Bob::new().within_unique_ptr();
+        let b = ffi::B::Fred::new().within_unique_ptr();
+        assert_eq!(a.get().as_ref().unwrap().to_str().unwrap(), "hello");
+        assert_eq!(b.get().as_ref().unwrap().to_str().unwrap(), "goodbye");
+    };
+    run_test(cxx, hdr, rs, &["A::Bob", "B::Fred"], &[]);
+}
+
+#[test]
+fn test_ns_struct_pod_request() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+    "};
+    let rs = quote! {
+        ffi::A::Bob { a: 12 };
+    };
+    run_test("", hdr, rs, &[], &["A::Bob"]);
+}
+
+#[test]
+fn test_conflicting_ns_funcs() {
+    let cxx = indoc! {"
+        uint32_t A::get() { return 10; }
+        uint32_t B::get() { return 20; }
+    "};
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            uint32_t get();
+        }
+        namespace B {
+            uint32_t get();
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::A::get(), 10);
+        assert_eq!(ffi::B::get(), 20);
+    };
+    run_test(cxx, hdr, rs, &["A::get", "B::get"], &[]);
+}
+
+#[ignore]
+// because currently we feed a flat namespace to cxx
+// This would be relatively easy to enable now that we have the facility
+// to add aliases to the 'use' statements we generate, plus
+// bridge_name_tracker to pick a unique name. TODO.
+#[test]
+fn test_conflicting_ns_structs() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+        namespace B {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+    "};
+    let rs = quote! {
+        ffi::A::Bob { a: 12 };
+        ffi::B::Bob { b: 12 };
+    };
+    run_test("", hdr, rs, &[], &["A::Bob", "B::Bob"]);
+}
+
+#[test]
+fn test_make_string() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+        };
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        let a = "hello".into_cpp();
+        assert_eq!(a.to_str().unwrap(), "hello");
+    };
+    run_test("", hdr, rs, &["Bob"], &[]);
+}
+
+#[test]
+fn test_string_make_unique() {
+    let hdr = indoc! {"
+        #include <string>
+        inline void take_string(const std::string*) {};
+    "};
+    let rs = quote! {
+        let s = ffi::make_string("");
+        unsafe { ffi::take_string(s.as_ref().unwrap()) };
+    };
+    run_test("", hdr, rs, &["take_string"], &[]);
+}
+
+#[test]
+fn test_string_constant() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        const char* STRING = \"Foo\";
+    "};
+    let rs = quote! {
+        let a = std::str::from_utf8(ffi::STRING).unwrap().trim_end_matches(char::from(0));
+        assert_eq!(a, "Foo");
+    };
+    run_test("", hdr, rs, &["STRING"], &[]);
+}
+
+#[test]
+fn test_string_let_cxx_string() {
+    let hdr = indoc! {"
+        #include <string>
+        inline void take_string(const std::string&) {};
+    "};
+    let rs = quote! {
+        autocxx::cxx::let_cxx_string!(s = "hello");
+        ffi::take_string(&s);
+    };
+    run_test("", hdr, rs, &["take_string"], &[]);
+}
+
+#[test]
+fn test_pod_constant_harmless_inside_type() {
+    // Check that the presence of this constant doesn't break anything.
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+        };
+        struct Anna {
+            uint32_t a;
+            const Bob BOB = Bob { 10 };
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &[], &["Anna"]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/93
+fn test_pod_constant() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+        };
+        const Bob BOB = Bob { 10 };
+    "};
+    let rs = quote! {
+        let a = &ffi::BOB;
+        assert_eq!(a.a, 10);
+    };
+    run_test("", hdr, rs, &["BOB"], &["Bob"]);
+}
+
+#[test]
+fn test_pod_static_harmless_inside_type() {
+    // Check that the presence of this constant doesn't break anything.
+    // Remove this test when the following one is enabled.
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+        };
+        struct Anna {
+            uint32_t a;
+            static Bob BOB;
+        };
+        Bob Anna::BOB = Bob { 10 };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &[], &["Anna"]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/93
+fn test_pod_static() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct Bob {
+            uint32_t a;
+        };
+        static Bob BOB = Bob { 10 };
+    "};
+    let rs = quote! {
+        let a = &ffi::BOB;
+        assert_eq!(a.a, 10);
+    };
+    run_test("", hdr, rs, &["BOB"], &["Bob"]);
+}
+
+#[test]
+#[ignore] // this probably requires code generation on the C++
+          // side. It's not at all clear how best to handle this.
+fn test_non_pod_constant() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        struct Bob {
+            std::string a;
+            std::string get() { return a };
+        };
+        const Bob BOB = Bob { \"hello\" };
+    "};
+    let rs = quote! {
+        let a = ffi::BOB;
+        // following line assumes that 'a' is a &Bob
+        // but who knows how we'll really do this.
+        assert_eq!(a.get().as_ref().unwrap().to_str().unwrap(), "hello");
+    };
+    run_test("", hdr, rs, &["BOB"], &[]);
+}
+
+#[test]
+fn test_templated_typedef() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+
+        template <typename STRING_TYPE> class BasicStringPiece {
+        public:
+            const STRING_TYPE* ptr_;
+            size_t length_;
+        };
+        typedef BasicStringPiece<uint8_t> StringPiece;
+
+        struct Origin {
+            Origin() {}
+            StringPiece host;
+        };
+    "};
+    let rs = quote! {
+        ffi::Origin::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["Origin"], &[]);
+}
+
+#[test]
+fn test_struct_templated_typedef() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+
+        struct Concrete {
+            uint8_t a;
+        };
+        template <typename STRING_TYPE> class BasicStringPiece {
+        public:
+            const STRING_TYPE* ptr_;
+            size_t length_;
+        };
+        typedef BasicStringPiece<Concrete> StringPiece;
+
+        struct Origin {
+            Origin() {}
+            StringPiece host;
+        };
+    "};
+    let rs = quote! {
+        ffi::Origin::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["Origin"], &[]);
+}
+
+#[test]
+fn test_enum_typedef() {
+    let hdr = indoc! {"
+        enum ConstraintSolverParameters_TrailCompression : int {
+            ConstraintSolverParameters_TrailCompression_NO_COMPRESSION = 0,
+            ConstraintSolverParameters_TrailCompression_COMPRESS_WITH_ZLIB = 1
+        };
+        typedef ConstraintSolverParameters_TrailCompression TrailCompression;
+    "};
+    let rs = quote! {
+        let _ = ffi::TrailCompression::ConstraintSolverParameters_TrailCompression_NO_COMPRESSION;
+    };
+    run_test("", hdr, rs, &["TrailCompression"], &[]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/264
+fn test_conflicting_usings() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <cstddef>
+        typedef size_t diff;
+        struct A {
+            using diff = diff;
+            diff a;
+        };
+        struct B {
+            using diff = diff;
+            diff a;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &[], &["A", "B"]);
+}
+
+#[test]
+fn test_conflicting_usings_with_self_declaration1() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <cstddef>
+        struct common_params {
+            using difference_type = ptrdiff_t;
+        };
+        template <typename Params>
+        class btree_node {
+            public:
+            using difference_type = typename Params::difference_type;
+            Params params;
+        };
+        template <typename Tree>
+        class btree_container {
+            public:
+            using difference_type = typename Tree::difference_type;
+            void clear() {}
+            Tree b;
+            uint32_t a;
+        };
+        typedef btree_container<btree_node<common_params>> my_tree;
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["my_tree"], &[]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/106
+fn test_string_templated_typedef() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+
+        template <typename STRING_TYPE> class BasicStringPiece {
+        public:
+            const STRING_TYPE* ptr_;
+            size_t length_;
+        };
+        typedef BasicStringPiece<std::string> StringPiece;
+
+        struct Origin {
+            Origin() {}
+            StringPiece host;
+        };
+    "};
+    let rs = quote! {
+        ffi::Origin::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["Origin"], &[]);
+}
+
+#[test]
+fn test_associated_type_problem() {
+    // Regression test for a potential bindgen bug
+    let hdr = indoc! {"
+        namespace a {
+        template <typename> class b {};
+        } // namespace a
+        class bl {
+        public:
+          a::b<bl> bm;
+        };
+        struct B {
+            int a;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["B"], &[]);
+}
+
+#[test]
+fn test_two_type_constructors() {
+    // https://github.com/google/autocxx/issues/877
+    let hdr = indoc! {"
+        struct A {
+            int a;
+        };
+        struct B {
+            int B;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A", "B"], &[]);
+}
+
+#[ignore] // https://github.com/rust-lang/rust-bindgen/issues/1924
+#[test]
+fn test_associated_type_templated_typedef_in_struct() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+
+        template <typename STRING_TYPE> class BasicStringPiece {
+        public:
+            typedef size_t size_type;
+            typedef typename STRING_TYPE::value_type value_type;
+            const value_type* ptr_;
+            size_type length_;
+        };
+
+        typedef BasicStringPiece<std::string> StringPiece;
+
+        struct Origin {
+            // void SetHost(StringPiece host);
+            StringPiece host;
+        };
+    "};
+    let rs = quote! {
+        ffi::Origin::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["Origin"], &[]);
+}
+
+#[test]
+fn test_associated_type_templated_typedef() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+
+        template <typename STRING_TYPE> class BasicStringPiece {
+        public:
+            typedef size_t size_type;
+            typedef typename STRING_TYPE::value_type value_type;
+            const value_type* ptr_;
+            size_type length_;
+        };
+
+        typedef BasicStringPiece<std::string> StringPiece;
+
+        struct Container {
+            Container() {}
+            const StringPiece& get_string_piece() const { return sp; }
+            StringPiece sp;
+        };
+
+        inline void take_string_piece(const StringPiece&) {}
+    "};
+    let rs = quote! {
+        let sp = ffi::Container::new().within_box();
+        ffi::take_string_piece(sp.get_string_piece());
+    };
+    run_test("", hdr, rs, &["take_string_piece", "Container"], &[]);
+}
+
+#[test]
+fn test_associated_type_templated_typedef_by_value_regular() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+
+        template <typename STRING_TYPE> class BasicStringPiece {
+        public:
+            BasicStringPiece() : ptr_(nullptr), length_(0) {}
+            typedef size_t size_type;
+            typedef typename STRING_TYPE::value_type value_type;
+            const value_type* ptr_;
+            size_type length_;
+        };
+
+        typedef BasicStringPiece<std::string> StringPiece;
+
+        inline StringPiece give_string_piece() {
+            StringPiece s;
+            return s;
+        }
+        inline void take_string_piece(StringPiece) {}
+    "};
+    let rs = quote! {
+        let sp = ffi::give_string_piece();
+        ffi::take_string_piece(sp);
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate!("take_string_piece")
+            generate!("give_string_piece")
+            instantiable!("StringPiece")
+        },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_associated_type_templated_typedef_by_value_forward_declaration() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+
+        template <typename STRING_TYPE> class BasicStringPiece;
+
+        typedef BasicStringPiece<std::string> StringPiece;
+
+        struct Container {
+            StringPiece give_string_piece() const;
+            void take_string_piece(StringPiece string_piece) const;
+            const StringPiece& get_string_piece() const;
+            uint32_t b;
+        };
+
+        inline void take_string_piece_by_ref(const StringPiece&) {}
+    "};
+    let cpp = indoc! {"
+        template <typename STRING_TYPE> class BasicStringPiece {
+        public:
+            BasicStringPiece() : ptr_(nullptr), length_(0) {}
+            typedef size_t size_type;
+            typedef typename STRING_TYPE::value_type value_type;
+            const value_type* ptr_;
+            size_type length_;
+        };
+
+        StringPiece Container::give_string_piece() const {
+            StringPiece s;
+            return s;
+        }
+        void Container::take_string_piece(StringPiece) const {}
+
+        StringPiece a;
+
+        const StringPiece& Container::get_string_piece() const {
+            return a;
+        }
+    "};
+    // As this template is forward declared we shouldn't be able to pass it by
+    // value, but we still want to be able to use it by reference.
+    let rs = quote! {
+        let cont = ffi::Container::new().within_box();
+        ffi::take_string_piece_by_ref(cont.as_ref().get_string_piece());
+    };
+    run_test(
+        cpp,
+        hdr,
+        rs,
+        &["take_string_piece_by_ref", "Container"],
+        &[],
+    );
+}
+
+#[test]
+fn test_remove_cv_t_pathological() {
+    let hdr = indoc! {"
+        template <class _Ty>
+        struct remove_cv {
+            using type = _Ty;
+            template <template <class> class _Fn>
+            using _Apply = _Fn<_Ty>;
+        };
+
+        template <class _Ty>
+        struct remove_cv<const _Ty> {
+            using type = _Ty;
+            template <template <class> class _Fn>
+            using _Apply = const _Fn<_Ty>;
+        };
+
+        template <class _Ty>
+        struct remove_cv<volatile _Ty> {
+            using type = _Ty;
+            template <template <class> class _Fn>
+            using _Apply = volatile _Fn<_Ty>;
+        };
+
+        template <class _Ty>
+        struct remove_cv<const volatile _Ty> {
+            using type = _Ty;
+            template <template <class> class _Fn>
+            using _Apply = const volatile _Fn<_Ty>;
+        };
+
+        template <class _Ty>
+        using remove_cv_t = typename remove_cv<_Ty>::type;
+
+        template <class _Ty>
+        struct remove_reference {
+            using type                 = _Ty;
+            using _Const_thru_ref_type = const _Ty;
+        };
+
+        template <class _Ty>
+        struct remove_reference<_Ty&> {
+            using type                 = _Ty;
+            using _Const_thru_ref_type = const _Ty&;
+        };
+
+        template <class _Ty>
+        struct remove_reference<_Ty&&> {
+            using type                 = _Ty;
+            using _Const_thru_ref_type = const _Ty&&;
+        };
+
+        template <class _Ty>
+        using remove_reference_t = typename remove_reference<_Ty>::type;
+
+        template <class _Ty>
+        using _Remove_cvref_t = remove_cv_t<remove_reference_t<_Ty>>;
+    "};
+
+    let rs = quote! {};
+
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate_all!()
+        },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_foreign_ns_func_arg_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+        namespace B {
+            inline uint32_t daft(A::Bob a) { return a.a; }
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A::Bob { a: 12 };
+        assert_eq!(ffi::B::daft(a), 12);
+    };
+    run_test("", hdr, rs, &["B::daft"], &["A::Bob"]);
+}
+
+#[test]
+fn test_foreign_ns_func_arg_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+                Bob(uint32_t _a) :a(_a) {}
+            };
+        }
+        namespace B {
+            inline uint32_t daft(A::Bob a) { return a.a; }
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A::Bob::new(12).within_unique_ptr();
+        assert_eq!(ffi::B::daft(a), 12);
+    };
+    run_test("", hdr, rs, &["B::daft", "A::Bob"], &[]);
+}
+
+#[test]
+fn test_foreign_ns_meth_arg_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+        namespace B {
+            struct C {
+                uint32_t a;
+                uint32_t daft(A::Bob a) const { return a.a; }
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A::Bob { a: 12 };
+        let b = ffi::B::C { a: 12 };
+        assert_eq!(b.daft(a), 12);
+    };
+    run_test("", hdr, rs, &[], &["A::Bob", "B::C"]);
+}
+
+#[test]
+fn test_foreign_ns_meth_arg_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+                Bob(uint32_t _a) :a(_a) {}
+            };
+        }
+        namespace B {
+            struct C {
+                uint32_t a;
+                uint32_t daft(A::Bob a) const { return a.a; }
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A::Bob::new(12).within_unique_ptr();
+        let b = ffi::B::C { a: 12 };
+        assert_eq!(b.daft(a), 12);
+    };
+    run_test("", hdr, rs, &["A::Bob"], &["B::C"]);
+}
+
+#[test]
+fn test_foreign_ns_cons_arg_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+        namespace B {
+            struct C {
+                uint32_t a;
+                C(const A::Bob& input) : a(input.a) {}
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A::Bob { a: 12 };
+        let b = ffi::B::C::new(&a).within_unique_ptr();
+        assert_eq!(b.as_ref().unwrap().a, 12);
+    };
+    run_test("", hdr, rs, &[], &["B::C", "A::Bob"]);
+}
+
+#[test]
+fn test_foreign_ns_cons_arg_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                Bob(uint32_t _a) :a(_a) {}
+                uint32_t a;
+            };
+        }
+        namespace B {
+            struct C {
+                uint32_t a;
+                C(const A::Bob& input) : a(input.a) {}
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A::Bob::new(12).within_unique_ptr();
+        let b = ffi::B::C::new(&a).within_unique_ptr();
+        assert_eq!(b.as_ref().unwrap().a, 12);
+    };
+    run_test("", hdr, rs, &["A::Bob"], &["B::C"]);
+}
+
+#[test]
+fn test_foreign_ns_func_ret_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+        namespace B {
+            inline A::Bob daft() { A::Bob bob; bob.a = 12; return bob; }
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::B::daft().a, 12);
+    };
+    run_test("", hdr, rs, &["B::daft"], &["A::Bob"]);
+}
+
+#[test]
+fn test_foreign_ns_func_ret_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+        namespace B {
+            inline A::Bob daft() { A::Bob bob; bob.a = 12; return bob; }
+        }
+    "};
+    let rs = quote! {
+        ffi::B::daft().within_box().as_ref();
+    };
+    run_test("", hdr, rs, &["B::daft", "A::Bob"], &[]);
+}
+
+#[test]
+fn test_foreign_ns_meth_ret_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+        namespace B {
+            struct C {
+                uint32_t a;
+                A::Bob daft() const { A::Bob bob; bob.a = 12; return bob; }
+            };
+        }
+    "};
+    let rs = quote! {
+        let b = ffi::B::C { a: 12 };
+        assert_eq!(b.daft().a, 12);
+    };
+    run_test("", hdr, rs, &[], &["A::Bob", "B::C"]);
+}
+
+#[test]
+fn test_foreign_ns_meth_ret_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        namespace A {
+            struct Bob {
+                uint32_t a;
+            };
+        }
+        namespace B {
+            struct C {
+                uint32_t a;
+                A::Bob daft() const { A::Bob bob; bob.a = 12; return bob; }
+            };
+        }
+    "};
+    let rs = quote! {
+        let b = ffi::B::C { a: 14 };
+        b.daft().within_unique_ptr().as_ref().unwrap();
+    };
+    run_test("", hdr, rs, &["A::Bob"], &["B::C"]);
+}
+
+#[test]
+fn test_root_ns_func_arg_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        namespace B {
+            inline uint32_t daft(Bob a) { return a.a; }
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12 };
+        assert_eq!(ffi::B::daft(a), 12);
+    };
+    run_test("", hdr, rs, &["B::daft"], &["Bob"]);
+}
+
+#[test]
+fn test_root_ns_func_arg_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+            Bob(uint32_t _a) :a(_a) {}
+        };
+        namespace B {
+            inline uint32_t daft(Bob a) { return a.a; }
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::new(12).within_unique_ptr();
+        assert_eq!(ffi::B::daft(a), 12);
+    };
+    run_test("", hdr, rs, &["B::daft", "Bob"], &[]);
+}
+
+#[test]
+fn test_root_ns_meth_arg_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        namespace B {
+            struct C {
+                uint32_t a;
+                uint32_t daft(Bob a) const { return a.a; }
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12 };
+        let b = ffi::B::C { a: 12 };
+        assert_eq!(b.daft(a), 12);
+    };
+    run_test("", hdr, rs, &[], &["Bob", "B::C"]);
+}
+
+#[test]
+fn test_root_ns_meth_arg_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+            Bob(uint32_t _a) :a(_a) {}
+        };
+        namespace B {
+            struct C {
+                uint32_t a;
+                uint32_t daft(Bob a) const { return a.a; }
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::new(12).within_unique_ptr();
+        let b = ffi::B::C { a: 12 };
+        assert_eq!(b.daft(a), 12);
+    };
+    run_test("", hdr, rs, &["Bob"], &["B::C"]);
+}
+
+#[test]
+fn test_root_ns_cons_arg_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        namespace B {
+            struct C {
+                uint32_t a;
+                C(const Bob& input) : a(input.a) {}
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::Bob { a: 12 };
+        let b = ffi::B::C::new(&a).within_unique_ptr();
+        assert_eq!(b.as_ref().unwrap().a, 12);
+    };
+    run_test("", hdr, rs, &[], &["B::C", "Bob"]);
+}
+
+#[test]
+fn test_root_ns_cons_arg_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            Bob(uint32_t _a) :a(_a) {}
+            uint32_t a;
+        };
+        namespace B {
+            struct C {
+                uint32_t a;
+                C(const Bob& input) : a(input.a) {}
+            };
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::Bob::new(12).within_unique_ptr();
+        let b = ffi::B::C::new(&a).within_unique_ptr();
+        assert_eq!(b.as_ref().unwrap().a, 12);
+    };
+    run_test("", hdr, rs, &["Bob"], &["B::C"]);
+}
+
+#[test]
+fn test_root_ns_func_ret_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        namespace B {
+            inline Bob daft() { Bob bob; bob.a = 12; return bob; }
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::B::daft().a, 12);
+    };
+    run_test("", hdr, rs, &["B::daft"], &["Bob"]);
+}
+
+#[test]
+fn test_root_ns_func_ret_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        namespace B {
+            inline Bob daft() { Bob bob; bob.a = 12; return bob; }
+        }
+    "};
+    let rs = quote! {
+        ffi::B::daft().within_unique_ptr().as_ref().unwrap();
+    };
+    run_test("", hdr, rs, &["B::daft", "Bob"], &[]);
+}
+
+#[test]
+fn test_root_ns_meth_ret_pod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        namespace B {
+            struct C {
+                uint32_t a;
+                Bob daft() const { Bob bob; bob.a = 12; return bob; }
+            };
+        }
+    "};
+    let rs = quote! {
+        let b = ffi::B::C { a: 12 };
+        assert_eq!(b.daft().a, 12);
+    };
+    run_test("", hdr, rs, &[], &["Bob", "B::C"]);
+}
+
+#[test]
+fn test_root_ns_meth_ret_nonpod() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct Bob {
+            uint32_t a;
+        };
+        namespace B {
+            struct C {
+                uint32_t a;
+                Bob daft() const { Bob bob; bob.a = 12; return bob; }
+            };
+        }
+    "};
+    let rs = quote! {
+        let b = ffi::B::C { a: 12 };
+        b.daft().within_unique_ptr().as_ref().unwrap();
+    };
+    run_test("", hdr, rs, &["Bob"], &["B::C"]);
+}
+
+#[test]
+fn test_forward_declaration() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <memory>
+        struct A;
+        struct B {
+            B() : a(0) {}
+            uint32_t a;
+            void daft(const A&) const {}
+            static B daft3(const A&) { B b; return b; }
+            A daft4();
+            std::unique_ptr<A> daft5();
+            const std::unique_ptr<A>& daft6();
+        };
+        A* get_a();
+        void delete_a(A*);
+    "};
+    let cpp = indoc! {"
+        struct A {
+            A() : a(0) {}
+            uint32_t a;
+        };
+        A* get_a() {
+            return new A();
+        }
+        void delete_a(A* a) {
+            delete a;
+        }
+        A B::daft4() {
+            A a;
+            return a;
+        }
+        std::unique_ptr<A> B::daft5() {
+            return std::make_unique<A>();
+        }
+        std::unique_ptr<A> fixed;
+        const std::unique_ptr<A>& B::daft6() {
+            return fixed;
+        }
+    "};
+    let rs = quote! {
+        let b = ffi::B::new().within_unique_ptr();
+        let a = ffi::get_a();
+        b.daft(unsafe { a.as_ref().unwrap() });
+        unsafe { ffi::delete_a(a) };
+    };
+    run_test(cpp, hdr, rs, &["B", "get_a", "delete_a"], &[]);
+}
+
+#[test]
+fn test_ulong() {
+    let hdr = indoc! {"
+    inline unsigned long daft(unsigned long a) { return a; }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::daft(autocxx::c_ulong(34)), autocxx::c_ulong(34));
+    };
+    run_test("", hdr, rs, &["daft"], &[]);
+}
+
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
+#[test]
+fn test_typedef_to_ulong() {
+    let hdr = indoc! {"
+        typedef unsigned long fiddly;
+        inline fiddly daft(fiddly a) { return a; }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::daft(autocxx::c_ulong(34)), autocxx::c_ulong(34));
+    };
+    run_test("", hdr, rs, &["daft"], &[]);
+}
+
+#[test]
+fn test_generate_typedef_to_ulong() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        typedef uint32_t fish_t;
+    "};
+    let rs = quote! {
+        let _: ffi::fish_t;
+    };
+    run_test("", hdr, rs, &[], &["fish_t"]);
+}
+
+#[test]
+fn test_ulong_method() {
+    let hdr = indoc! {"
+    class A {
+        public:
+        A() {};
+        unsigned long daft(unsigned long a) const { return a; }
+    };
+    "};
+    let rs = quote! {
+        let a = ffi::A::new().within_unique_ptr();
+        assert_eq!(a.as_ref().unwrap().daft(autocxx::c_ulong(34)), autocxx::c_ulong(34));
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_ulong_wrapped_method() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    struct B {
+        B() {};
+        uint32_t a;
+    };
+    class A {
+        public:
+        A() {};
+        unsigned long daft(unsigned long a, B) const { return a; }
+    };
+    "};
+    let rs = quote! {
+        let b = ffi::B::new().within_unique_ptr();
+        let a = ffi::A::new().within_unique_ptr();
+        assert_eq!(a.as_ref().unwrap().daft(autocxx::c_ulong(34), b), autocxx::c_ulong(34));
+    };
+    run_test("", hdr, rs, &["A", "B"], &[]);
+}
+
+#[test]
+fn test_reserved_name() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        inline uint32_t async(uint32_t a) { return a; }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::async_(34), 34);
+    };
+    run_test("", hdr, rs, &["async_"], &[]);
+}
+
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
+#[test]
+fn test_nested_type() {
+    // Test that we can import APIs that use nested types.
+    // As a regression test, we also test that the nested type `A::B` doesn't conflict with the
+    // top-level type `B`. This used to cause compile errors.
+    let hdr = indoc! {"
+        struct A {
+            A() {}
+            struct B {
+                B() {}
+            };
+            enum C {};
+            using D = int;
+        };
+        struct B {
+            B() {}
+            void method_on_top_level_type() const {}
+        };
+        void take_A_B(A::B);
+        void take_A_C(A::C);
+        void take_A_D(A::D);
+    "};
+    let rs = quote! {
+        let _ = ffi::A::new().within_unique_ptr();
+        let b = ffi::B::new().within_unique_ptr();
+        b.as_ref().unwrap().method_on_top_level_type();
+    };
+    run_test("", hdr, rs, &["A", "B", "take_A_B", "take_A_C"], &[]);
+}
+
+#[test]
+fn test_nested_type_in_namespace() {
+    // Test that we can import APIs that use nested types in a namespace.
+    // We can't make this part of the previous test as autocxx drops the
+    // namespace, so `A::B` and `N::A::B` would be imported as the same
+    // type.
+    let hdr = indoc! {"
+        namespace N {
+            struct A {
+                A() {}
+                struct B {
+                    B() {}
+                };
+            };
+        };
+        void take_A_B(N::A::B);
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["take_A_B"], &[]);
+}
+
+#[test]
+fn test_nested_enum_in_namespace() {
+    let hdr = indoc! {"
+        namespace N {
+            struct A {
+                A() {}
+                enum B {
+                    C,
+                    D,
+                };
+            };
+        };
+        void take_A_B(N::A::B);
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["take_A_B"], &[]);
+}
+
+#[test]
+fn test_abstract_nested_type() {
+    let hdr = indoc! {"
+        namespace N {
+            class A {
+            public:
+                A() {}
+                class B {
+                private:
+                    B() {}
+                public:
+                    virtual ~B() {}
+                    virtual void Foo() = 0;
+                };
+            };
+        };
+        void take_A_B(const N::A::B&);
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["take_A_B", "N::A_B"], &[]);
+}
+
+#[test]
+fn test_nested_type_constructor() {
+    let hdr = indoc! {"
+        #include <string>
+        class A {
+        public:
+            class B {
+            public:
+                B(const std::string&) {}
+                int b;
+            };
+            int a;
+        };
+    "};
+    let rs = quote! {
+        ffi::A_B::new(&ffi::make_string("Hello")).within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["A_B"], &[]);
+}
+
+#[test]
+fn test_generic_type() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <string>
+        template<typename TY>
+        struct Container {
+            Container(TY a_) : a(a_) {}
+            TY a;
+        };
+        struct Secondary {
+            Secondary() {}
+            void take_a(const Container<char>) const {}
+            void take_b(const Container<uint16_t>) const {}
+            uint16_t take_c(std::string a) const { return 10 + a.size(); }
+        };
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        let item = ffi::Secondary::new().within_unique_ptr();
+        assert_eq!(item.take_c("hello".into_cpp()), 15)
+    };
+    run_test("", hdr, rs, &["Secondary"], &[]);
+}
+
+#[test]
+fn test_cycle_generic_type() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        template<typename TY>
+        struct Container {
+            Container(TY a_) : a(a_) {}
+            TY a;
+        };
+        inline Container<char> make_thingy() {
+            Container<char> a('a');
+            return a;
+        }
+        typedef Container<char> Concrete;
+        inline uint32_t take_thingy(Concrete a) {
+            return a.a;
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::take_thingy(ffi::make_thingy()), 'a' as u32)
+    };
+    run_test("", hdr, rs, &["take_thingy", "make_thingy"], &[]);
+}
+
+#[test]
+fn test_virtual_fns() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        class A {
+        public:
+            A(uint32_t num) : b(num) {}
+            virtual uint32_t foo(uint32_t a) { return a+1; };
+            virtual ~A() {}
+            uint32_t b;
+        };
+        class B: public A {
+        public:
+            B() : A(3), c(4) {}
+            virtual uint32_t foo(uint32_t a) { return a+2; };
+            uint32_t c;
+        };
+    "};
+    let rs = quote! {
+        let mut a = ffi::A::new(12).within_unique_ptr();
+        assert_eq!(a.pin_mut().foo(2), 3);
+        let mut b = ffi::B::new().within_unique_ptr();
+        assert_eq!(b.pin_mut().foo(2), 4);
+    };
+    run_test("", hdr, rs, &["A", "B"], &[]);
+}
+
+#[test]
+fn test_const_virtual_fns() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        class A {
+        public:
+            A(uint32_t num) : b(num) {}
+            virtual uint32_t foo(uint32_t a) const { return a+1; };
+            virtual ~A() {}
+            uint32_t b;
+        };
+        class B: public A {
+        public:
+            B() : A(3), c(4) {}
+            virtual uint32_t foo(uint32_t a) const { return a+2; };
+            uint32_t c;
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::A::new(12).within_unique_ptr();
+        assert_eq!(a.foo(2), 3);
+        let b = ffi::B::new().within_unique_ptr();
+        assert_eq!(b.foo(2), 4);
+    };
+    run_test("", hdr, rs, &["A", "B"], &[]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/197
+fn test_virtual_fns_inheritance() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        class A {
+        public:
+            A(uint32_t num) : b(num) {}
+            virtual uint32_t foo(uint32_t a) { return a+1; };
+            virtual ~A() {}
+            uint32_t b;
+        };
+        class B: public A {
+        public:
+            B() : A(3), c(4) {}
+            uint32_t c;
+        };
+    "};
+    let rs = quote! {
+        let mut b = ffi::B::new().within_unique_ptr();
+        assert_eq!(b.pin_mut().foo(2), 3);
+    };
+    run_test("", hdr, rs, &["B"], &[]);
+}
+
+#[test]
+fn test_vector_cycle_up() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <vector>
+        #include <memory>
+        struct A {
+            uint32_t a;
+        };
+        inline uint32_t take_vec(std::unique_ptr<std::vector<A>> many_as) {
+            return many_as->size();
+        }
+        inline std::unique_ptr<std::vector<A>> get_vec() {
+            auto items = std::make_unique<std::vector<A>>();
+            items->push_back(A { 3 });
+            items->push_back(A { 4 });
+            return items;
+        }
+    "};
+    let rs = quote! {
+        let v = ffi::get_vec();
+        assert_eq!(v.as_ref().unwrap().is_empty(), false);
+        assert_eq!(ffi::take_vec(v), 2);
+    };
+    run_test("", hdr, rs, &["take_vec", "get_vec"], &[]);
+}
+
+#[test]
+fn test_vector_cycle_bare() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <vector>
+        struct A {
+            uint32_t a;
+        };
+        inline uint32_t take_vec(std::vector<A> many_as) {
+            return many_as.size();
+        }
+        inline std::vector<A> get_vec() {
+            std::vector<A> items;
+            items.push_back(A { 3 });
+            items.push_back(A { 4 });
+            return items;
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::take_vec(ffi::get_vec()), 2);
+    };
+    run_test("", hdr, rs, &["take_vec", "get_vec"], &[]);
+}
+
+#[test]
+fn test_typedef_to_std() {
+    let hdr = indoc! {"
+        #include <string>
+        typedef std::string my_string;
+        inline uint32_t take_str(my_string a) {
+            return a.size();
+        }
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        assert_eq!(ffi::take_str("hello".into_cpp()), 5);
+    };
+    run_test("", hdr, rs, &["take_str"], &[]);
+}
+
+#[test]
+fn test_typedef_to_up_in_fn_call() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <memory>
+        typedef std::unique_ptr<std::string> my_string;
+        inline uint32_t take_str(my_string a) {
+            return a->size();
+        }
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        assert_eq!(ffi::take_str("hello".into_cpp()), 5);
+    };
+    run_test("", hdr, rs, &["take_str"], &[]);
+}
+
+#[test]
+fn test_typedef_in_pod_struct() {
+    let hdr = indoc! {"
+        #include <string>
+        typedef uint32_t my_int;
+        struct A {
+            my_int a;
+        };
+        inline uint32_t take_a(A a) {
+            return a.a;
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A {
+            a: 32,
+        };
+        assert_eq!(ffi::take_a(a), 32);
+    };
+    run_test("", hdr, rs, &["take_a"], &["A"]);
+}
+
+#[test]
+fn test_cint_in_pod_struct() {
+    let hdr = indoc! {"
+        #include <string>
+        struct A {
+            int a;
+        };
+        inline uint32_t take_a(A a) {
+            return a.a;
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::A {
+            a: 32,
+        };
+        assert_eq!(ffi::take_a(a), 32);
+    };
+    run_test("", hdr, rs, &["take_a"], &["A"]);
+}
+
+#[test]
+fn test_string_in_struct() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <memory>
+        struct A {
+            std::string a;
+        };
+        inline A make_a(std::string b) {
+            A bob;
+            bob.a = b;
+            return bob;
+        }
+        inline uint32_t take_a(A a) {
+            return a.a.size();
+        }
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
+    };
+    run_test("", hdr, rs, &["make_a", "take_a"], &[]);
+}
+
+#[test]
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+fn test_up_in_struct() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <memory>
+        struct A {
+            std::unique_ptr<std::string> a;
+        };
+        inline A make_a(std::string b) {
+            A bob;
+            bob.a = std::make_unique<std::string>(b);
+            return bob;
+        }
+        inline uint32_t take_a(A a) {
+            return a.a->size();
+        }
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
+    };
+    run_test("", hdr, rs, &["make_a", "take_a"], &[]);
+}
+
+#[test]
+fn test_typedef_to_std_in_struct() {
+    let hdr = indoc! {"
+        #include <string>
+        typedef std::string my_string;
+        struct A {
+            my_string a;
+        };
+        inline A make_a(std::string b) {
+            A bob;
+            bob.a = b;
+            return bob;
+        }
+        inline uint32_t take_a(A a) {
+            return a.a.size();
+        }
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
+    };
+    run_test("", hdr, rs, &["make_a", "take_a"], &[]);
+}
+
+#[test]
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+fn test_typedef_to_up_in_struct() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <memory>
+        typedef std::unique_ptr<std::string> my_string;
+        struct A {
+            my_string a;
+        };
+        inline A make_a(std::string b) {
+            A bob;
+            bob.a = std::make_unique<std::string>(b);
+            return bob;
+        }
+        inline uint32_t take_a(A a) {
+            return a.a->size();
+        }
+    "};
+    let rs = quote! {
+        use ffi::ToCppString;
+        assert_eq!(ffi::take_a(as_new(ffi::make_a("hello".into_cpp()))), 5);
+    };
+    run_test("", hdr, rs, &["make_a", "take_a"], &[]);
+}
+
+#[test]
+fn test_float() {
+    let hdr = indoc! {"
+    inline float daft(float a) { return a; }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::daft(34.0f32), 34.0f32);
+    };
+    run_test("", hdr, rs, &["daft"], &[]);
+}
+
+#[test]
+fn test_double() {
+    let hdr = indoc! {"
+    inline double daft(double a) { return a; }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::daft(34.0f64), 34.0f64);
+    };
+    run_test("", hdr, rs, &["daft"], &[]);
+}
+
+#[test]
+fn test_issues_217_222() {
+    let hdr = indoc! {"
+    #include <string>
+    #include <cstdint>
+    #include <cstddef>
+
+    template <typename STRING_TYPE> class BasicStringPiece {
+        public:
+         typedef size_t size_type;
+         typedef typename STRING_TYPE::traits_type traits_type;
+         typedef typename STRING_TYPE::value_type value_type;
+         typedef const value_type* pointer;
+         typedef const value_type& reference;
+         typedef const value_type& const_reference;
+         typedef ptrdiff_t difference_type;
+         typedef const value_type* const_iterator;
+         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+         static const size_type npos;
+    };
+
+    template<typename CHAR>
+    class Replacements {
+     public:
+      Replacements() {
+      }
+      void SetScheme(const CHAR*) {
+      }
+      uint16_t a;
+    };
+
+    struct Component {
+        uint16_t a;
+    };
+
+    template <typename STR>
+    class StringPieceReplacements : public Replacements<typename STR::value_type> {
+        private:
+         using CharT = typename STR::value_type;
+         using StringPieceT = BasicStringPiece<STR>;
+         using ParentT = Replacements<CharT>;
+         using SetterFun = void (ParentT::*)(const CharT*, const Component&);
+         void SetImpl(SetterFun, StringPieceT) {
+        }
+        public:
+        void SetSchemeStr(const CharT* str) { SetImpl(&ParentT::SetScheme, str); }
+    };
+
+    class GURL {
+        public:
+        typedef StringPieceReplacements<std::string> UrlReplacements;
+        GURL() {}
+        GURL ReplaceComponents(const Replacements<char>&) const {
+            return GURL();
+        }
+        uint16_t a;
+    };
+    "};
+    let rs = quote! {
+        ffi::GURL::new().within_unique_ptr();
+    };
+    // The block! directives here are to avoid running into
+    // https://github.com/rust-lang/rust-bindgen/pull/1975
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! { generate!("GURL") block!("StringPiece") block!("Replacements") },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+#[ignore] // https://github.com/rust-lang/rust-bindgen/pull/1975, https://github.com/google/autocxx/issues/106
+fn test_dependent_qualified_type() {
+    let hdr = indoc! {"
+    #include <stddef.h>
+    struct MyString {
+        typedef char value_type;
+    };
+    template<typename T> struct MyStringView {
+        typedef typename T::value_type view_value_type;
+        const view_value_type* start;
+        size_t length;
+    };
+    const char* HELLO = \"hello\";
+    inline MyStringView<MyString> make_string_view() {
+        MyStringView<MyString> r;
+        r.start = HELLO;
+        r.length = 2;
+        return r;
+    }
+    inline size_t take_string_view(const MyStringView<MyString>& bit) {
+        return bit.length;
+    }
+    "};
+    let rs = quote! {
+        let sv = ffi::make_string_view();
+        assert_eq!(ffi::take_string_view(sv.as_ref().unwrap()), 2);
+    };
+    run_test("", hdr, rs, &["take_string_view", "make_string_view"], &[]);
+}
+
+#[test]
+fn test_simple_dependent_qualified_type() {
+    // bindgen seems to cope with this case just fine
+    let hdr = indoc! {"
+    #include <stddef.h>
+    #include <stdint.h>
+    struct MyString {
+        typedef char value_type;
+    };
+    template<typename T> struct MyStringView {
+        typedef typename T::value_type view_value_type;
+        const view_value_type* start;
+        size_t length;
+    };
+    typedef MyStringView<MyString>::view_value_type MyChar;
+    inline MyChar make_char() {
+        return 'a';
+    }
+    inline uint32_t take_char(MyChar c) {
+        return static_cast<unsigned char>(c);
+    }
+    "};
+    let rs = quote! {
+        let c = ffi::make_char();
+        assert_eq!(ffi::take_char(c), 97);
+    };
+    run_test("", hdr, rs, &["make_char", "take_char"], &[]);
+}
+
+#[test]
+fn test_ignore_dependent_qualified_type() {
+    let hdr = indoc! {"
+    #include <stddef.h>
+    struct MyString {
+        typedef char value_type;
+    };
+    template<typename T> struct MyStringView {
+        typedef typename T::value_type view_value_type;
+        const view_value_type* start;
+        size_t length;
+    };
+    MyStringView<MyString> make_string_view();
+    struct B {
+        B() {}
+        inline size_t take_string_view(const MyStringView<MyString> bit) {
+            return bit.length;
+        }
+    };
+    "};
+    let cpp = indoc! {"
+    const char* HELLO = \"hello\";
+    MyStringView<MyString> make_string_view() {
+        MyStringView<MyString> r;
+        r.start = HELLO;
+        r.length = 2;
+        return r;
+    }
+    "};
+    let rs = quote! {
+        ffi::B::new().within_unique_ptr();
+    };
+    run_test(cpp, hdr, rs, &["B"], &[]);
+}
+
+#[test]
+fn test_ignore_dependent_qualified_type_reference() {
+    let hdr = indoc! {"
+    #include <stddef.h>
+    struct MyString {
+        typedef char value_type;
+    };
+    template<typename T> struct MyStringView {
+        typedef typename T::value_type view_value_type;
+        const view_value_type* start;
+        size_t length;
+    };
+    MyStringView<MyString> make_string_view();
+    struct B {
+        B() {}
+        inline size_t take_string_view(const MyStringView<MyString>& bit) {
+            return bit.length;
+        }
+    };
+    "};
+    let cpp = indoc! {"
+    const char* HELLO = \"hello\";
+    MyStringView<MyString> make_string_view() {
+        MyStringView<MyString> r;
+        r.start = HELLO;
+        r.length = 2;
+        return r;
+    }
+    "};
+    let rs = quote! {
+        ffi::B::new().within_unique_ptr();
+    };
+    run_test(cpp, hdr, rs, &["B"], &[]);
+}
+
+#[test]
+fn test_specialization() {
+    let hdr = indoc! {"
+    #include <stddef.h>
+    #include <stdint.h>
+    #include <string>
+    #include <type_traits>
+
+    template <typename T, bool = std::is_trivially_destructible<T>::value>
+    struct OptionalStorageBase {
+        T value_;
+    };
+
+    template <typename T,
+    bool = std::is_trivially_copy_constructible<T>::value,
+    bool = std::is_trivially_move_constructible<T>::value>
+    struct OptionalStorage : OptionalStorageBase<T> {};
+
+    template <typename T>
+    struct OptionalStorage<T,
+                       true /* trivially copy constructible */,
+                       false /* trivially move constructible */>
+    : OptionalStorageBase<T> {
+    };
+
+    template <typename T>
+    struct OptionalStorage<T,
+                       false /* trivially copy constructible */,
+                       true /* trivially move constructible */>
+    : OptionalStorageBase<T> {
+    };
+
+    template <typename T>
+    struct OptionalStorage<T,
+                       true /* trivially copy constructible */,
+                       true /* trivially move constructible */>
+    : OptionalStorageBase<T> {
+    };
+
+    template <typename T>
+    class OptionalBase {
+    private:
+        OptionalStorage<T> storage_;
+    };
+
+    template <typename T>
+    class Optional : public OptionalBase<T> {
+
+    };
+
+    struct B {
+        B() {}
+        void take_optional(Optional<std::string>) {}
+        uint32_t a;
+    };
+    "};
+    let rs = quote! {
+        ffi::B::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["B"], &[]);
+}
+
+#[test]
+fn test_private_constructor_make_unique() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    struct A {
+    private:
+        A() {};
+    public:
+        uint32_t a;
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/266
+fn test_take_array() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    uint32_t take_array(const uint32_t a[4]) {
+        return a[0] + a[2];
+    }
+    "};
+    let rs = quote! {
+        let c: [u32; 4usize] = [ 10, 20, 30, 40 ];
+        let c = c as *const [_];
+        assert_eq!(ffi::take_array(&c), 40);
+    };
+    run_test("", hdr, rs, &["take_array"], &[]);
+}
+
+#[test]
+fn test_take_array_in_struct() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    struct data {
+        char a[4];
+    };
+    uint32_t take_array(const data a) {
+        return a.a[0] + a.a[2];
+    }
+    "};
+    let rs = quote! {
+        let c = ffi::data { a: [ 10, 20, 30, 40 ] };
+        assert_eq!(ffi::take_array(c), 40);
+    };
+    run_test("", hdr, rs, &["take_array"], &["data"]);
+}
+
+#[test]
+fn test_union_ignored() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    union A {
+        uint32_t a;
+        float b;
+    };
+    struct B {
+        B() :a(1) {}
+        uint32_t take_union(A) const {
+            return 3;
+        }
+        uint32_t get_a() const { return 2; }
+        uint32_t a;
+    };
+    "};
+    let rs = quote! {
+        let b = ffi::B::new().within_unique_ptr();
+        assert_eq!(b.get_a(), 2);
+    };
+    run_test("", hdr, rs, &["B"], &[]);
+}
+
+#[test]
+fn test_double_underscores_ignored() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    struct __FOO {
+        uint32_t a;
+    };
+    struct B {
+        B() :a(1) {}
+        uint32_t take_foo(__FOO) const {
+            return 3;
+        }
+        void do__something() const { }
+        uint32_t get_a() const { return 2; }
+        uint32_t a;
+    };
+
+    struct __default { __default() = default; };
+    struct __destructor { ~__destructor() = default; };
+    struct __copy { __copy(const __copy&) = default; };
+    struct __copy_operator { __copy_operator &operator=(const __copy_operator&) = default; };
+    struct __move { __move(__move&&) = default; };
+    struct __move_operator { __move_operator &operator=(const __move_operator&) = default; };
+    "};
+    let rs = quote! {
+        let b = ffi::B::new().within_unique_ptr();
+        assert_eq!(b.get_a(), 2);
+    };
+    run_test(
+        "",
+        hdr,
+        rs,
+        &[
+            "B",
+            "__default",
+            "__destructor",
+            "__copy",
+            "__copy_operator",
+            "__move",
+            "__move_operator",
+        ],
+        &[],
+    );
+}
+
+// This test fails on Windows gnu but not on Windows msvc
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[test]
+fn test_double_underscore_typedef_ignored() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    typedef int __int32_t;
+    typedef __int32_t __darwin_pid_t;
+    typedef __darwin_pid_t pid_t;
+    struct B {
+        B() :a(1) {}
+        uint32_t take_foo(pid_t) const {
+            return 3;
+        }
+        uint32_t get_a() const { return 2; }
+        uint32_t a;
+    };
+    "};
+    let rs = quote! {
+        let b = ffi::B::new().within_unique_ptr();
+        assert_eq!(b.get_a(), 2);
+    };
+    run_test("", hdr, rs, &["B"], &[]);
+}
+
+#[test]
+fn test_double_underscores_fn_namespace() {
+    let hdr = indoc! {"
+    namespace __B {
+        inline void a() {}
+    };
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_all!() },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_typedef_to_ptr_is_marked_unsafe() {
+    let hdr = indoc! {"
+    struct _xlocalefoo; /* forward reference */
+    typedef struct _xlocalefoo * locale_tfoo;
+    extern \"C\" {
+        locale_tfoo duplocalefoo(locale_tfoo);
+    }
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["duplocalefoo"], &[]);
+}
+
+#[test]
+fn test_issue_264() {
+    let hdr = indoc! {"
+    namespace a {
+        typedef int b;
+        //inline namespace c {}
+        template <typename> class aa;
+        inline namespace c {
+        template <typename d, typename = d, typename = aa<d>> class e;
+        }
+        typedef e<char> f;
+        template <typename g, typename, template <typename> typename> struct h {
+          using i = g;
+        };
+        template <typename g, template <typename> class k> using j = h<g, void, k>;
+        template <typename g, template <typename> class k>
+        using m = typename j<g, k>::i;
+        template <typename> struct l { typedef b ab; };
+        template <typename p> class aa {
+        public:
+          typedef p n;
+        };
+        struct r {
+          template <typename p> using o = typename p::c;
+        };
+        template <typename ad> struct u : r {
+          typedef typename ad::n n;
+          using ae = m<n, o>;
+          template <typename af, typename> struct v { using i = typename l<f>::ab; };
+          using ab = typename v<ad, ae>::i;
+        };
+        } // namespace a
+        namespace q {
+        template <typename ad> struct w : a::u<ad> {};
+        } // namespace q
+        namespace a {
+        inline namespace c {
+        template <typename, typename, typename ad> class e {
+          typedef q::w<ad> s;
+        public:
+          typedef typename s::ab ab;
+        };
+        } // namespace c
+        } // namespace a
+        namespace ag {
+        namespace ah {
+        typedef a::f::ab t;
+        class ai {
+        public:
+          t aj;
+        };
+        class al;
+        namespace am {
+        class an {
+        public:
+          void ao(ai);
+        };
+        } // namespace am
+        class ap {
+        public:
+          al aq();
+        };
+        class ar {
+        public:
+          am::an as;
+        };
+        class al {
+        public:
+          ar at;
+        };
+        struct au {
+          ap av;
+        };
+        } // namespace ah
+        } // namespace ag
+        namespace operations_research {
+        class aw {
+        public:
+          ag::ah::au ax;
+        };
+        class Solver {
+        public:
+          aw ay;
+        };
+        } // namespace operations_research
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        directives_from_lists(&["operations_research::Solver"], &[], None),
+        make_cpp17_adder(),
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_unexpected_use() {
+    // https://github.com/google/autocxx/issues/303
+    let hdr = indoc! {"
+        typedef int a;
+        namespace b {
+        namespace c {
+        enum d : a;
+        }
+        } // namespace b
+        namespace {
+        using d = b::c::d;
+        }
+        namespace content {
+        class RenderFrameHost {
+        public:
+            RenderFrameHost() {}
+        d e;
+        };
+        } // namespace content
+        "};
+    let rs = quote! {
+        let _ = ffi::content::RenderFrameHost::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["content::RenderFrameHost"], &[]);
+}
+
+#[test]
+fn test_get_pure_virtual() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        class A {
+        public:
+            virtual ~A() {}
+            virtual uint32_t get_val() const = 0;
+        };
+        class B : public A {
+        public:
+            virtual uint32_t get_val() const { return 3; }
+        };
+        const B b;
+        inline const A* get_a() { return &b; };
+    "};
+    let rs = quote! {
+        let a = ffi::get_a();
+        let a_ref = unsafe { a.as_ref() }.unwrap();
+        assert_eq!(a_ref.get_val(), 3);
+    };
+    run_test("", hdr, rs, &["A", "get_a"], &[]);
+}
+
+#[test]
+fn test_abstract_class_no_make_unique() {
+    // We shouldn't generate a new().within_unique_ptr() for abstract classes.
+    // The test is successful if the bindings compile, i.e. if autocxx doesn't
+    // attempt to instantiate the class.
+    let hdr = indoc! {"
+        class A {
+        public:
+            A() {}
+            virtual ~A() {}
+            virtual void foo() const = 0;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_derived_abstract_class_no_make_unique() {
+    let hdr = indoc! {"
+        class A {
+        public:
+            A();
+            virtual ~A() {}
+            virtual void foo() const = 0;
+        };
+
+        class B : public A {
+        public:
+            B();
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A", "B"], &[]);
+}
+
+#[test]
+fn test_recursive_derived_abstract_class_no_make_unique() {
+    let hdr = indoc! {"
+        class A {
+        public:
+            A() {}
+            virtual ~A() {}
+            virtual void foo() const = 0;
+        };
+
+        class B : public A {
+        public:
+            B() {};
+        };
+
+        class C : public B {
+        public:
+            C() {};
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A", "B", "C"], &[]);
+}
+
+#[test]
+fn test_derived_abstract_class_with_no_allowlisting_no_make_unique() {
+    let hdr = indoc! {"
+        class A {
+        public:
+            A();
+            virtual ~A() {}
+            virtual void foo() const = 0;
+        };
+
+        class B : public A {
+        public:
+            B();
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["B"], &[]);
+}
+
+#[test]
+fn test_vector_of_pointers() {
+    // Just ensures the troublesome API is ignored
+    let hdr = indoc! {"
+        #include <vector>
+        namespace operations_research {
+        class a;
+        class Solver {
+        public:
+          struct b c(std::vector<a *>);
+        };
+        class a {};
+        } // namespace operations_research
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["operations_research::Solver"], &[]);
+}
+
+#[test]
+fn test_vec_and_up_of_primitives() {
+    let hdr = indoc! {"
+        #include <vector>
+        #include <memory>
+        #include <cstdint>
+        class Value {
+        public:
+            Value(std::vector<uint32_t>) {} // OK
+            Value(std::unique_ptr<uint32_t>) {} // should be ignored
+            Value(std::vector<int>) {} // should be ignored
+            Value(std::unique_ptr<int>) {} // should be ignored
+            Value(std::vector<char>) {} // should be ignored
+            Value(std::unique_ptr<char>) {} // should be ignored
+            Value(std::vector<float>) {} // OK
+            Value(std::unique_ptr<float>) {} // should be ignored
+            Value(std::vector<bool>) {} // should be ignored
+            Value(std::unique_ptr<bool>) {} // should be ignored
+            Value(std::vector<size_t>) {} // OK
+            Value(std::unique_ptr<size_t>) {} // should be ignored
+        };
+        inline std::vector<uint32_t> make_vec_uint32_t() {
+            std::vector<uint32_t> a;
+            return a;
+        }
+        inline std::vector<float> make_vec_float() {
+            std::vector<float> a;
+            return a;
+        }
+        inline std::vector<size_t> make_vec_size_t() {
+            std::vector<size_t> a;
+            return a;
+        }
+    "};
+    let rs = quote! {
+        ffi::Value::new(ffi::make_vec_uint32_t()).within_box();
+        ffi::Value::new6(ffi::make_vec_float()).within_box();
+        ffi::Value::new10(ffi::make_vec_size_t()).within_box();
+    };
+    run_test(
+        "",
+        hdr,
+        rs,
+        &[
+            "Value",
+            "make_vec_uint32_t",
+            "make_vec_float",
+            "make_vec_size_t",
+        ],
+        &[],
+    );
+}
+
+#[test]
+fn test_pointer_to_pointer() {
+    // Just ensures the troublesome API is ignored
+    let hdr = indoc! {"
+        namespace operations_research {
+        class a;
+        class Solver {
+        public:
+          struct b c(a **);
+        };
+        class a {};
+        } // namespace operations_research
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["operations_research::Solver"], &[]);
+}
+
+#[test]
+fn test_defines_effective() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #ifdef FOO
+        inline uint32_t a() { return 4; }
+        #endif
+    "};
+    let rs = quote! {
+        ffi::a();
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! { generate!("a") },
+        make_clang_arg_adder(&["-DFOO"]),
+        None,
+        None,
+    );
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/227
+fn test_function_pointer_template() {
+    let hdr = indoc! {"
+        typedef int a;
+        namespace std {
+        template <typename> class b;
+        }
+        typedef a c;
+        namespace operations_research {
+        class d;
+        class Solver {
+        public:
+            typedef std::b<c()> IndexEvaluator3;
+            d e(IndexEvaluator3);
+        };
+        class d {};
+        } // namespace operations_research
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["operations_research::Solver"], &[]);
+}
+
+#[test]
+fn test_cvoid() {
+    let hdr = indoc! {"
+        #include <memory>
+        #include <cstdint>
+        inline void* a() {
+            return static_cast<void*>(new int(3));
+        }
+        inline uint32_t b(void* p) {
+            int* p_int = static_cast<int*>(p);
+            auto val = *p_int;
+            delete p_int;
+            return val;
+        }
+    "};
+    let rs = quote! {
+        let ptr = ffi::a();
+        let res = unsafe { ffi::b(ptr) };
+        assert_eq!(res, 3);
+    };
+    run_test("", hdr, rs, &["a", "b"], &[]);
+}
+
+#[test]
+fn test_c_schar() {
+    let hdr = indoc! {"
+        inline signed char a() {
+            return 8;
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::a(), 8);
+    };
+    run_test("", hdr, rs, &["a"], &[]);
+}
+
+#[test]
+fn test_c_uchar() {
+    let hdr = indoc! {"
+        inline unsigned char a() {
+            return 8;
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::a(), 8);
+    };
+    run_test("", hdr, rs, &["a"], &[]);
+}
+
+#[test]
+fn test_c_ulonglong() {
+    // We don't test all the different variable-length integer types which we populate.
+    // If one works, they probably all do. Hopefully.
+    let hdr = indoc! {"
+        inline unsigned long long a() {
+            return 8;
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::a(), autocxx::c_ulonglong(8));
+    };
+    run_test("", hdr, rs, &["a"], &[]);
+}
+
+#[test]
+fn test_string_transparent_function() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+        inline uint32_t take_string(std::string a) { return a.size(); }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::take_string("hello"), 5);
+    };
+    run_test("", hdr, rs, &["take_string"], &[]);
+}
+
+#[test]
+fn test_string_transparent_method() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+        struct A {
+            A() {}
+            inline uint32_t take_string(std::string a) const { return a.size(); }
+        };
+    "};
+    let rs = quote! {
+        let a = ffi::A::new().within_unique_ptr();
+        assert_eq!(a.take_string("hello"), 5);
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_string_transparent_static_method() {
+    let hdr = indoc! {"
+        #include <string>
+        #include <cstdint>
+        struct A {
+            A() {}
+            static inline uint32_t take_string(std::string a) { return a.size(); }
+        };
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::A::take_string("hello"), 5);
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/490
+fn test_issue_490() {
+    let hdr = indoc! {"
+        typedef int a;
+        typedef long unsigned size_t;
+        namespace std {
+        namespace {
+        using ::size_t;
+        template <class b, b c> struct g { static const b value = c; };
+        template <bool d> using e = g<bool, d>;
+        typedef e<true> true_type;
+        template <size_t, size_t> struct ag {};
+        template <class b> typename b ::h move();
+        template <class> class allocator;
+        template <class> class vector;
+        } // namespace
+        } // namespace std
+        void *operator new(size_t, void *);
+        namespace std {
+        namespace {
+        template <class> struct iterator;
+        template <class b, class> struct ay { using h = b *; };
+        template <class b> struct bj { b bk; };
+        template <class bm, class> class bn : bj<bm> {};
+        template <class b, class i = b> class unique_ptr {
+        typedef i bp;
+        typedef typename ay<b, bp>::h bh;
+        bn<bh, bp> bq;
+
+        public:
+        unique_ptr();
+        unique_ptr(bh);
+        bh get() const;
+        bh release();
+        };
+        template <class = void> struct bt;
+        } // namespace
+        } // namespace std
+        typedef a bv;
+        namespace absl {
+        template <typename ce> class cj {
+        public:
+        using bh = ce *;
+        using iterator = bh;
+        };
+        namespace j {
+        template <class ce> struct cp {
+        using k = ce;
+        using cq = std::bt<>;
+        };
+        template <class ce> using cr = typename cp<ce>::k;
+        template <class ce> using cs = typename cp<ce>::cq;
+        template <class, class, class, class> class ct {
+        public:
+        class iterator {};
+        class cu {
+            cu(iterator);
+            iterator cv;
+        };
+        };
+        template <typename> struct cw;
+        } // namespace j
+        template <class ce, class k = j::cr<ce>, class cq = j::cs<ce>,
+                class cx = std::allocator<ce>>
+        class cy : public j::ct<j::cw<ce>, k, cq, cx> {};
+        } // namespace absl
+        namespace cz {
+        template <typename da> class db { std::ag<sizeof(a), alignof(da)> c; };
+        } // namespace cz
+        namespace spanner {
+        class l;
+        class ColumnList {
+        public:
+        typedef absl::cj<l>::iterator iterator;
+        iterator begin();
+        };
+        class dd {
+        union {
+            cz::db<absl::cy<bv>::cu> e;
+        };
+        };
+        class Row {
+        public:
+        bool f(dd);
+        };
+        } // namespace spanner
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["spanner::Row", "spanner::ColumnList"], &[]);
+}
+
+#[test]
+fn test_immovable_object() {
+    let hdr = indoc! {"
+        class A {
+        public:
+            A();
+            A(A&&) = delete;
+        };
+
+        class B{
+        public:
+            B();
+            B(const B&) = delete;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A", "B"], &[]);
+}
+
+#[test]
+fn test_struct_with_reference() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <utility>
+        struct A {
+            uint32_t a;
+        };
+        struct B {
+            B(const A& param) : a(param) {}
+            const A& a;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A", "B"], &[]);
+}
+
+#[test]
+fn test_struct_with_rvalue() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <utility>
+        struct A {
+            uint32_t a;
+        };
+        struct B {
+            B(A&& param) : a(std::move(param)) {}
+            A&& a;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A", "B"], &[]);
+}
+
+#[test]
+fn test_immovable_nested_object() {
+    let hdr = indoc! {"
+        struct C {
+            class A {
+            public:
+                A();
+                A(A&&) = delete;
+            };
+
+            class B{
+            public:
+                B();
+                B(const B&) = delete;
+            };
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["C_A", "C_B"], &[]);
+}
+
+#[test]
+fn test_type_called_type() {
+    let hdr = indoc! {"
+        namespace a {
+            template<int _Len>
+            struct b
+            {
+                union type
+                {
+                    unsigned char __data[_Len];
+                    struct foo {
+                        int a;
+                    };
+                };
+            };
+        }
+        inline void take_type(a::b<4>::type) {}
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["take_type"], &[]);
+}
+
+#[test]
+fn test_bridge_conflict_ty() {
+    let hdr = indoc! {"
+        namespace a {
+            struct Key { int a; };
+        }
+        namespace b {
+            struct Key { int a; };
+        }
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["a::Key", "b::Key"], &[]);
+}
+
+#[test]
+fn test_bridge_conflict_ty_fn() {
+    let hdr = indoc! {"
+        namespace a {
+            struct Key { int a; };
+        }
+        namespace b {
+            inline void Key() {}
+        }
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["a::Key", "b::Key"], &[]);
+}
+
+#[test]
+fn test_issue_506() {
+    let hdr = indoc! {"
+        namespace std {
+            template <class, class> class am;
+            typedef am<char, char> an;
+        } // namespace std
+        namespace be {
+            class bf {
+            virtual std::an bg() = 0;
+            };
+            class bh : bf {};
+        } // namespace be
+        namespace spanner {
+            class Database;
+            class Row {
+            public:
+            Row(be::bh *);
+            };
+        } // namespace spanner
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["spanner::Database", "spanner::Row"], &[]);
+}
+
+#[test]
+fn test_private_inheritance() {
+    let hdr = indoc! {"
+        class A {
+        public:
+            void foo() {}
+            int a;
+        };
+        class B : A {
+        public:
+            void bar() {}
+            int b;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A", "B"], &[]);
+}
+
+#[test]
+fn test_error_generated_for_static_data() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct A {
+            A() {}
+            uint32_t a;
+        };
+        static A FOO = A();
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! { generate!("FOO")},
+        None,
+        Some(make_error_finder("FOO")),
+        None,
+    );
+}
+
+#[test]
+fn test_error_generated_for_array_dependent_function() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <functional>
+        inline void take_func(std::function<bool(const uint32_t number)>) {
+        }
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! { generate! ("take_func")},
+        None,
+        Some(make_error_finder("take_func")),
+        None,
+    );
+}
+
+#[test]
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
+fn test_error_generated_for_array_dependent_method() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <functional>
+        struct A {
+            void take_func(std::function<bool(const uint32_t number)>) {
+            }
+        };
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! { generate! ("A")},
+        None,
+        Some(make_string_finder(
+            ["take_func", "couldn't be generated"]
+                .map(|s| s.to_string())
+                .to_vec(),
+        )),
+        None,
+    );
+}
+
+#[test]
+fn test_error_generated_for_pod_with_nontrivial_destructor() {
+    // take_a is necessary here because cxx won't generate the required
+    // static assertions unless the type is actually used in some context
+    // where cxx needs to decide it's trivial or non-trivial.
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <functional>
+        struct A {
+            ~A() {}
+        };
+        inline void take_a(A) {}
+    "};
+    let rs = quote! {};
+    run_test_expect_fail("", hdr, rs, &["take_a"], &["A"]);
+}
+
+#[test]
+fn test_error_generated_for_pod_with_nontrivial_move_constructor() {
+    // take_a is necessary here because cxx won't generate the required
+    // static assertions unless the type is actually used in some context
+    // where cxx needs to decide it's trivial or non-trivial.
+    let hdr = indoc! {"
+        #include <cstdint>
+        #include <functional>
+        struct A {
+            A() = default;
+            A(A&&) {}
+        };
+        inline void take_a(A) {}
+    "};
+    let rs = quote! {};
+    run_test_expect_fail("", hdr, rs, &["take_a"], &["A"]);
+}
+
+#[test]
+fn test_double_destruction() {
+    let hdr = indoc! {"
+        #include <stdio.h>
+        #include <stdlib.h>
+        // A simple type to let Rust verify the destructor is run.
+        struct NotTriviallyDestructible {
+            NotTriviallyDestructible() = default;
+            NotTriviallyDestructible(const NotTriviallyDestructible&) = default;
+            NotTriviallyDestructible(NotTriviallyDestructible&&) = default;
+
+            ~NotTriviallyDestructible() {}
+        };
+
+        struct ExplicitlyDefaulted {
+            ExplicitlyDefaulted() = default;
+            ~ExplicitlyDefaulted() = default;
+
+            NotTriviallyDestructible flag;
+        };
+    "};
+    let rs = quote! {
+        moveit! {
+            let mut moveit_t = ffi::ExplicitlyDefaulted::new();
+        }
+    };
+    match do_run_test(
+        "",
+        hdr,
+        rs,
+        directives_from_lists(
+            &[],
+            &["NotTriviallyDestructible", "ExplicitlyDefaulted"],
+            None,
+        ),
+        None,
+        None,
+        None,
+    ) {
+        Err(TestError::CppBuild(_)) => {} // be sure this fails due to a static_assert
+        // rather than some runtime problem
+        _ => panic!("Test didn't fail as expected"),
+    };
+}
+
+#[test]
+fn test_keyword_function() {
+    let hdr = indoc! {"
+        inline void move(int) {};
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["move_"], &[]);
+}
+
+#[test]
+fn test_keyword_method() {
+    let hdr = indoc! {"
+        struct A {
+            int a;
+            inline void move() {};
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_doc_passthru() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        /// Elephants!
+        struct A {
+            uint32_t a;
+        };
+        /// Giraffes!
+        struct B {
+            uint32_t a;
+        };
+        /// Rhinos!
+        inline uint32_t get_a() { return 3; }
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        directives_from_lists(&["A", "get_a"], &["B"], None),
+        None,
+        Some(make_string_finder(
+            ["Giraffes", "Elephants", "Rhinos"]
+                .map(|s| s.to_string())
+                .to_vec(),
+        )),
+        None,
+    );
+}
+
+#[test]
+fn test_closure() {
+    // Ensuring presence of this closure doesn't break other things
+    let hdr = indoc! {"
+    #include <functional>
+    #include <cstdint>
+
+    inline bool take_closure(std::function<bool(const uint32_t number)> fn) {
+        return fn(5);
+    }
+    inline uint32_t get_a() {
+        return 3;
+    }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::get_a(), 3);
+    };
+    run_test("", hdr, rs, &["get_a"], &[]);
+}
+
+#[test]
+fn test_multiply_nested_inner_type() {
+    let hdr = indoc! {"
+        struct Turkey {
+            struct Duck {
+                struct Hen {
+                    int wings;
+                };
+                struct HenWithDefault {
+                    HenWithDefault() = default;
+                    int wings;
+                };
+                struct HenWithDestructor {
+                    ~HenWithDestructor() = default;
+                    int wings;
+                };
+                struct HenWithCopy {
+                    HenWithCopy() = default;
+                    HenWithCopy(const HenWithCopy&) = default;
+                    int wings;
+                };
+                struct HenWithMove {
+                    HenWithMove() = default;
+                    HenWithMove(HenWithMove&&) = default;
+                    int wings;
+                };
+            };
+        };
+        "};
+    let rs = quote! {
+        ffi::Turkey_Duck_Hen::new().within_unique_ptr();
+        ffi::Turkey_Duck_HenWithDefault::new().within_unique_ptr();
+        ffi::Turkey_Duck_HenWithDestructor::new().within_unique_ptr();
+        ffi::Turkey_Duck_HenWithCopy::new().within_unique_ptr();
+        ffi::Turkey_Duck_HenWithMove::new().within_unique_ptr();
+
+        moveit! {
+            let hen = ffi::Turkey_Duck_Hen::new();
+            let moved_hen = autocxx::moveit::new::mov(hen);
+            let _copied_hen = autocxx::moveit::new::copy(moved_hen);
+
+            let hen = ffi::Turkey_Duck_HenWithDefault::new();
+            let moved_hen = autocxx::moveit::new::mov(hen);
+            let _copied_hen = autocxx::moveit::new::copy(moved_hen);
+
+            let _hen = ffi::Turkey_Duck_HenWithDestructor::new();
+
+            let hen = ffi::Turkey_Duck_HenWithCopy::new();
+            let _copied_hen = autocxx::moveit::new::copy(hen);
+
+            let hen = ffi::Turkey_Duck_HenWithMove::new();
+            let _moved_hen = autocxx::moveit::new::mov(hen);
+        }
+    };
+    run_test(
+        "",
+        hdr,
+        rs,
+        &[],
+        &[
+            "Turkey_Duck_Hen",
+            "Turkey_Duck_HenWithDefault",
+            "Turkey_Duck_HenWithDestructor",
+            "Turkey_Duck_HenWithCopy",
+            "Turkey_Duck_HenWithMove",
+        ],
+    );
+}
+
+#[test]
+fn test_underscored_namespace_for_inner_type() {
+    let hdr = indoc! {"
+        namespace __foo {
+            struct daft {
+                struct bob {
+                    int a;
+                };
+                int a;
+            };
+        }
+        inline void bar(__foo::daft::bob) {}
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["bar"], &[]);
+}
+
+#[test]
+fn test_blocklist_not_overly_broad() {
+    // This is a regression test. We used to block anything that starts with "rust" or "std",
+    // not just items in the "rust" and "std" namespaces. We therefore test that functions starting
+    // with "rust" or "std" get imported.
+    let hdr = indoc! {"
+    inline void rust_func() { }
+    inline void std_func() { }
+    "};
+    let rs = quote! {
+        ffi::rust_func();
+        ffi::std_func();
+    };
+    run_test("", hdr, rs, &["rust_func", "std_func"], &[]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/837
+fn test_ref_qualified_method() {
+    let hdr = indoc! {"
+        struct A {
+            void foo() & {}
+        };
+    "};
+    let rs = quote! {
+        A::new().within_unique_ptr().foo();
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[test]
+fn test_stringview() {
+    // Test that APIs using std::string_view do not otherwise cause errors.
+    let hdr = indoc! {"
+        #include <string_view>
+        #include <string>
+        void take_string_view(std::string_view) {}
+        std::string_view return_string_view(const std::string& a) { return std::string_view(a); }
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        directives_from_lists(&["take_string_view", "return_string_view"], &[], None),
+        make_cpp17_adder(),
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_include_cpp_alone() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        inline uint32_t give_int() {
+            return 5;
+        }
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let rs = quote! {
+        use autocxx::include_cpp;
+        include_cpp! {
+            #hexathorpe include "input.h"
+            safety!(unsafe_ffi)
+            generate!("give_int")
+        }
+        fn main() {
+            assert_eq!(ffi::give_int(), 5);
+        }
+    };
+    do_run_test_manual("", hdr, rs, None, None).unwrap();
+}
+
+#[test]
+fn test_include_cpp_in_path() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        inline uint32_t give_int() {
+            return 5;
+        }
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let rs = quote! {
+            autocxx::include_cpp! {
+                #hexathorpe include "input.h"
+                safety!(unsafe_ffi)
+                generate!("give_int")
+            }
+            fn main() {
+                assert_eq!(ffi::give_int(), 5);
+            }
+    };
+    do_run_test_manual("", hdr, rs, None, None).unwrap();
+}
+
+#[test]
+fn test_bitset() {
+    let hdr = indoc! {"
+        #include <cstddef>
+        template <size_t _N_words, size_t _Size>
+        class __bitset
+        {
+        public:
+            typedef size_t              __storage_type;
+            __storage_type __first_[_N_words];
+            inline bool all() {
+                return false;
+            }
+        };
+
+        template <size_t _Size>
+        class bitset
+            : private __bitset<_Size == 0 ? 0 : (_Size - 1) / (sizeof(size_t) * 8) + 1, _Size>
+        {
+        public:
+            static const unsigned __n_words = _Size == 0 ? 0 : (_Size - 1) / (sizeof(size_t) * 8) + 1;
+            typedef __bitset<__n_words, _Size> base;
+            bool all() const noexcept;
+        };
+
+
+        typedef bitset<1> mybitset;
+    "};
+
+    let rs = quote! {};
+
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate_all!()
+        },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_cint_vector() {
+    let hdr = indoc! {"
+        #include <vector>
+        #include <cstdint>
+        inline std::vector<int32_t> give_vec() {
+            return std::vector<int32_t> {1,2};
+        }
+    "};
+
+    let rs = quote! {
+        assert_eq!(ffi::give_vec().as_ref().unwrap().as_slice(), &[1,2]);
+    };
+
+    run_test("", hdr, rs, &["give_vec"], &[]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/422
+fn test_int_vector() {
+    let hdr = indoc! {"
+        #include <vector>
+        std::vector<int> give_vec() {
+            return std::vector<int> {1,2};
+        }
+    "};
+
+    let rs = quote! {
+        assert_eq!(ffi::give_vec().as_ref().unwrap().as_slice(), &[autocxx::c_int(1),autocxx::c_int(2)]);
+    };
+
+    run_test("", hdr, rs, &["give_vec"], &[]);
+}
+
+#[test]
+fn test_size_t() {
+    let hdr = indoc! {"
+        #include <cstddef>
+        inline size_t get_count() { return 7; }
+    "};
+
+    let rs = quote! {
+        ffi::get_count();
+    };
+
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        directives_from_lists(&["get_count"], &[], None),
+        None,
+        Some(make_rust_code_finder(vec![
+            quote! {fn get_count() -> usize},
+        ])),
+        None,
+    );
+}
+
+#[test]
+fn test_deleted_function() {
+    // We shouldn't generate bindings for deleted functions.
+    // The test is successful if the bindings compile, i.e. if autocxx doesn't
+    // attempt to call the deleted function.
+    let hdr = indoc! {"
+        class A {
+        public:
+            void foo() = delete;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_ignore_move_constructor() {
+    let hdr = indoc! {"
+        class A {
+        public:
+            A() {}
+            A(A&&) {};
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_ignore_function_with_rvalue_ref() {
+    let hdr = indoc! {"
+        #include <string>
+
+        void moveme(std::string &&);
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["moveme"], &[]);
+}
+
+#[test]
+fn test_take_nonpod_rvalue_from_up() {
+    let hdr = indoc! {"
+        #include <string>
+        struct A {
+            std::string a;
+        };
+        inline void take_a(A&&) {};
+    "};
+    let rs = quote! {
+        let a = ffi::A::new().within_unique_ptr();
+        ffi::take_a(a);
+
+        let a2 = ffi::A::new().within_box();
+        ffi::take_a(a2);
+    };
+    run_test("", hdr, rs, &["A", "take_a"], &[]);
+}
+
+#[test]
+fn test_take_nonpod_rvalue_from_stack() {
+    let hdr = indoc! {"
+        #include <string>
+        struct A {
+            std::string a;
+        };
+        inline void take_a(A&&) {};
+    "};
+    let rs = quote! {
+        moveit! { let a = ffi::A::new() };
+        ffi::take_a(a);
+    };
+    run_test("", hdr, rs, &["A", "take_a"], &[]);
+}
+
+#[test]
+fn test_overloaded_ignored_function() {
+    // When overloaded functions are ignored during import, the placeholder
+    // functions generated for them should have unique names, just as they
+    // would have if they had been imported successfully.
+    // The test is successful if the bindings compile.
+    let hdr = indoc! {"
+        struct Blocked {};
+        class A {
+        public:
+            void take_blocked(Blocked);
+            void take_blocked(Blocked, int);
+        };
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate!("A")
+            block!("Blocked")
+        },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_namespaced_constant() {
+    let hdr = indoc! {"
+        namespace A {
+            const int kConstant = 3;
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::A::kConstant, 3);
+    };
+    run_test("", hdr, rs, &["A::kConstant"], &[]);
+}
+
+#[test]
+fn test_issue_470_492() {
+    let hdr = indoc! {"
+        namespace std {
+            template <bool, typename _Iftrue, typename _Iffalse> struct a;
+        }
+        template <typename> struct b;
+        template <typename d> struct c {
+            typedef std::a<b<d>::c, int, int> e;
+        };
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate_all!()
+        },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_no_impl() {
+    let hdr = indoc! {"
+        struct A {
+            int a;
+        };
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            exclude_impls!()
+            exclude_utilities!()
+            generate!("A")
+        },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_generate_all() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        inline uint32_t give_int() {
+            return 5;
+        }
+    "};
+    let rs = quote! {
+        assert_eq!(ffi::give_int(), 5);
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate_all!()
+        },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_std_thing() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        namespace std {
+            struct A {
+                uint8_t a;
+            };
+        }
+        typedef char daft;
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate_all!()
+        },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_two_mods() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct A {
+            uint32_t a;
+        };
+        inline A give_a() {
+            A a;
+            a.a = 5;
+            return a;
+        }
+        inline uint32_t get_a(A a) {
+            return a.a;
+        }
+        struct B {
+            uint32_t a;
+        };
+        inline B give_b() {
+            B a;
+            a.a = 8;
+            return a;
+        }
+        inline uint32_t get_b(B a) {
+            return a.a;
+        }
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let rs = quote! {
+        use autocxx::prelude::*;
+        include_cpp! {
+            #hexathorpe include "input.h"
+            safety!(unsafe_ffi)
+            generate!("give_a")
+            generate!("get_a")
+        }
+        include_cpp! {
+            #hexathorpe include "input.h"
+            name!(ffi2)
+            generate!("give_b")
+            generate!("get_b")
+        }
+        fn main() {
+            let a = ffi::give_a().within_unique_ptr();
+            assert_eq!(ffi::get_a(a), 5);
+            let b = unsafe { ffi2::give_b().within_unique_ptr() };
+            assert_eq!(unsafe { ffi2::get_b(b) }, 8);
+        }
+    };
+    do_run_test_manual("", hdr, rs, None, None).unwrap();
+}
+
+#[test]
+fn test_manual_bridge() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        inline uint32_t give_int() {
+            return 5;
+        }
+        inline uint32_t give_int2() {
+            return 5;
+        }
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let rs = quote! {
+        autocxx::include_cpp! {
+            #hexathorpe include "input.h"
+            safety!(unsafe_ffi)
+            generate!("give_int")
+        }
+        #[cxx::bridge]
+        mod ffi2 {
+            unsafe extern "C++" {
+                include!("input.h");
+                fn give_int2() -> u32;
+            }
+        }
+        fn main() {
+            assert_eq!(ffi::give_int(), 5);
+            assert_eq!(ffi2::give_int2(), 5);
+        }
+    };
+    do_run_test_manual("", hdr, rs, None, None).unwrap();
+}
+
+#[test]
+fn test_manual_bridge_mixed_types() {
+    let hdr = indoc! {"
+        #include <memory>
+        struct A {
+            int a;
+        };
+        inline int take_A(const A& a) {
+            return a.a;
+        }
+        inline std::unique_ptr<A> give_A() {
+            auto a = std::make_unique<A>();
+            a->a = 5;
+            return a;
+        }
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let rs = quote! {
+        use autocxx::prelude::*;
+        autocxx::include_cpp! {
+            #hexathorpe include "input.h"
+            safety!(unsafe_ffi)
+            generate!("take_A")
+            generate!("A")
+        }
+        #[cxx::bridge]
+        mod ffi2 {
+            unsafe extern "C++" {
+                include!("input.h");
+                type A = crate::ffi::A;
+                fn give_A() -> UniquePtr<A>;
+            }
+        }
+        fn main() {
+            let a = ffi2::give_A();
+            assert_eq!(ffi::take_A(&a), autocxx::c_int(5));
+        }
+    };
+    do_run_test_manual("", hdr, rs, None, None).unwrap();
+}
+
+#[test]
+fn test_extern_cpp_type_cxx_bridge() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct A {
+            A() : a(0) {}
+            int a;
+        };
+        inline void handle_a(const A&) {
+        }
+        inline A create_a() {
+            A a;
+            return a;
+        }
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let rs = quote! {
+        use autocxx::prelude::*;
+        include_cpp! {
+            #hexathorpe include "input.h"
+            safety!(unsafe_ffi)
+            generate!("handle_a")
+            generate!("create_a")
+            extern_cpp_opaque_type!("A", crate::ffi2::A)
+        }
+        #[cxx::bridge]
+        pub mod ffi2 {
+            unsafe extern "C++" {
+                include!("input.h");
+                type A;
+            }
+            impl UniquePtr<A> {}
+        }
+        fn main() {
+            let a = ffi::create_a();
+            ffi::handle_a(&a);
+        }
+    };
+    do_run_test_manual("", hdr, rs, None, None).unwrap();
+}
+
+#[test]
+fn test_extern_cpp_type_two_include_cpp() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct A {
+            A() : a(0) {}
+            int a;
+        };
+        enum B {
+            VARIANT,
+        };
+        inline void handle_a(const A&) {
+        }
+        inline A create_a(B) {
+            A a;
+            return a;
+        }
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let rs = quote! {
+        pub mod base {
+            autocxx::include_cpp! {
+                #hexathorpe include "input.h"
+                name!(ffi2)
+                safety!(unsafe_ffi)
+                generate!("A")
+                generate!("B")
+            }
+            pub use ffi2::*;
+        }
+        pub mod dependent {
+            autocxx::include_cpp! {
+                #hexathorpe include "input.h"
+                safety!(unsafe_ffi)
+                generate!("handle_a")
+                generate!("create_a")
+                extern_cpp_type!("A", crate::base::A)
+                extern_cpp_type!("B", super::super::base::B)
+                pod!("B")
+            }
+            pub use ffi::*;
+        }
+        fn main() {
+            use autocxx::prelude::*;
+            let a = dependent::create_a(base::B::VARIANT).within_box();
+            dependent::handle_a(&a);
+        }
+    };
+    do_run_test_manual("", hdr, rs, None, None).unwrap();
+}
+
+#[test]
+#[ignore] // because we currently require UniquePtrTarget which this can't implement
+fn test_extern_cpp_type_manual() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct A {
+            int a;
+        };
+        inline void handle_a(const A& a) {
+        }
+        inline A create_a() {
+            A a;
+            return a;
+        }
+    "};
+    let hexathorpe = Token![#](Span::call_site());
+    let rs = quote! {
+        autocxx::include_cpp! {
+            #hexathorpe include "input.h"
+            safety!(unsafe_ffi)
+            generate!("handle_a")
+            generate!("create_a")
+            extern_cpp_type!("A", crate::ffi2::A)
+        }
+        pub mod ffi2 {
+            use autocxx::cxx::{type_id, ExternType};
+            #[repr(C)]
+            pub struct A {
+                a: std::os::raw::c_int
+            }
+            unsafe impl ExternType for A {
+                type Kind = autocxx::cxx::kind::Opaque;
+                type Id = type_id!("A");
+            }
+
+        }
+        fn main() {
+            let a = ffi2::A { a: 3 };
+            ffi::handle_a(&a);
+        }
+    };
+    do_run_test_manual("", hdr, rs, None, None).unwrap();
+}
+
+#[test]
+fn test_issue486() {
+    let hdr = indoc! {"
+        namespace a {
+            namespace spanner {
+                class Key;
+            }
+        } // namespace a
+        namespace spanner {
+            class Key {
+                public:
+                    bool b(a::spanner::Key &);
+            };
+        } // namespace spanner
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["spanner::Key"], &[]);
+}
+
+#[test]
+#[ignore]
+fn test_issue616() {
+    let hdr = indoc! {"
+        namespace N {
+            template <typename> class B{};
+            template <typename c> class C {
+            public:
+            using U = B<c>;
+            };
+            }
+            class A : N::C<A> {
+            U u;
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_shared_ptr() {
+    let hdr = indoc! {"
+        #include <memory>
+        struct A {
+            int a;
+        };
+        inline std::shared_ptr<A> make_shared_int() {
+            return std::make_shared<A>(A { 3 });
+        }
+        inline int take_shared_int(std::shared_ptr<A> a) {
+            return a->a;
+        }
+        inline std::weak_ptr<A> shared_to_weak(std::shared_ptr<A> a) {
+            return std::weak_ptr<A>(a);
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::make_shared_int();
+        assert_eq!(ffi::take_shared_int(a.clone()), autocxx::c_int(3));
+        ffi::shared_to_weak(a).upgrade();
+    };
+    run_test(
+        "",
+        hdr,
+        rs,
+        &["make_shared_int", "take_shared_int", "shared_to_weak"],
+        &[],
+    );
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/799
+fn test_shared_ptr_const() {
+    let hdr = indoc! {"
+        #include <memory>
+        inline std::shared_ptr<const int> make_shared_int() {
+            return std::make_shared<const int>(3);
+        }
+        inline int take_shared_int(std::shared_ptr<const int> a) {
+            return *a;
+        }
+    "};
+    let rs = quote! {
+        let a = ffi::make_shared_int();
+        assert_eq!(ffi::take_shared_int(a.clone()), autocxx::c_int(3));
+    };
+    run_test("", hdr, rs, &["make_shared_int", "take_shared_int"], &[]);
+}
+
+#[test]
+fn test_rust_reference() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    struct RustType;
+    inline uint32_t take_rust_reference(const RustType&) {
+        return 4;
+    }
+    "};
+    let rs = quote! {
+        let foo = RustType(3);
+        assert_eq!(ffi::take_rust_reference(&foo), 4);
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate!("take_rust_reference")
+            extern_rust_type!(RustType)
+        },
+        None,
+        None,
+        Some(quote! {
+            pub struct RustType(i32);
+        }),
+    );
+}
+
+#[test]
+fn test_rust_reference_autodiscover() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    struct RustType;
+    inline uint32_t take_rust_reference(const RustType&) {
+        return 4;
+    }
+    "};
+    let rs = quote! {
+        let foo = RustType(3);
+        let result = ffi::take_rust_reference(&foo);
+        assert_eq!(result, 4);
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {},
+        Some(Box::new(EnableAutodiscover)),
+        None,
+        Some(quote! {
+            #[autocxx::extern_rust::extern_rust_type]
+            pub struct RustType(i32);
+        }),
+    );
+}
+
+#[test]
+fn test_pass_thru_rust_reference() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    struct RustType;
+    inline const RustType& pass_rust_reference(const RustType& a) {
+        return a;
+    }
+    "};
+    let rs = quote! {
+        let foo = RustType(3);
+        assert_eq!(ffi::pass_rust_reference(&foo).0, 3);
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate!("pass_rust_reference")
+            extern_rust_type!(RustType)
+        },
+        None,
+        None,
+        Some(quote! {
+            pub struct RustType(i32);
+        }),
+    );
+}
+
+#[test]
+fn test_extern_rust_method() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        struct RustType;
+        uint32_t examine(const RustType& foo);
+    "};
+    let cxx = indoc! {"
+        uint32_t examine(const RustType& foo) {
+            return foo.get();
+        }"};
+    let rs = quote! {
+        let a = RustType(74);
+        assert_eq!(ffi::examine(&a), 74);
+    };
+    run_test_ex(
+        cxx,
+        hdr,
+        rs,
+        directives_from_lists(&["examine"], &[], None),
+        Some(Box::new(EnableAutodiscover)),
+        None,
+        Some(quote! {
+            #[autocxx::extern_rust::extern_rust_type]
+            pub struct RustType(i32);
+            impl RustType {
+                #[autocxx::extern_rust::extern_rust_function]
+                pub fn get(&self) -> i32 {
+                    return self.0
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_rust_reference_no_autodiscover() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    struct RustType;
+    inline uint32_t take_rust_reference(const RustType&) {
+        return 4;
+    }
+    "};
+    let rs = quote! {
+        let foo = RustType(3);
+        let result = ffi::take_rust_reference(&foo);
+        assert_eq!(result, 4);
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        directives_from_lists(&["take_rust_reference"], &[], None),
+        None,
+        None,
+        Some(quote! {
+            #[autocxx::extern_rust::extern_rust_type]
+            pub struct RustType(i32);
+        }),
+    );
+}
+
+#[test]
+#[cfg_attr(skip_windows_msvc_failing_tests, ignore)]
+// TODO - replace make_clang_arg_adder with something that knows how to add an MSVC-suitable
+// directive for the cc build.
+fn test_cpp17() {
+    let hdr = indoc! {"
+        static_assert(__cplusplus >= 201703L, \"This file expects a C++17 compatible compiler.\");
+        inline void foo() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            ffi::foo();
+        },
+        quote! {
+            generate!("foo")
+        },
+        make_cpp17_adder(),
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_box() {
+    let hdr = indoc! {"
+        #include <cxx.h>
+        struct Foo;
+        inline void take_box(rust::Box<Foo>) {
+        }
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            ffi::take_box(Box::new(Foo { a: "Hello".into() }))
+        },
+        quote! {
+            generate!("take_box")
+            extern_rust_type!(Foo)
+        },
+        None,
+        None,
+        Some(quote! {
+            pub struct Foo {
+                a: String,
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_box_via_extern_rust() {
+    let hdr = indoc! {"
+        #include <cxx.h>
+        struct Foo;
+        inline void take_box(rust::Box<Foo>) {
+        }
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            ffi::take_box(Box::new(Foo { a: "Hello".into() }))
+        },
+        quote! {},
+        Some(Box::new(EnableAutodiscover)),
+        None,
+        Some(quote! {
+            #[autocxx::extern_rust::extern_rust_type]
+            pub struct Foo {
+                a: String,
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_box_via_extern_rust_in_mod() {
+    let hdr = indoc! {"
+        #include <cxx.h>
+        struct Foo;
+        inline void take_box(rust::Box<Foo>) {
+        }
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            ffi::take_box(Box::new(bar::Foo { a: "Hello".into() }))
+        },
+        quote! {},
+        Some(Box::new(EnableAutodiscover)),
+        None,
+        Some(quote! {
+            mod bar {
+                #[autocxx::extern_rust::extern_rust_type]
+                pub struct Foo {
+                    pub a: String,
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_extern_rust_fn_simple() {
+    let cpp = indoc! {"
+        void foo() {
+            my_rust_fun();
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cxx.h>
+        inline void do_thing() {}
+    "};
+    run_test_ex(
+        cpp,
+        hdr,
+        quote! {
+            ffi::do_thing();
+        },
+        quote! {
+            generate!("do_thing")
+        },
+        Some(Box::new(EnableAutodiscover)),
+        None,
+        Some(quote! {
+            #[autocxx::extern_rust::extern_rust_function]
+            fn my_rust_fun() {
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_extern_rust_fn_in_mod() {
+    let hdr = indoc! {"
+        #include <cxx.h>
+        inline void do_thing() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! {
+            generate!("do_thing")
+        },
+        Some(Box::new(EnableAutodiscover)),
+        None,
+        Some(quote! {
+            mod bar {
+                #[autocxx::extern_rust::extern_rust_function]
+                pub fn my_rust_fun() {
+
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_issue_956() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        inline void take_int(int&) {}
+        inline void take_uin16(uint16_t&) {}
+        inline void take_char16(char16_t &) {}
+    "};
+    run_test(
+        "",
+        hdr,
+        quote! {},
+        &["take_int", "take_uin16", "take_char16"],
+        &[],
+    );
+}
+
+#[test]
+fn test_extern_rust_fn_no_autodiscover() {
+    let hdr = indoc! {"
+        #include <cxx.h>
+    "};
+    let cpp = indoc! {"
+        void call_it() {
+            my_rust_fun();
+        }
+    "};
+    run_test_ex(
+        cpp,
+        hdr,
+        quote! {},
+        quote! {},
+        None,
+        None,
+        Some(quote! {
+            mod bar {
+                #[autocxx::extern_rust::extern_rust_function]
+                pub fn my_rust_fun() {
+
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_mut() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual void foo() = 0;
+        virtual ~Observer() {}
+    };
+    inline void bar() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+        },
+        quote! {
+            generate!("bar")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+                fn foo(&mut self) {
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_const() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual void foo() const = 0;
+        virtual ~Observer() {}
+    };
+    inline void bar() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+        },
+        quote! {
+            generate!("bar")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+                fn foo(&self) {
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_calls_impossible() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual void foo() const = 0;
+        virtual ~Observer() {}
+    };
+    inline void bar() {}
+    "};
+    run_test_expect_fail_ex(
+        "",
+        hdr,
+        quote! {
+            MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+        },
+        quote! {
+            generate!("bar")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+                fn foo(&self) {
+                    use ffi::Observer_supers;
+                    self.foo_super()
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_not_pub() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual void foo() const = 0;
+        virtual ~Observer() {}
+    };
+    inline void bar() {}
+    "};
+    run_test_expect_fail_ex(
+        "",
+        hdr,
+        quote! {
+            MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+        },
+        quote! {
+            generate!("bar")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+                fn foo(&self) {
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_ptr_param() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    struct A {
+        uint8_t a;
+    };
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual void foo(const A*) const {};
+        virtual ~Observer() {}
+    };
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+        },
+        quote! {
+            generate!("A")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+                unsafe fn foo(&self, a: *const ffi::A) {
+                    use ffi::Observer_supers;
+                    self.foo_super(a)
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_return() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual uint32_t foo() const = 0;
+        virtual ~Observer() {}
+    };
+    inline void bar() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+        },
+        quote! {
+            generate!("bar")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+                fn foo(&self) -> u32 {
+                    4
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_passed_to_fn() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual uint32_t foo() const = 0;
+        virtual ~Observer() {}
+    };
+    inline void take_observer(const Observer&) {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            let o = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+            ffi::take_observer(o.borrow().as_ref());
+        },
+        quote! {
+            generate!("take_observer")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+                fn foo(&self) -> u32 {
+                    4
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_derive_defaults() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual uint32_t foo() const = 0;
+        virtual ~Observer() {}
+    };
+    inline void take_observer(const Observer&) {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            use autocxx::subclass::CppSubclassDefault;
+            let o = MyObserver::default_rust_owned();
+            ffi::take_observer(o.borrow().as_ref());
+        },
+        quote! {
+            generate!("take_observer")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            #[autocxx::subclass::subclass]
+            #[derive(Default)]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl ffi::Observer_methods for MyObserver {
+                fn foo(&self) -> u32 {
+                    4
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_non_pv_subclass_simple() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual void foo() const {}
+        virtual ~Observer() {}
+    };
+    inline void bar() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+            obs.borrow().foo();
+        },
+        quote! {
+            generate!("bar")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_two_subclasses() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual void foo() const {}
+        virtual ~Observer() {}
+    };
+    inline void bar() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            let obs = MyObserverA::new_rust_owned(MyObserverA { a: 3, cpp_peer: Default::default() });
+            obs.borrow().foo();
+            let obs = MyObserverB::new_rust_owned(MyObserverB { a: 3, cpp_peer: Default::default() });
+            obs.borrow().foo();
+        },
+        quote! {
+            generate!("bar")
+            subclass!("Observer",MyObserverA)
+            subclass!("Observer",MyObserverB)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserverA {
+                a: u32
+            }
+            impl Observer_methods for MyObserverA {
+            }
+            #[autocxx::subclass::subclass]
+            pub struct MyObserverB {
+                a: u32
+            }
+            impl Observer_methods for MyObserverB {
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_two_superclasses_with_same_name_method() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class ObserverA {
+    public:
+        ObserverA() {}
+        virtual void foo() const {}
+        virtual ~ObserverA() {}
+    };
+
+    class ObserverB {
+        public:
+            ObserverB() {}
+            virtual void foo() const {}
+            virtual ~ObserverB() {}
+        };
+    inline void bar() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            let obs = MyObserverA::new_rust_owned(MyObserverA { a: 3, cpp_peer: Default::default() });
+            obs.borrow().foo();
+            let obs = MyObserverB::new_rust_owned(MyObserverB { a: 3, cpp_peer: Default::default() });
+            obs.borrow().foo();
+        },
+        quote! {
+            generate!("bar")
+            subclass!("ObserverA",MyObserverA)
+            subclass!("ObserverB",MyObserverB)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::ObserverA_methods;
+            use ffi::ObserverB_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserverA {
+                a: u32
+            }
+            impl ObserverA_methods for MyObserverA {
+            }
+            #[autocxx::subclass::subclass]
+            pub struct MyObserverB {
+                a: u32
+            }
+            impl ObserverB_methods for MyObserverB {
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_protected_constructor() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    protected:
+        Observer() {}
+    public:
+        virtual void foo() const {}
+        virtual ~Observer() {}
+    };
+    inline void bar() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+            obs.borrow().foo();
+        },
+        quote! {
+            generate!("bar")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_protected_method() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer() {}
+        virtual void foo() const {}
+        virtual ~Observer() {}
+    protected:
+        virtual void baz() const {}
+    };
+    inline void bar() {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            let obs = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+            obs.borrow().foo();
+        },
+        quote! {
+            generate!("bar")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+                fn baz(&self) {
+                }
+
+                fn foo(&self) {
+                    use ffi::Observer_supers;
+                    self.baz_super()
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_allocation_not_self_owned() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    extern \"C\" void mark_freed() noexcept;
+    extern \"C\" void mark_allocated() noexcept;
+
+    class TestObserver {
+    public:
+        TestObserver() {
+            mark_allocated();
+        }
+        virtual void a() const = 0;
+        virtual ~TestObserver() {
+            mark_freed();
+        }
+    };
+    inline void TriggerTestObserverA(const TestObserver& obs) {
+        obs.a();
+    }
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+
+            // Test when owned by C++
+            let obs = MyTestObserver::new_cpp_owned(
+                MyTestObserver::new()
+            );
+            assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+            let obs_superclass = obs.as_ref().unwrap(); // &subclass
+            let obs_superclass = unsafe { std::mem::transmute::<&ffi::MyTestObserverCpp, &ffi::TestObserver>(obs_superclass) };
+            ffi::TriggerTestObserverA(obs_superclass);
+            assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
+            std::mem::drop(obs);
+            Lazy::force(&STATUS).lock().unwrap().a_called = false;
+            assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+
+            // Test when owned by Rust
+            let obs = MyTestObserver::new_rust_owned(
+                MyTestObserver::new()
+            );
+            //let cpp_peer_ptr = unsafe { obs.borrow_mut().peer_mut().get_unchecked_mut() as *mut ffi::MyTestObserverCpp };
+            assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+            ffi::TriggerTestObserverA(obs.as_ref().borrow().as_ref());
+            assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
+            Lazy::force(&STATUS).lock().unwrap().a_called = false;
+            std::mem::drop(obs);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+        },
+        quote! {
+            generate!("TriggerTestObserverA")
+            subclass!("TestObserver",MyTestObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use once_cell::sync::Lazy;
+            use std::sync::Mutex;
+
+            use autocxx::subclass::CppSubclass;
+            use ffi::TestObserver_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyTestObserver {
+                data: ExternalEngine,
+            }
+            impl TestObserver_methods for MyTestObserver {
+                fn a(&self) {
+                    self.data.do_something();
+                }
+            }
+            impl MyTestObserver {
+                fn new() -> Self {
+                    Self {
+                        cpp_peer: Default::default(),
+                        data: ExternalEngine::default(),
+                    }
+                }
+            }
+
+            #[no_mangle]
+            pub fn mark_allocated() {
+                Lazy::force(&STATUS).lock().unwrap().cpp_allocated = true;
+            }
+
+            #[no_mangle]
+            pub fn mark_freed() {
+                Lazy::force(&STATUS).lock().unwrap().cpp_allocated = false;
+            }
+
+            #[derive(Default)]
+            struct Status {
+                cpp_allocated: bool,
+                rust_allocated: bool,
+                a_called: bool,
+            }
+
+            static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
+
+            pub struct ExternalEngine;
+
+            impl ExternalEngine {
+                fn do_something(&self) {
+                    Lazy::force(&STATUS).lock().unwrap().a_called = true;
+                }
+            }
+
+            impl Default for ExternalEngine {
+                fn default() -> Self {
+                    Lazy::force(&STATUS).lock().unwrap().rust_allocated = true;
+                    ExternalEngine
+                }
+            }
+
+            impl Drop for ExternalEngine {
+                fn drop(&mut self) {
+                    Lazy::force(&STATUS).lock().unwrap().rust_allocated = false;
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_allocation_self_owned() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    extern \"C\" void mark_freed() noexcept;
+    extern \"C\" void mark_allocated() noexcept;
+
+    class TestObserver {
+    public:
+        TestObserver() {
+            mark_allocated();
+        }
+        virtual void a() const = 0;
+        virtual ~TestObserver() {
+            mark_freed();
+        }
+    };
+    inline void TriggerTestObserverA(const TestObserver& obs) {
+        const_cast<TestObserver&>(obs).a();
+    }
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+
+            // Test when owned by C++
+            let obs = MyTestObserver::new_cpp_owned(
+                MyTestObserver::new(false)
+            );
+            assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+            let obs_superclass = obs.as_ref().unwrap(); // &subclass
+            let obs_superclass = unsafe { std::mem::transmute::<&ffi::MyTestObserverCpp, &ffi::TestObserver>(obs_superclass) };
+
+            ffi::TriggerTestObserverA(obs_superclass);
+            assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
+            std::mem::drop(obs);
+            Lazy::force(&STATUS).lock().unwrap().a_called = false;
+            assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+
+            // Test when owned by Rust
+            let obs = MyTestObserver::new_rust_owned(
+                MyTestObserver::new(false)
+            );
+            assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+            ffi::TriggerTestObserverA(obs.as_ref().borrow().as_ref());
+
+            assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
+            Lazy::force(&STATUS).lock().unwrap().a_called = false;
+            std::mem::drop(obs);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+
+            // Test when self-owned
+            let obs = MyTestObserver::new_self_owned(
+                MyTestObserver::new(true)
+            );
+            let obs_superclass_ptr: *const ffi::TestObserver = obs.as_ref().borrow().as_ref();
+            // Retain just a pointer on the Rust side, so there is no Rust-side
+            // ownership.
+            std::mem::drop(obs);
+            assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+            assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().a_called);
+            ffi::TriggerTestObserverA(unsafe { obs_superclass_ptr.as_ref().unwrap() });
+
+            assert!(Lazy::force(&STATUS).lock().unwrap().a_called);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().cpp_allocated);
+        },
+        quote! {
+            generate!("TriggerTestObserverA")
+            subclass!("TestObserver",MyTestObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use once_cell::sync::Lazy;
+            use std::sync::Mutex;
+
+            use autocxx::subclass::CppSubclass;
+            use autocxx::subclass::CppSubclassSelfOwned;
+            use ffi::TestObserver_methods;
+            #[autocxx::subclass::subclass(self_owned)]
+            pub struct MyTestObserver {
+                data: ExternalEngine,
+                self_owning: bool,
+            }
+            impl TestObserver_methods for MyTestObserver {
+                fn a(&self) {
+                    self.data.do_something();
+                    if self.self_owning {
+                        self.delete_self();
+                    }
+                }
+            }
+            impl MyTestObserver {
+                fn new(self_owning: bool) -> Self {
+                    Self {
+                        cpp_peer: Default::default(),
+                        data: ExternalEngine::default(),
+                        self_owning,
+                    }
+                }
+            }
+
+            #[no_mangle]
+            pub fn mark_allocated() {
+                Lazy::force(&STATUS).lock().unwrap().cpp_allocated = true;
+            }
+
+            #[no_mangle]
+            pub fn mark_freed() {
+                Lazy::force(&STATUS).lock().unwrap().cpp_allocated = false;
+            }
+
+            #[derive(Default)]
+            struct Status {
+                cpp_allocated: bool,
+                rust_allocated: bool,
+                a_called: bool,
+            }
+
+            static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
+
+            pub struct ExternalEngine;
+
+            impl ExternalEngine {
+                fn do_something(&self) {
+                    Lazy::force(&STATUS).lock().unwrap().a_called = true;
+                }
+            }
+
+            impl Default for ExternalEngine {
+                fn default() -> Self {
+                    Lazy::force(&STATUS).lock().unwrap().rust_allocated = true;
+                    ExternalEngine
+                }
+            }
+
+            impl Drop for ExternalEngine {
+                fn drop(&mut self) {
+                    Lazy::force(&STATUS).lock().unwrap().rust_allocated = false;
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_calls() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    extern \"C\" void mark_c_called() noexcept;
+    extern \"C\" void mark_d_called() noexcept;
+    extern \"C\" void mark_e_called() noexcept;
+    extern \"C\" void mark_f_called() noexcept;
+    extern \"C\" void mark_g_called() noexcept;
+    extern \"C\" void mark_h_called() noexcept;
+
+    class TestObserver {
+    public:
+        TestObserver() {}
+        virtual uint32_t a(uint32_t) const = 0;
+        virtual uint32_t b(uint32_t) = 0;
+        virtual uint32_t c(uint32_t) const { mark_c_called(); return 0; };
+        virtual uint32_t d(uint32_t) { mark_d_called(); return 0; };
+        virtual uint32_t e(uint32_t) const { mark_e_called(); return 0; };
+        virtual uint32_t f(uint32_t) { mark_f_called(); return 0; };
+        virtual uint32_t g(uint32_t) const { mark_g_called(); return 0; };
+        virtual uint32_t h(uint32_t) { mark_h_called(); return 0; };
+        virtual ~TestObserver() {}
+    };
+
+    extern TestObserver* obs;
+
+    inline void register_observer(TestObserver& a) {
+        obs = &a;
+    }
+    inline uint32_t call_a(uint32_t param) {
+        return obs->a(param);
+    }
+    inline uint32_t call_b(uint32_t param) {
+        return obs->b(param);
+    }
+    inline uint32_t call_c(uint32_t param) {
+        return obs->c(param);
+    }
+    inline uint32_t call_d(uint32_t param) {
+        return obs->d(param);
+    }
+    inline uint32_t call_e(uint32_t param) {
+        return obs->e(param);
+    }
+    inline uint32_t call_f(uint32_t param) {
+        return obs->f(param);
+    }
+    inline uint32_t call_g(uint32_t param) {
+        return obs->g(param);
+    }
+    inline uint32_t call_h(uint32_t param) {
+        return obs->h(param);
+    }
+    "};
+    run_test_ex(
+        "TestObserver* obs;",
+        hdr,
+        quote! {
+            let obs = MyTestObserver::new_rust_owned(
+                MyTestObserver::default()
+            );
+            ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
+            assert_eq!(ffi::call_a(1), 2);
+            assert!(Lazy::force(&STATUS).lock().unwrap().sub_a_called);
+            *Lazy::force(&STATUS).lock().unwrap() = Default::default();
+
+            assert_eq!(ffi::call_b(1), 3);
+            assert!(Lazy::force(&STATUS).lock().unwrap().sub_b_called);
+            *Lazy::force(&STATUS).lock().unwrap() = Default::default();
+
+            assert_eq!(ffi::call_c(1), 4);
+            assert!(Lazy::force(&STATUS).lock().unwrap().sub_c_called);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().super_c_called);
+            *Lazy::force(&STATUS).lock().unwrap() = Default::default();
+
+            assert_eq!(ffi::call_d(1), 5);
+            assert!(Lazy::force(&STATUS).lock().unwrap().sub_d_called);
+            assert!(!Lazy::force(&STATUS).lock().unwrap().super_d_called);
+            *Lazy::force(&STATUS).lock().unwrap() = Default::default();
+
+            assert_eq!(ffi::call_e(1), 0);
+            assert!(Lazy::force(&STATUS).lock().unwrap().sub_e_called);
+            assert!(Lazy::force(&STATUS).lock().unwrap().super_e_called);
+            *Lazy::force(&STATUS).lock().unwrap() = Default::default();
+
+            assert_eq!(ffi::call_f(1), 0);
+            assert!(Lazy::force(&STATUS).lock().unwrap().sub_f_called);
+            assert!(Lazy::force(&STATUS).lock().unwrap().super_f_called);
+            *Lazy::force(&STATUS).lock().unwrap() = Default::default();
+
+            assert_eq!(ffi::call_g(1), 0);
+            assert!(Lazy::force(&STATUS).lock().unwrap().super_g_called);
+            *Lazy::force(&STATUS).lock().unwrap() = Default::default();
+
+            assert_eq!(ffi::call_h(1), 0);
+            assert!(Lazy::force(&STATUS).lock().unwrap().super_h_called);
+            *Lazy::force(&STATUS).lock().unwrap() = Default::default();
+        },
+        quote! {
+            generate!("register_observer")
+            generate!("call_a")
+            generate!("call_b")
+            generate!("call_c")
+            generate!("call_d")
+            generate!("call_e")
+            generate!("call_f")
+            generate!("call_g")
+            generate!("call_h")
+            subclass!("TestObserver",MyTestObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use once_cell::sync::Lazy;
+            use std::sync::Mutex;
+
+            use autocxx::subclass::CppSubclass;
+            use ffi::TestObserver_methods;
+            #[autocxx::subclass::subclass]
+            #[derive(Default)]
+            pub struct MyTestObserver {
+            }
+            impl TestObserver_methods for MyTestObserver {
+
+                // a and b are pure virtual
+                fn a(&self, param: u32) -> u32 {
+                    Lazy::force(&STATUS).lock().unwrap().sub_a_called = true;
+                    param + 1
+                }
+                fn b(&mut self, param: u32) -> u32 {
+                    Lazy::force(&STATUS).lock().unwrap().sub_b_called = true;
+                    param + 2
+                }
+
+                // c and d we override the superclass
+                fn c(&self, param: u32) -> u32 {
+                    Lazy::force(&STATUS).lock().unwrap().sub_c_called = true;
+                    param + 3
+                }
+                fn d(&mut self, param: u32) -> u32 {
+                    Lazy::force(&STATUS).lock().unwrap().sub_d_called = true;
+                    param + 4
+                }
+
+                // e and f we call through to the superclass
+                fn e(&self, param: u32) -> u32 {
+                    Lazy::force(&STATUS).lock().unwrap().sub_e_called = true;
+                    self.peer().e_super(param)
+                }
+                fn f(&mut self, param: u32) -> u32 {
+                    Lazy::force(&STATUS).lock().unwrap().sub_f_called = true;
+                    self.peer_mut().f_super(param)
+                }
+
+                // g and h we do not do anything, so calls should only call
+                // the superclass
+            }
+
+            #[no_mangle]
+            pub fn mark_c_called() {
+                Lazy::force(&STATUS).lock().unwrap().super_c_called = true;
+            }
+            #[no_mangle]
+            pub fn mark_d_called() {
+                Lazy::force(&STATUS).lock().unwrap().super_d_called = true;
+            }
+            #[no_mangle]
+            pub fn mark_e_called() {
+                Lazy::force(&STATUS).lock().unwrap().super_e_called = true;
+            }
+            #[no_mangle]
+            pub fn mark_f_called() {
+                Lazy::force(&STATUS).lock().unwrap().super_f_called = true;
+            }
+            #[no_mangle]
+            pub fn mark_g_called() {
+                Lazy::force(&STATUS).lock().unwrap().super_g_called = true;
+            }
+            #[no_mangle]
+            pub fn mark_h_called() {
+                Lazy::force(&STATUS).lock().unwrap().super_h_called = true;
+            }
+
+            #[derive(Default)]
+            struct Status {
+                super_c_called: bool,
+                super_d_called: bool,
+                super_e_called: bool,
+                super_f_called: bool,
+                super_g_called: bool,
+                super_h_called: bool,
+                sub_a_called: bool,
+                sub_b_called: bool,
+                sub_c_called: bool,
+                sub_d_called: bool,
+                sub_e_called: bool,
+                sub_f_called: bool,
+            }
+
+            static STATUS: Lazy<Mutex<Status>> = Lazy::new(|| Mutex::new(Status::default()));
+        }),
+    );
+}
+
+#[test]
+fn test_cycle_nonpod_simple() {
+    let hdr = indoc! {"
+    #include <string>
+    struct NonPod {
+        std::string a;
+    };
+    inline NonPod make_non_pod(std::string a) {
+        NonPod p;
+        p.a = a;
+        return p;
+    }
+    inline NonPod call_n(NonPod param) {
+        return param;
+    }
+    "};
+    let rs = quote! {
+        let nonpod = ffi::make_non_pod("hello").within_unique_ptr();
+        ffi::call_n(nonpod).within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["NonPod", "make_non_pod", "call_n"], &[])
+}
+
+#[test]
+fn test_pv_subclass_types() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    #include <string>
+    #include <vector>
+
+    struct Fwd;
+    struct Pod {
+        uint32_t a;
+    };
+    struct NonPod {
+        std::string a;
+    };
+    class TestObserver {
+    public:
+        TestObserver() {}
+        virtual std::string s(std::string p) const { return p; }
+        virtual Pod p(Pod p) const { return p; }
+        virtual NonPod n(NonPod p) const { return p; }
+        virtual void f(const Fwd&) const { }
+        virtual std::vector<NonPod> v(std::vector<NonPod> v) const { return v; }
+        virtual const std::vector<NonPod>& vr(const std::vector<NonPod>& vr) const { return vr; }
+        virtual const std::vector<Fwd>& vfr(const std::vector<Fwd>& vfr) const { return vfr; }
+        virtual ~TestObserver() {}
+    };
+
+    extern TestObserver* obs;
+
+    inline void register_observer(TestObserver& a) {
+        obs = &a;
+    }
+    inline std::string call_s(std::string param) {
+        return obs->s(param);
+    }
+    inline Pod call_p(Pod param) {
+        return obs->p(param);
+    }
+    inline NonPod call_n(NonPod param) {
+        return obs->n(param);
+    }
+    inline NonPod make_non_pod(std::string a) {
+        NonPod p;
+        p.a = a;
+        return p;
+    }
+    "};
+    run_test_ex(
+        "TestObserver* obs;",
+        hdr,
+        quote! {
+            let obs = MyTestObserver::new_rust_owned(
+                MyTestObserver::default()
+            );
+            ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
+            ffi::call_p(ffi::Pod { a: 3 });
+            ffi::call_s("hello");
+            ffi::call_n(ffi::make_non_pod("goodbye").within_unique_ptr());
+        },
+        quote! {
+            generate!("register_observer")
+            generate!("call_s")
+            generate!("call_n")
+            generate!("call_p")
+            generate!("NonPod")
+            generate!("make_non_pod")
+            generate_pod!("Pod")
+            subclass!("TestObserver",MyTestObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::TestObserver_methods;
+            #[autocxx::subclass::subclass]
+            #[derive(Default)]
+            pub struct MyTestObserver {
+            }
+            impl TestObserver_methods for MyTestObserver {
+                fn s(&self, p: cxx::UniquePtr<cxx::CxxString>) -> cxx::UniquePtr<cxx::CxxString> {
+                    self.peer().s_super(p)
+                }
+
+                fn p(&self, p: ffi::Pod) -> ffi::Pod {
+                    self.peer().p_super(p)
+                }
+
+                fn n(&self, p: cxx::UniquePtr<ffi::NonPod>) -> cxx::UniquePtr<ffi::NonPod> {
+                    self.peer().n_super(p)
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_constructors() {
+    // Also tests a Rust-side subclass type which is an empty struct
+    let hdr = indoc! {"
+    #include <cstdint>
+    #include <string>
+
+    class TestObserver {
+    public:
+        TestObserver() {}
+        TestObserver(uint8_t) {}
+        TestObserver(std::string) {}
+        virtual void call() const { }
+        virtual ~TestObserver() {}
+    };
+
+    extern TestObserver* obs;
+
+    inline void register_observer(TestObserver& a) {
+        obs = &a;
+    }
+    inline void do_a_thing() {
+        return obs->call();
+    }
+    "};
+    run_test_ex(
+        "TestObserver* obs;",
+        hdr,
+        quote! {
+            let obs = MyTestObserver::new_rust_owned(
+                MyTestObserver::default()
+            );
+            ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
+            ffi::do_a_thing();
+        },
+        quote! {
+            generate!("register_observer")
+            generate!("do_a_thing")
+            subclass!("TestObserver",MyTestObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::prelude::*;
+            #[subclass]
+            #[derive(Default)]
+            pub struct MyTestObserver;
+            impl ffi::TestObserver_methods for MyTestObserver {
+                fn call(&self) {
+                    self.peer().call_super()
+                }
+            }
+            impl CppPeerConstructor<ffi::MyTestObserverCpp> for MyTestObserver {
+                fn make_peer(&mut self, peer_holder: CppSubclassRustPeerHolder<Self>) -> cxx::UniquePtr<ffi::MyTestObserverCpp> {
+                    ffi::MyTestObserverCpp::new1(peer_holder, 3u8).within_unique_ptr()
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_fancy_constructor() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    class Observer {
+    public:
+        Observer(uint8_t) {}
+        virtual uint32_t foo() const = 0;
+        virtual ~Observer() {}
+    };
+    inline void take_observer(const Observer&) {}
+    "};
+    run_test_expect_fail_ex(
+        "",
+        hdr,
+        quote! {
+            let o = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() }, ffi::MyObserverCpp::make_unique);
+            ffi::take_observer(o.borrow().as_ref());
+        },
+        quote! {
+            generate!("take_observer")
+            subclass!("Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            use ffi::Observer_methods;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl Observer_methods for MyObserver {
+                fn foo(&self) -> u32 {
+                    4
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_non_pv_subclass_overloads() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    #include <string>
+
+    class TestObserver {
+    public:
+        TestObserver() {}
+        virtual void call(uint8_t) const {}
+        virtual void call(std::string) const {}
+        virtual ~TestObserver() {}
+    };
+
+    extern TestObserver* obs;
+
+    inline void register_observer(TestObserver& a) {
+        obs = &a;
+    }
+    inline void do_a_thing() {
+        return obs->call(8);
+    }
+    "};
+    run_test_ex(
+        "TestObserver* obs;",
+        hdr,
+        quote! {
+            let obs = MyTestObserver::new_rust_owned(
+                MyTestObserver::default()
+            );
+            ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
+            ffi::do_a_thing();
+        },
+        quote! {
+            generate!("register_observer")
+            generate!("do_a_thing")
+            subclass!("TestObserver",MyTestObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::prelude::*;
+            #[subclass]
+            #[derive(Default)]
+            pub struct MyTestObserver;
+            impl ffi::TestObserver_methods for MyTestObserver {
+                fn call(&self, a: u8) {
+                    self.peer().call_super(a)
+                }
+                fn call1(&self, a: cxx::UniquePtr<cxx::CxxString>) {
+                    self.peer().call1_super(a)
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_overrides() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    #include <string>
+
+    class TestObserver {
+    public:
+        TestObserver() {}
+        virtual void call(uint8_t) const = 0;
+        virtual void call(std::string) const = 0;
+        virtual ~TestObserver() {}
+    };
+
+    extern TestObserver* obs;
+
+    inline void register_observer(TestObserver& a) {
+        obs = &a;
+    }
+    inline void do_a_thing() {
+        return obs->call(8);
+    }
+    "};
+    run_test_ex(
+        "TestObserver* obs;",
+        hdr,
+        quote! {
+            let obs = MyTestObserver::new_rust_owned(
+                MyTestObserver::default()
+            );
+            ffi::register_observer(obs.as_ref().borrow_mut().pin_mut());
+            ffi::do_a_thing();
+        },
+        quote! {
+            generate!("register_observer")
+            generate!("do_a_thing")
+            subclass!("TestObserver",MyTestObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::prelude::*;
+            #[subclass]
+            #[derive(Default)]
+            pub struct MyTestObserver;
+            impl ffi::TestObserver_methods for MyTestObserver {
+                fn call(&self, _a: u8) {
+                }
+                fn call1(&self, _a: cxx::UniquePtr<cxx::CxxString>) {
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_pv_subclass_namespaced_superclass() {
+    let hdr = indoc! {"
+    #include <cstdint>
+
+    namespace a {
+    class Observer {
+    public:
+        Observer() {}
+        virtual uint32_t foo() const = 0;
+        virtual ~Observer() {}
+    };
+    }
+    inline void take_observer(const a::Observer&) {}
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {
+            let o = MyObserver::new_rust_owned(MyObserver { a: 3, cpp_peer: Default::default() });
+            ffi::take_observer(o.borrow().as_ref());
+        },
+        quote! {
+            generate!("take_observer")
+            subclass!("a::Observer",MyObserver)
+        },
+        None,
+        None,
+        Some(quote! {
+            use autocxx::subclass::CppSubclass;
+            #[autocxx::subclass::subclass]
+            pub struct MyObserver {
+                a: u32
+            }
+            impl ffi::a::Observer_methods for MyObserver {
+                fn foo(&self) -> u32 {
+                    4
+                }
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_no_constructor_make_unique() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    struct A {
+        uint32_t a;
+    };
+    "};
+    let rs = quote! {
+        ffi::A::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_constructor_moveit() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        A() {}
+        void set(uint32_t val) { a = val; }
+        uint32_t get() const { return a; }
+        uint32_t a;
+        std::string so_we_are_non_trivial;
+    };
+    "};
+    let rs = quote! {
+        moveit! {
+            let mut stack_obj = ffi::A::new();
+        }
+        stack_obj.as_mut().set(42);
+        assert_eq!(stack_obj.get(), 42);
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_move_out_of_uniqueptr() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        A() {}
+        std::string so_we_are_non_trivial;
+    };
+    inline A get_a() {
+        A a;
+        return a;
+    }
+    "};
+    let rs = quote! {
+        let a = ffi::get_a().within_unique_ptr();
+        moveit! {
+            let _stack_obj = autocxx::moveit::new::mov(a);
+        }
+    };
+    run_test("", hdr, rs, &["A", "get_a"], &[]);
+}
+
+#[test]
+fn test_implicit_constructor_with_typedef_field() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct B {
+        uint32_t b;
+    };
+    typedef struct B C;
+    struct A {
+        B field;
+        uint32_t a;
+        std::string so_we_are_non_trivial;
+    };
+    "};
+    let rs = quote! {
+        moveit! {
+            let mut stack_obj = ffi::A::new();
+        }
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_implicit_constructor_with_array_field() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        uint32_t a[3];
+        std::string so_we_are_non_trivial;
+    };
+    "};
+    let rs = quote! {
+        moveit! {
+            let mut _stack_obj = ffi::A::new();
+        }
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_implicit_constructor_moveit() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        void set(uint32_t val) { a = val; }
+        uint32_t get() const { return a; }
+        uint32_t a;
+        std::string so_we_are_non_trivial;
+    };
+    "};
+    let rs = quote! {
+        moveit! {
+            let mut stack_obj = ffi::A::new();
+        }
+        stack_obj.as_mut().set(42);
+        assert_eq!(stack_obj.get(), 42);
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_pass_by_value_moveit() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        void set(uint32_t val) { a = val; }
+        uint32_t a;
+        std::string so_we_are_non_trivial;
+    };
+    inline void take_a(A) {}
+    struct B {
+        B() {}
+        B(const B&) {}
+        B(B&&) {}
+        std::string so_we_are_non_trivial;
+    };
+    inline void take_b(B) {}
+    "};
+    let rs = quote! {
+        moveit! {
+            let mut stack_obj = ffi::A::new();
+        }
+        stack_obj.as_mut().set(42);
+        ffi::take_a(&*stack_obj);
+        ffi::take_a(as_copy(stack_obj.as_ref()));
+        ffi::take_a(as_copy(stack_obj.as_ref()));
+        // A has no move constructor so we can't consume it.
+
+        let heap_obj = ffi::A::new().within_unique_ptr();
+        ffi::take_a(heap_obj.as_ref().unwrap());
+        ffi::take_a(&heap_obj);
+        ffi::take_a(autocxx::as_copy(heap_obj.as_ref().unwrap()));
+        ffi::take_a(heap_obj); // consume
+
+        let heap_obj2 = ffi::A::new().within_box();
+        ffi::take_a(heap_obj2.as_ref().get_ref());
+        ffi::take_a(&heap_obj2);
+        ffi::take_a(autocxx::as_copy(heap_obj2.as_ref().get_ref()));
+        ffi::take_a(heap_obj2); // consume
+
+        moveit! {
+            let mut stack_obj = ffi::B::new();
+        }
+        ffi::take_b(&*stack_obj);
+        ffi::take_b(as_copy(stack_obj.as_ref()));
+        ffi::take_b(as_copy(stack_obj.as_ref()));
+        ffi::take_b(as_mov(stack_obj)); // due to move constructor
+
+        // Test direct-from-New-to-param.
+        ffi::take_b(as_new(ffi::B::new()));
+    };
+    run_test("", hdr, rs, &["A", "take_a", "B", "take_b"], &[]);
+}
+
+#[test]
+fn test_nonconst_reference_parameter() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+
+    // Force generating a wrapper for the second `take_a`.
+    struct NOP { void take_a() {}; };
+
+    struct A {
+        std::string so_we_are_non_trivial;
+    };
+    inline void take_a(A&) {}
+    "};
+    let rs = quote! {
+        let mut heap_obj = ffi::A::new().within_unique_ptr();
+        ffi::take_a(heap_obj.pin_mut());
+    };
+    run_test("", hdr, rs, &["NOP", "A", "take_a"], &[]);
+}
+
+#[test]
+fn test_nonconst_reference_method_parameter() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+
+    // Force generating a wrapper for the second `take_a`.
+    struct NOP { void take_a() {}; };
+
+    struct A {
+        std::string so_we_are_non_trivial;
+    };
+    struct B {
+        inline void take_a(A&) const {}
+    };
+    "};
+    let rs = quote! {
+        let mut a = ffi::A::new().within_unique_ptr();
+        let b = ffi::B::new().within_unique_ptr();
+        b.take_a(a.pin_mut());
+    };
+    run_test("", hdr, rs, &["NOP", "A", "B"], &[]);
+}
+
+fn destruction_test(ident: proc_macro2::Ident, extra_bit: Option<TokenStream>) {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    extern bool gConstructed;
+    struct A {
+        A() { gConstructed = true; }
+        virtual ~A() { gConstructed = false; }
+        void set(uint32_t val) { a = val; }
+        uint32_t get() const { return a; }
+        uint32_t a;
+        std::string so_we_are_non_trivial;
+    };
+    inline bool is_constructed() { return gConstructed; }
+    struct B: public A {
+        uint32_t b;
+    };
+    "};
+    let cpp = indoc! {"
+        bool gConstructed = false;
+    "};
+    let rs = quote! {
+        assert!(!ffi::is_constructed());
+        {
+            moveit! {
+                let mut _stack_obj = ffi::#ident::new();
+            }
+            assert!(ffi::is_constructed());
+            #extra_bit
+        }
+        assert!(!ffi::is_constructed());
+    };
+    run_test(cpp, hdr, rs, &[&ident.to_string(), "is_constructed"], &[]);
+}
+
+#[test]
+fn test_destructor_moveit() {
+    destruction_test(
+        parse_quote! { A },
+        Some(quote! {
+            _stack_obj.as_mut().set(42);
+            assert_eq!(_stack_obj.get(), 42);
+        }),
+    );
+}
+
+#[test]
+fn test_destructor_derived_moveit() {
+    destruction_test(parse_quote! { B }, None);
+}
+
+#[test]
+fn test_copy_and_move_constructor_moveit() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        A() {}
+        A(const A& other) : a(other.a+1) {}
+        A(A&& other) : a(other.a+2) { other.a = 666; }
+        void set(uint32_t val) { a = val; }
+        uint32_t get() const { return a; }
+        uint32_t a;
+        std::string so_we_are_non_trivial;
+    };
+    "};
+    let rs = quote! {
+        moveit! {
+            let mut stack_obj = ffi::A::new();
+        }
+        stack_obj.as_mut().set(42);
+        moveit! {
+            let stack_obj2 = autocxx::moveit::new::copy(stack_obj.as_ref());
+        }
+        assert_eq!(stack_obj2.get(), 43);
+        assert_eq!(stack_obj.get(), 42);
+        moveit! {
+            let stack_obj3 = autocxx::moveit::new::mov(stack_obj);
+        }
+        assert_eq!(stack_obj3.get(), 44);
+        // Following line prevented by moveit, even though it would
+        // be possible in C++.
+        // assert_eq!(stack_obj.get(), 666);
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+// This test fails on Windows gnu but not on Windows msvc
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[test]
+fn test_uniqueptr_moveit() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        A() {}
+        void set(uint32_t val) { a = val; }
+        uint32_t get() const { return a; }
+        uint32_t a;
+        std::string so_we_are_non_trivial;
+    };
+    "};
+    let rs = quote! {
+        use autocxx::moveit::EmplaceUnpinned;
+        let mut up_obj = cxx::UniquePtr::emplace(ffi::A::new());
+        up_obj.as_mut().unwrap().set(42);
+        assert_eq!(up_obj.get(), 42);
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+// This test fails on Windows gnu but not on Windows msvc
+#[cfg_attr(skip_windows_gnu_failing_tests, ignore)]
+#[test]
+fn test_various_emplacement() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        A() {}
+        void set(uint32_t val) { a = val; }
+        uint32_t get() const { return a; }
+        uint32_t a;
+        std::string so_we_are_non_trivial;
+    };
+    "};
+    let rs = quote! {
+        use autocxx::moveit::EmplaceUnpinned;
+        use autocxx::moveit::Emplace;
+        let mut up_obj = cxx::UniquePtr::emplace(ffi::A::new());
+        up_obj.pin_mut().set(666);
+        // Can't current move out of a UniquePtr
+        let mut box_obj = Box::emplace(ffi::A::new());
+        box_obj.as_mut().set(667);
+        let box_obj2 = Box::emplace(autocxx::moveit::new::mov(box_obj));
+        moveit! { let back_on_stack = autocxx::moveit::new::mov(box_obj2); }
+        assert_eq!(back_on_stack.get(), 667);
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_emplace_uses_overridden_new_and_delete() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        A() {}
+        void* operator new(size_t count);
+        void operator delete(void* ptr) noexcept;
+        void* operator new(size_t count, void* ptr);
+        std::string so_we_are_non_trivial;
+    };
+    void reset_flags();
+    bool was_new_called();
+    bool was_delete_called();
+    "};
+    let cxx = indoc! {"
+        bool new_called;
+        bool delete_called;
+        void reset_flags() {
+            new_called = false;
+            delete_called = false;
+        }
+        void* A::operator new(size_t count) {
+            new_called = true;
+            return ::operator new(count);
+        }
+        void* A::operator new(size_t count, void* ptr) {
+            return ::operator new(count, ptr);
+        }
+        void A::operator delete(void* ptr) noexcept {
+            delete_called = true;
+            ::operator delete(ptr);
+        }
+        bool was_new_called() {
+            return new_called;
+        }
+        bool was_delete_called() {
+            return delete_called;
+        }
+    "};
+    let rs = quote! {
+        ffi::reset_flags();
+        {
+            let _ = ffi::A::new().within_unique_ptr();
+            assert!(ffi::was_new_called());
+        }
+        assert!(ffi::was_delete_called());
+        ffi::reset_flags();
+        {
+            use autocxx::moveit::EmplaceUnpinned;
+            let _ = cxx::UniquePtr::emplace(ffi::A::new());
+        }
+        assert!(ffi::was_delete_called());
+    };
+    run_test(
+        cxx,
+        hdr,
+        rs,
+        &["A", "reset_flags", "was_new_called", "was_delete_called"],
+        &[],
+    );
+}
+
+#[test]
+fn test_pass_by_reference_to_value_param() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        A() : count(0) {}
+        std::string so_we_are_non_trivial;
+        uint32_t count;
+    };
+    void take_a(A a) {
+        a.count++;
+    }
+    uint32_t report_on_a(const A& a) {
+        return a.count;
+    }
+    "};
+    let rs = quote! {
+        let a = ffi::A::new().within_unique_ptr();
+        ffi::take_a(a.as_ref().unwrap());
+        ffi::take_a(&a); // syntactic sugar
+        assert_eq!(ffi::report_on_a(&a), 0); // should have acted upon copies
+    };
+    run_test("", hdr, rs, &["A", "take_a", "report_on_a"], &[]);
+}
+
+#[test]
+fn test_explicit_everything() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    struct A {
+        A() {} // default constructor
+        A(A&&) {} // move constructor
+        A(const A&) {} // copy constructor
+        A& operator=(const A&) { return *this; } // copy assignment operator
+        A& operator=(A&&) { return *this; } // move assignment operator
+        ~A() {} // destructor
+        void set(uint32_t val) { a = val; }
+        uint32_t get() const { return a; }
+        uint32_t a;
+        std::string so_we_are_non_trivial;
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_generate_ns() {
+    let hdr = indoc! {"
+    namespace A {
+        inline void foo() {}
+        inline void bar() {}
+    }
+    namespace B {
+        inline void baz() {}
+    }
+    "};
+    let rs = quote! {
+        ffi::A::foo();
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! {
+            generate_ns!("A")
+            safety!(unsafe_ffi)
+        },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_no_constructor_make_unique_ns() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    namespace B {
+    struct A {
+        uint32_t a;
+    };
+    }
+    "};
+    let rs = quote! {
+        ffi::B::A::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &["B::A"], &[]);
+}
+
+#[test]
+fn test_no_constructor_pod_make_unique() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    struct A {
+        uint32_t a;
+    };
+    "};
+    let rs = quote! {
+        ffi::A::new().within_unique_ptr();
+    };
+    run_test("", hdr, rs, &[], &["A"]);
+}
+
+#[test]
+fn test_no_constructor_pv() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    class A {
+    public:
+        virtual ~A() {}
+        virtual void foo() = 0;
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_suppress_system_includes() {
+    let hdr = indoc! {"
+    #include <stdint.h>
+    #include <string>
+    inline void a() {};
+    "};
+    let rs = quote! {};
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! { generate("a")},
+        Some(Box::new(SetSuppressSystemHeaders)),
+        Some(Box::new(NoSystemHeadersChecker)),
+        None,
+    );
+}
+
+#[test]
+fn test_no_rvo_move() {
+    let hdr = indoc! {"
+    #include <memory>
+    class A {
+    public:
+        static std::unique_ptr<A> create() { return std::make_unique<A>(); }
+    };
+    "};
+    let rs = quote! {
+        ffi::A::create();
+    };
+    run_test_ex(
+        "",
+        hdr,
+        rs,
+        quote! { generate!("A") },
+        None,
+        Some(Box::new(CppMatcher::new(
+            &["return A::create();"],
+            &["return std::move(A::create());"],
+        ))),
+        None,
+    );
+}
+
+#[test]
+fn test_abstract_up() {
+    let hdr = indoc! {"
+    #include <memory>
+    class A {
+    public:
+        virtual void foo() const = 0;
+        virtual ~A() {}
+    };
+    class B : public A {
+    public:
+        void foo() const {}
+    };
+    inline std::unique_ptr<A> get_a() { return std::make_unique<B>(); }
+    "};
+    let rs = quote! {
+        let a = ffi::get_a();
+        a.foo();
+    };
+    run_test("", hdr, rs, &["A", "get_a"], &[]);
+}
+
+#[test]
+fn test_abstract_private() {
+    let hdr = indoc! {"
+    #include <memory>
+    class A {
+        virtual void foo() const = 0;
+    public:
+        virtual ~A() {}
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_abstract_issue_979() {
+    let hdr = indoc! {"
+    class Test {
+        virtual ~Test() {}
+        virtual void TestBody() = 0;
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["Test"], &[]);
+}
+
+#[test]
+fn test_class_having_protected_method() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    class A {
+    protected:
+        inline uint32_t protected_method() { return 0; }
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &[], &["A"]);
+}
+
+#[test]
+fn test_protected_inner_class() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    inline uint32_t DoMath(uint32_t a)  {
+        return a * 3;
+    }
+
+    class A {
+    protected:
+        inline uint32_t protected_method() { return 0; }
+
+        struct B {
+            int x;
+        };
+
+        inline B protected_method_2() {
+            return { 0 };
+        }
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_private_inner_class() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    inline uint32_t DoMath(uint32_t a)  {
+        return a * 3;
+    }
+
+    class A {
+    protected:
+        inline uint32_t protected_method() { return 0; }
+
+    private:
+        struct B {
+            int x;
+        };
+
+        inline B private_method_2() {
+            return { 0 };
+        }
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_class_having_private_method() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    class A {
+    private:
+        inline uint32_t private_method() { return 0; }
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &[], &["A"]);
+}
+
+#[test]
+#[ignore] // https://github.com/google/autocxx/issues/787
+fn test_chrono_problem() {
+    let hdr = indoc! {"
+    #include <chrono>
+    struct Clock {
+      typedef std::chrono::nanoseconds duration;
+    };
+    struct Class {
+      int a() { return 42; }
+      std::chrono::time_point<Clock> b();
+    };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &[], &["Class"]);
+}
+
+fn size_and_alignment_test(pod: bool) {
+    static TYPES: [(&str, &str); 6] = [
+        ("A", "struct A { uint8_t a; };"),
+        ("B", "struct B { uint32_t a; };"),
+        ("C", "struct C { uint64_t a; };"),
+        ("D", "enum D { Z, X };"),
+        ("E", "struct E { uint8_t a; uint32_t b; };"),
+        ("F", "struct F { uint32_t a; uint8_t b; };"),
+    ];
+    let type_definitions = TYPES.iter().map(|(_, def)| *def).join("\n");
+    let function_definitions = TYPES.iter().map(|(name, _)| format!("inline size_t get_sizeof_{}() {{ return sizeof({}); }}\ninline size_t get_alignof_{}() {{ return alignof({}); }}\n",
+    name, name, name, name)).join("\n");
+    let hdr = format!(
+        indoc! {"
+        #include <cstdint>
+        #include <cstddef>
+        {}
+        {}
+    "},
+        type_definitions, function_definitions
+    );
+    #[allow(clippy::unnecessary_to_owned)] // wrongly triggers on into_iter() below
+    let allowlist_fns: Vec<String> = TYPES
+        .iter()
+        .flat_map(|(name, _)| {
+            [
+                format!("get_sizeof_{}", name),
+                format!("get_alignof_{}", name),
+            ]
+            .to_vec()
+            .into_iter()
+        })
+        .collect_vec();
+    let allowlist_types: Vec<String> = TYPES.iter().map(|(name, _)| name.to_string()).collect_vec();
+    let allowlist_both = allowlist_types
+        .iter()
+        .cloned()
+        .chain(allowlist_fns.iter().cloned())
+        .collect_vec();
+    let allowlist_types: Vec<&str> = allowlist_types.iter().map(AsRef::as_ref).collect_vec();
+    let allowlist_fns: Vec<&str> = allowlist_fns.iter().map(AsRef::as_ref).collect_vec();
+    let allowlist_both: Vec<&str> = allowlist_both.iter().map(AsRef::as_ref).collect_vec();
+    let rs = TYPES.iter().fold(quote! {}, |mut accumulator, (name, _)| {
+        let get_align_symbol =
+            proc_macro2::Ident::new(&format!("get_alignof_{}", name), Span::call_site());
+        let get_size_symbol =
+            proc_macro2::Ident::new(&format!("get_sizeof_{}", name), Span::call_site());
+        let type_symbol = proc_macro2::Ident::new(name, Span::call_site());
+        accumulator.extend(quote! {
+            let c_size = ffi::#get_size_symbol();
+            let c_align = ffi::#get_align_symbol();
+            assert_eq!(std::mem::size_of::<ffi::#type_symbol>(), c_size);
+            assert_eq!(std::mem::align_of::<ffi::#type_symbol>(), c_align);
+        });
+        accumulator
+    });
+    if pod {
+        run_test("", &hdr, rs, &allowlist_fns, &allowlist_types);
+    } else {
+        run_test("", &hdr, rs, &allowlist_both, &[]);
+    }
+}
+
+#[test]
+fn test_sizes_and_alignment_nonpod() {
+    size_and_alignment_test(false)
+}
+
+#[test]
+fn test_sizes_and_alignment_pod() {
+    size_and_alignment_test(true)
+}
+
+#[test]
+fn test_nested_class_methods() {
+    let hdr = indoc! {"
+    #include <cstdint>
+    class A {
+    public:
+        virtual ~A() {}
+        struct B {
+            virtual void b() const {}
+        };
+        virtual void a() const {}
+        struct C {
+            virtual void b() const {}
+        };
+        virtual void c() const {}
+        struct D {
+            virtual void b() const {}
+        };
+    };
+    "};
+    let rs = quote! {
+        let a = ffi::A::new().within_unique_ptr();
+        a.a();
+        a.c();
+    };
+    run_test("", hdr, rs, &["A"], &[]);
+}
+
+#[test]
+fn test_call_superclass() {
+    let hdr = indoc! {"
+    #include <memory>
+    class A {
+    public:
+        virtual void foo() const {};
+        virtual ~A() {}
+    };
+    class B : public A {
+    public:
+        void bar() const {}
+    };
+    inline std::unique_ptr<B> get_b() { return std::make_unique<B>(); }
+    "};
+    let rs = quote! {
+        let b = ffi::get_b();
+        b.as_ref().unwrap().as_ref().foo();
+    };
+    run_test("", hdr, rs, &["A", "B", "get_b"], &[]);
+}
+
+#[test]
+fn test_pass_superclass() {
+    let hdr = indoc! {"
+    #include <memory>
+    class A {
+    public:
+        virtual void foo() const {};
+        virtual ~A() {}
+    };
+    class B : public A {
+    public:
+        void bar() const {}
+    };
+    inline std::unique_ptr<B> get_b() { return std::make_unique<B>(); }
+    inline void take_a(const A&) {}
+    "};
+    let rs = quote! {
+        let b = ffi::get_b();
+        ffi::take_a(b.as_ref().unwrap().as_ref());
+    };
+    run_test("", hdr, rs, &["A", "B", "get_b", "take_a"], &[]);
+}
+
+#[test]
+fn test_issue486_multi_types() {
+    let hdr = indoc! {"
+        namespace a {
+            namespace spanner {
+                struct Key {};
+            }
+        } // namespace a
+        namespace b {
+            namespace spanner {
+                typedef int Key;
+            }
+        } // namespace b
+        namespace c {
+            namespace spanner {
+                enum Key { A, B };
+            }
+        } // namespace c
+        namespace spanner {
+            class Key {
+                public:
+                    bool a(a::spanner::Key &);
+                    bool b(b::spanner::Key &);
+                    bool c(c::spanner::Key &);
+            };
+        } // namespace spanner
+    "};
+    let rs = quote! {};
+    run_test(
+        "",
+        hdr,
+        rs,
+        &["spanner::Key", "a::spanner::Key", "b::spanner::Key"],
+        &[],
+    );
+}
+
+#[test]
+/// Tests types with various forms of copy, move, and default constructors. Calls the things which
+/// should be generated, and will produce C++ compile failures if other wrappers are generated.
+///
+/// Specifically, we can have the cross product of any of these:
+///   * Explicitly deleted
+///   * Implicitly defaulted
+///   * User declared
+///   * Explicitly defaulted
+///     Not handled yet: https://github.com/google/autocxx/issues/815.
+///     Once this is handled, add equivalents of all the implicitly defaulted cases, at all
+///     visibility levels.
+/// applied to each of these:
+///   * Default constructor
+///   * Copy constructor
+///   * Move constructor
+/// in any of these:
+///   * The class itself
+///   * A base class
+///   * A field of the class
+///   * A field of a base class
+/// with any of these access modifiers:
+///   * private (impossible for implicitly defaulted)
+///   * protected (impossible for implicitly defaulted)
+///   * public
+///
+/// Various combinations of these lead to the default versions being deleted. The move and copy
+/// ones also interact with each other in various ways.
+///
+/// TODO: Remove all the `int x` members after https://github.com/google/autocxx/issues/832 is
+/// fixed.
+fn test_implicit_constructor_rules() {
+    let cxx = "";
+    let hdr = indoc! {"
+        struct AllImplicitlyDefaulted {
+            void a() const {}
+        };
+
+        struct PublicDeleted {
+            PublicDeleted() = delete;
+            PublicDeleted(const PublicDeleted&) = delete;
+            PublicDeleted(PublicDeleted&&) = delete;
+
+            void a() const {}
+
+            int x;
+        };
+        struct PublicDeletedDefault {
+            PublicDeletedDefault() = delete;
+
+            void a() const {}
+
+            int x;
+        };
+        struct PublicDeletedCopy {
+            PublicDeletedCopy() = default;
+            PublicDeletedCopy(const PublicDeletedCopy&) = delete;
+
+            void a() const {}
+
+            int x;
+        };
+        struct PublicDeletedCopyNoDefault {
+            PublicDeletedCopyNoDefault(const PublicDeletedCopyNoDefault&) = delete;
+
+            void a() const {}
+
+            int x;
+        };
+        struct PublicMoveDeletedCopy {
+            PublicMoveDeletedCopy() = default;
+            PublicMoveDeletedCopy(const PublicMoveDeletedCopy&) = delete;
+            PublicMoveDeletedCopy(PublicMoveDeletedCopy&&) = default;
+
+            void a() const {}
+
+            int x;
+        };
+        struct PublicDeletedMove {
+            PublicDeletedMove() = default;
+            PublicDeletedMove(PublicDeletedMove&&) = delete;
+
+            void a() const {}
+
+            int x;
+        };
+        struct PublicDeletedDestructor {
+            PublicDeletedDestructor() = default;
+            ~PublicDeletedDestructor() = delete;
+
+            void a() const {}
+
+            int x;
+        };
+        struct PublicDestructor {
+            PublicDestructor() = default;
+            ~PublicDestructor() = default;
+
+            void a() const {}
+
+            int x;
+        };
+
+        struct ProtectedDeleted {
+            void a() const {}
+
+            int x;
+
+          protected:
+            ProtectedDeleted() = delete;
+            ProtectedDeleted(const ProtectedDeleted&) = delete;
+            ProtectedDeleted(ProtectedDeleted&&) = delete;
+        };
+        struct ProtectedDeletedDefault {
+            void a() const {}
+
+            int x;
+
+          protected:
+            ProtectedDeletedDefault() = delete;
+        };
+        struct ProtectedDeletedCopy {
+            ProtectedDeletedCopy() = default;
+
+            void a() const {}
+
+            int x;
+
+          protected:
+            ProtectedDeletedCopy(const ProtectedDeletedCopy&) = delete;
+        };
+        struct ProtectedDeletedCopyNoDefault {
+            void a() const {}
+
+            int x;
+
+          protected:
+            ProtectedDeletedCopyNoDefault(const ProtectedDeletedCopyNoDefault&) = delete;
+        };
+        struct ProtectedMoveDeletedCopy {
+            ProtectedMoveDeletedCopy() = default;
+
+            void a() const {}
+
+            int x;
+
+          protected:
+            ProtectedMoveDeletedCopy(const ProtectedMoveDeletedCopy&) = delete;
+            ProtectedMoveDeletedCopy(ProtectedMoveDeletedCopy&&) = default;
+        };
+        struct ProtectedDeletedMove {
+            ProtectedDeletedMove() = default;
+
+            void a() const {}
+
+            int x;
+
+          protected:
+            ProtectedDeletedMove(ProtectedDeletedMove&&) = delete;
+        };
+        struct ProtectedDeletedDestructor {
+            ProtectedDeletedDestructor() = default;
+
+            void a() const {}
+
+            int x;
+
+          protected:
+            ~ProtectedDeletedDestructor() = delete;
+        };
+        struct ProtectedDestructor {
+            ProtectedDestructor() = default;
+
+            void a() const {}
+
+            int x;
+
+          protected:
+            ~ProtectedDestructor() = default;
+        };
+
+        struct PrivateDeleted {
+            void a() const {}
+
+            int x;
+
+          private:
+            PrivateDeleted() = delete;
+            PrivateDeleted(const PrivateDeleted&) = delete;
+            PrivateDeleted(PrivateDeleted&&) = delete;
+        };
+        struct PrivateDeletedDefault {
+            void a() const {}
+
+            int x;
+
+          private:
+            PrivateDeletedDefault() = delete;
+        };
+        struct PrivateDeletedCopy {
+            PrivateDeletedCopy() = default;
+
+            void a() const {}
+
+            int x;
+
+          private:
+            PrivateDeletedCopy(const PrivateDeletedCopy&) = delete;
+        };
+        struct PrivateDeletedCopyNoDefault {
+            void a() const {}
+
+            int x;
+
+          private:
+            PrivateDeletedCopyNoDefault(const PrivateDeletedCopyNoDefault&) = delete;
+        };
+        struct PrivateMoveDeletedCopy {
+            PrivateMoveDeletedCopy() = default;
+
+            void a() const {}
+
+            int x;
+
+          private:
+            PrivateMoveDeletedCopy(const PrivateMoveDeletedCopy&) = delete;
+            PrivateMoveDeletedCopy(PrivateMoveDeletedCopy&&) = default;
+        };
+        struct PrivateDeletedMove {
+            PrivateDeletedMove() = default;
+
+            void a() const {}
+
+            int x;
+
+          private:
+            PrivateDeletedMove(PrivateDeletedMove&&) = delete;
+        };
+        struct PrivateDeletedDestructor {
+            PrivateDeletedDestructor() = default;
+
+            void a() const {}
+
+            int x;
+
+          private:
+            ~PrivateDeletedDestructor() = delete;
+        };
+        struct PrivateDestructor {
+            PrivateDestructor() = default;
+
+            void a() const {}
+
+            int x;
+
+          private:
+            ~PrivateDestructor() = default;
+        };
+
+        struct NonConstCopy {
+            NonConstCopy() = default;
+
+            NonConstCopy(NonConstCopy&) {}
+            NonConstCopy(NonConstCopy&&) = default;
+
+            void a() const {}
+        };
+        struct TwoCopy {
+            TwoCopy() = default;
+
+            TwoCopy(TwoCopy&) {}
+            TwoCopy(const TwoCopy&) {}
+            TwoCopy(TwoCopy&&) = default;
+
+            void a() const {}
+        };
+
+        struct MemberPointerDeleted {
+            PublicDeleted *x;
+
+            void a() const {}
+        };
+
+        struct MemberConstPointerDeleted {
+            PublicDeleted *const x;
+
+            void a() const {}
+        };
+
+        struct MemberConst {
+            const int x;
+
+            void a() const {}
+        };
+
+        struct MemberReferenceDeleted {
+            PublicDeleted &x;
+
+            void a() const {}
+        };
+
+        struct MemberConstReferenceDeleted {
+            const PublicDeleted &x;
+
+            void a() const {}
+        };
+
+        struct MemberReference {
+            int &x;
+
+            void a() const {}
+        };
+
+        struct MemberConstReference {
+            const int &x;
+
+            void a() const {}
+        };
+
+        struct MemberRvalueReferenceDeleted {
+            PublicDeleted &&x;
+
+            void a() const {}
+        };
+
+        struct MemberRvalueReference {
+            int &&x;
+
+            void a() const {}
+        };
+
+        struct BasePublicDeleted : public PublicDeleted {};
+        struct BasePublicDeletedDefault : public PublicDeletedDefault {};
+        struct BasePublicDeletedCopy : public PublicDeletedCopy {};
+        struct BasePublicDeletedCopyNoDefault : public PublicDeletedCopyNoDefault { };
+        struct BasePublicMoveDeletedCopy : public PublicMoveDeletedCopy {};
+        struct BasePublicDeletedMove : public PublicDeletedMove {};
+        struct BasePublicDeletedDestructor : public PublicDeletedDestructor {};
+        struct BasePublicDestructor : public PublicDestructor {};
+
+        struct MemberPublicDeleted {
+            void a() const {}
+
+            PublicDeleted member;
+        };
+        struct MemberPublicDeletedDefault {
+            void a() const {}
+
+            PublicDeletedDefault member;
+        };
+        struct MemberPublicDeletedCopy {
+            void a() const {}
+
+            PublicDeletedCopy member;
+        };
+        struct MemberPublicDeletedCopyNoDefault {
+            void a() const {}
+
+            PublicDeletedCopyNoDefault member;
+        };
+        struct MemberPublicMoveDeletedCopy {
+            void a() const {}
+
+            PublicMoveDeletedCopy member;
+        };
+        struct MemberPublicDeletedMove {
+            void a() const {}
+
+            PublicDeletedMove member;
+        };
+        struct MemberPublicDeletedDestructor {
+            void a() const {}
+
+            PublicDeletedDestructor member;
+        };
+        struct MemberPublicDestructor {
+            void a() const {}
+
+            PublicDestructor member;
+        };
+
+        struct BaseMemberPublicDeleted : public MemberPublicDeleted {};
+        struct BaseMemberPublicDeletedDefault : public MemberPublicDeletedDefault {};
+        struct BaseMemberPublicDeletedCopy : public MemberPublicDeletedCopy {};
+        struct BaseMemberPublicDeletedCopyNoDefault : public MemberPublicDeletedCopyNoDefault {};
+        struct BaseMemberPublicMoveDeletedCopy : public MemberPublicMoveDeletedCopy {};
+        struct BaseMemberPublicDeletedMove : public MemberPublicDeletedMove {};
+        struct BaseMemberPublicDeletedDestructor : public MemberPublicDeletedDestructor {};
+        struct BaseMemberPublicDestructor : public MemberPublicDestructor {};
+
+        struct BaseProtectedDeleted : public ProtectedDeleted {};
+        struct BaseProtectedDeletedDefault : public ProtectedDeletedDefault {};
+        struct BaseProtectedDeletedCopy : public ProtectedDeletedCopy {};
+        struct BaseProtectedDeletedCopyNoDefault : public ProtectedDeletedCopyNoDefault {};
+        struct BaseProtectedMoveDeletedCopy : public ProtectedMoveDeletedCopy {};
+        struct BaseProtectedDeletedMove : public ProtectedDeletedMove {};
+        struct BaseProtectedDeletedDestructor : public ProtectedDeletedDestructor {};
+        struct BaseProtectedDestructor : public ProtectedDestructor {};
+
+        struct MemberProtectedDeleted {
+            void a() const {}
+
+            ProtectedDeleted member;
+        };
+        struct MemberProtectedDeletedDefault {
+            void a() const {}
+
+            ProtectedDeletedDefault member;
+        };
+        struct MemberProtectedDeletedCopy {
+            void a() const {}
+
+            ProtectedDeletedCopy member;
+        };
+        struct MemberProtectedDeletedCopyNoDefault {
+            void a() const {}
+
+            ProtectedDeletedCopyNoDefault member;
+        };
+        struct MemberProtectedMoveDeletedCopy {
+            void a() const {}
+
+            ProtectedMoveDeletedCopy member;
+        };
+        struct MemberProtectedDeletedMove {
+            void a() const {}
+
+            ProtectedDeletedMove member;
+        };
+        struct MemberProtectedDeletedDestructor {
+            void a() const {}
+
+            ProtectedDeletedDestructor member;
+        };
+        struct MemberProtectedDestructor {
+            void a() const {}
+
+            ProtectedDestructor member;
+        };
+
+        struct BaseMemberProtectedDeleted : public MemberProtectedDeleted {};
+        struct BaseMemberProtectedDeletedDefault : public MemberProtectedDeletedDefault {};
+        struct BaseMemberProtectedDeletedCopy : public MemberProtectedDeletedCopy {};
+        struct BaseMemberProtectedDeletedCopyNoDefault : public MemberProtectedDeletedCopyNoDefault {};
+        struct BaseMemberProtectedMoveDeletedCopy : public MemberProtectedMoveDeletedCopy {};
+        struct BaseMemberProtectedDeletedMove : public MemberProtectedDeletedMove {};
+        struct BaseMemberProtectedDeletedDestructor : public MemberProtectedDeletedDestructor {};
+        struct BaseMemberProtectedDestructor : public MemberProtectedDestructor {};
+
+        struct BasePrivateDeleted : public PrivateDeleted {};
+        struct BasePrivateDeletedDefault : public PrivateDeletedDefault {};
+        struct BasePrivateDeletedCopy : public PrivateDeletedCopy {};
+        struct BasePrivateDeletedCopyNoDefault : public PrivateDeletedCopyNoDefault {};
+        struct BasePrivateMoveDeletedCopy : public PrivateMoveDeletedCopy {};
+        struct BasePrivateDeletedMove : public PrivateDeletedMove {};
+        struct BasePrivateDeletedDestructor : public PrivateDeletedDestructor {};
+        struct BasePrivateDestructor : public PrivateDestructor {};
+
+        struct MemberPrivateDeleted {
+            void a() const {}
+
+            PrivateDeleted member;
+        };
+        struct MemberPrivateDeletedDefault {
+            void a() const {}
+
+            PrivateDeletedDefault member;
+        };
+        struct MemberPrivateDeletedCopy {
+            void a() const {}
+
+            PrivateDeletedCopy member;
+        };
+        struct MemberPrivateDeletedCopyNoDefault {
+            void a() const {}
+
+            PrivateDeletedCopyNoDefault member;
+        };
+        struct MemberPrivateMoveDeletedCopy {
+            void a() const {}
+
+            PrivateMoveDeletedCopy member;
+        };
+        struct MemberPrivateDeletedMove {
+            void a() const {}
+
+            PrivateDeletedMove member;
+        };
+        struct MemberPrivateDeletedDestructor {
+            void a() const {}
+
+            PrivateDeletedDestructor member;
+        };
+        struct MemberPrivateDestructor {
+            void a() const {}
+
+            PrivateDestructor member;
+        };
+
+        struct BaseMemberPrivateDeleted : public MemberPrivateDeleted {};
+        struct BaseMemberPrivateDeletedDefault : public MemberPrivateDeletedDefault {};
+        struct BaseMemberPrivateDeletedCopy : public MemberPrivateDeletedCopy {};
+        struct BaseMemberPrivateDeletedCopyNoDefault : public MemberPrivateDeletedCopyNoDefault {};
+        struct BaseMemberPrivateMoveDeletedCopy : public MemberPrivateMoveDeletedCopy {};
+        struct BaseMemberPrivateDeletedMove : public MemberPrivateDeletedMove {};
+        struct BaseMemberPrivateDeletedDestructor : public MemberPrivateDeletedDestructor {};
+        struct BaseMemberPrivateDestructor : public MemberPrivateDestructor {};
+    "};
+    let rs = quote! {
+        // Some macros to test various operations on our types. Note that some of them define
+        // functions which take arguments that the APIs defined in this test have no way to
+        // produce, because we have C++ types which can't be constructed (for example). In a real
+        // program, there might be other C++ APIs which can instantiate these types.
+
+        // TODO: https://github.com/google/autocxx/issues/829: Should this be merged with
+        // `test_make_unique`? Currently types where the Rust wrappers permit this but not that
+        // aren't running C++ destructors.
+        macro_rules! test_constructible {
+            [$t:ty] => {
+                moveit! {
+                    let _moveit_t = <$t>::new();
+                }
+            }
+        }
+        macro_rules! test_make_unique {
+            [$t:ty] => {
+                let _unique_t = <$t>::new().within_unique_ptr();
+            }
+        }
+        macro_rules! test_copyable {
+            [$t:ty] => {
+                {
+                    fn test_copyable(moveit_t: impl autocxx::moveit::new::New<Output = $t>) {
+                        moveit! {
+                            let moveit_t = moveit_t;
+                            let _copied_t = autocxx::moveit::new::copy(moveit_t);
+                        }
+                    }
+                }
+            }
+        }
+        macro_rules! test_movable {
+            [$t:ty] => {
+                {
+                    fn test_movable(moveit_t: impl autocxx::moveit::new::New<Output = $t>) {
+                        moveit! {
+                            let moveit_t = moveit_t;
+                            let _moved_t = autocxx::moveit::new::mov(moveit_t);
+                        }
+                    }
+                }
+            }
+        }
+        macro_rules! test_call_a {
+            [$t:ty] => {
+                {
+                    fn test_call_a(t: &$t) {
+                        t.a();
+                    }
+                }
+            }
+        }
+        macro_rules! test_call_a_as {
+            [$t:ty, $parent:ty] => {
+                {
+                    fn test_call_a(t: &$t) {
+                        let t: &$parent = t.as_ref();
+                        t.a();
+                    }
+                }
+            }
+        }
+
+        test_constructible![ffi::AllImplicitlyDefaulted];
+        test_make_unique![ffi::AllImplicitlyDefaulted];
+        test_copyable![ffi::AllImplicitlyDefaulted];
+        test_movable![ffi::AllImplicitlyDefaulted];
+        test_call_a![ffi::AllImplicitlyDefaulted];
+
+        test_call_a![ffi::PublicDeleted];
+
+        test_copyable![ffi::PublicDeletedDefault];
+        test_movable![ffi::PublicDeletedDefault];
+        test_call_a![ffi::PublicDeletedDefault];
+
+        test_constructible![ffi::PublicDeletedCopy];
+        test_make_unique![ffi::PublicDeletedCopy];
+        test_call_a![ffi::PublicDeletedCopy];
+
+        test_call_a![ffi::PublicDeletedCopyNoDefault];
+
+        test_constructible![ffi::PublicMoveDeletedCopy];
+        test_make_unique![ffi::PublicMoveDeletedCopy];
+        test_movable![ffi::PublicMoveDeletedCopy];
+        test_call_a![ffi::PublicMoveDeletedCopy];
+
+        test_constructible![ffi::PublicDeletedMove];
+        test_make_unique![ffi::PublicDeletedMove];
+        test_call_a![ffi::PublicDeletedMove];
+
+        test_constructible![ffi::PublicDeletedDestructor];
+        test_copyable![ffi::PublicDeletedDestructor];
+        test_call_a![ffi::PublicDeletedDestructor];
+
+        test_constructible![ffi::PublicDestructor];
+        test_make_unique![ffi::PublicDestructor];
+        test_copyable![ffi::PublicDestructor];
+        test_call_a![ffi::PublicDestructor];
+
+        test_call_a![ffi::ProtectedDeleted];
+
+        test_copyable![ffi::ProtectedDeletedDefault];
+        test_movable![ffi::ProtectedDeletedDefault];
+        test_call_a![ffi::ProtectedDeletedDefault];
+
+        test_constructible![ffi::ProtectedDeletedCopy];
+        test_make_unique![ffi::ProtectedDeletedCopy];
+        test_call_a![ffi::ProtectedDeletedCopy];
+
+        test_call_a![ffi::ProtectedDeletedCopyNoDefault];
+
+        test_constructible![ffi::ProtectedMoveDeletedCopy];
+        test_make_unique![ffi::ProtectedMoveDeletedCopy];
+        test_call_a![ffi::ProtectedMoveDeletedCopy];
+
+        test_constructible![ffi::ProtectedDeletedMove];
+        test_make_unique![ffi::ProtectedDeletedMove];
+        test_call_a![ffi::ProtectedDeletedMove];
+
+        test_constructible![ffi::ProtectedDeletedDestructor];
+        test_copyable![ffi::ProtectedDeletedDestructor];
+        test_call_a![ffi::ProtectedDeletedDestructor];
+
+        test_constructible![ffi::ProtectedDestructor];
+        test_copyable![ffi::ProtectedDestructor];
+        test_call_a![ffi::ProtectedDestructor];
+
+        test_call_a![ffi::PrivateDeleted];
+
+        test_copyable![ffi::PrivateDeletedDefault];
+        test_movable![ffi::PrivateDeletedDefault];
+        test_call_a![ffi::PrivateDeletedDefault];
+
+        test_constructible![ffi::PrivateDeletedCopy];
+        test_make_unique![ffi::PrivateDeletedCopy];
+        test_call_a![ffi::PrivateDeletedCopy];
+
+        test_call_a![ffi::PrivateDeletedCopyNoDefault];
+
+        test_constructible![ffi::PrivateMoveDeletedCopy];
+        test_make_unique![ffi::PrivateMoveDeletedCopy];
+        test_call_a![ffi::PrivateMoveDeletedCopy];
+
+        test_constructible![ffi::PrivateDeletedMove];
+        test_make_unique![ffi::PrivateDeletedMove];
+        test_call_a![ffi::PrivateDeletedMove];
+
+        test_constructible![ffi::PrivateDeletedDestructor];
+        test_copyable![ffi::PrivateDeletedDestructor];
+        test_call_a![ffi::PrivateDeletedDestructor];
+
+        test_constructible![ffi::PrivateDestructor];
+        test_copyable![ffi::PrivateDestructor];
+        test_call_a![ffi::PrivateDestructor];
+
+        test_constructible![ffi::NonConstCopy];
+        test_make_unique![ffi::NonConstCopy];
+        test_movable![ffi::NonConstCopy];
+        test_call_a![ffi::NonConstCopy];
+
+        test_constructible![ffi::TwoCopy];
+        test_make_unique![ffi::TwoCopy];
+        test_copyable![ffi::TwoCopy];
+        test_movable![ffi::TwoCopy];
+        test_call_a![ffi::TwoCopy];
+
+        // TODO: https://github.com/google/autocxx/issues/865
+        // Treat pointers and references differently so this has a default constructor.
+        //test_constructible![ffi::MemberPointerDeleted];
+        //test_make_unique![ffi::MemberPointerDeleted];
+        test_copyable![ffi::MemberPointerDeleted];
+        test_movable![ffi::MemberPointerDeleted];
+        test_call_a![ffi::MemberPointerDeleted];
+
+        test_copyable![ffi::MemberConstPointerDeleted];
+        test_movable![ffi::MemberConstPointerDeleted];
+        test_call_a![ffi::MemberConstPointerDeleted];
+
+        //test_copyable![ffi::MemberConst];
+        //test_movable![ffi::MemberConst];
+        //test_call_a![ffi::MemberConst];
+
+        test_copyable![ffi::MemberReferenceDeleted];
+        test_movable![ffi::MemberReferenceDeleted];
+        test_call_a![ffi::MemberReferenceDeleted];
+
+        test_copyable![ffi::MemberConstReferenceDeleted];
+        test_movable![ffi::MemberConstReferenceDeleted];
+        test_call_a![ffi::MemberConstReferenceDeleted];
+
+        test_copyable![ffi::MemberReference];
+        test_movable![ffi::MemberReference];
+        test_call_a![ffi::MemberReference];
+
+        test_copyable![ffi::MemberConstReference];
+        test_movable![ffi::MemberConstReference];
+        test_call_a![ffi::MemberConstReference];
+
+        test_movable![ffi::MemberRvalueReferenceDeleted];
+        test_call_a![ffi::MemberRvalueReferenceDeleted];
+
+        test_movable![ffi::MemberRvalueReference];
+        test_call_a![ffi::MemberRvalueReference];
+
+        test_call_a_as![ffi::BasePublicDeleted, ffi::PublicDeleted];
+
+        test_copyable![ffi::BasePublicDeletedDefault];
+        test_movable![ffi::BasePublicDeletedDefault];
+        test_call_a_as![ffi::BasePublicDeletedDefault, ffi::PublicDeletedDefault];
+
+        test_constructible![ffi::BasePublicDeletedCopy];
+        test_make_unique![ffi::BasePublicDeletedCopy];
+        test_call_a_as![ffi::BasePublicDeletedCopy, ffi::PublicDeletedCopy];
+
+        test_call_a_as![ffi::BasePublicDeletedCopyNoDefault, ffi::PublicDeletedCopyNoDefault];
+
+        test_constructible![ffi::BasePublicMoveDeletedCopy];
+        test_make_unique![ffi::BasePublicMoveDeletedCopy];
+        test_movable![ffi::BasePublicMoveDeletedCopy];
+        test_call_a_as![ffi::BasePublicMoveDeletedCopy, ffi::PublicMoveDeletedCopy];
+
+        test_constructible![ffi::BasePublicDeletedMove];
+        test_make_unique![ffi::BasePublicDeletedMove];
+        test_call_a_as![ffi::BasePublicDeletedMove, ffi::PublicDeletedMove];
+
+        test_call_a_as![ffi::BasePublicDeletedDestructor, ffi::PublicDeletedDestructor];
+
+        test_constructible![ffi::BasePublicDestructor];
+        test_make_unique![ffi::BasePublicDestructor];
+        test_copyable![ffi::BasePublicDestructor];
+        test_call_a_as![ffi::BasePublicDestructor, ffi::PublicDestructor];
+
+        test_call_a![ffi::MemberPublicDeleted];
+
+        test_copyable![ffi::MemberPublicDeletedDefault];
+        test_movable![ffi::MemberPublicDeletedDefault];
+        test_call_a![ffi::MemberPublicDeletedDefault];
+
+        test_constructible![ffi::MemberPublicDeletedCopy];
+        test_make_unique![ffi::MemberPublicDeletedCopy];
+        test_call_a![ffi::MemberPublicDeletedCopy];
+
+        test_call_a![ffi::MemberPublicDeletedCopyNoDefault];
+
+        test_constructible![ffi::MemberPublicMoveDeletedCopy];
+        test_make_unique![ffi::MemberPublicMoveDeletedCopy];
+        test_movable![ffi::MemberPublicMoveDeletedCopy];
+        test_call_a![ffi::MemberPublicMoveDeletedCopy];
+
+        test_constructible![ffi::MemberPublicDeletedMove];
+        test_make_unique![ffi::MemberPublicDeletedMove];
+        test_call_a![ffi::MemberPublicDeletedMove];
+
+        test_call_a![ffi::MemberPublicDeletedDestructor];
+
+        test_constructible![ffi::MemberPublicDestructor];
+        test_make_unique![ffi::MemberPublicDestructor];
+        test_copyable![ffi::MemberPublicDestructor];
+        test_call_a![ffi::MemberPublicDestructor];
+
+        test_call_a_as![ffi::BaseMemberPublicDeleted, ffi::MemberPublicDeleted];
+
+        test_copyable![ffi::BaseMemberPublicDeletedDefault];
+        test_movable![ffi::BaseMemberPublicDeletedDefault];
+        test_call_a_as![ffi::BaseMemberPublicDeletedDefault, ffi::MemberPublicDeletedDefault];
+
+        test_constructible![ffi::BaseMemberPublicDeletedCopy];
+        test_make_unique![ffi::BaseMemberPublicDeletedCopy];
+        test_call_a_as![ffi::BaseMemberPublicDeletedCopy, ffi::MemberPublicDeletedCopy];
+
+        test_call_a_as![ffi::BaseMemberPublicDeletedCopyNoDefault, ffi::MemberPublicDeletedCopyNoDefault];
+
+        test_constructible![ffi::BaseMemberPublicMoveDeletedCopy];
+        test_make_unique![ffi::BaseMemberPublicMoveDeletedCopy];
+        test_movable![ffi::BaseMemberPublicMoveDeletedCopy];
+        test_call_a_as![ffi::BaseMemberPublicMoveDeletedCopy, ffi::MemberPublicMoveDeletedCopy];
+
+        test_constructible![ffi::BaseMemberPublicDeletedMove];
+        test_make_unique![ffi::BaseMemberPublicDeletedMove];
+        test_call_a_as![ffi::BaseMemberPublicDeletedMove, ffi::MemberPublicDeletedMove];
+
+        test_call_a_as![ffi::BaseMemberPublicDeletedDestructor, ffi::MemberPublicDeletedDestructor];
+
+        test_constructible![ffi::BaseMemberPublicDestructor];
+        test_make_unique![ffi::BaseMemberPublicDestructor];
+        test_copyable![ffi::BaseMemberPublicDestructor];
+        test_call_a_as![ffi::BaseMemberPublicDestructor, ffi::MemberPublicDestructor];
+
+        test_call_a_as![ffi::BaseProtectedDeleted, ffi::ProtectedDeleted];
+
+        test_copyable![ffi::BaseProtectedDeletedDefault];
+        test_movable![ffi::BaseProtectedDeletedDefault];
+        test_call_a_as![ffi::BaseProtectedDeletedDefault, ffi::ProtectedDeletedDefault];
+
+        test_constructible![ffi::BaseProtectedDeletedCopy];
+        test_make_unique![ffi::BaseProtectedDeletedCopy];
+        test_call_a_as![ffi::BaseProtectedDeletedCopy, ffi::ProtectedDeletedCopy];
+
+        test_call_a_as![ffi::BaseProtectedDeletedCopyNoDefault, ffi::ProtectedDeletedCopyNoDefault];
+
+        test_constructible![ffi::BaseProtectedMoveDeletedCopy];
+        test_make_unique![ffi::BaseProtectedMoveDeletedCopy];
+        test_movable![ffi::BaseProtectedMoveDeletedCopy];
+        test_call_a_as![ffi::BaseProtectedMoveDeletedCopy, ffi::ProtectedMoveDeletedCopy];
+
+        test_constructible![ffi::BaseProtectedDeletedMove];
+        test_make_unique![ffi::BaseProtectedDeletedMove];
+        test_call_a_as![ffi::BaseProtectedDeletedMove, ffi::ProtectedDeletedMove];
+
+        test_call_a_as![ffi::BaseProtectedDeletedDestructor, ffi::ProtectedDeletedDestructor];
+
+        test_constructible![ffi::BaseProtectedDestructor];
+        test_make_unique![ffi::BaseProtectedDestructor];
+        test_copyable![ffi::BaseProtectedDestructor];
+        test_call_a_as![ffi::BaseProtectedDestructor, ffi::ProtectedDestructor];
+
+        test_call_a![ffi::MemberProtectedDeleted];
+
+        test_copyable![ffi::MemberProtectedDeletedDefault];
+        test_movable![ffi::MemberProtectedDeletedDefault];
+        test_call_a![ffi::MemberProtectedDeletedDefault];
+
+        test_constructible![ffi::MemberProtectedDeletedCopy];
+        test_make_unique![ffi::MemberProtectedDeletedCopy];
+        test_call_a![ffi::MemberProtectedDeletedCopy];
+
+        test_call_a![ffi::MemberProtectedDeletedCopyNoDefault];
+
+        test_constructible![ffi::MemberProtectedMoveDeletedCopy];
+        test_make_unique![ffi::MemberProtectedMoveDeletedCopy];
+        test_call_a![ffi::MemberProtectedMoveDeletedCopy];
+
+        test_constructible![ffi::MemberProtectedDeletedMove];
+        test_make_unique![ffi::MemberProtectedDeletedMove];
+        test_call_a![ffi::MemberProtectedDeletedMove];
+
+        test_call_a![ffi::MemberProtectedDeletedDestructor];
+
+        test_call_a![ffi::MemberProtectedDestructor];
+
+        test_call_a_as![ffi::BaseMemberProtectedDeleted, ffi::MemberProtectedDeleted];
+
+        test_copyable![ffi::BaseMemberProtectedDeletedDefault];
+        test_movable![ffi::BaseMemberProtectedDeletedDefault];
+        test_call_a_as![ffi::BaseMemberProtectedDeletedDefault, ffi::MemberProtectedDeletedDefault];
+
+        test_constructible![ffi::BaseMemberProtectedDeletedCopy];
+        test_make_unique![ffi::BaseMemberProtectedDeletedCopy];
+        test_call_a_as![ffi::BaseMemberProtectedDeletedCopy, ffi::MemberProtectedDeletedCopy];
+
+        test_call_a_as![ffi::BaseMemberProtectedDeletedCopyNoDefault, ffi::MemberProtectedDeletedCopyNoDefault];
+
+        test_constructible![ffi::BaseMemberProtectedMoveDeletedCopy];
+        test_make_unique![ffi::BaseMemberProtectedMoveDeletedCopy];
+        test_call_a_as![ffi::BaseMemberProtectedMoveDeletedCopy, ffi::MemberProtectedMoveDeletedCopy];
+
+        test_constructible![ffi::BaseMemberProtectedDeletedMove];
+        test_make_unique![ffi::BaseMemberProtectedDeletedMove];
+        test_call_a_as![ffi::BaseMemberProtectedDeletedMove, ffi::MemberProtectedDeletedMove];
+
+        test_call_a_as![ffi::BaseMemberProtectedDeletedDestructor, ffi::MemberProtectedDeletedDestructor];
+
+        test_call_a_as![ffi::BaseMemberProtectedDestructor, ffi::MemberProtectedDestructor];
+
+        test_call_a_as![ffi::BasePrivateDeleted, ffi::PrivateDeleted];
+
+        test_copyable![ffi::BasePrivateDeletedDefault];
+        test_movable![ffi::BasePrivateDeletedDefault];
+        test_call_a_as![ffi::BasePrivateDeletedDefault, ffi::PrivateDeletedDefault];
+
+        test_constructible![ffi::BasePrivateDeletedCopy];
+        test_make_unique![ffi::BasePrivateDeletedCopy];
+        test_call_a_as![ffi::BasePrivateDeletedCopy, ffi::PrivateDeletedCopy];
+
+        test_call_a_as![ffi::BasePrivateDeletedCopyNoDefault, ffi::PrivateDeletedCopyNoDefault];
+
+        test_constructible![ffi::BasePrivateMoveDeletedCopy];
+        test_make_unique![ffi::BasePrivateMoveDeletedCopy];
+        test_call_a_as![ffi::BasePrivateMoveDeletedCopy, ffi::PrivateMoveDeletedCopy];
+
+        test_constructible![ffi::BasePrivateDeletedMove];
+        test_make_unique![ffi::BasePrivateDeletedMove];
+        test_call_a_as![ffi::BasePrivateDeletedMove, ffi::PrivateDeletedMove];
+
+        test_call_a_as![ffi::BasePrivateDeletedDestructor, ffi::PrivateDeletedDestructor];
+
+        test_call_a_as![ffi::BasePrivateDestructor, ffi::PrivateDestructor];
+
+        test_call_a![ffi::MemberPrivateDeleted];
+
+        test_copyable![ffi::MemberPrivateDeletedDefault];
+        test_movable![ffi::MemberPrivateDeletedDefault];
+        test_call_a![ffi::MemberPrivateDeletedDefault];
+
+        test_constructible![ffi::MemberPrivateDeletedCopy];
+        test_make_unique![ffi::MemberPrivateDeletedCopy];
+        test_call_a![ffi::MemberPrivateDeletedCopy];
+
+        test_call_a![ffi::MemberPrivateDeletedCopyNoDefault];
+
+        test_constructible![ffi::MemberPrivateMoveDeletedCopy];
+        test_make_unique![ffi::MemberPrivateMoveDeletedCopy];
+        test_call_a![ffi::MemberPrivateMoveDeletedCopy];
+
+        test_constructible![ffi::MemberPrivateDeletedMove];
+        test_make_unique![ffi::MemberPrivateDeletedMove];
+        test_call_a![ffi::MemberPrivateDeletedMove];
+
+        test_call_a![ffi::MemberPrivateDeletedDestructor];
+
+        test_call_a![ffi::MemberPrivateDestructor];
+
+        test_call_a_as![ffi::BaseMemberPrivateDeleted, ffi::MemberPrivateDeleted];
+
+        test_copyable![ffi::BaseMemberPrivateDeletedDefault];
+        test_movable![ffi::BaseMemberPrivateDeletedDefault];
+        test_call_a_as![ffi::BaseMemberPrivateDeletedDefault, ffi::MemberPrivateDeletedDefault];
+
+        test_constructible![ffi::BaseMemberPrivateDeletedCopy];
+        test_make_unique![ffi::BaseMemberPrivateDeletedCopy];
+        test_call_a_as![ffi::BaseMemberPrivateDeletedCopy, ffi::MemberPrivateDeletedCopy];
+
+        test_call_a_as![ffi::BaseMemberPrivateDeletedCopyNoDefault, ffi::MemberPrivateDeletedCopyNoDefault];
+
+        test_constructible![ffi::BaseMemberPrivateMoveDeletedCopy];
+        test_make_unique![ffi::BaseMemberPrivateMoveDeletedCopy];
+        test_call_a_as![ffi::BaseMemberPrivateMoveDeletedCopy, ffi::MemberPrivateMoveDeletedCopy];
+
+        test_constructible![ffi::BaseMemberPrivateDeletedMove];
+        test_make_unique![ffi::BaseMemberPrivateDeletedMove];
+        test_call_a_as![ffi::BaseMemberPrivateDeletedMove, ffi::MemberPrivateDeletedMove];
+
+        test_call_a_as![ffi::BaseMemberPrivateDeletedDestructor, ffi::MemberPrivateDeletedDestructor];
+
+        test_call_a_as![ffi::BaseMemberPrivateDestructor, ffi::MemberPrivateDestructor];
+    };
+    run_test(
+        cxx,
+        hdr,
+        rs,
+        &[
+            "AllImplicitlyDefaulted",
+            "PublicDeleted",
+            "PublicDeletedDefault",
+            "PublicDeletedCopy",
+            "PublicDeletedCopyNoDefault",
+            "PublicMoveDeletedCopy",
+            "PublicDeletedMove",
+            "PublicDeletedDestructor",
+            "PublicDestructor",
+            "ProtectedDeleted",
+            "ProtectedDeletedDefault",
+            "ProtectedDeletedCopy",
+            "ProtectedDeletedCopyNoDefault",
+            "ProtectedMoveDeletedCopy",
+            "ProtectedDeletedMove",
+            "ProtectedDeletedDestructor",
+            "ProtectedDestructor",
+            "PrivateDeleted",
+            "PrivateDeletedDefault",
+            "PrivateDeletedCopy",
+            "PrivateDeletedCopyNoDefault",
+            "PrivateMoveDeletedCopy",
+            "PrivateDeletedMove",
+            "PrivateDeletedDestructor",
+            "PrivateDestructor",
+            "NonConstCopy",
+            "TwoCopy",
+            "MemberPointerDeleted",
+            "MemberConstPointerDeleted",
+            // TODO: Handle top-level const on C++ members correctly.
+            //"MemberConst",
+            "MemberReferenceDeleted",
+            "MemberConstReferenceDeleted",
+            "MemberReference",
+            "MemberConstReference",
+            "MemberRvalueReferenceDeleted",
+            "MemberRvalueReference",
+            "BasePublicDeleted",
+            "BasePublicDeletedDefault",
+            "BasePublicDeletedCopy",
+            "BasePublicDeletedCopyNoDefault",
+            "BasePublicMoveDeletedCopy",
+            "BasePublicDeletedMove",
+            "BasePublicDeletedDestructor",
+            "BasePublicDestructor",
+            "MemberPublicDeleted",
+            "MemberPublicDeletedDefault",
+            "MemberPublicDeletedCopy",
+            "MemberPublicDeletedCopyNoDefault",
+            "MemberPublicMoveDeletedCopy",
+            "MemberPublicDeletedMove",
+            "MemberPublicDeletedDestructor",
+            "MemberPublicDestructor",
+            "BaseMemberPublicDeleted",
+            "BaseMemberPublicDeletedDefault",
+            "BaseMemberPublicDeletedCopy",
+            "BaseMemberPublicDeletedCopyNoDefault",
+            "BaseMemberPublicMoveDeletedCopy",
+            "BaseMemberPublicDeletedMove",
+            "BaseMemberPublicDeletedDestructor",
+            "BaseMemberPublicDestructor",
+            "BaseProtectedDeleted",
+            "BaseProtectedDeletedDefault",
+            "BaseProtectedDeletedCopy",
+            "BaseProtectedDeletedCopyNoDefault",
+            "BaseProtectedMoveDeletedCopy",
+            "BaseProtectedDeletedMove",
+            "BaseProtectedDeletedDestructor",
+            "BaseProtectedDestructor",
+            "MemberProtectedDeleted",
+            "MemberProtectedDeletedDefault",
+            "MemberProtectedDeletedCopy",
+            "MemberProtectedDeletedCopyNoDefault",
+            "MemberProtectedMoveDeletedCopy",
+            "MemberProtectedDeletedMove",
+            "MemberProtectedDeletedDestructor",
+            "MemberProtectedDestructor",
+            "BaseMemberProtectedDeleted",
+            "BaseMemberProtectedDeletedDefault",
+            "BaseMemberProtectedDeletedCopy",
+            "BaseMemberProtectedDeletedCopyNoDefault",
+            "BaseMemberProtectedMoveDeletedCopy",
+            "BaseMemberProtectedDeletedMove",
+            "BaseMemberProtectedDeletedDestructor",
+            "BaseMemberProtectedDestructor",
+            "BasePrivateDeleted",
+            "BasePrivateDeletedDefault",
+            "BasePrivateDeletedCopy",
+            "BasePrivateDeletedCopyNoDefault",
+            "BasePrivateMoveDeletedCopy",
+            "BasePrivateDeletedMove",
+            "BasePrivateDeletedDestructor",
+            "BasePrivateDestructor",
+            "MemberPrivateDeleted",
+            "MemberPrivateDeletedDefault",
+            "MemberPrivateDeletedCopy",
+            "MemberPrivateDeletedCopyNoDefault",
+            "MemberPrivateMoveDeletedCopy",
+            "MemberPrivateDeletedMove",
+            "MemberPrivateDeletedDestructor",
+            "MemberPrivateDestructor",
+            "BaseMemberPrivateDeleted",
+            "BaseMemberPrivateDeletedDefault",
+            "BaseMemberPrivateDeletedCopy",
+            "BaseMemberPrivateDeletedCopyNoDefault",
+            "BaseMemberPrivateMoveDeletedCopy",
+            "BaseMemberPrivateDeletedMove",
+            "BaseMemberPrivateDeletedDestructor",
+            "BaseMemberPrivateDestructor",
+        ],
+        &[],
+    );
+}
+
+#[test]
+/// Test that destructors hidden in various places are correctly called.
+///
+/// Some types are excluded because we know they behave poorly due to
+/// https://github.com/google/autocxx/issues/829.
+fn test_tricky_destructors() {
+    let cxx = "";
+    let hdr = indoc! {"
+        #include <stdio.h>
+        #include <stdlib.h>
+        // A simple type to let Rust verify the destructor is run.
+        struct DestructorFlag {
+            DestructorFlag() = default;
+            DestructorFlag(const DestructorFlag&) = default;
+            DestructorFlag(DestructorFlag&&) = default;
+
+            ~DestructorFlag() {
+                if (!flag) return;
+                if (*flag) {
+                    fprintf(stderr, \"DestructorFlag is already set\\n\");
+                    abort();
+                }
+                *flag = true;
+                // Note we deliberately do NOT clear the value of `flag`, to catch Rust calling
+                // this destructor twice.
+            }
+
+            bool *flag = nullptr;
+        };
+
+        struct ImplicitlyDefaulted {
+            DestructorFlag flag;
+
+            void set_flag(bool *flag_pointer) { flag.flag = flag_pointer; }
+        };
+        struct ExplicitlyDefaulted {
+            ExplicitlyDefaulted() = default;
+            ~ExplicitlyDefaulted() = default;
+
+            DestructorFlag flag;
+
+            void set_flag(bool *flag_pointer) { flag.flag = flag_pointer; }
+        };
+        struct Explicit {
+            Explicit() = default;
+            ~Explicit() {}
+
+            DestructorFlag flag;
+
+            void set_flag(bool *flag_pointer) { flag.flag = flag_pointer; }
+        };
+
+        struct BaseImplicitlyDefaulted : public ImplicitlyDefaulted {
+            void set_flag(bool *flag_pointer) { ImplicitlyDefaulted::set_flag(flag_pointer); }
+        };
+        struct BaseExplicitlyDefaulted : public ExplicitlyDefaulted {
+            void set_flag(bool *flag_pointer) { ExplicitlyDefaulted::set_flag(flag_pointer); }
+        };
+        struct BaseExplicit : public Explicit {
+            void set_flag(bool *flag_pointer) { Explicit::set_flag(flag_pointer); }
+        };
+
+        struct MemberImplicitlyDefaulted {
+            ImplicitlyDefaulted member;
+
+            void set_flag(bool *flag_pointer) { member.set_flag(flag_pointer); }
+        };
+        struct MemberExplicitlyDefaulted {
+            ExplicitlyDefaulted member;
+
+            void set_flag(bool *flag_pointer) { member.set_flag(flag_pointer); }
+        };
+        struct MemberExplicit {
+            Explicit member;
+
+            void set_flag(bool *flag_pointer) { member.set_flag(flag_pointer); }
+        };
+
+        struct BaseMemberImplicitlyDefaulted : public MemberImplicitlyDefaulted {
+            void set_flag(bool *flag_pointer) { MemberImplicitlyDefaulted::set_flag(flag_pointer); }
+        };
+        struct BaseMemberExplicitlyDefaulted : public MemberExplicitlyDefaulted {
+            void set_flag(bool *flag_pointer) { MemberExplicitlyDefaulted::set_flag(flag_pointer); }
+        };
+        struct BaseMemberExplicit : public MemberExplicit {
+            void set_flag(bool *flag_pointer) { MemberExplicit::set_flag(flag_pointer); }
+        };
+    "};
+    let rs = quote! {
+        macro_rules! test_type {
+            [$t:ty] => {
+                let mut unique_t = <$t>::new().within_unique_ptr();
+                let mut destructor_flag = false;
+                unsafe {
+                    unique_t.pin_mut().set_flag(&mut destructor_flag);
+                }
+                std::mem::drop(unique_t);
+                assert!(destructor_flag, "Destructor did not run with make_unique for {}", quote::quote!{$t});
+
+                moveit! {
+                    let mut moveit_t = <$t>::new();
+                }
+                let mut destructor_flag = false;
+                unsafe {
+                    moveit_t.as_mut().set_flag(&mut destructor_flag);
+                }
+                std::mem::drop(moveit_t);
+                assert!(destructor_flag, "Destructor did not run with moveit for {}", quote::quote!{$t});
+            }
+        }
+
+        test_type![ffi::ImplicitlyDefaulted];
+        test_type![ffi::ExplicitlyDefaulted];
+        test_type![ffi::Explicit];
+        test_type![ffi::BaseImplicitlyDefaulted];
+        test_type![ffi::BaseExplicitlyDefaulted];
+        test_type![ffi::BaseExplicit];
+        test_type![ffi::MemberImplicitlyDefaulted];
+        test_type![ffi::MemberExplicitlyDefaulted];
+        test_type![ffi::MemberExplicit];
+        test_type![ffi::BaseMemberImplicitlyDefaulted];
+        test_type![ffi::BaseMemberExplicitlyDefaulted];
+        test_type![ffi::BaseMemberExplicit];
+    };
+    run_test(
+        cxx,
+        hdr,
+        rs,
+        &[
+            "DestructorFlag",
+            "ImplicitlyDefaulted",
+            "ExplicitlyDefaulted",
+            "Explicit",
+            "BaseImplicitlyDefaulted",
+            "BaseExplicitlyDefaulted",
+            "BaseExplicit",
+            "MemberImplicitlyDefaulted",
+            "MemberExplicitlyDefaulted",
+            "MemberExplicit",
+            "BaseMemberImplicitlyDefaulted",
+            "BaseMemberExplicitlyDefaulted",
+            "BaseMemberExplicit",
+        ],
+        &[],
+    );
+}
+
+#[test]
+fn test_concretize() {
+    let hdr = indoc! {"
+        #include <string>
+        template<typename CONTENTS>
+        class Container {
+        private:
+            CONTENTS* contents;
+        };
+        struct B {
+            std::string a;
+        };
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! {
+            concrete!("Container<B>", ContainerOfB)
+            generate!("B")
+        },
+        None,
+        None,
+        Some(quote! {
+            struct HasAField {
+                contents: ffi::ContainerOfB
+            }
+        }),
+    );
+}
+
+#[test]
+fn test_doc_comments_survive() {
+    let hdr = indoc! {"
+        #include <cstdint>
+        /// Struct line A
+        /// Struct line B
+        struct A { int b; };
+
+        /// POD struct line A
+        /// POD struct line B
+        struct B {
+            /// Field line A
+            /// Field line B
+            uint32_t b;
+
+            /// Method line A
+            /// Method line B
+            void foo() {}
+        };
+
+        /// Enum line A
+        /// Enum line B
+        enum C {
+            /// Variant line A
+            /// Variant line B
+            VARIANT,
+        };
+
+        /// Function line A
+        /// Function line B
+        inline void D() {}
+    "};
+
+    let expected_messages = [
+        "Struct",
+        "POD struct",
+        "Field",
+        "Method",
+        "Enum",
+        "Variant",
+        "Function",
+    ]
+    .into_iter()
+    .flat_map(|l| [format!("{} line A", l), format!("{} line B", l)])
+    .collect_vec();
+
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        directives_from_lists(&["A", "C", "D"], &["B"], None),
+        None,
+        Some(make_string_finder(expected_messages)),
+        None,
+    );
+}
+
+#[test]
+fn optional_param_in_copy_constructor() {
+    let hdr = indoc! {"
+        struct A {
+            A(const A &other, bool optional_arg = false);
+        };
+    "};
+    run_test("", hdr, quote! {}, &["A"], &[]);
+}
+
+#[test]
+fn param_in_copy_constructor() {
+    let hdr = indoc! {"
+        struct A {
+            A(const A &other, bool arg);
+        };
+    "};
+    run_test("", hdr, quote! {}, &["A"], &[]);
+}
+
+#[test]
+fn test_variadic() {
+    let hdr = indoc! {"
+        class SomeClass{
+        public:
+            inline void foo(int, ... ) {}
+        };
+    "};
+    run_test("", hdr, quote! {}, &["SomeClass"], &[]);
+}
+
+#[test]
+fn test_typedef_to_enum() {
+    let hdr = indoc! {"
+        enum b {};
+        class c {
+        public:
+          typedef b d;
+          d e();
+        };
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_all!() },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_typedef_to_ns_enum() {
+    let hdr = indoc! {"
+        namespace a {
+        enum b {};
+        class c {
+        public:
+          typedef b d;
+          d e();
+        };
+        } // namespace
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_all!() },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_typedef_unsupported_type_pub() {
+    let hdr = indoc! {"
+        #include <set>
+        namespace NS{
+            class cls{
+                public:
+                    typedef std::set<int> InnerType;
+                };
+        }
+    "};
+
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_ns!("NS") },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_typedef_unsupported_type_pri() {
+    let hdr = indoc! {"
+        #include <set>
+        namespace NS{
+            class cls{
+                private:
+                    typedef std::set<int> InnerType;
+                };
+        }
+    "};
+
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_ns!("NS") },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_array_trouble1() {
+    let hdr = indoc! {"
+        namespace a {
+        template <typename b> struct array {
+          typedef b c;
+          typedef c d;
+        };
+        } // namespace a
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_all!() },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_array_trouble2() {
+    let hdr = indoc! {"
+        template <typename b> struct array {
+          typedef b c;
+          typedef c d;
+        };
+    "};
+    run_test("", hdr, quote! {}, &["array_d"], &[]);
+}
+
+#[test]
+fn test_issue_1087a() {
+    let hdr = indoc! {"
+        template <typename _CharT> class a {
+          _CharT b;
+        };
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_all!() },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_issue_1087b() {
+    let hdr = indoc! {"
+        template <typename _CharT> class a {
+          typedef _CharT b;
+          b c;
+        };
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_all!() },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_issue_1087c() {
+    let hdr = indoc! {"
+        namespace {
+        namespace {
+        template <typename _CharT> class a {
+          typedef _CharT b;
+          b c;
+        };
+        }
+        }
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_all!() },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_issue_1089() {
+    let hdr = indoc! {"
+        namespace a {
+        template <typename c, c> struct d;
+        template <bool, typename, typename> struct ab;
+        inline namespace {
+        namespace ac {
+        template <typename, template <typename> class, typename> struct bh;
+        template <template <typename> class ad, typename... bi>
+        using bj = bh<void, ad, bi...>;
+        template <typename ad> using bk = typename ad::b;
+        template <typename> struct bm;
+        } // namespace ac
+        template <typename ad>
+        struct b : ab<ac::bj<ac::bk, ad>::e, ac::bm<ad>, d<bool, ad ::e>>::bg {};
+        } // namespace
+        } // namespace a
+    "};
+    run_test_ex(
+        "",
+        hdr,
+        quote! {},
+        quote! { generate_all!() },
+        None,
+        None,
+        None,
+    );
+}
+
+#[test]
+fn test_pass_rust_str_and_return_struct() {
+    let cxx = indoc! {"
+        A take_str_return_struct(rust::Str) {
+            A a;
+            return a;
+        }
+    "};
+    let hdr = indoc! {"
+        #include <cxx.h>
+        struct A {};
+        A take_str_return_struct(rust::Str);
+    "};
+    let rs = quote! {
+        ffi::take_str_return_struct("hi");
+    };
+    run_test(cxx, hdr, rs, &["take_str_return_struct"], &[]);
+}
+
+#[test]
+fn test_issue_1065a() {
+    let hdr = indoc! {"
+        #include <memory>
+        #include <vector>
+
+        template <typename at> class au {
+        std::unique_ptr<at> aw;
+        };
+        class bb;
+        using bc = au<bb>;
+        class RenderFrameHost {
+        public:
+        virtual std::vector<bc> &bd() = 0;
+        virtual ~RenderFrameHost() {}
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["RenderFrameHost"], &[]);
+}
+
+#[test]
+fn test_issue_1065b() {
+    let hdr = indoc! {"
+        #include <memory>
+        #include <vector>
+
+        class bb;
+        using bc = std::unique_ptr<bb>;
+        class RenderFrameHost {
+        public:
+        virtual std::vector<bc> &bd() = 0;
+        virtual ~RenderFrameHost() {}
+        };
+    "};
+    let rs = quote! {};
+    run_test("", hdr, rs, &["RenderFrameHost"], &[]);
+}
+
+// Yet to test:
+// - Ifdef
+// - Out param pointers
+// - ExcludeUtilities
+// - Struct fields which are typedefs
+// Negative tests:
+// - Private methods
+// - Private fields
diff --git a/integration-tests/tests/lib.rs b/integration-tests/tests/lib.rs
new file mode 100644
index 0000000..17f076a
--- /dev/null
+++ b/integration-tests/tests/lib.rs
@@ -0,0 +1,11 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod builder_modifiers;
+mod code_checkers;
+mod integration_test;
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
new file mode 100644
index 0000000..d1d633a
--- /dev/null
+++ b/macro/Cargo.toml
@@ -0,0 +1,31 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-macro"
+version = "0.22.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+license = "MIT OR Apache-2.0"
+description = "Safe autogenerated interop between Rust and C++"
+repository = "https://github.com/google/autocxx"
+edition = "2021"
+keywords = ["ffi"]
+categories = ["development-tools::ffi", "api-bindings"]
+
+[lib]
+proc-macro = true
+
+[dependencies]
+autocxx-parser = { path="../parser", version="=0.22.0" }
+proc-macro-error = "1.0"
+proc-macro2 = "1.0.11"
+quote = "1.0"
+
+[dependencies.syn]
+version = "1.0"
+features = [ "full" ]
diff --git a/macro/README.md b/macro/README.md
new file mode 100644
index 0000000..9b91d4a
--- /dev/null
+++ b/macro/README.md
@@ -0,0 +1 @@
+This crate is a [component of autocxx](https://google.github.io/autocxx/).
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
new file mode 100644
index 0000000..01ccd69
--- /dev/null
+++ b/macro/src/lib.rs
@@ -0,0 +1,131 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![forbid(unsafe_code)]
+
+use autocxx_parser::{IncludeCpp, SubclassAttrs};
+use proc_macro::TokenStream;
+use proc_macro2::{Ident, Span};
+use proc_macro_error::{abort, proc_macro_error};
+use quote::quote;
+use syn::parse::Parser;
+use syn::{parse_macro_input, parse_quote, Fields, Item, ItemStruct, Visibility};
+
+/// Implementation of the `include_cpp` macro. See documentation for `autocxx` crate.
+#[proc_macro_error]
+#[proc_macro]
+pub fn include_cpp_impl(input: TokenStream) -> TokenStream {
+    let include_cpp = parse_macro_input!(input as IncludeCpp);
+    TokenStream::from(include_cpp.generate_rs())
+}
+
+/// Attribute to state that a Rust `struct` is a C++ subclass.
+/// This adds an additional field to the struct which autocxx uses to
+/// track a C++ instantiation of this Rust subclass.
+#[proc_macro_error]
+#[proc_macro_attribute]
+pub fn subclass(attr: TokenStream, item: TokenStream) -> TokenStream {
+    let mut s: ItemStruct =
+        syn::parse(item).unwrap_or_else(|_| abort!(Span::call_site(), "Expected a struct"));
+    if !matches!(s.vis, Visibility::Public(..)) {
+        use syn::spanned::Spanned;
+        abort!(s.vis.span(), "Rust subclasses of C++ types must by public");
+    }
+    let id = &s.ident;
+    let cpp_ident = Ident::new(&format!("{}Cpp", id), Span::call_site());
+    let input = quote! {
+        cpp_peer: autocxx::subclass::CppSubclassCppPeerHolder<ffi:: #cpp_ident>
+    };
+    let parser = syn::Field::parse_named;
+    let new_field = parser.parse2(input).unwrap();
+    s.fields = match &mut s.fields {
+        Fields::Named(fields) => {
+            fields.named.push(new_field);
+            s.fields
+        },
+        Fields::Unit => Fields::Named(parse_quote! {
+            {
+                #new_field
+            }
+        }),
+        _ => abort!(Span::call_site(), "Expect a struct with named fields - use struct A{} or struct A; as opposed to struct A()"),
+    };
+    let subclass_attrs: SubclassAttrs = syn::parse(attr)
+        .unwrap_or_else(|_| abort!(Span::call_site(), "Unable to parse attributes"));
+    let self_owned_bit = if subclass_attrs.self_owned {
+        Some(quote! {
+            impl autocxx::subclass::CppSubclassSelfOwned<ffi::#cpp_ident> for #id {}
+        })
+    } else {
+        None
+    };
+    let toks = quote! {
+        #s
+
+        impl autocxx::subclass::CppSubclass<ffi::#cpp_ident> for #id {
+            fn peer_holder_mut(&mut self) -> &mut autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
+                &mut self.cpp_peer
+            }
+            fn peer_holder(&self) -> &autocxx::subclass::CppSubclassCppPeerHolder<ffi::#cpp_ident> {
+                &self.cpp_peer
+            }
+        }
+
+        #self_owned_bit
+    };
+    toks.into()
+}
+
+/// Attribute to state that a Rust type is to be exported to C++
+/// in the `extern "Rust"` section of the generated `cxx` bindings.
+#[proc_macro_error]
+#[proc_macro_attribute]
+pub fn extern_rust_type(attr: TokenStream, input: TokenStream) -> TokenStream {
+    if !attr.is_empty() {
+        abort!(Span::call_site(), "Expected no attributes");
+    }
+    let i: Item =
+        syn::parse(input.clone()).unwrap_or_else(|_| abort!(Span::call_site(), "Expected an item"));
+    match i {
+        Item::Struct(..) | Item::Enum(..) | Item::Fn(..) => {}
+        _ => abort!(Span::call_site(), "Expected a struct or enum"),
+    }
+    input
+}
+
+/// Attribute to state that a Rust function is to be exported to C++
+/// in the `extern "Rust"` section of the generated `cxx` bindings.
+#[proc_macro_error]
+#[proc_macro_attribute]
+pub fn extern_rust_function(attr: TokenStream, input: TokenStream) -> TokenStream {
+    if !attr.is_empty() {
+        abort!(Span::call_site(), "Expected no attributes");
+    }
+    let i: Item =
+        syn::parse(input.clone()).unwrap_or_else(|_| abort!(Span::call_site(), "Expected an item"));
+    match i {
+        Item::Fn(..) => {}
+        _ => abort!(Span::call_site(), "Expected a function"),
+    }
+    input
+}
+
+/// Attribute which should never be encountered in real life.
+/// This is something which features in the Rust source code generated
+/// by autocxx-bindgen and passed to autocxx-engine, which should never
+/// normally be compiled by rustc before it undergoes further processing.
+#[proc_macro_error]
+#[proc_macro_attribute]
+pub fn cpp_semantics(_attr: TokenStream, _input: TokenStream) -> TokenStream {
+    abort!(
+        Span::call_site(),
+        "Please do not attempt to compile this code. \n\
+        This code is the output from the autocxx-specific version of bindgen, \n\
+        and should be interpreted by autocxx-engine before further usage."
+    );
+}
diff --git a/parser/Cargo.toml b/parser/Cargo.toml
new file mode 100644
index 0000000..481f21d
--- /dev/null
+++ b/parser/Cargo.toml
@@ -0,0 +1,36 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-parser"
+version = "0.22.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+license = "MIT OR Apache-2.0"
+description = "Safe autogenerated interop between Rust and C++"
+repository = "https://github.com/google/autocxx"
+edition = "2021"
+keywords = ["ffi"]
+categories = ["development-tools::ffi", "api-bindings"]
+
+[dependencies]
+log = "0.4"
+proc-macro2 = "1.0"
+quote = "1.0"
+serde = { version = "1.0", features = [ "derive" ]}
+thiserror = "1.0"
+once_cell = "1.10"
+itertools = "0.10.3"
+indexmap = { version="1.8", features = ["serde"]}
+serde_json = "1.0"
+
+[dependencies.syn]
+version = "1.0.39"
+features = [ "full", "extra-traits" ]
+
+[features]
+reproduction_case = []
diff --git a/parser/README.md b/parser/README.md
new file mode 100644
index 0000000..9b91d4a
--- /dev/null
+++ b/parser/README.md
@@ -0,0 +1 @@
+This crate is a [component of autocxx](https://google.github.io/autocxx/).
diff --git a/parser/src/config.rs b/parser/src/config.rs
new file mode 100644
index 0000000..4204acf
--- /dev/null
+++ b/parser/src/config.rs
@@ -0,0 +1,500 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+use indexmap::set::IndexSet as HashSet;
+use std::borrow::Cow;
+use std::collections::hash_map::DefaultHasher;
+use std::hash::{Hash, Hasher};
+
+use itertools::Itertools;
+use proc_macro2::Span;
+use quote::ToTokens;
+
+#[cfg(feature = "reproduction_case")]
+use quote::format_ident;
+use syn::{
+    parse::{Parse, ParseStream},
+    Signature, Token, TypePath,
+};
+use syn::{Ident, Result as ParseResult};
+use thiserror::Error;
+
+use crate::{directives::get_directives, RustPath};
+
+use quote::quote;
+
+#[derive(PartialEq, Clone, Debug, Hash)]
+pub enum UnsafePolicy {
+    AllFunctionsSafe,
+    AllFunctionsUnsafe,
+}
+
+impl Default for UnsafePolicy {
+    fn default() -> Self {
+        Self::AllFunctionsUnsafe
+    }
+}
+
+impl Parse for UnsafePolicy {
+    fn parse(input: ParseStream) -> ParseResult<Self> {
+        if input.parse::<Option<Token![unsafe]>>()?.is_some() {
+            return Ok(UnsafePolicy::AllFunctionsSafe);
+        }
+        let r = match input.parse::<Option<syn::Ident>>()? {
+            Some(id) => {
+                if id == "unsafe_ffi" {
+                    Ok(UnsafePolicy::AllFunctionsSafe)
+                } else {
+                    Err(syn::Error::new(id.span(), "expected unsafe_ffi"))
+                }
+            }
+            None => Ok(UnsafePolicy::AllFunctionsUnsafe),
+        };
+        if !input.is_empty() {
+            return Err(syn::Error::new(
+                Span::call_site(),
+                "unexpected tokens within safety directive",
+            ));
+        }
+        r
+    }
+}
+
+impl ToTokens for UnsafePolicy {
+    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+        if *self == UnsafePolicy::AllFunctionsSafe {
+            tokens.extend(quote! { unsafe })
+        }
+    }
+}
+
+/// An entry in the allowlist.
+#[derive(Hash, Debug)]
+pub enum AllowlistEntry {
+    Item(String),
+    Namespace(String),
+}
+
+impl AllowlistEntry {
+    fn to_bindgen_item(&self) -> String {
+        match self {
+            AllowlistEntry::Item(i) => i.clone(),
+            AllowlistEntry::Namespace(ns) => format!("{}::.*", ns),
+        }
+    }
+}
+
+/// Allowlist configuration.
+#[derive(Hash, Debug)]
+pub enum Allowlist {
+    Unspecified(Vec<AllowlistEntry>),
+    All,
+    Specific(Vec<AllowlistEntry>),
+}
+
+/// Errors that may be encountered while adding allowlist entries.
+#[derive(Error, Debug)]
+pub enum AllowlistErr {
+    #[error("Conflict between generate/generate_ns! and generate_all! - use one not both")]
+    ConflictingGenerateAndGenerateAll,
+}
+
+impl Allowlist {
+    pub fn push(&mut self, item: AllowlistEntry) -> Result<(), AllowlistErr> {
+        match self {
+            Allowlist::Unspecified(ref mut uncommitted_list) => {
+                let new_list = uncommitted_list
+                    .drain(..)
+                    .chain(std::iter::once(item))
+                    .collect();
+                *self = Allowlist::Specific(new_list);
+            }
+            Allowlist::All => {
+                return Err(AllowlistErr::ConflictingGenerateAndGenerateAll);
+            }
+            Allowlist::Specific(list) => list.push(item),
+        };
+        Ok(())
+    }
+
+    pub(crate) fn set_all(&mut self) -> Result<(), AllowlistErr> {
+        if matches!(self, Allowlist::Specific(..)) {
+            return Err(AllowlistErr::ConflictingGenerateAndGenerateAll);
+        }
+        *self = Allowlist::All;
+        Ok(())
+    }
+}
+
+#[allow(clippy::derivable_impls)] // nightly-only
+impl Default for Allowlist {
+    fn default() -> Self {
+        Allowlist::Unspecified(Vec::new())
+    }
+}
+
+#[derive(Debug, Hash)]
+pub struct Subclass {
+    pub superclass: String,
+    pub subclass: Ident,
+}
+
+#[derive(Clone, Hash)]
+pub struct RustFun {
+    pub path: RustPath,
+    pub sig: Signature,
+    pub receiver: Option<Ident>,
+}
+
+impl std::fmt::Debug for RustFun {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("RustFun")
+            .field("path", &self.path)
+            .field("sig", &self.sig.to_token_stream().to_string())
+            .finish()
+    }
+}
+
+#[derive(Debug, Clone, Hash)]
+pub struct ExternCppType {
+    pub rust_path: TypePath,
+    pub opaque: bool,
+}
+
+/// Newtype wrapper so we can implement Hash.
+#[derive(Debug, Default)]
+pub struct ExternCppTypeMap(pub HashMap<String, ExternCppType>);
+
+impl std::hash::Hash for ExternCppTypeMap {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        for (k, v) in &self.0 {
+            k.hash(state);
+            v.hash(state);
+        }
+    }
+}
+
+/// Newtype wrapper so we can implement Hash.
+#[derive(Debug, Default)]
+pub struct ConcretesMap(pub HashMap<String, Ident>);
+
+impl std::hash::Hash for ConcretesMap {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        for (k, v) in &self.0 {
+            k.hash(state);
+            v.hash(state);
+        }
+    }
+}
+
+#[derive(Debug, Default, Hash)]
+pub struct IncludeCppConfig {
+    pub inclusions: Vec<String>,
+    pub unsafe_policy: UnsafePolicy,
+    pub parse_only: bool,
+    pub exclude_impls: bool,
+    pub(crate) pod_requests: Vec<String>,
+    pub allowlist: Allowlist,
+    pub(crate) blocklist: Vec<String>,
+    pub(crate) constructor_blocklist: Vec<String>,
+    pub instantiable: Vec<String>,
+    pub(crate) exclude_utilities: bool,
+    pub(crate) mod_name: Option<Ident>,
+    pub rust_types: Vec<RustPath>,
+    pub subclasses: Vec<Subclass>,
+    pub extern_rust_funs: Vec<RustFun>,
+    pub concretes: ConcretesMap,
+    pub externs: ExternCppTypeMap,
+}
+
+impl Parse for IncludeCppConfig {
+    fn parse(input: ParseStream) -> ParseResult<Self> {
+        let mut config = IncludeCppConfig::default();
+
+        while !input.is_empty() {
+            let has_hexathorpe = input.parse::<Option<syn::token::Pound>>()?.is_some();
+            let ident: syn::Ident = input.parse()?;
+            let args;
+            let (possible_directives, to_parse, parse_completely) = if has_hexathorpe {
+                (&get_directives().need_hexathorpe, input, false)
+            } else {
+                input.parse::<Option<syn::token::Bang>>()?;
+                syn::parenthesized!(args in input);
+                (&get_directives().need_exclamation, &args, true)
+            };
+            let all_possible = possible_directives.keys().join(", ");
+            let ident_str = ident.to_string();
+            match possible_directives.get(&ident_str) {
+                None => {
+                    return Err(syn::Error::new(
+                        ident.span(),
+                        format!("expected {}", all_possible),
+                    ));
+                }
+                Some(directive) => directive.parse(to_parse, &mut config, &ident.span())?,
+            }
+            if parse_completely && !to_parse.is_empty() {
+                return Err(syn::Error::new(
+                    ident.span(),
+                    format!("found unexpected input within the directive {}", ident_str),
+                ));
+            }
+            if input.is_empty() {
+                break;
+            }
+        }
+        Ok(config)
+    }
+}
+
+impl IncludeCppConfig {
+    pub fn get_pod_requests(&self) -> &[String] {
+        &self.pod_requests
+    }
+
+    pub fn get_mod_name(&self) -> Ident {
+        self.mod_name
+            .as_ref()
+            .cloned()
+            .unwrap_or_else(|| Ident::new("ffi", Span::call_site()))
+    }
+
+    /// Whether to avoid generating the standard helpful utility
+    /// functions which we normally include in every mod.
+    pub fn exclude_utilities(&self) -> bool {
+        self.exclude_utilities
+    }
+
+    /// Items which the user has explicitly asked us to generate;
+    /// we should raise an error if we weren't able to do so.
+    pub fn must_generate_list(&self) -> Box<dyn Iterator<Item = String> + '_> {
+        if let Allowlist::Specific(items) = &self.allowlist {
+            Box::new(
+                items
+                    .iter()
+                    .filter_map(|i| match i {
+                        AllowlistEntry::Item(i) => Some(i),
+                        AllowlistEntry::Namespace(_) => None,
+                    })
+                    .chain(self.pod_requests.iter())
+                    .cloned(),
+            )
+        } else {
+            Box::new(self.pod_requests.iter().cloned())
+        }
+    }
+
+    /// The allowlist of items to be passed into bindgen, if any.
+    pub fn bindgen_allowlist(&self) -> Option<Box<dyn Iterator<Item = String> + '_>> {
+        match &self.allowlist {
+            Allowlist::All => None,
+            Allowlist::Specific(items) => Some(Box::new(
+                items
+                    .iter()
+                    .map(AllowlistEntry::to_bindgen_item)
+                    .chain(self.pod_requests.iter().cloned())
+                    .chain(self.active_utilities())
+                    .chain(self.subclasses.iter().flat_map(|sc| {
+                        [
+                            format!("{}Cpp", sc.subclass),
+                            sc.subclass.to_string(), // TODO may not be necessary
+                            sc.superclass.clone(),
+                        ]
+                    })),
+            )),
+            Allowlist::Unspecified(_) => unreachable!(),
+        }
+    }
+
+    fn active_utilities(&self) -> Vec<String> {
+        if self.exclude_utilities {
+            Vec::new()
+        } else {
+            vec![self.get_makestring_name()]
+        }
+    }
+
+    fn is_subclass_or_superclass(&self, cpp_name: &str) -> bool {
+        self.subclasses
+            .iter()
+            .flat_map(|sc| {
+                [
+                    Cow::Owned(sc.subclass.to_string()),
+                    Cow::Borrowed(&sc.superclass),
+                ]
+            })
+            .any(|item| cpp_name == item.as_str())
+    }
+
+    /// Whether this type is on the allowlist specified by the user.
+    ///
+    /// A note on the allowlist handling in general. It's used in two places:
+    /// 1) As directives to bindgen
+    /// 2) After bindgen has generated code, to filter the APIs which
+    ///    we pass to cxx.
+    /// This second pass may seem redundant. But sometimes bindgen generates
+    /// unnecessary stuff.
+    pub fn is_on_allowlist(&self, cpp_name: &str) -> bool {
+        self.active_utilities().iter().any(|item| *item == cpp_name)
+            || self.is_subclass_or_superclass(cpp_name)
+            || self.is_subclass_holder(cpp_name)
+            || self.is_subclass_cpp(cpp_name)
+            || self.is_rust_fun(cpp_name)
+            || self.is_concrete_type(cpp_name)
+            || match &self.allowlist {
+                Allowlist::Unspecified(_) => panic!("Eek no allowlist yet"),
+                Allowlist::All => true,
+                Allowlist::Specific(items) => items.iter().any(|entry| match entry {
+                    AllowlistEntry::Item(i) => i == cpp_name,
+                    AllowlistEntry::Namespace(ns) => cpp_name.starts_with(ns),
+                }),
+            }
+    }
+
+    pub fn is_on_blocklist(&self, cpp_name: &str) -> bool {
+        self.blocklist.contains(&cpp_name.to_string())
+    }
+
+    pub fn is_on_constructor_blocklist(&self, cpp_name: &str) -> bool {
+        self.constructor_blocklist.contains(&cpp_name.to_string())
+    }
+
+    pub fn get_blocklist(&self) -> impl Iterator<Item = &String> {
+        self.blocklist.iter()
+    }
+
+    fn is_concrete_type(&self, cpp_name: &str) -> bool {
+        self.concretes.0.values().any(|val| *val == cpp_name)
+    }
+
+    /// Get a hash of the contents of this `include_cpp!` block.
+    pub fn get_hash(&self) -> u64 {
+        let mut s = DefaultHasher::new();
+        self.hash(&mut s);
+        s.finish()
+    }
+
+    /// In case there are multiple sets of ffi mods in a single binary,
+    /// endeavor to return a name which can be used to make symbols
+    /// unique.
+    pub fn uniquify_name_per_mod(&self, name: &str) -> String {
+        format!("{}_{:#x}", name, self.get_hash())
+    }
+
+    pub fn get_makestring_name(&self) -> String {
+        self.uniquify_name_per_mod("autocxx_make_string")
+    }
+
+    pub fn is_rust_type(&self, id: &Ident) -> bool {
+        self.rust_types
+            .iter()
+            .any(|rt| rt.get_final_ident() == &id.to_string())
+            || self.is_subclass_holder(&id.to_string())
+    }
+
+    fn is_rust_fun(&self, possible_fun: &str) -> bool {
+        self.extern_rust_funs
+            .iter()
+            .map(|fun| &fun.sig.ident)
+            .any(|id| id == possible_fun)
+    }
+
+    pub fn superclasses(&self) -> impl Iterator<Item = &String> {
+        let mut uniquified = HashSet::new();
+        uniquified.extend(self.subclasses.iter().map(|sc| &sc.superclass));
+        uniquified.into_iter()
+    }
+
+    pub fn is_subclass_holder(&self, id: &str) -> bool {
+        self.subclasses
+            .iter()
+            .any(|sc| format!("{}Holder", sc.subclass) == id)
+    }
+
+    fn is_subclass_cpp(&self, id: &str) -> bool {
+        self.subclasses
+            .iter()
+            .any(|sc| format!("{}Cpp", sc.subclass) == id)
+    }
+
+    /// Return the filename to which generated .rs should be written.
+    pub fn get_rs_filename(&self) -> String {
+        format!(
+            "autocxx-{}-gen.rs",
+            self.mod_name
+                .as_ref()
+                .map(|id| id.to_string())
+                .unwrap_or_else(|| "ffi-default".into())
+        )
+    }
+
+    pub fn confirm_complete(&mut self) {
+        if matches!(self.allowlist, Allowlist::Unspecified(_)) {
+            self.allowlist = Allowlist::Specific(Vec::new());
+        }
+    }
+
+    /// Used in reduction to substitute all included headers with a single
+    /// preprocessed replacement.
+    pub fn replace_included_headers(&mut self, replacement: &str) {
+        self.inclusions.clear();
+        self.inclusions.push(replacement.to_string());
+    }
+}
+
+#[cfg(feature = "reproduction_case")]
+impl ToTokens for IncludeCppConfig {
+    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+        let directives = get_directives();
+        let hexathorpe = syn::token::Pound(Span::call_site());
+        for (id, directive) in &directives.need_hexathorpe {
+            let id = format_ident!("{}", id);
+            for output in directive.output(self) {
+                tokens.extend(quote! {
+                    #hexathorpe #id #output
+                })
+            }
+        }
+        for (id, directive) in &directives.need_exclamation {
+            let id = format_ident!("{}", id);
+            for output in directive.output(self) {
+                tokens.extend(quote! {
+                    #id ! (#output)
+                })
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod parse_tests {
+    use crate::config::UnsafePolicy;
+    use syn::parse_quote;
+    #[test]
+    fn test_safety_unsafe() {
+        let us: UnsafePolicy = parse_quote! {
+            unsafe
+        };
+        assert_eq!(us, UnsafePolicy::AllFunctionsSafe)
+    }
+
+    #[test]
+    fn test_safety_unsafe_ffi() {
+        let us: UnsafePolicy = parse_quote! {
+            unsafe_ffi
+        };
+        assert_eq!(us, UnsafePolicy::AllFunctionsSafe)
+    }
+
+    #[test]
+    fn test_safety_safe() {
+        let us: UnsafePolicy = parse_quote! {};
+        assert_eq!(us, UnsafePolicy::AllFunctionsUnsafe)
+    }
+}
diff --git a/parser/src/directives.rs b/parser/src/directives.rs
new file mode 100644
index 0000000..160829e
--- /dev/null
+++ b/parser/src/directives.rs
@@ -0,0 +1,540 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+
+use once_cell::sync::OnceCell;
+use proc_macro2::Span;
+use proc_macro2::{Ident, TokenStream};
+use quote::{quote, ToTokens};
+use syn::parse::ParseStream;
+
+use crate::config::{Allowlist, AllowlistErr};
+use crate::directive_names::{EXTERN_RUST_FUN, EXTERN_RUST_TYPE, SUBCLASS};
+use crate::{AllowlistEntry, IncludeCppConfig};
+use crate::{ParseResult, RustFun, RustPath};
+
+pub(crate) struct DirectivesMap {
+    pub(crate) need_hexathorpe: HashMap<String, Box<dyn Directive>>,
+    pub(crate) need_exclamation: HashMap<String, Box<dyn Directive>>,
+}
+
+static DIRECTIVES: OnceCell<DirectivesMap> = OnceCell::new();
+
+pub(crate) fn get_directives() -> &'static DirectivesMap {
+    DIRECTIVES.get_or_init(|| {
+        let mut need_hexathorpe: HashMap<String, Box<dyn Directive>> = HashMap::new();
+        need_hexathorpe.insert("include".into(), Box::new(Inclusion));
+        let mut need_exclamation: HashMap<String, Box<dyn Directive>> = HashMap::new();
+        need_exclamation.insert("generate".into(), Box::new(Generate(false)));
+        need_exclamation.insert("generate_pod".into(), Box::new(Generate(true)));
+        need_exclamation.insert("generate_ns".into(), Box::new(GenerateNs));
+        need_exclamation.insert("generate_all".into(), Box::new(GenerateAll));
+        need_exclamation.insert("safety".into(), Box::new(Safety));
+        need_exclamation.insert(
+            "pod".into(),
+            Box::new(StringList(
+                |config| &mut config.pod_requests,
+                |config| &config.pod_requests,
+            )),
+        );
+        need_exclamation.insert(
+            "block".into(),
+            Box::new(StringList(
+                |config| &mut config.blocklist,
+                |config| &config.blocklist,
+            )),
+        );
+        need_exclamation.insert(
+            "block_constructors".into(),
+            Box::new(StringList(
+                |config| &mut config.constructor_blocklist,
+                |config| &config.constructor_blocklist,
+            )),
+        );
+        need_exclamation.insert(
+            "instantiable".into(),
+            Box::new(StringList(
+                |config| &mut config.instantiable,
+                |config| &config.instantiable,
+            )),
+        );
+        need_exclamation.insert(
+            "parse_only".into(),
+            Box::new(BoolFlag(
+                |config| &mut config.parse_only,
+                |config| &config.parse_only,
+            )),
+        );
+        need_exclamation.insert(
+            "exclude_impls".into(),
+            Box::new(BoolFlag(
+                |config| &mut config.exclude_impls,
+                |config| &config.exclude_impls,
+            )),
+        );
+        need_exclamation.insert(
+            "exclude_utilities".into(),
+            Box::new(BoolFlag(
+                |config| &mut config.exclude_utilities,
+                |config| &config.exclude_utilities,
+            )),
+        );
+        need_exclamation.insert("name".into(), Box::new(ModName));
+        need_exclamation.insert("concrete".into(), Box::new(Concrete));
+        need_exclamation.insert("rust_type".into(), Box::new(RustType { output: false }));
+        need_exclamation.insert(EXTERN_RUST_TYPE.into(), Box::new(RustType { output: true }));
+        need_exclamation.insert(SUBCLASS.into(), Box::new(Subclass));
+        need_exclamation.insert(EXTERN_RUST_FUN.into(), Box::new(ExternRustFun));
+        need_exclamation.insert(
+            "extern_cpp_type".into(),
+            Box::new(ExternCppType { opaque: false }),
+        );
+        need_exclamation.insert(
+            "extern_cpp_opaque_type".into(),
+            Box::new(ExternCppType { opaque: true }),
+        );
+
+        DirectivesMap {
+            need_hexathorpe,
+            need_exclamation,
+        }
+    })
+}
+
+/// Trait for handling an `include_cpp!` configuration directive.
+pub(crate) trait Directive: Send + Sync {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        span: &Span,
+    ) -> ParseResult<()>;
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a>;
+}
+
+struct Inclusion;
+
+impl Directive for Inclusion {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _span: &Span,
+    ) -> ParseResult<()> {
+        let hdr: syn::LitStr = args.parse()?;
+        config.inclusions.push(hdr.value());
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        Box::new(config.inclusions.iter().map(|val| quote! { #val }))
+    }
+}
+
+/// Directive for either `generate!` (false) or `generate_pod!` (true).
+struct Generate(bool);
+
+impl Directive for Generate {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        span: &Span,
+    ) -> ParseResult<()> {
+        let generate: syn::LitStr = args.parse()?;
+        config
+            .allowlist
+            .push(AllowlistEntry::Item(generate.value()))
+            .map_err(|e| allowlist_err_to_syn_err(e, span))?;
+        if self.0 {
+            config.pod_requests.push(generate.value());
+        }
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        match &config.allowlist {
+            Allowlist::Specific(items) if !self.0 => Box::new(
+                items
+                    .iter()
+                    .flat_map(|i| match i {
+                        AllowlistEntry::Item(s) => Some(s),
+                        _ => None,
+                    })
+                    .map(|s| quote! { #s }),
+            ),
+            Allowlist::Unspecified(_) => panic!("Allowlist mode not yet determined"),
+            _ => Box::new(std::iter::empty()),
+        }
+    }
+}
+
+struct GenerateNs;
+
+impl Directive for GenerateNs {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        span: &Span,
+    ) -> ParseResult<()> {
+        let generate: syn::LitStr = args.parse()?;
+        config
+            .allowlist
+            .push(AllowlistEntry::Namespace(generate.value()))
+            .map_err(|e| allowlist_err_to_syn_err(e, span))?;
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        match &config.allowlist {
+            Allowlist::Specific(items) => Box::new(
+                items
+                    .iter()
+                    .flat_map(|i| match i {
+                        AllowlistEntry::Namespace(s) => Some(s),
+                        _ => None,
+                    })
+                    .map(|s| quote! { #s }),
+            ),
+            Allowlist::Unspecified(_) => panic!("Allowlist mode not yet determined"),
+            _ => Box::new(std::iter::empty()),
+        }
+    }
+}
+
+struct GenerateAll;
+
+impl Directive for GenerateAll {
+    fn parse(
+        &self,
+        _args: ParseStream,
+        config: &mut IncludeCppConfig,
+        span: &Span,
+    ) -> ParseResult<()> {
+        config
+            .allowlist
+            .set_all()
+            .map_err(|e| allowlist_err_to_syn_err(e, span))?;
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        match &config.allowlist {
+            Allowlist::All => Box::new(std::iter::once(TokenStream::new())),
+            Allowlist::Unspecified(_) => panic!("Allowlist mode not yet determined"),
+            _ => Box::new(std::iter::empty()),
+        }
+    }
+}
+
+struct Safety;
+
+impl Directive for Safety {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _ident_span: &Span,
+    ) -> ParseResult<()> {
+        config.unsafe_policy = args.parse()?;
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        let policy = &config.unsafe_policy;
+        match config.unsafe_policy {
+            crate::UnsafePolicy::AllFunctionsSafe => {
+                Box::new(std::iter::once(policy.to_token_stream()))
+            }
+            crate::UnsafePolicy::AllFunctionsUnsafe => Box::new(std::iter::empty()),
+        }
+    }
+}
+
+fn allowlist_err_to_syn_err(err: AllowlistErr, span: &Span) -> syn::Error {
+    syn::Error::new(*span, format!("{}", err))
+}
+
+struct StringList<SET, GET>(SET, GET)
+where
+    SET: Fn(&mut IncludeCppConfig) -> &mut Vec<String>,
+    GET: Fn(&IncludeCppConfig) -> &Vec<String>;
+
+impl<SET, GET> Directive for StringList<SET, GET>
+where
+    SET: Fn(&mut IncludeCppConfig) -> &mut Vec<String> + Sync + Send,
+    GET: Fn(&IncludeCppConfig) -> &Vec<String> + Sync + Send,
+{
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _ident_span: &Span,
+    ) -> ParseResult<()> {
+        let val: syn::LitStr = args.parse()?;
+        self.0(config).push(val.value());
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        Box::new(self.1(config).iter().map(|val| {
+            quote! {
+                #val
+            }
+        }))
+    }
+}
+
+struct BoolFlag<SET, GET>(SET, GET)
+where
+    SET: Fn(&mut IncludeCppConfig) -> &mut bool,
+    GET: Fn(&IncludeCppConfig) -> &bool;
+
+impl<SET, GET> Directive for BoolFlag<SET, GET>
+where
+    SET: Fn(&mut IncludeCppConfig) -> &mut bool + Sync + Send,
+    GET: Fn(&IncludeCppConfig) -> &bool + Sync + Send,
+{
+    fn parse(
+        &self,
+        _args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _ident_span: &Span,
+    ) -> ParseResult<()> {
+        *self.0(config) = true;
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        if *self.1(config) {
+            Box::new(std::iter::once(quote! {}))
+        } else {
+            Box::new(std::iter::empty())
+        }
+    }
+}
+
+struct ModName;
+
+impl Directive for ModName {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _ident_span: &Span,
+    ) -> ParseResult<()> {
+        let id: Ident = args.parse()?;
+        config.mod_name = Some(id);
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        match &config.mod_name {
+            None => Box::new(std::iter::empty()),
+            Some(id) => Box::new(std::iter::once(quote! { #id })),
+        }
+    }
+}
+
+struct Concrete;
+
+impl Directive for Concrete {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _ident_span: &Span,
+    ) -> ParseResult<()> {
+        let definition: syn::LitStr = args.parse()?;
+        args.parse::<syn::token::Comma>()?;
+        let rust_id: syn::Ident = args.parse()?;
+        config.concretes.0.insert(definition.value(), rust_id);
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        Box::new(config.concretes.0.iter().map(|(k, v)| {
+            quote! {
+                #k,#v
+            }
+        }))
+    }
+}
+
+struct RustType {
+    output: bool,
+}
+
+impl Directive for RustType {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _ident_span: &Span,
+    ) -> ParseResult<()> {
+        let id: Ident = args.parse()?;
+        config.rust_types.push(RustPath::new_from_ident(id));
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        if self.output {
+            Box::new(config.rust_types.iter().map(|rp| rp.to_token_stream()))
+        } else {
+            Box::new(std::iter::empty())
+        }
+    }
+}
+
+struct Subclass;
+
+impl Directive for Subclass {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _ident_span: &Span,
+    ) -> ParseResult<()> {
+        let superclass: syn::LitStr = args.parse()?;
+        args.parse::<syn::token::Comma>()?;
+        let subclass: syn::Ident = args.parse()?;
+        config.subclasses.push(crate::config::Subclass {
+            superclass: superclass.value(),
+            subclass,
+        });
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        Box::new(config.subclasses.iter().map(|sc| {
+            let superclass = &sc.superclass;
+            let subclass = &sc.subclass;
+            quote! {
+                #superclass,#subclass
+            }
+        }))
+    }
+}
+
+struct ExternRustFun;
+
+impl Directive for ExternRustFun {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _ident_span: &Span,
+    ) -> ParseResult<()> {
+        let path: RustPath = args.parse()?;
+        args.parse::<syn::token::Comma>()?;
+        let sig: syn::Signature = args.parse()?;
+        config.extern_rust_funs.push(RustFun {
+            path,
+            sig,
+            receiver: None,
+        });
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        Box::new(config.extern_rust_funs.iter().map(|erf| {
+            let p = &erf.path;
+            let s = &erf.sig;
+            quote! { #p,#s }
+        }))
+    }
+}
+
+struct ExternCppType {
+    opaque: bool,
+}
+
+impl Directive for ExternCppType {
+    fn parse(
+        &self,
+        args: ParseStream,
+        config: &mut IncludeCppConfig,
+        _ident_span: &Span,
+    ) -> ParseResult<()> {
+        let definition: syn::LitStr = args.parse()?;
+        args.parse::<syn::token::Comma>()?;
+        let rust_path: syn::TypePath = args.parse()?;
+        config.externs.0.insert(
+            definition.value(),
+            crate::config::ExternCppType {
+                rust_path,
+                opaque: self.opaque,
+            },
+        );
+        Ok(())
+    }
+
+    fn output<'a>(
+        &self,
+        config: &'a IncludeCppConfig,
+    ) -> Box<dyn Iterator<Item = TokenStream> + 'a> {
+        let opaque_needed = self.opaque;
+        Box::new(
+            config
+                .externs
+                .0
+                .iter()
+                .filter_map(move |(definition, details)| {
+                    if details.opaque == opaque_needed {
+                        let rust_path = &details.rust_path;
+                        Some(quote! {
+                            #definition, #rust_path
+                        })
+                    } else {
+                        None
+                    }
+                }),
+        )
+    }
+}
diff --git a/parser/src/file_locations.rs b/parser/src/file_locations.rs
new file mode 100644
index 0000000..a113d0f
--- /dev/null
+++ b/parser/src/file_locations.rs
@@ -0,0 +1,159 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use proc_macro2::TokenStream;
+use quote::quote;
+use std::{fs::File, path::PathBuf};
+
+use crate::{multi_bindings::MultiBindings, IncludeCppConfig};
+
+/// The strategy used to generate, and to find generated, files.
+/// As standard, these are based off the OUT_DIR set by Cargo,
+/// but our code can't assume it can read OUT_DIR as it may
+/// be running in the rust-analyzer proc macro server where it's
+/// not available. We need to give provision for custom locations
+/// and we need our code generator build script to be able to pass
+/// locations through to the proc macro by env vars.
+///
+/// On the whole this class concerns itself with directory names
+/// and allows the actual file name to be determined elsewhere
+/// (based on a hash of the contents of `include_cpp!`.) But
+/// some types of build system need to know the precise file _name_
+/// produced by the codegen phase and passed into the macro phase,
+/// so we have some options for that. See `gen --help` for details.
+pub enum FileLocationStrategy {
+    Custom(PathBuf),
+    FromAutocxxRsFile(PathBuf),
+    FromAutocxxRs(PathBuf),
+    FromOutDir(PathBuf),
+    FromAutocxxRsJsonArchive(PathBuf),
+    UnknownMaybeFromOutdir,
+}
+
+static BUILD_DIR_NAME: &str = "autocxx-build-dir";
+static RS_DIR_NAME: &str = "rs";
+static AUTOCXX_RS: &str = "AUTOCXX_RS";
+static AUTOCXX_RS_FILE: &str = "AUTOCXX_RS_FILE";
+static AUTOCXX_RS_JSON_ARCHIVE: &str = "AUTOCXX_RS_JSON_ARCHIVE";
+
+impl FileLocationStrategy {
+    pub fn new() -> Self {
+        match std::env::var_os(AUTOCXX_RS_JSON_ARCHIVE) {
+            Some(of) => FileLocationStrategy::FromAutocxxRsJsonArchive(PathBuf::from(of)),
+            None => match std::env::var_os(AUTOCXX_RS_FILE) {
+                Some(of) => FileLocationStrategy::FromAutocxxRsFile(PathBuf::from(of)),
+                None => match std::env::var_os(AUTOCXX_RS) {
+                    None => match std::env::var_os("OUT_DIR") {
+                        None => FileLocationStrategy::UnknownMaybeFromOutdir,
+                        Some(od) => FileLocationStrategy::FromOutDir(PathBuf::from(od)),
+                    },
+                    Some(acrs) => FileLocationStrategy::FromAutocxxRs(PathBuf::from(acrs)),
+                },
+            },
+        }
+    }
+
+    pub fn new_custom(gen_dir: PathBuf) -> Self {
+        FileLocationStrategy::Custom(gen_dir)
+    }
+
+    /// Make a macro to include a given generated Rust file name.
+    /// This can't simply be calculated from `get_rs_dir` because
+    /// of limitations in rust-analyzer.
+    pub fn make_include(&self, config: &IncludeCppConfig) -> TokenStream {
+        match self {
+            FileLocationStrategy::FromAutocxxRs(custom_dir) => {
+                let fname = config.get_rs_filename();
+                let fname = custom_dir.join(fname).to_str().unwrap().to_string();
+                quote! {
+                    include!( #fname );
+                }
+            }
+            FileLocationStrategy::Custom(_) => panic!("Should never happen in the macro"),
+            FileLocationStrategy::UnknownMaybeFromOutdir | FileLocationStrategy::FromOutDir(_) => {
+                let fname = config.get_rs_filename();
+                let fname = format!("/{}/{}/{}", BUILD_DIR_NAME, RS_DIR_NAME, fname);
+                // rust-analyzer works better if we ask Rust to do the path
+                // concatenation rather than doing it in proc-macro code.
+                // proc-macro code does not itself have access to the value of
+                // OUT_DIR, but if we put it into a macro like the below,
+                // rust-analyzer can cope.
+                quote! {
+                    include!(concat!(env!("OUT_DIR"), #fname));
+                }
+            }
+            FileLocationStrategy::FromAutocxxRsFile(fname) => {
+                let fname = fname
+                    .to_str()
+                    .expect("AUTOCXX_RS_FILE environment variable contained non-UTF8 characters");
+                quote! {
+                    include!( #fname );
+                }
+            }
+            FileLocationStrategy::FromAutocxxRsJsonArchive(fname) => {
+                let archive = File::open(fname).unwrap_or_else(|_| panic!("Unable to open {}. This may mean you didn't run the codegen tool (autocxx_gen) before building the Rust code.", fname.to_string_lossy()));
+                let multi_bindings: MultiBindings = serde_json::from_reader(archive)
+                    .unwrap_or_else(|_| {
+                        panic!("Unable to interpret {} as JSON", fname.to_string_lossy())
+                    });
+                multi_bindings.get(config).unwrap_or_else(|err| panic!("Unable to find a suitable set of bindings within the JSON archive {} ({}). This likely means that the codegen tool hasn't been rerun since some changes in your include_cpp! macro.", fname.to_string_lossy(), err))
+            }
+        }
+    }
+
+    fn get_gen_dir(&self, suffix: &str) -> PathBuf {
+        let root = match self {
+            FileLocationStrategy::Custom(gen_dir)
+            | FileLocationStrategy::FromAutocxxRs(gen_dir) => gen_dir.clone(),
+            FileLocationStrategy::FromOutDir(out_dir) => out_dir.join(BUILD_DIR_NAME),
+            FileLocationStrategy::UnknownMaybeFromOutdir => {
+                panic!("Could not determine OUT_DIR or AUTOCXX_RS dir")
+            }
+            FileLocationStrategy::FromAutocxxRsFile(_) => {
+                panic!("It's invalid to set AUTOCXX_RS_FILE during the codegen phase.")
+            }
+            FileLocationStrategy::FromAutocxxRsJsonArchive(_) => {
+                panic!("It's invalid to set AUTOCXX_RS_JSON_ARCHIVE during the codegen phase.")
+            }
+        };
+        root.join(suffix)
+    }
+
+    /// Location to generate Rust files.
+    pub fn get_rs_dir(&self) -> PathBuf {
+        self.get_gen_dir(RS_DIR_NAME)
+    }
+
+    /// Location to generate C++ header files.
+    pub fn get_include_dir(&self) -> PathBuf {
+        self.get_gen_dir("include")
+    }
+
+    /// Location to generate C++ code.
+    pub fn get_cxx_dir(&self) -> PathBuf {
+        self.get_gen_dir("cxx")
+    }
+
+    /// From a build script, inform cargo how to set environment variables
+    /// to make them available to the procedural macro.
+    pub fn set_cargo_env_vars_for_build(&self) {
+        if let FileLocationStrategy::Custom(_) = self {
+            println!(
+                "cargo:rustc-env={}={}",
+                AUTOCXX_RS,
+                self.get_rs_dir().to_str().unwrap()
+            );
+        }
+    }
+}
+
+impl Default for FileLocationStrategy {
+    fn default() -> Self {
+        Self::new()
+    }
+}
diff --git a/parser/src/lib.rs b/parser/src/lib.rs
new file mode 100644
index 0000000..9e3ba7e
--- /dev/null
+++ b/parser/src/lib.rs
@@ -0,0 +1,83 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![forbid(unsafe_code)]
+
+mod config;
+mod directives;
+pub mod file_locations;
+mod multi_bindings;
+mod path;
+mod subclass_attrs;
+
+pub use config::{
+    AllowlistEntry, ExternCppType, IncludeCppConfig, RustFun, Subclass, UnsafePolicy,
+};
+use file_locations::FileLocationStrategy;
+pub use multi_bindings::{MultiBindings, MultiBindingsErr};
+pub use path::RustPath;
+use proc_macro2::TokenStream as TokenStream2;
+pub use subclass_attrs::SubclassAttrs;
+use syn::Result as ParseResult;
+use syn::{
+    parse::{Parse, ParseStream},
+    Macro,
+};
+
+#[doc(hidden)]
+/// Ensure consistency between the `include_cpp!` parser
+/// and the standalone macro discoverer
+pub mod directive_names {
+    pub static EXTERN_RUST_TYPE: &str = "extern_rust_type";
+    pub static EXTERN_RUST_FUN: &str = "extern_rust_function";
+    pub static SUBCLASS: &str = "subclass";
+}
+
+/// Core of the autocxx engine. See `generate` for most details
+/// on how this works.
+pub struct IncludeCpp {
+    config: IncludeCppConfig,
+}
+
+impl Parse for IncludeCpp {
+    fn parse(input: ParseStream) -> ParseResult<Self> {
+        let config = input.parse::<IncludeCppConfig>()?;
+        Ok(Self { config })
+    }
+}
+
+impl IncludeCpp {
+    pub fn new_from_syn(mac: Macro) -> ParseResult<Self> {
+        mac.parse_body::<IncludeCpp>()
+    }
+
+    /// Generate the Rust bindings.
+    pub fn generate_rs(&self) -> TokenStream2 {
+        if self.config.parse_only {
+            return TokenStream2::new();
+        }
+        FileLocationStrategy::new().make_include(&self.config)
+    }
+
+    pub fn get_config(&self) -> &IncludeCppConfig {
+        &self.config
+    }
+}
+
+#[cfg(test)]
+mod parse_tests {
+    use crate::IncludeCpp;
+    use syn::parse_quote;
+
+    #[test]
+    fn test_basic() {
+        let _i: IncludeCpp = parse_quote! {
+            generate_all!()
+        };
+    }
+}
diff --git a/parser/src/multi_bindings.rs b/parser/src/multi_bindings.rs
new file mode 100644
index 0000000..4ca86d9
--- /dev/null
+++ b/parser/src/multi_bindings.rs
@@ -0,0 +1,93 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::IndexMap;
+use proc_macro2::TokenStream;
+use serde::{Deserialize, Serialize};
+
+use crate::IncludeCppConfig;
+
+/// Struct which stores multiple sets of bindings and can be serialized
+/// to disk. This is used when our build system uses `autocxx_gen`; that
+/// can handle multiple `include_cpp!` macros and therefore generate multiple
+/// sets of Rust bindings. We can't simply `include!` those because there's
+/// no (easy) way to pass their details from the codegen phase across to
+/// the Rust macro phase. Instead, we use this data structure to store
+/// several sets of .rs bindings in a single file, and then the macro
+/// extracts the correct set of bindings at expansion time.
+#[derive(Serialize, Deserialize, Default)]
+pub struct MultiBindings(IndexMap<u64, String>);
+
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum MultiBindingsErr {
+    #[error("unable to find the desired bindings within the archive of Rust bindings produced by the autocxx code generation phase")]
+    MissingBindings,
+    #[error("the stored bindings within the JSON file could not be parsed as valid Rust tokens")]
+    BindingsNotParseable,
+}
+
+impl MultiBindings {
+    /// Insert some generated Rust bindings into this data structure.
+    pub fn insert(&mut self, config: &IncludeCppConfig, bindings: TokenStream) {
+        self.0.insert(config.get_hash(), bindings.to_string());
+    }
+
+    /// Retrieves the bindings corresponding to a given [`IncludeCppConfig`].
+    pub fn get(&self, config: &IncludeCppConfig) -> Result<TokenStream, MultiBindingsErr> {
+        match self.0.get(&(config.get_hash())) {
+            None => Err(MultiBindingsErr::MissingBindings),
+            Some(bindings) => Ok(bindings
+                .parse()
+                .map_err(|_| MultiBindingsErr::BindingsNotParseable)?),
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use proc_macro2::Span;
+    use quote::quote;
+    use syn::parse_quote;
+
+    use crate::IncludeCppConfig;
+
+    use super::MultiBindings;
+
+    #[test]
+    fn test_multi_bindings() {
+        let hexathorpe = syn::token::Pound(Span::call_site());
+        let config1: IncludeCppConfig = parse_quote! {
+            #hexathorpe include "a.h"
+            generate!("Foo")
+        };
+        let config2: IncludeCppConfig = parse_quote! {
+            #hexathorpe include "b.h"
+            generate!("Bar")
+        };
+        let config3: IncludeCppConfig = parse_quote! {
+            #hexathorpe include "c.h"
+            generate!("Bar")
+        };
+        let mut multi_bindings = MultiBindings::default();
+        multi_bindings.insert(&config1, quote! { first; });
+        multi_bindings.insert(&config2, quote! { second; });
+        let json = serde_json::to_string(&multi_bindings).unwrap();
+        let multi_bindings2: MultiBindings = serde_json::from_str(&json).unwrap();
+        assert_eq!(
+            multi_bindings2.get(&config2).unwrap().to_string(),
+            "second ;"
+        );
+        assert_eq!(
+            multi_bindings2.get(&config1).unwrap().to_string(),
+            "first ;"
+        );
+        assert!(multi_bindings2.get(&config3).is_err());
+    }
+}
diff --git a/parser/src/path.rs b/parser/src/path.rs
new file mode 100644
index 0000000..415b2ef
--- /dev/null
+++ b/parser/src/path.rs
@@ -0,0 +1,67 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::ParseResult;
+use proc_macro2::Ident;
+use quote::{quote, ToTokens, TokenStreamExt};
+use syn::parse::{Parse, ParseStream};
+
+/// A little like [`syn::Path`] but simpler - contains only identifiers,
+/// no path arguments. Guaranteed to always have at least one identifier.
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct RustPath(Vec<Ident>);
+
+impl RustPath {
+    pub fn new_from_ident(id: Ident) -> Self {
+        Self(vec![id])
+    }
+
+    #[must_use]
+    pub fn append(&self, id: Ident) -> Self {
+        Self(self.0.iter().cloned().chain(std::iter::once(id)).collect())
+    }
+
+    pub fn get_final_ident(&self) -> &Ident {
+        self.0.last().unwrap()
+    }
+
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+}
+
+impl ToTokens for RustPath {
+    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+        let mut it = self.0.iter();
+        let mut id = it.next();
+        while id.is_some() {
+            id.unwrap().to_tokens(tokens);
+            let next = it.next();
+            if next.is_some() {
+                tokens.append_all(quote! { :: });
+            }
+            id = next;
+        }
+    }
+}
+
+impl Parse for RustPath {
+    fn parse(input: ParseStream) -> ParseResult<Self> {
+        let id: Ident = input.parse()?;
+        let mut p = RustPath::new_from_ident(id);
+        while input.parse::<Option<syn::token::Colon2>>()?.is_some() {
+            let id: Ident = input.parse()?;
+            p = p.append(id);
+        }
+        Ok(p)
+    }
+}
diff --git a/parser/src/subclass_attrs.rs b/parser/src/subclass_attrs.rs
new file mode 100644
index 0000000..9174bec
--- /dev/null
+++ b/parser/src/subclass_attrs.rs
@@ -0,0 +1,58 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use proc_macro2::Ident;
+use quote::ToTokens;
+use syn::Result as ParseResult;
+use syn::{
+    parse::{Parse, ParseStream},
+    token::Comma,
+};
+
+#[derive(Default)]
+pub struct SubclassAttrs {
+    pub self_owned: bool,
+    pub superclass: Option<String>,
+}
+
+impl Parse for SubclassAttrs {
+    fn parse(input: ParseStream) -> ParseResult<Self> {
+        let mut me = Self::default();
+        let mut id = input.parse::<Option<Ident>>()?;
+        while id.is_some() {
+            match id {
+                Some(id) if id == "self_owned" => me.self_owned = true,
+                Some(id) if id == "superclass" => {
+                    let args;
+                    syn::parenthesized!(args in input);
+                    let superclass: syn::LitStr = args.parse()?;
+                    if me.superclass.is_some() {
+                        return Err(syn::Error::new_spanned(
+                            id.into_token_stream(),
+                            "Expected single superclass specification",
+                        ));
+                    }
+                    me.superclass = Some(superclass.value());
+                }
+                Some(id) => {
+                    return Err(syn::Error::new_spanned(
+                        id.into_token_stream(),
+                        "Expected self_owned or superclass",
+                    ))
+                }
+                None => {}
+            };
+            let comma = input.parse::<Option<Comma>>()?;
+            if comma.is_none() {
+                break;
+            }
+            id = input.parse::<Option<Ident>>()?;
+        }
+        Ok(me)
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..6592011
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,638 @@
+#![doc = include_str!("../README.md")]
+
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// The crazy macro_rules magic in this file is thanks to dtolnay@
+// and is a way of attaching rustdoc to each of the possible directives
+// within the include_cpp outer macro. None of the directives actually
+// do anything - all the magic is handled entirely by
+// autocxx_macro::include_cpp_impl.
+
+mod rvalue_param;
+pub mod subclass;
+mod value_param;
+
+#[cfg_attr(doc, aquamarine::aquamarine)]
+/// Include some C++ headers in your Rust project.
+///
+/// This macro allows you to include one or more C++ headers within
+/// your Rust code, and call their functions fairly naturally.
+///
+/// # Examples
+///
+/// C++ header (`input.h`):
+/// ```cpp
+/// #include <cstdint>
+///
+/// uint32_t do_math(uint32_t a);
+/// ```
+///
+/// Rust code:
+/// ```
+/// # use autocxx_macro::include_cpp_impl as include_cpp;
+/// include_cpp!(
+/// #   parse_only!()
+///     #include "input.h"
+///     generate!("do_math")
+///     safety!(unsafe)
+/// );
+///
+/// # mod ffi { pub fn do_math(a: u32) -> u32 { a+3 } }
+/// # fn main() {
+/// ffi::do_math(3);
+/// # }
+/// ```
+///
+/// The resulting bindings will use idiomatic Rust wrappers for types from the [cxx]
+/// crate, for example [`cxx::UniquePtr`] or [`cxx::CxxString`]. Due to the care and thought
+/// that's gone into the [cxx] crate, such bindings are pleasant and idiomatic to use
+/// from Rust, and usually don't require the `unsafe` keyword.
+///
+/// For full documentation, see [the manual](https://google.github.io/autocxx/).
+///
+/// # The [`include_cpp`] macro
+///
+/// Within the braces of the `include_cpp!{...}` macro, you should provide
+/// a list of at least the following:
+///
+/// * `#include "cpp_header.h"`: a header filename to parse and include
+/// * `generate!("type_or_function_name")`: a type or function name whose declaration
+///   should be made available to C++. (See the section on Allowlisting, below).
+/// * Optionally, `safety!(unsafe)` - see discussion of [`safety`].
+///
+/// Other directives are possible as documented in this crate.
+///
+/// Now, try to build your Rust project. `autocxx` may fail to generate bindings
+/// for some of the items you specified with [generate] directives: remove
+/// those directives for now, then see the next section for advice.
+///
+/// # Allowlisting
+///
+/// How do you inform autocxx which bindings to generate? There are three
+/// strategies:
+///
+/// * *Recommended*: provide various [`generate`] directives in the
+///   [`include_cpp`] macro. This can specify functions or types.
+/// * *Not recommended*: in your `build.rs`, call [`Builder::auto_allowlist`].
+///   This will attempt to spot _uses_ of FFI bindings anywhere in your Rust code
+///   and build the allowlist that way. This is experimental and has known limitations.
+/// * *Strongly not recommended*: use [`generate_all`]. This will attempt to
+///   generate Rust bindings for _any_ C++ type or function discovered in the
+///   header files. This is generally a disaster if you're including any
+///   remotely complex header file: we'll try to generate bindings for all sorts
+///   of STL types. This will be slow, and some may well cause problems.
+///   Effectively this is just a debug option to discover such problems. Don't
+///   use it!
+///
+/// # Internals
+///
+/// For documentation on how this all actually _works_, see
+/// `IncludeCppEngine` within the `autocxx_engine` crate.
+#[macro_export]
+macro_rules! include_cpp {
+    (
+        $(#$include:ident $lit:literal)*
+        $($mac:ident!($($arg:tt)*))*
+    ) => {
+        $($crate::$include!{__docs})*
+        $($crate::$mac!{__docs})*
+        $crate::include_cpp_impl! {
+            $(#include $lit)*
+            $($mac!($($arg)*))*
+        }
+    };
+}
+
+/// Include a C++ header. A directive to be included inside
+/// [include_cpp] - see [include_cpp] for details
+#[macro_export]
+macro_rules! include {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate Rust bindings for the given C++ type or function.
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+/// See also [generate_pod].
+#[macro_export]
+macro_rules! generate {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate as "plain old data" and add to allowlist.
+/// Generate Rust bindings for the given C++ type such that
+/// it can be passed and owned by value in Rust. This only works
+/// for C++ types which have trivial move constructors and no
+/// destructor - you'll encounter a compile error otherwise.
+/// If your type doesn't match that description, use [generate]
+/// instead, and own the type using [UniquePtr][cxx::UniquePtr].
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! generate_pod {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate Rust bindings for all C++ types and functions
+/// in a given namespace.
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+/// See also [generate].
+#[macro_export]
+macro_rules! generate_ns {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate Rust bindings for all C++ types and functions
+/// found. Highly experimental and not recommended.
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+/// See also [generate].
+#[macro_export]
+macro_rules! generate_all {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate as "plain old data". For use with [generate_all]
+/// and similarly experimental.
+#[macro_export]
+macro_rules! pod {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Skip the normal generation of a `make_string` function
+/// and other utilities which we might generate normally.
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! exclude_utilities {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Entirely block some type from appearing in the generated
+/// code. This can be useful if there is a type which is not
+/// understood by bindgen or autocxx, and incorrect code is
+/// otherwise generated.
+/// This is 'greedy' in the sense that any functions/methods
+/// which take or return such a type will _also_ be blocked.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! block {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Avoid generating implicit constructors for this type.
+/// The rules for when to generate C++ implicit constructors
+/// are complex, and if autocxx gets it wrong, you can block
+/// such constructors using this.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! block_constructors {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// The name of the mod to be generated with the FFI code.
+/// The default is `ffi`.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! name {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// A concrete type to make, for example
+/// `concrete!("Container<Contents>")`.
+/// All types msut already be on the allowlist by having used
+/// `generate!` or similar.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! concrete {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Specifies a global safety policy for functions generated
+/// from these headers. By default (without such a `safety!`
+/// directive) all such functions are marked as `unsafe` and
+/// therefore can only be called within an `unsafe {}` block
+/// or some `unsafe` function which you create.
+///
+/// Alternatively, by specifying a `safety!` block you can
+/// declare that most generated functions are in fact safe.
+/// Specifically, you'd specify:
+/// `safety!(unsafe)`
+/// or
+/// `safety!(unsafe_ffi)`
+/// These two options are functionally identical. If you're
+/// unsure, simply use `unsafe`. The reason for the
+/// latter option is if you have code review policies which
+/// might want to give a different level of scrutiny to
+/// C++ interop as opposed to other types of unsafe Rust code.
+/// Maybe in your organization, C++ interop is less scary than
+/// a low-level Rust data structure using pointer manipulation.
+/// Or maybe it's more scary. Either way, using `unsafe` for
+/// the data structure and using `unsafe_ffi` for the C++
+/// interop allows you to apply different linting tools and
+/// policies to the different options.
+///
+/// Irrespective, C++ code is of course unsafe. It's worth
+/// noting that use of C++ can cause unexpected unsafety at
+/// a distance in faraway Rust code. As with any use of the
+/// `unsafe` keyword in Rust, *you the human* are declaring
+/// that you've analyzed all possible ways that the code
+/// can be used and you are guaranteeing to the compiler that
+/// no badness can occur. Good luck.
+///
+/// Generated C++ APIs which use raw pointers remain `unsafe`
+/// no matter what policy you choose.
+#[macro_export]
+macro_rules! safety {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Whether to avoid generating [`cxx::UniquePtr`] and [`cxx::Vector`]
+/// implementations. This is primarily useful for reducing test cases and
+/// shouldn't be used in normal operation.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! exclude_impls {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Indicates that a C++ type is not to be generated by autocxx in this case,
+/// but instead should refer to some pre-existing Rust type.
+/// Note that the size and alignment of this type *must* be correct.
+/// If you wish for the type to be POD, you can use a `pod!` directive too.
+///
+/// The syntax is:
+/// `extern_cpp_type!("CppNameGoesHere", path::to::rust::type)`
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! extern_cpp_type {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Indicates that a C++ type is not to be generated by autocxx in this case,
+/// but instead should refer to some pre-existing Rust type. Unlike
+/// `extern_cpp_type!`, there's no need for the size and alignment of this
+/// type to be correct.
+///
+/// The syntax is:
+/// `extern_cpp_opaque_type!("CppNameGoesHere", path::to::rust::type)`
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! extern_cpp_opaque_type {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Deprecated - use [`extern_rust_type`] instead.
+#[macro_export]
+#[deprecated]
+macro_rules! rust_type {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// See [`extern_rust::extern_rust_type`].
+#[macro_export]
+macro_rules! extern_rust_type {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// See [`subclass::subclass`].
+#[macro_export]
+macro_rules! subclass {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Indicates that a C++ type can definitely be instantiated. This has effect
+/// only in a very specific case:
+/// * the type is a typedef to something else
+/// * the 'something else' can't be fully inspected by autocxx, possibly
+///   becaue it relies on dependent qualified types or some other template
+///   arrangement that bindgen cannot fully understand.
+/// In such circumstances, autocxx normally has to err on the side of caution
+/// and assume that some type within the 'something else' is itself a forward
+/// declaration. That means, the opaque typedef won't be storable within
+/// a [`cxx::UniquePtr`]. If you know that no forward declarations are involved,
+/// you can declare the typedef type is instantiable and then you'll be able to
+/// own it within Rust.
+///
+/// The syntax is:
+/// `instantiable!("CppNameGoesHere")`
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! instantiable {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! usage {
+    (__docs) => {};
+    ($($tt:tt)*) => {
+        compile_error! {r#"usage:  include_cpp! {
+                   #include "path/to/header.h"
+                   generate!(...)
+                   generate_pod!(...)
+               }
+"#}
+    };
+}
+
+use std::pin::Pin;
+
+#[doc(hidden)]
+pub use autocxx_macro::include_cpp_impl;
+
+#[doc(hidden)]
+pub use autocxx_macro::cpp_semantics;
+
+macro_rules! ctype_wrapper {
+    ($r:ident, $c:expr, $d:expr) => {
+        #[doc=$d]
+        #[derive(Debug, Eq, Copy, Clone, PartialEq, Hash)]
+        #[allow(non_camel_case_types)]
+        #[repr(transparent)]
+        pub struct $r(pub ::std::os::raw::$r);
+
+        /// # Safety
+        ///
+        /// We assert that the namespace and type ID refer to a C++
+        /// type which is equivalent to this Rust type.
+        unsafe impl cxx::ExternType for $r {
+            type Id = cxx::type_id!($c);
+            type Kind = cxx::kind::Trivial;
+        }
+
+        impl From<::std::os::raw::$r> for $r {
+            fn from(val: ::std::os::raw::$r) -> Self {
+                Self(val)
+            }
+        }
+
+        impl From<$r> for ::std::os::raw::$r {
+            fn from(val: $r) -> Self {
+                val.0
+            }
+        }
+    };
+}
+
+ctype_wrapper!(
+    c_ulonglong,
+    "c_ulonglong",
+    "Newtype wrapper for an unsigned long long"
+);
+ctype_wrapper!(c_longlong, "c_longlong", "Newtype wrapper for a long long");
+ctype_wrapper!(c_ulong, "c_ulong", "Newtype wrapper for an unsigned long");
+ctype_wrapper!(c_long, "c_long", "Newtype wrapper for a long");
+ctype_wrapper!(
+    c_ushort,
+    "c_ushort",
+    "Newtype wrapper for an unsigned short"
+);
+ctype_wrapper!(c_short, "c_short", "Newtype wrapper for an short");
+ctype_wrapper!(c_uint, "c_uint", "Newtype wrapper for an unsigned int");
+ctype_wrapper!(c_int, "c_int", "Newtype wrapper for an int");
+ctype_wrapper!(c_uchar, "c_uchar", "Newtype wrapper for an unsigned char");
+
+/// Newtype wrapper for a C void. Only useful as a `*c_void`
+#[allow(non_camel_case_types)]
+#[repr(transparent)]
+pub struct c_void(pub ::std::os::raw::c_void);
+
+/// # Safety
+///
+/// We assert that the namespace and type ID refer to a C++
+/// type which is equivalent to this Rust type.
+unsafe impl cxx::ExternType for c_void {
+    type Id = cxx::type_id!(c_void);
+    type Kind = cxx::kind::Trivial;
+}
+
+/// A C++ `char16_t`
+#[allow(non_camel_case_types)]
+#[repr(transparent)]
+pub struct c_char16_t(pub u16);
+
+/// # Safety
+///
+/// We assert that the namespace and type ID refer to a C++
+/// type which is equivalent to this Rust type.
+unsafe impl cxx::ExternType for c_char16_t {
+    type Id = cxx::type_id!(c_char16_t);
+    type Kind = cxx::kind::Trivial;
+}
+
+/// autocxx couldn't generate these bindings.
+/// If you come across a method, type or function which refers to this type,
+/// it indicates that autocxx couldn't generate that binding. A documentation
+/// comment should be attached indicating the reason.
+pub struct BindingGenerationFailure {
+    _unallocatable: [*const u8; 0],
+    _pinned: core::marker::PhantomData<core::marker::PhantomPinned>,
+}
+
+/// Tools to export Rust code to C++.
+// These are in a mod to avoid shadowing the definitions of the
+// directives above, which, being macro_rules, are unavoidably
+// in the crate root but must be function-style macros to keep
+// the include_cpp impl happy.
+pub mod extern_rust {
+
+    /// Declare that this is a Rust type which is to be exported to C++.
+    /// You can use this in two ways:
+    /// * as an attribute macro on a Rust type, for instance:
+    ///   ```
+    ///   # use autocxx_macro::extern_rust_type as extern_rust_type;
+    ///   #[extern_rust_type]
+    ///   struct Bar;
+    ///   ```
+    /// * as a directive within the [include_cpp] macro, in which case
+    ///   provide the type path in brackets:
+    ///   ```
+    ///   # use autocxx_macro::include_cpp_impl as include_cpp;
+    ///   include_cpp!(
+    ///   #   parse_only!()
+    ///       #include "input.h"
+    ///       extern_rust_type!(Bar)
+    ///       safety!(unsafe)
+    ///   );
+    ///   struct Bar;
+    ///   ```
+    /// These may be used within references in the signatures of C++ functions,
+    /// for instance. This will contribute to an `extern "Rust"` section of the
+    /// generated `cxx` bindings, and this type will appear in the C++ header
+    /// generated for use in C++.
+    pub use autocxx_macro::extern_rust_type;
+
+    /// Declare that a given function is a Rust function which is to be exported
+    /// to C++. This is used as an attribute macro on a Rust function, for instance:
+    /// ```
+    /// # use autocxx_macro::extern_rust_function as extern_rust_function;
+    /// #[extern_rust_function]
+    /// pub fn call_me_from_cpp() { }
+    /// ```
+    pub use autocxx_macro::extern_rust_function;
+}
+
+/// Equivalent to [`std::convert::AsMut`], but returns a pinned mutable reference
+/// such that cxx methods can be called on it.
+pub trait PinMut<T>: AsRef<T> {
+    /// Return a pinned mutable reference to a type.
+    fn pin_mut(&mut self) -> std::pin::Pin<&mut T>;
+}
+
+/// Provides utility functions to emplace any [`moveit::New`] into a
+/// [`cxx::UniquePtr`]. Automatically imported by the autocxx prelude
+/// and implemented by any (autocxx-related) [`moveit::New`].
+pub trait WithinUniquePtr {
+    type Inner: UniquePtrTarget + MakeCppStorage;
+    fn within_unique_ptr(self) -> cxx::UniquePtr<Self::Inner>;
+}
+
+/// Provides utility functions to emplace any [`moveit::New`] into a
+/// [`Box`]. Automatically imported by the autocxx prelude
+/// and implemented by any (autocxx-related) [`moveit::New`].
+pub trait WithinBox {
+    type Inner;
+    fn within_box(self) -> Pin<Box<Self::Inner>>;
+}
+
+use cxx::kind::Trivial;
+use cxx::ExternType;
+use moveit::MakeCppStorage;
+use moveit::{Emplace, EmplaceUnpinned};
+
+impl<N, T> WithinUniquePtr for N
+where
+    N: New<Output = T>,
+    T: UniquePtrTarget + MakeCppStorage,
+{
+    type Inner = T;
+    fn within_unique_ptr(self) -> cxx::UniquePtr<T> {
+        UniquePtr::emplace(self)
+    }
+}
+
+impl<N, T> WithinBox for N
+where
+    N: New<Output = T>,
+{
+    type Inner = T;
+    fn within_box(self) -> Pin<Box<T>> {
+        Box::emplace(self)
+    }
+}
+
+/// Emulates the [`WithinUniquePtr`] trait, but for trivial (plain old data) types.
+/// This allows such types to behave identically if a type is changed from
+/// `generate!` to `generate_pod!`.
+///
+/// (Ideally, this would be the exact same trait as [`WithinUniquePtr`] but this runs
+/// the risk of conflicting implementations. Negative trait bounds would solve
+/// this!)
+pub trait WithinUniquePtrTrivial: UniquePtrTarget + Sized + Unpin {
+    fn within_unique_ptr(self) -> cxx::UniquePtr<Self>;
+}
+
+impl<T> WithinUniquePtrTrivial for T
+where
+    T: UniquePtrTarget + ExternType<Kind = Trivial> + Sized + Unpin,
+{
+    fn within_unique_ptr(self) -> cxx::UniquePtr<T> {
+        UniquePtr::new(self)
+    }
+}
+
+/// Emulates the [`WithinBox`] trait, but for trivial (plain old data) types.
+/// This allows such types to behave identically if a type is changed from
+/// `generate!` to `generate_pod!`.
+///
+/// (Ideally, this would be the exact same trait as [`WithinBox`] but this runs
+/// the risk of conflicting implementations. Negative trait bounds would solve
+/// this!)
+pub trait WithinBoxTrivial: Sized + Unpin {
+    fn within_box(self) -> Pin<Box<Self>>;
+}
+
+impl<T> WithinBoxTrivial for T
+where
+    T: ExternType<Kind = Trivial> + Sized + Unpin,
+{
+    fn within_box(self) -> Pin<Box<T>> {
+        Pin::new(Box::new(self))
+    }
+}
+
+use cxx::memory::UniquePtrTarget;
+use cxx::UniquePtr;
+use moveit::New;
+pub use rvalue_param::RValueParam;
+pub use rvalue_param::RValueParamHandler;
+pub use value_param::as_copy;
+pub use value_param::as_mov;
+pub use value_param::as_new;
+pub use value_param::ValueParam;
+pub use value_param::ValueParamHandler;
+
+/// Imports which you're likely to want to use.
+pub mod prelude {
+    pub use crate::as_copy;
+    pub use crate::as_mov;
+    pub use crate::as_new;
+    pub use crate::c_int;
+    pub use crate::c_long;
+    pub use crate::c_longlong;
+    pub use crate::c_short;
+    pub use crate::c_uchar;
+    pub use crate::c_uint;
+    pub use crate::c_ulong;
+    pub use crate::c_ulonglong;
+    pub use crate::c_ushort;
+    pub use crate::c_void;
+    pub use crate::cpp_semantics;
+    pub use crate::include_cpp;
+    pub use crate::PinMut;
+    pub use crate::RValueParam;
+    pub use crate::ValueParam;
+    pub use crate::WithinBox;
+    pub use crate::WithinBoxTrivial;
+    pub use crate::WithinUniquePtr;
+    pub use crate::WithinUniquePtrTrivial;
+    pub use cxx::UniquePtr;
+    pub use moveit::moveit;
+    pub use moveit::new::New;
+    pub use moveit::Emplace;
+    pub use moveit::EmplaceUnpinned;
+}
+
+/// Re-export moveit for ease of consumers.
+pub use moveit;
+
+/// Re-export cxx such that clients can use the same version as
+/// us. This doesn't enable clients to avoid depending on the cxx
+/// crate too, unfortunately, since generated cxx::bridge code
+/// refers explicitly to ::cxx. See
+/// <https://github.com/google/autocxx/issues/36>
+pub use cxx;
diff --git a/src/rvalue_param.rs b/src/rvalue_param.rs
new file mode 100644
index 0000000..4acc52e
--- /dev/null
+++ b/src/rvalue_param.rs
@@ -0,0 +1,131 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! It would be highly desirable to share a lot of this code with `value_param.rs`
+//! but this proves to be surprisingly fiddly.
+
+use cxx::{memory::UniquePtrTarget, UniquePtr};
+use moveit::MoveRef;
+use std::{
+    marker::{PhantomData, PhantomPinned},
+    pin::Pin,
+};
+
+/// A trait representing a parameter to a C++ function which is received
+/// by rvalue (i.e. by move).
+///
+/// # Panics
+///
+/// The implementations of this trait which take a [`cxx::UniquePtr`] will
+/// panic if the pointer is NULL.
+///
+/// # Safety
+///
+/// Implementers must guarantee that the pointer returned by `get_ptr`
+/// is of the correct size and alignment of `T`.
+pub unsafe trait RValueParam<T>: Sized {
+    /// Retrieve the pointer to the underlying item, to be passed to C++.
+    /// Note that on the C++ side this is currently passed to `std::move`
+    /// and therefore may be mutated.
+    #[doc(hidden)]
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T;
+}
+
+unsafe impl<T> RValueParam<T> for UniquePtr<T>
+where
+    T: UniquePtrTarget,
+{
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked(
+                (*Pin::into_inner_unchecked(stack))
+                    .as_mut()
+                    .expect("Passed a NULL UniquePtr as a C++ rvalue parameter"),
+            )) as *mut T
+        }
+    }
+}
+
+unsafe impl<T> RValueParam<T> for Pin<Box<T>> {
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked((*Pin::into_inner_unchecked(stack)).as_mut())) as *mut T
+        }
+    }
+}
+
+unsafe impl<'a, T> RValueParam<T> for Pin<MoveRef<'a, T>> {
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked((*Pin::into_inner_unchecked(stack)).as_mut())) as *mut T
+        }
+    }
+}
+
+/// Implementation detail for how we pass rvalue parameters into C++.
+/// This type is instantiated by auto-generated autocxx code each time we
+/// need to pass a value parameter into C++, and will take responsibility
+/// for extracting that value parameter from the [`RValueParam`] and doing
+/// any later cleanup.
+#[doc(hidden)]
+pub struct RValueParamHandler<T, RVP>
+where
+    RVP: RValueParam<T>,
+{
+    // We can't populate this on 'new' because the object may move.
+    // Hence this is an Option - it's None until populate is called.
+    space: Option<RVP>,
+    _pinned: PhantomPinned,
+    _data: PhantomData<T>,
+}
+
+impl<T, RVP: RValueParam<T>> RValueParamHandler<T, RVP> {
+    /// Populate this stack space if needs be. Note safety guarantees
+    /// on [`get_ptr`].
+    ///
+    /// # Safety
+    ///
+    /// Callers must guarantee that this type will not move
+    /// in memory between calls to [`populate`] and [`get_ptr`].
+    /// Callers must call [`populate`] exactly once prior to calling [`get_ptr`].
+    pub unsafe fn populate(self: Pin<&mut Self>, param: RVP) {
+        // Structural pinning, as documented in [`std::pin`].
+        // Safety: we will not move the contents of the pin.
+        *Pin::into_inner_unchecked(self.map_unchecked_mut(|s| &mut s.space)) = Some(param)
+    }
+
+    /// Return a pointer to the underlying value which can be passed to C++.
+    /// Per the unsafety contract of [`populate`], the object must not have moved
+    /// since it was created, and [`populate`] has been called exactly once
+    /// prior to this call.
+    pub fn get_ptr(self: Pin<&mut Self>) -> *mut T {
+        // Structural pinning, as documented in [`std::pin`]. `map_unchecked_mut` doesn't play
+        // nicely with `unwrap`, so we have to do it manually.
+        unsafe {
+            RVP::get_ptr(Pin::new_unchecked(
+                self.get_unchecked_mut().space.as_mut().unwrap(),
+            ))
+        }
+    }
+}
+
+impl<T, VP: RValueParam<T>> Default for RValueParamHandler<T, VP> {
+    fn default() -> Self {
+        Self {
+            space: None,
+            _pinned: PhantomPinned,
+            _data: PhantomData,
+        }
+    }
+}
diff --git a/src/subclass.rs b/src/subclass.rs
new file mode 100644
index 0000000..d2827ca
--- /dev/null
+++ b/src/subclass.rs
@@ -0,0 +1,397 @@
+//! Module to make Rust subclasses of C++ classes. See [`CppSubclass`]
+//! for details.
+
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{
+    cell::RefCell,
+    pin::Pin,
+    rc::{Rc, Weak},
+};
+
+use cxx::{memory::UniquePtrTarget, UniquePtr};
+
+/// Deprecated - use [`subclass`] instead.
+#[deprecated]
+pub use autocxx_macro::subclass as is_subclass;
+
+/// Declare a Rust subclass of a C++ class.
+/// You can use this in two ways:
+/// * As an attribute macro on a struct which is to be a subclass.
+///   In this case, you must specify the superclass as described below.
+///   For instance,
+///   ```nocompile
+///   # use autocxx_macro::subclass as subclass;
+///   #[subclass(superclass("MyCppSuperclass"))]
+///   struct Bar {};
+///   ```
+/// * as a directive within the [include_cpp] macro, in which case you
+///   must provide two arguments of the superclass and then the
+///   subclass:
+///   ```
+///   # use autocxx_macro::include_cpp_impl as include_cpp;
+///   include_cpp!(
+///   #   parse_only!()
+///       #include "input.h"
+///       subclass!("MyCppSuperclass",Bar)
+///       safety!(unsafe)
+///   );
+///   struct Bar {
+///     // ...
+///   }
+///   ```
+///   In this latter case, you'll need to implement the trait
+///   [`CppSubclass`] for the struct, so it's
+///   generally easier to use the former option.
+///
+/// See [`CppSubclass`] for information about the
+/// multiple steps you need to take to be able to make Rust
+/// subclasses of a C++ class.
+pub use autocxx_macro::subclass;
+
+/// A prelude containing all the traits and macros required to create
+/// Rust subclasses of C++ classes. It's recommended that you:
+///
+/// ```rust
+/// use autocxx::subclass::prelude::*;
+/// ```
+pub mod prelude {
+    pub use super::{
+        is_subclass, subclass, CppPeerConstructor, CppSubclass, CppSubclassDefault,
+        CppSubclassRustPeerHolder, CppSubclassSelfOwned, CppSubclassSelfOwnedDefault,
+    };
+}
+
+/// A trait representing the C++ side of a Rust/C++ subclass pair.
+#[doc(hidden)]
+pub trait CppSubclassCppPeer: UniquePtrTarget {
+    fn relinquish_ownership(&self);
+}
+
+/// A type used for how the C++ side of a Rust/C++ subclass pair refers to
+/// the Rust side.
+#[doc(hidden)]
+pub enum CppSubclassRustPeerHolder<T> {
+    Owned(Rc<RefCell<T>>),
+    Unowned(Weak<RefCell<T>>),
+}
+
+impl<T> CppSubclassRustPeerHolder<T> {
+    pub fn get(&self) -> Option<Rc<RefCell<T>>> {
+        match self {
+            CppSubclassRustPeerHolder::Owned(strong) => Some(strong.clone()),
+            CppSubclassRustPeerHolder::Unowned(weak) => weak.upgrade(),
+        }
+    }
+    pub fn relinquish_ownership(self) -> Self {
+        match self {
+            CppSubclassRustPeerHolder::Owned(strong) => {
+                CppSubclassRustPeerHolder::Unowned(Rc::downgrade(&strong))
+            }
+            _ => self,
+        }
+    }
+}
+
+/// A type showing how the Rust side of a Rust/C++ subclass pair refers to
+/// the C++ side.
+#[doc(hidden)]
+pub enum CppSubclassCppPeerHolder<CppPeer: CppSubclassCppPeer> {
+    Empty,
+    Owned(Box<UniquePtr<CppPeer>>),
+    Unowned(*mut CppPeer),
+}
+
+impl<CppPeer: CppSubclassCppPeer> Default for CppSubclassCppPeerHolder<CppPeer> {
+    fn default() -> Self {
+        CppSubclassCppPeerHolder::Empty
+    }
+}
+
+impl<CppPeer: CppSubclassCppPeer> CppSubclassCppPeerHolder<CppPeer> {
+    fn pin_mut(&mut self) -> Pin<&mut CppPeer> {
+        match self {
+            CppSubclassCppPeerHolder::Empty => panic!("Peer not set up"),
+            CppSubclassCppPeerHolder::Owned(peer) => peer.pin_mut(),
+            CppSubclassCppPeerHolder::Unowned(peer) => unsafe {
+                // Safety: guaranteed safe because this is a pointer to a C++ object,
+                // and C++ never moves things in memory.
+                Pin::new_unchecked(peer.as_mut().unwrap())
+            },
+        }
+    }
+    fn get(&self) -> &CppPeer {
+        match self {
+            CppSubclassCppPeerHolder::Empty => panic!("Peer not set up"),
+            CppSubclassCppPeerHolder::Owned(peer) => peer.as_ref(),
+            // Safety: guaranteed safe because this is a pointer to a C++ object,
+            // and C++ never moves things in memory.
+            CppSubclassCppPeerHolder::Unowned(peer) => unsafe { peer.as_ref().unwrap() },
+        }
+    }
+    fn set_owned(&mut self, peer: UniquePtr<CppPeer>) {
+        *self = Self::Owned(Box::new(peer));
+    }
+    fn set_unowned(&mut self, peer: &mut UniquePtr<CppPeer>) {
+        // Safety: guaranteed safe because this is a pointer to a C++ object,
+        // and C++ never moves things in memory.
+        *self = Self::Unowned(unsafe {
+            std::pin::Pin::<&mut CppPeer>::into_inner_unchecked(peer.pin_mut())
+        });
+    }
+}
+
+fn make_owning_peer<CppPeer, PeerConstructor, Subclass, PeerBoxer>(
+    me: Subclass,
+    peer_constructor: PeerConstructor,
+    peer_boxer: PeerBoxer,
+) -> Rc<RefCell<Subclass>>
+where
+    CppPeer: CppSubclassCppPeer,
+    Subclass: CppSubclass<CppPeer>,
+    PeerConstructor:
+        FnOnce(&mut Subclass, CppSubclassRustPeerHolder<Subclass>) -> UniquePtr<CppPeer>,
+    PeerBoxer: FnOnce(Rc<RefCell<Subclass>>) -> CppSubclassRustPeerHolder<Subclass>,
+{
+    let me = Rc::new(RefCell::new(me));
+    let holder = peer_boxer(me.clone());
+    let cpp_side = peer_constructor(&mut me.as_ref().borrow_mut(), holder);
+    me.as_ref()
+        .borrow_mut()
+        .peer_holder_mut()
+        .set_owned(cpp_side);
+    me
+}
+
+/// A trait to be implemented by a subclass which knows how to construct
+/// its C++ peer object. Specifically, the implementation here will
+/// arrange to call one or other of the `make_unique` methods to be
+/// found on the superclass of the C++ object. If the superclass
+/// has a single trivial constructor, then this is implemented
+/// automatically for you. If there are multiple constructors, or
+/// a single constructor which takes parameters, you'll need to implement
+/// this trait for your subclass in order to call the correct
+/// constructor.
+pub trait CppPeerConstructor<CppPeer: CppSubclassCppPeer>: Sized {
+    /// Create the C++ peer. This method will be automatically generated
+    /// for you *except* in cases where the superclass has multiple constructors,
+    /// or its only constructor takes parameters. In such a case you'll need
+    /// to implement this by calling a `make_unique` method on the
+    /// `<my subclass name>Cpp` type, passing `peer_holder` as the first
+    /// argument.
+    fn make_peer(&mut self, peer_holder: CppSubclassRustPeerHolder<Self>) -> UniquePtr<CppPeer>;
+}
+
+/// A subclass of a C++ type.
+///
+/// To create a Rust subclass of a C++ class, you must do these things:
+/// * Create a `struct` to act as your subclass, and add the #[`macro@crate::subclass`] attribute.
+///   This adds a field to your struct for autocxx record-keeping. You can
+///   instead choose to implement [`CppSubclass`] a different way, in which case
+///   you must provide the [`macro@crate::subclass`] inside your [`crate::include_cpp`]
+///   macro. (`autocxx` will do the required codegen for your subclass
+///   whether it discovers a [`macro@crate::subclass`] directive inside your
+///   [`crate::include_cpp`], or elsewhere used as an attribute macro,
+///   or both.)
+/// * Use the [`CppSubclass`] trait, and instantiate the subclass using
+///   [`CppSubclass::new_rust_owned`] or [`CppSubclass::new_cpp_owned`]
+///   constructors. (You can use [`CppSubclassSelfOwned`] if you need that
+///   instead; also, see [`CppSubclassSelfOwnedDefault`] and [`CppSubclassDefault`]
+///   to arrange for easier constructors to exist.
+/// * You _may_ need to implement [`CppPeerConstructor`] for your subclass,
+///   but only if autocxx determines that there are multiple possible superclass
+///   constructors so you need to call one explicitly (or if there's a single
+///   non-trivial superclass constructor.) autocxx will implemente this trait
+///   for you if there's no ambiguity.
+///
+/// # How to access your Rust structure from outside
+///
+/// Use [`CppSubclass::new_rust_owned`] then use [`std::cell::RefCell::borrow`]
+/// or [`std::cell::RefCell::borrow_mut`] to obtain the underlying Rust struct.
+///
+/// # How to call C++ methods on the subclass
+///
+/// Do the same. You should find that your subclass struct `impl`s all the
+/// C++ methods belonging to the superclass.
+///
+/// # How to implement virtual methods
+///
+/// Simply add an `impl` for the `struct`, implementing the relevant method.
+/// The C++ virtual function call will be redirected to your Rust implementation.
+///
+/// # How _not_ to implement virtual methods
+///
+/// If you don't want to implement a virtual method, don't: the superclass
+/// method will be called instead. Naturally, you must implement any pure virtual
+/// methods.
+///
+/// # How it works
+///
+/// This actually consists of two objects: this object itself and a C++-side
+/// peer. The ownership relationship between those two things can work in three
+/// different ways:
+/// 1. Neither object is owned by Rust. The C++ peer is owned by a C++
+///    [`UniquePtr`] held elsewhere in C++. That C++ peer then owns
+///    this Rust-side object via a strong [`Rc`] reference. This is the
+///    ownership relationship set up by [`CppSubclass::new_cpp_owned`].
+/// 2. The object pair is owned by Rust. Specifically, by a strong
+///    [`Rc`] reference to this Rust-side object. In turn, the Rust-side object
+///    owns the C++-side peer via a [`UniquePtr`]. This is what's set up by
+///    [`CppSubclass::new_rust_owned`]. The C++-side peer _does not_ own the Rust
+///    object; it just has a weak pointer. (Otherwise we'd get a reference
+///    loop and nothing would ever be freed.)
+/// 3. The object pair is self-owned and will stay around forever until
+///    [`CppSubclassSelfOwned::delete_self`] is called. In this case there's a strong reference
+///    from the C++ to the Rust and from the Rust to the C++. This is useful
+///    for cases where the subclass is listening for events, and needs to
+///    stick around until a particular event occurs then delete itself.
+///
+/// # Limitations
+///
+/// * *Re-entrancy*. The main thing to look out for is re-entrancy. If a
+///   (non-const) virtual method is called on your type, which then causes you
+///   to call back into C++, which results in a _second_ call into a (non-const)
+///   virtual method, we will try to create two mutable references to your
+///   subclass which isn't allowed in Rust and will therefore panic.
+///
+///   A future version of autocxx may provide the option of treating all
+///   non-const methods (in C++) as const methods on the Rust side, which will
+///   give the option of using interior mutability ([`std::cell::RefCell`])
+///   for you to safely handle this situation, whilst remaining compatible
+///   with existing C++ interfaces. If you need this, indicate support on
+///   [this issue](https://github.com/google/autocxx/issues/622).
+///
+/// * *Thread safety*. The subclass object is not thread-safe and shouldn't
+///   be passed to different threads in C++. A future version of this code
+///   will give the option to use `Arc` and `Mutex` internally rather than
+///   `Rc` and `RefCell`, solving this problem.
+///
+/// * *Protected methods.* We don't do anything clever here - they're public.
+///
+/// * *Non-trivial class hierarchies*. We don't yet consider virtual methods
+///   on base classes of base classes. This is a temporary limitation,
+///   [see this issue](https://github.com/google/autocxx/issues/610).
+pub trait CppSubclass<CppPeer: CppSubclassCppPeer>: CppPeerConstructor<CppPeer> {
+    /// Return the field which holds the C++ peer object. This is normally
+    /// implemented by the #[`is_subclass`] macro, but you're welcome to
+    /// implement it yourself if you prefer.
+    fn peer_holder(&self) -> &CppSubclassCppPeerHolder<CppPeer>;
+
+    /// Return the field which holds the C++ peer object. This is normally
+    /// implemented by the #[`is_subclass`] macro, but you're welcome to
+    /// implement it yourself if you prefer.
+    fn peer_holder_mut(&mut self) -> &mut CppSubclassCppPeerHolder<CppPeer>;
+
+    /// Return a reference to the C++ part of this object pair.
+    /// This can be used to register listeners, etc.
+    fn peer(&self) -> &CppPeer {
+        self.peer_holder().get()
+    }
+
+    /// Return a mutable reference to the C++ part of this object pair.
+    /// This can be used to register listeners, etc.
+    fn peer_mut(&mut self) -> Pin<&mut CppPeer> {
+        self.peer_holder_mut().pin_mut()
+    }
+
+    /// Creates a new instance of this subclass. This instance is owned by the
+    /// returned [`cxx::UniquePtr`] and thus would typically be returned immediately
+    /// to C++ such that it can be owned on the C++ side.
+    fn new_cpp_owned(me: Self) -> UniquePtr<CppPeer> {
+        let me = Rc::new(RefCell::new(me));
+        let holder = CppSubclassRustPeerHolder::Owned(me.clone());
+        let mut borrowed = me.as_ref().borrow_mut();
+        let mut cpp_side = borrowed.make_peer(holder);
+        borrowed.peer_holder_mut().set_unowned(&mut cpp_side);
+        cpp_side
+    }
+
+    /// Creates a new instance of this subclass. This instance is not owned
+    /// by C++, and therefore will be deleted when it goes out of scope in
+    /// Rust.
+    fn new_rust_owned(me: Self) -> Rc<RefCell<Self>> {
+        make_owning_peer(
+            me,
+            |obj, holder| obj.make_peer(holder),
+            |me| CppSubclassRustPeerHolder::Unowned(Rc::downgrade(&me)),
+        )
+    }
+}
+
+/// Trait to be implemented by subclasses which are self-owned, i.e. not owned
+/// externally by either Rust or C++ code, and thus need the ability to delete
+/// themselves when some virtual function is called.
+pub trait CppSubclassSelfOwned<CppPeer: CppSubclassCppPeer>: CppSubclass<CppPeer> {
+    /// Creates a new instance of this subclass which owns itself.
+    /// This is useful
+    /// for observers (etc.) which self-register to listen to events.
+    /// If an event occurs which would cause this to want to unregister,
+    /// use [`CppSubclassSelfOwned::delete_self`].
+    /// The return value may be useful to register this, etc. but can ultimately
+    /// be discarded without destroying this object.
+    fn new_self_owned(me: Self) -> Rc<RefCell<Self>> {
+        make_owning_peer(
+            me,
+            |obj, holder| obj.make_peer(holder),
+            CppSubclassRustPeerHolder::Owned,
+        )
+    }
+
+    /// Relinquishes ownership from the C++ side. If there are no outstanding
+    /// references from the Rust side, this will result in the destruction
+    /// of this subclass instance.
+    fn delete_self(&self) {
+        self.peer().relinquish_ownership()
+    }
+}
+
+/// Provides default constructors for subclasses which implement `Default`.
+pub trait CppSubclassDefault<CppPeer: CppSubclassCppPeer>: CppSubclass<CppPeer> + Default {
+    /// Create a Rust-owned instance of this subclass, initializing with default values. See
+    /// [`CppSubclass`] for more details of the ownership models available.
+    fn default_rust_owned() -> Rc<RefCell<Self>>;
+
+    /// Create a C++-owned instance of this subclass, initializing with default values. See
+    /// [`CppSubclass`] for more details of the ownership models available.
+    fn default_cpp_owned() -> UniquePtr<CppPeer>;
+}
+
+impl<T, CppPeer> CppSubclassDefault<CppPeer> for T
+where
+    T: CppSubclass<CppPeer> + Default,
+    CppPeer: CppSubclassCppPeer,
+{
+    fn default_rust_owned() -> Rc<RefCell<Self>> {
+        Self::new_rust_owned(Self::default())
+    }
+
+    fn default_cpp_owned() -> UniquePtr<CppPeer> {
+        Self::new_cpp_owned(Self::default())
+    }
+}
+
+/// Provides default constructors for subclasses which implement `Default`
+/// and are self-owning.
+pub trait CppSubclassSelfOwnedDefault<CppPeer: CppSubclassCppPeer>:
+    CppSubclassSelfOwned<CppPeer> + Default
+{
+    /// Create a self-owned instance of this subclass, initializing with default values. See
+    /// [`CppSubclass`] for more details of the ownership models available.
+    fn default_self_owned() -> Rc<RefCell<Self>>;
+}
+
+impl<T, CppPeer> CppSubclassSelfOwnedDefault<CppPeer> for T
+where
+    T: CppSubclassSelfOwned<CppPeer> + Default,
+    CppPeer: CppSubclassCppPeer,
+{
+    fn default_self_owned() -> Rc<RefCell<Self>> {
+        Self::new_self_owned(Self::default())
+    }
+}
diff --git a/src/value_param.rs b/src/value_param.rs
new file mode 100644
index 0000000..8e564a1
--- /dev/null
+++ b/src/value_param.rs
@@ -0,0 +1,300 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cxx::{memory::UniquePtrTarget, UniquePtr};
+use moveit::{CopyNew, DerefMove, MoveNew, New};
+use std::{marker::PhantomPinned, mem::MaybeUninit, ops::Deref, pin::Pin};
+
+/// A trait representing a parameter to a C++ function which is received
+/// by value.
+///
+/// Rust has the concept of receiving parameters by _move_ or by _reference_.
+/// C++ has the concept of receiving a parameter by 'value', which means
+/// the parameter gets copied.
+///
+/// To make it easy to pass such parameters from Rust, this trait exists.
+/// It is implemented both for references `&T` and for `UniquePtr<T>`,
+/// subject to the presence or absence of suitable copy and move constructors.
+/// This allows you to pass in parameters by copy (as is ergonomic and normal
+/// in C++) retaining the original parameter; or by move semantics thus
+/// destroying the object you're passing in. Simply use a reference if you want
+/// copy semantics, or the item itself if you want move semantics.
+///
+/// It is not recommended that you implement this trait, nor that you directly
+/// use its methods, which are for use by `autocxx` generated code only.
+///
+/// # Use of `moveit` traits
+///
+/// Most of the implementations of this trait require the type to implement
+/// [`CopyNew`], which is simply the `autocxx`/`moveit` way of saying that
+/// the type has a copy constructor in C++.
+///
+/// # Being explicit
+///
+/// If you wish to explicitly force either a move or a copy of some type,
+/// use [`as_mov`] or [`as_copy`].
+///
+/// # Performance
+///
+/// At present, some additional copying occurs for all implementations of
+/// this trait other than that for [`cxx::UniquePtr`]. In the future it's
+/// hoped that the implementation for `&T where T: CopyNew` can also avoid
+/// this extra copying.
+///
+/// # Panics
+///
+/// The implementations of this trait which take a [`cxx::UniquePtr`] will
+/// panic if the pointer is NULL.
+///
+/// # Safety
+///
+/// Implementers must guarantee that the pointer returned by `get_ptr`
+/// is of the correct size and alignment of `T`.
+pub unsafe trait ValueParam<T> {
+    /// Any stack storage required. If, as part of passing to C++,
+    /// we need to store a temporary copy of the value, this will be `T`,
+    /// otherwise `()`.
+    #[doc(hidden)]
+    type StackStorage;
+    /// Populate the stack storage given as a parameter. Only called if you
+    /// return `true` from `needs_stack_space`.
+    ///
+    /// # Safety
+    ///
+    /// Callers must guarantee that this object will not move in memory
+    /// between this call and any subsequent `get_ptr` call or drop.
+    #[doc(hidden)]
+    unsafe fn populate_stack_space(self, this: Pin<&mut Option<Self::StackStorage>>);
+    /// Retrieve the pointer to the underlying item, to be passed to C++.
+    /// Note that on the C++ side this is currently passed to `std::move`
+    /// and therefore may be mutated.
+    #[doc(hidden)]
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T;
+    #[doc(hidden)]
+    /// Any special drop steps required for the stack storage. This is not
+    /// necessary if the `StackStorage` type is something self-dropping
+    /// such as `UniquePtr`; it's only necessary if it's something where
+    /// manual management is required such as `MaybeUninit`.
+    fn do_drop(_stack: Pin<&mut Self::StackStorage>) {}
+}
+
+unsafe impl<T> ValueParam<T> for &T
+where
+    T: CopyNew,
+{
+    type StackStorage = MaybeUninit<T>;
+
+    unsafe fn populate_stack_space(self, mut stack: Pin<&mut Option<Self::StackStorage>>) {
+        // Safety: we won't move/swap things within the pin.
+        let slot = Pin::into_inner_unchecked(stack.as_mut());
+        *slot = Some(MaybeUninit::uninit());
+        crate::moveit::new::copy(self).new(Pin::new_unchecked(slot.as_mut().unwrap()))
+    }
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        // Safety: it's OK to (briefly) create a reference to the T because we
+        // populated it within `populate_stack_space`. It's OK to unpack the pin
+        // because we're not going to move the contents.
+        unsafe { Pin::into_inner_unchecked(stack).assume_init_mut() as *mut T }
+    }
+
+    fn do_drop(stack: Pin<&mut Self::StackStorage>) {
+        // Switch to MaybeUninit::assume_init_drop when stabilized
+        // Safety: per caller guarantees of populate_stack_space, we know this hasn't moved.
+        unsafe { std::ptr::drop_in_place(Pin::into_inner_unchecked(stack).assume_init_mut()) };
+    }
+}
+
+unsafe impl<T> ValueParam<T> for UniquePtr<T>
+where
+    T: UniquePtrTarget,
+{
+    type StackStorage = UniquePtr<T>;
+
+    unsafe fn populate_stack_space(self, mut stack: Pin<&mut Option<Self::StackStorage>>) {
+        // Safety: we will not move the contents of the pin.
+        *Pin::into_inner_unchecked(stack.as_mut()) = Some(self)
+    }
+
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked(
+                (*Pin::into_inner_unchecked(stack))
+                    .as_mut()
+                    .expect("Passed a NULL UniquePtr as a C++ value parameter"),
+            )) as *mut T
+        }
+    }
+}
+
+unsafe impl<T> ValueParam<T> for Pin<Box<T>> {
+    type StackStorage = Pin<Box<T>>;
+
+    unsafe fn populate_stack_space(self, mut stack: Pin<&mut Option<Self::StackStorage>>) {
+        // Safety: we will not move the contents of the pin.
+        *Pin::into_inner_unchecked(stack.as_mut()) = Some(self)
+    }
+
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked((*Pin::into_inner_unchecked(stack)).as_mut())) as *mut T
+        }
+    }
+}
+
+unsafe impl<'a, T: 'a> ValueParam<T> for &'a UniquePtr<T>
+where
+    T: UniquePtrTarget + CopyNew,
+{
+    type StackStorage = <&'a T as ValueParam<T>>::StackStorage;
+
+    unsafe fn populate_stack_space(self, stack: Pin<&mut Option<Self::StackStorage>>) {
+        self.as_ref()
+            .expect("Passed a NULL &UniquePtr as a C++ value parameter")
+            .populate_stack_space(stack)
+    }
+
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        <&'a T as ValueParam<T>>::get_ptr(stack)
+    }
+
+    fn do_drop(stack: Pin<&mut Self::StackStorage>) {
+        <&'a T as ValueParam<T>>::do_drop(stack)
+    }
+}
+
+unsafe impl<'a, T: 'a> ValueParam<T> for &'a Pin<Box<T>>
+where
+    T: CopyNew,
+{
+    type StackStorage = <&'a T as ValueParam<T>>::StackStorage;
+
+    unsafe fn populate_stack_space(self, stack: Pin<&mut Option<Self::StackStorage>>) {
+        self.as_ref().get_ref().populate_stack_space(stack)
+    }
+
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        <&'a T as ValueParam<T>>::get_ptr(stack)
+    }
+
+    fn do_drop(stack: Pin<&mut Self::StackStorage>) {
+        <&'a T as ValueParam<T>>::do_drop(stack)
+    }
+}
+
+/// Explicitly force a value parameter to be taken using any type of [`crate::moveit::new::New`],
+/// i.e. a constructor.
+pub fn as_new<N: New<Output = T>, T>(constructor: N) -> impl ValueParam<T> {
+    ByNew(constructor)
+}
+
+/// Explicitly force a value parameter to be taken by copy.
+pub fn as_copy<P: Deref<Target = T>, T>(ptr: P) -> impl ValueParam<T>
+where
+    T: CopyNew,
+{
+    ByNew(crate::moveit::new::copy(ptr))
+}
+
+/// Explicitly force a value parameter to be taken usign C++ move semantics.
+pub fn as_mov<P: DerefMove + Deref<Target = T>, T>(ptr: P) -> impl ValueParam<T>
+where
+    P: DerefMove,
+    P::Target: MoveNew,
+{
+    ByNew(crate::moveit::new::mov(ptr))
+}
+
+#[doc(hidden)]
+pub struct ByNew<N: New>(N);
+
+unsafe impl<N, T> ValueParam<T> for ByNew<N>
+where
+    N: New<Output = T>,
+{
+    type StackStorage = MaybeUninit<T>;
+
+    unsafe fn populate_stack_space(self, mut stack: Pin<&mut Option<Self::StackStorage>>) {
+        // Safety: we won't move/swap things within the pin.
+        let slot = Pin::into_inner_unchecked(stack.as_mut());
+        *slot = Some(MaybeUninit::uninit());
+        self.0.new(Pin::new_unchecked(slot.as_mut().unwrap()))
+    }
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        // Safety: it's OK to (briefly) create a reference to the T because we
+        // populated it within `populate_stack_space`. It's OK to unpack the pin
+        // because we're not going to move the contents.
+        unsafe { Pin::into_inner_unchecked(stack).assume_init_mut() as *mut T }
+    }
+
+    fn do_drop(stack: Pin<&mut Self::StackStorage>) {
+        // Switch to MaybeUninit::assume_init_drop when stabilized
+        // Safety: per caller guarantees of populate_stack_space, we know this hasn't moved.
+        unsafe { std::ptr::drop_in_place(Pin::into_inner_unchecked(stack).assume_init_mut()) };
+    }
+}
+
+/// Implementation detail for how we pass value parameters into C++.
+/// This type is instantiated by auto-generated autocxx code each time we
+/// need to pass a value parameter into C++, and will take responsibility
+/// for extracting that value parameter from the [`ValueParam`] and doing
+/// any later cleanup.
+#[doc(hidden)]
+pub struct ValueParamHandler<T, VP: ValueParam<T>> {
+    // We can't populate this on 'new' because the object may move.
+    // Hence this is an Option - it's None until populate is called.
+    space: Option<VP::StackStorage>,
+    _pinned: PhantomPinned,
+}
+
+impl<T, VP: ValueParam<T>> ValueParamHandler<T, VP> {
+    /// Populate this stack space if needs be. Note safety guarantees
+    /// on [`get_ptr`].
+    ///
+    /// # Safety
+    ///
+    /// Callers must call [`populate`] exactly once prior to calling [`get_ptr`].
+    pub unsafe fn populate(self: Pin<&mut Self>, param: VP) {
+        // Structural pinning, as documented in [`std::pin`].
+        param.populate_stack_space(self.map_unchecked_mut(|s| &mut s.space))
+    }
+
+    /// Return a pointer to the underlying value which can be passed to C++.
+    ///
+    /// Per the unsafety contract of [`populate`], [`populate`] has been called exactly once
+    /// prior to this call.
+    pub fn get_ptr(self: Pin<&mut Self>) -> *mut T {
+        // Structural pinning, as documented in [`std::pin`]. `map_unchecked_mut` doesn't play
+        // nicely with `unwrap`, so we have to do it manually.
+        unsafe {
+            VP::get_ptr(Pin::new_unchecked(
+                self.get_unchecked_mut().space.as_mut().unwrap(),
+            ))
+        }
+    }
+}
+
+impl<T, VP: ValueParam<T>> Default for ValueParamHandler<T, VP> {
+    fn default() -> Self {
+        Self {
+            space: None,
+            _pinned: PhantomPinned,
+        }
+    }
+}
+
+impl<T, VP: ValueParam<T>> Drop for ValueParamHandler<T, VP> {
+    fn drop(&mut self) {
+        if let Some(space) = self.space.as_mut() {
+            unsafe { VP::do_drop(Pin::new_unchecked(space)) }
+        }
+    }
+}
diff --git a/tools/mdbook-preprocessor/Cargo.toml b/tools/mdbook-preprocessor/Cargo.toml
new file mode 100644
index 0000000..19d775d
--- /dev/null
+++ b/tools/mdbook-preprocessor/Cargo.toml
@@ -0,0 +1,36 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-mdbook-preprocessor"
+version = "0.22.0"
+authors = ["adetaylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+[dependencies]
+clap = { version = "3", features = [ "cargo" ] }
+serde_json = "1"
+itertools = "0.10"
+anyhow = "1"
+regex = "1"
+autocxx-integration-tests = { path = "../../integration-tests", version="=0.22.0"}
+rayon = "1.5"
+gag = "1.0"
+env_logger = "0.9.0"
+
+[dependencies.syn]
+version = "1.0.39"
+features = [ "parsing" ]
+
+[dependencies.proc-macro2]
+version = "1.0.11"
+features = [ "span-locations" ]
+
+[dependencies.mdbook]
+version = "0.4"
+default-features = false
diff --git a/tools/mdbook-preprocessor/src/main.rs b/tools/mdbook-preprocessor/src/main.rs
new file mode 100644
index 0000000..1bb4e31
--- /dev/null
+++ b/tools/mdbook-preprocessor/src/main.rs
@@ -0,0 +1,377 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{
+    borrow::Cow,
+    collections::HashSet,
+    fmt::Display,
+    io::{self, Read},
+    path::PathBuf,
+    process,
+};
+
+use anyhow::Error;
+use clap::{crate_authors, crate_version, Arg, ArgMatches, Command};
+use itertools::Itertools;
+use mdbook::{book::Book, preprocess::CmdPreprocessor};
+use proc_macro2::{Span, TokenStream};
+use rayon::prelude::*;
+use syn::{Expr, __private::ToTokens, spanned::Spanned};
+
+static LONG_ABOUT: &str =
+    "This is an mdbook preprocessor tailored for autocxx code examples. Autocxx
+code examples don't fit well 'mdbook test' or even alternatives such as
+'skeptic' or 'doc_comment' for these reasons:
+
+a) A single code example consists of both Rust and C++ code. They must be
+   linked into a separate executable, i.e. we must make one executable per
+   doc test.
+b) The code examples must be presented/formatted nicely with suitable
+   separate blocks for the Rust and C++ code.
+c) mdbook test is not good at handling doctests which have dependencies.
+
+This preprocessor will find code snippets like this:
+```rust,autocxx
+autocxx_integration_tests::doctest(
+\" /* any C++ implementation code */\",
+\" /* C++ header code */\",
+{
+/* complete Rust code including 'main' */
+)
+```
+
+and will build and run them, while emitting better formatted markdown blocks
+for subsequent preprocessors and renderers.
+";
+
+static RUST_MDBOOK_SINGLE_TEST: &str = "RUST_MDBOOK_SINGLE_TEST";
+
+fn main() {
+    let matches = Command::new("autocxx-mdbook-preprocessor")
+        .version(crate_version!())
+        .author(crate_authors!())
+        .about("Expands and tests code examples in the autocxx book.")
+        .long_about(LONG_ABOUT)
+        .subcommand(
+            Command::new("supports")
+                .arg(Arg::new("renderer").required(true))
+                .about("Whether a given renderer is supported by this preprocessor"),
+        )
+        .arg(
+            Arg::new("skip_tests")
+                .short('s')
+                .help("Skip running doctests"),
+        )
+        .arg(
+            Arg::new("manifest_dir")
+            .long("manifest-dir")
+            .help("Path to directory containing outermost autocxx Cargo.toml; necessary for trybuild to build test code successfully")
+            .default_value_os(calculate_cargo_dir().as_os_str())
+        )
+        .get_matches();
+    if let Some(supports_matches) = matches.subcommand_matches("supports") {
+        // Only do our preprocessing and testing for the html renderer, not linkcheck.
+        if supports_matches.value_of("renderer") == Some("html") {
+            process::exit(0);
+        } else {
+            process::exit(1);
+        }
+    }
+    preprocess(&matches).unwrap();
+}
+
+fn calculate_cargo_dir() -> PathBuf {
+    let mut path = std::env::current_exe().unwrap();
+    for _ in 0..3 {
+        path = path.parent().map(|p| p.to_path_buf()).unwrap_or(path);
+    }
+    path.join("integration-tests")
+}
+
+fn preprocess(args: &ArgMatches) -> Result<(), Error> {
+    let (_, mut book) = CmdPreprocessor::parse_input(io::stdin())?;
+
+    env_logger::builder().init();
+    let mut test_cases = Vec::new();
+
+    Book::for_each_mut(&mut book, |sec| {
+        if let mdbook::BookItem::Chapter(chapter) = sec {
+            let filename = chapter
+                .path
+                .as_ref()
+                .map(|pb| pb.to_string_lossy())
+                .unwrap_or_default()
+                .to_string();
+            chapter.content = substitute_chapter(&chapter.content, &filename, &mut test_cases);
+        }
+    });
+
+    // Now run any test cases we accumulated.
+    if !args.is_present("skip_tests") {
+        let stdout_gag = gag::BufferRedirect::stdout().unwrap();
+        let num_tests = test_cases.len();
+        let fails: Vec<_> = test_cases
+            .into_par_iter()
+            .enumerate()
+            .filter_map(|(counter, case)| {
+                if let Ok(test) = std::env::var(RUST_MDBOOK_SINGLE_TEST) {
+                    let desired_id: usize = test.parse().unwrap();
+                    if desired_id != (counter + 1) {
+                        return None;
+                    }
+                }
+                eprintln!(
+                    "Running doctest {}/{} at {}",
+                    counter + 1,
+                    num_tests,
+                    &case.location
+                );
+                let err = autocxx_integration_tests::doctest(
+                    &case.cpp,
+                    &case.hdr,
+                    case.rs,
+                    args.value_of_os("manifest_dir").unwrap(),
+                );
+                let desc = match err {
+                    Ok(_) => "passed".to_string(),
+                    Err(ref err) => format!("failed: {:?}", err),
+                };
+                eprintln!(
+                    "Doctest {}/{} at {} {}.",
+                    counter + 1,
+                    num_tests,
+                    &case.location,
+                    desc
+                );
+                if err.is_err() {
+                    Some(TestId {
+                        location: case.location,
+                        test_id: counter + 1,
+                    })
+                } else {
+                    None
+                }
+            })
+            .collect();
+        let mut stdout_str = String::new();
+        stdout_gag
+            .into_inner()
+            .read_to_string(&mut stdout_str)
+            .unwrap();
+        if !stdout_str.is_empty() {
+            eprintln!("Stdout from tests:\n{}", stdout_str);
+        }
+        if !fails.is_empty() {
+            panic!(
+                "One or more tests failed: {}. To rerun an individual test use {}.",
+                fails.into_iter().sorted().map(|s| s.to_string()).join(", "),
+                RUST_MDBOOK_SINGLE_TEST
+            );
+        }
+    }
+
+    serde_json::to_writer(io::stdout(), &book)?;
+
+    Ok(())
+}
+
+fn substitute_chapter(chapter: &str, filename: &str, test_cases: &mut Vec<TestCase>) -> String {
+    let mut state = ChapterParseState::Start;
+    let mut out = Vec::new();
+    for (line_no, line) in chapter.lines().enumerate() {
+        let line_type = recognize_line(line);
+        let mut push_line = true;
+        state = match state {
+            ChapterParseState::Start => match line_type {
+                LineType::CodeBlockStart | LineType::CodeBlockEnd => {
+                    ChapterParseState::OtherCodeBlock
+                }
+                LineType::CodeBlockStartAutocxx(block_flags) => {
+                    push_line = false;
+                    ChapterParseState::OurCodeBlock(block_flags, Vec::new())
+                }
+                LineType::Misc => ChapterParseState::Start,
+            },
+            ChapterParseState::OtherCodeBlock => match line_type {
+                LineType::CodeBlockEnd => ChapterParseState::Start,
+                LineType::Misc => ChapterParseState::OtherCodeBlock,
+                _ => panic!("Found confusing conflicting block markers"),
+            },
+            ChapterParseState::OurCodeBlock(flags, mut lines) => match line_type {
+                LineType::Misc => {
+                    push_line = false;
+                    lines.push(line.to_string());
+                    ChapterParseState::OurCodeBlock(flags, lines)
+                }
+                LineType::CodeBlockEnd => {
+                    let location = MiniSpan {
+                        filename: filename.to_string(),
+                        start_line: line_no - lines.len(),
+                    };
+                    out.extend(handle_code_block(flags, lines, location, test_cases));
+                    push_line = false;
+                    ChapterParseState::Start
+                }
+                _ => panic!("Found something unexpected in one of our code blocks"),
+            },
+        };
+        if push_line {
+            out.push(line.to_string());
+        }
+    }
+
+    out.join("\n")
+}
+
+#[derive(PartialEq, Eq, PartialOrd, Ord)]
+struct TestId {
+    location: MiniSpan,
+    test_id: usize,
+}
+
+impl Display for TestId {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "(ID {}): {}", self.test_id, self.location)
+    }
+}
+
+/// Like `proc_macro2::Span` but only has the starting line. For basic
+/// diagnostics.
+#[derive(PartialEq, Eq, PartialOrd, Ord)]
+struct MiniSpan {
+    filename: String,
+    start_line: usize,
+}
+
+impl Display for MiniSpan {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{} line {}", self.filename, self.start_line)
+    }
+}
+
+struct TestCase {
+    cpp: String,
+    hdr: String,
+    rs: TokenStream,
+    location: MiniSpan,
+}
+
+unsafe impl Send for TestCase {}
+
+enum ChapterParseState {
+    Start,
+    OtherCodeBlock,
+    OurCodeBlock(HashSet<String>, Vec<String>), // have found rust,autocxx
+}
+
+enum LineType {
+    CodeBlockStart,
+    CodeBlockStartAutocxx(HashSet<String>),
+    CodeBlockEnd,
+    Misc,
+}
+
+fn code_block_flags(line: &str) -> HashSet<String> {
+    let line = &line[3..];
+    line.split(',').map(|s| s.to_string()).collect()
+}
+
+fn recognize_line(line: &str) -> LineType {
+    if line.starts_with("```") && line.len() > 3 {
+        let flags = code_block_flags(line);
+        if flags.contains("autocxx") {
+            LineType::CodeBlockStartAutocxx(flags)
+        } else {
+            LineType::CodeBlockStart
+        }
+    } else if line == "```" {
+        LineType::CodeBlockEnd
+    } else {
+        LineType::Misc
+    }
+}
+
+fn handle_code_block(
+    flags: HashSet<String>,
+    lines: Vec<String>,
+    location: MiniSpan,
+    test_cases: &mut Vec<TestCase>,
+) -> impl Iterator<Item = String> {
+    let input_str = lines.join("\n");
+    let fn_call = syn::parse_str::<syn::Expr>(&input_str)
+        .unwrap_or_else(|_| panic!("Unable to parse outer function at {}", location));
+    let fn_call = match fn_call {
+        Expr::Call(expr) => expr,
+        _ => panic!("Parsing unexpected"),
+    };
+    let mut args_iter = fn_call.args.iter();
+    let cpp = unescape_quotes(&extract_span(&lines, args_iter.next().unwrap().span()));
+    let hdr = unescape_quotes(&extract_span(&lines, args_iter.next().unwrap().span()));
+    let rs = extract_span(&lines, args_iter.next().unwrap().span());
+    let mut output = vec![
+        "#### C++ header:".to_string(),
+        "```cpp".to_string(),
+        hdr.to_string(),
+        "```".to_string(),
+    ];
+    if !cpp.is_empty() && !flags.contains("hidecpp") {
+        output.push("#### C++ implementation:".to_string());
+        output.push("```cpp".to_string());
+        output.push(cpp.to_string());
+        output.push("```".to_string());
+    }
+    output.push("#### Rust:".to_string());
+    output.push("```rust,noplayground".to_string());
+    output.push(escape_hexathorpes(&rs).to_string());
+    output.push("```".to_string());
+
+    // Don't run the test cases yet, because we want the preprocessor to spot
+    // basic formatting errors before getting into the time consuming business of
+    // running tests.
+    if !flags.contains("nocompile") {
+        test_cases.push(TestCase {
+            cpp,
+            hdr,
+            rs: syn::parse_file(&rs)
+                .unwrap_or_else(|_| panic!("Unable to parse code at {}", location))
+                .to_token_stream(),
+            location,
+        });
+    }
+
+    output.into_iter()
+}
+
+fn extract_span(text: &[String], span: Span) -> Cow<str> {
+    let start_line = span.start().line - 1;
+    let start_col = span.start().column;
+    let end_line = span.end().line - 1;
+    let end_col = span.end().column;
+    if start_line == end_line {
+        Cow::Borrowed(&text[start_line][start_col + 1..end_col - 1])
+    } else {
+        let start_subset = &text[start_line][start_col + 1..];
+        let end_subset = &text[end_line][..end_col - 1];
+        let mid_lines = &text[start_line + 1..end_line];
+        Cow::Owned(
+            std::iter::once(start_subset.to_string())
+                .chain(mid_lines.iter().cloned())
+                .chain(std::iter::once(end_subset.to_string()))
+                .join("\n"),
+        )
+    }
+}
+
+fn escape_hexathorpes(input: &str) -> Cow<str> {
+    let re = regex::Regex::new(r"(?m)^(?P<ws>\s*)#(?P<c>.*)").unwrap();
+    re.replace_all(input, "$ws##$c")
+}
+
+fn unescape_quotes(input: &str) -> String {
+    input.replace("\\\"", "\"")
+}
diff --git a/tools/publish-all.sh b/tools/publish-all.sh
new file mode 100755
index 0000000..b43b95b
--- /dev/null
+++ b/tools/publish-all.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -e
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/.."
+
+DIRS="$DIR/parser $DIR/engine $DIR/macro $DIR $DIR/gen/build $DIR/integration-tests $DIR/gen/cmd"
+
+for CRATE in $DIRS; do
+  pushd $CRATE
+  echo "Publish: $CRATE"
+  cargo publish
+  popd
+  sleep 30 # sometimes crates.io takes a moment, and our
+           # crates are interdependent.
+done
diff --git a/tools/reduce/Cargo.toml b/tools/reduce/Cargo.toml
new file mode 100644
index 0000000..092ccac
--- /dev/null
+++ b/tools/reduce/Cargo.toml
@@ -0,0 +1,37 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-reduce"
+version = "0.22.0"
+authors = ["adetaylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+autocxx-engine = { version = "=0.22.0", path="../../engine" }
+autocxx-parser = { version = "=0.22.0", path="../../parser", features = [ "reproduction_case" ] }
+clap = { version = "3.1.2", features = ["cargo"] }
+tempfile = "3.1"
+indoc = "1.0"
+itertools = "0.10"
+serde_json = "1.0"
+serde = "1.0"
+serde_derive = "1.0"
+syn = "1.0.39"
+quote = "1.0"
+cxx-gen = "0.7.54"
+regex = "1.5"
+indexmap = "1.8"
+
+[dev-dependencies]
+assert_cmd = "1.0.3"
+tempdir = "0.3.7"
+indoc = "1.0"
+proc-macro2 = "1.0"
\ No newline at end of file
diff --git a/tools/reduce/README.md b/tools/reduce/README.md
new file mode 100644
index 0000000..e981883
--- /dev/null
+++ b/tools/reduce/README.md
@@ -0,0 +1,14 @@
+Reduction tool for https://docs.rs/autocxx/latest/autocxx/.
+
+Typical command-line with a repro.json and a compile error "
+
+```
+  cargo run --release -- --problem $EXPECTED_COMPILE_ERROR -k --creduce-arg=--n --creduce-arg=192 repro -r repro.json
+```
+
+From Chromium,
+
+```
+  CLANG_PATH=~/chromium/src/third_party/llvm-build/Release+Asserts/bin/clang++ AUTOCXX_REPRO_CASE=repro.json autoninja -C out/Release chrome
+  CLANG_PATH=~/chromium/src/third_party/llvm-build/Release+Asserts/bin/clang++ cargo run --release -- --problem $EXPECTED_COMPILE_ERROR -k --clang-arg=-std=c++17 --creduce-arg=--n --creduce-arg=192 repro -r ~/dev/chromium/src/out/Release/repro.json
+```
diff --git a/tools/reduce/src/main.rs b/tools/reduce/src/main.rs
new file mode 100644
index 0000000..17c5bf0
--- /dev/null
+++ b/tools/reduce/src/main.rs
@@ -0,0 +1,562 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![forbid(unsafe_code)]
+
+use std::{
+    borrow::Cow,
+    fs::File,
+    io::Write,
+    os::unix::prelude::PermissionsExt,
+    path::{Path, PathBuf},
+};
+
+use autocxx_engine::{get_clang_path, make_clang_args, preprocess};
+use autocxx_parser::IncludeCppConfig;
+use clap::{crate_authors, crate_version, Arg, ArgMatches, Command};
+use indexmap::IndexSet;
+use indoc::indoc;
+use itertools::Itertools;
+use quote::ToTokens;
+use regex::Regex;
+use tempfile::TempDir;
+
+static LONG_HELP: &str = indoc! {"
+Command line utility to minimize autocxx bug cases.
+
+This is a wrapper for creduce.
+
+Example command-line:
+autocxx-reduce file -I my-inc-dir -h my-header -d 'generate!(\"MyClass\")' -k -- --n 64
+"};
+
+fn main() {
+    let matches = Command::new("autocxx-reduce")
+        .version(crate_version!())
+        .author(crate_authors!())
+        .about("Reduce a C++ test case")
+        .long_about(LONG_HELP)
+        .subcommand(Command::new("file")
+                                      .about("reduce a header file")
+
+                                    .arg(
+                                        Arg::new("inc")
+                                            .short('I')
+                                            .long("inc")
+                                            .multiple_occurrences(true)
+                                            .number_of_values(1)
+                                            .value_name("INCLUDE DIRS")
+                                            .help("include path")
+                                            .takes_value(true),
+                                    )
+                                    .arg(
+                                        Arg::new("define")
+                                            .short('D')
+                                            .long("define")
+                                            .multiple_occurrences(true)
+                                            .number_of_values(1)
+                                            .value_name("DEFINE")
+                                            .help("macro definition")
+                                            .takes_value(true),
+                                    )
+                                    .arg(
+                                        Arg::new("header")
+                                            .long("header")
+                                            .multiple_occurrences(true)
+                                            .number_of_values(1)
+                                            .required(true)
+                                            .value_name("HEADER")
+                                            .help("header file name")
+                                            .takes_value(true),
+                                    )
+
+                                .arg(
+                                    Arg::new("directive")
+                                        .short('d')
+                                        .long("directive")
+                                        .multiple_occurrences(true)
+                                        .number_of_values(1)
+                                        .value_name("DIRECTIVE")
+                                        .help("directives to put within include_cpp!")
+                                        .takes_value(true),
+                                )
+                            )
+                            .subcommand(Command::new("repro")
+                                                          .about("reduce a repro case JSON file")
+                                            .arg(
+                                                Arg::new("repro")
+                                                    .short('r')
+                                                    .long("repro")
+                                                    .required(true)
+                                                    .value_name("REPRODUCTION CASE JSON")
+                                                    .help("reproduction case JSON file name")
+                                                    .takes_value(true),
+                                            )
+                                            .arg(
+                                        Arg::new("header")
+                                            .long("header")
+                                            .multiple_occurrences(true)
+                                            .number_of_values(1)
+                                            .value_name("HEADER")
+                                            .help("header file name; specify to resume a part-completed run")
+                                            .takes_value(true),
+                                    )
+                                        )
+        .arg(
+            Arg::new("problem")
+                .short('p')
+                .long("problem")
+                .required(true)
+                .value_name("PROBLEM")
+                .help("problem string we're looking for... may be in logs, or in generated C++, or generated .rs")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("creduce")
+                .long("creduce")
+                .value_name("PATH")
+                .help("creduce binary location")
+                .default_value("creduce")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("output")
+                .short('o')
+                .long("output")
+                .value_name("OUTPUT")
+                .help("where to write minimized output")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("gen-cmd")
+                .short('g')
+                .long("gen-cmd")
+                .value_name("GEN-CMD")
+                .help("where to find autocxx-gen")
+                .takes_value(true),
+        )
+        .arg(
+            Arg::new("keep")
+                .short('k')
+                .long("keep-dir")
+                .help("keep the temporary directory for debugging purposes"),
+        )
+        .arg(
+            Arg::new("clang-args")
+                .short('c')
+                .long("clang-arg")
+                .multiple_occurrences(true)
+                .value_name("CLANG_ARG")
+                .help("Extra arguments to pass to Clang"),
+        )
+        .arg(
+            Arg::new("creduce-args")
+                .long("creduce-arg")
+                .multiple_occurrences(true)
+                .value_name("CREDUCE_ARG")
+                .help("Extra arguments to pass to Clang"),
+        )
+        .arg(
+            Arg::new("no-precompile")
+                .long("no-precompile")
+                .help("Do not precompile the C++ header before passing to autocxxgen"),
+        )
+        .arg(
+            Arg::new("no-postcompile")
+                .long("no-postcompile")
+                .help("Do not post-compile the C++ generated by autocxxgen"),
+        )
+        .arg(
+            Arg::new("suppress-cxx-inclusions")
+                .long("suppress-cxx-inclusions")
+                .takes_value(true)
+                .possible_value("yes")
+                .possible_value("no")
+                .possible_value("auto")
+                .default_value("auto")
+                .help("Whether the preprocessed header already includes cxx.h. If so, we'll try to suppress the natural behavior of cxx to include duplicate definitions of some of the types within gen0.cc.")
+        )
+        .arg_required_else_help(true)
+        .get_matches();
+    run(matches).unwrap();
+}
+
+fn run(matches: ArgMatches) -> Result<(), std::io::Error> {
+    let keep_tmp = matches.is_present("keep");
+    let tmp_dir = TempDir::new()?;
+    let r = do_run(matches, &tmp_dir);
+    if keep_tmp {
+        println!(
+            "Keeping temp dir created at: {}",
+            tmp_dir.into_path().to_str().unwrap()
+        );
+    }
+    r
+}
+
+#[derive(serde_derive::Deserialize)]
+struct ReproCase {
+    config: String,
+    header: String,
+}
+
+fn do_run(matches: ArgMatches, tmp_dir: &TempDir) -> Result<(), std::io::Error> {
+    let rs_path = tmp_dir.path().join("input.rs");
+    let concat_path = tmp_dir.path().join("concat.h");
+    match matches.subcommand_matches("repro") {
+        None => {
+            let submatches = matches.subcommand_matches("file").unwrap();
+            let incs: Vec<_> = submatches
+                .values_of("inc")
+                .unwrap_or_default()
+                .map(PathBuf::from)
+                .collect();
+            let defs: Vec<_> = submatches.values_of("define").unwrap_or_default().collect();
+            let headers: Vec<_> = submatches.values_of("header").unwrap_or_default().collect();
+            assert!(!headers.is_empty());
+            let listing_path = tmp_dir.path().join("listing.h");
+            create_concatenated_header(&headers, &listing_path)?;
+            announce_progress(&format!(
+                "Preprocessing {:?} to {:?}",
+                listing_path, concat_path
+            ));
+            preprocess(&listing_path, &concat_path, &incs, &defs)?;
+            let directives: Vec<_> = std::iter::once("#include \"concat.h\"\n".to_string())
+                .chain(
+                    submatches
+                        .values_of("directive")
+                        .unwrap_or_default()
+                        .map(|s| format!("{}\n", s)),
+                )
+                .collect();
+            create_rs_file(&rs_path, &directives)?;
+        }
+        Some(submatches) => {
+            let case: ReproCase = serde_json::from_reader(File::open(PathBuf::from(
+                submatches.value_of("repro").unwrap(),
+            ))?)
+            .unwrap();
+            // Replace the headers in the config
+            let mut config: IncludeCppConfig = syn::parse_str(&case.config).unwrap();
+            config.replace_included_headers("concat.h");
+            create_file(
+                &rs_path,
+                &format!("autocxx::include_cpp!({});", config.to_token_stream()),
+            )?;
+            if let Some(header) = submatches.value_of("header") {
+                std::fs::copy(PathBuf::from(header), &concat_path)?;
+            } else {
+                create_file(&concat_path, &case.header)?
+            }
+        }
+    }
+
+    let suppress_cxx_classes = match matches.value_of("suppress-cxx-inclusions").unwrap() {
+        "yes" => true,
+        "no" => false,
+        "auto" => detect_cxx_h(&concat_path)?,
+        _ => panic!("unexpected value"),
+    };
+
+    let cxx_suppressions = if suppress_cxx_classes {
+        get_cxx_suppressions()
+    } else {
+        Vec::new()
+    };
+
+    let extra_clang_args: Vec<_> = matches
+        .values_of("clang-args")
+        .unwrap_or_default()
+        .map(Cow::Borrowed)
+        .chain(cxx_suppressions.into_iter().map(Cow::Owned))
+        .collect();
+    let extra_clang_args: Vec<&str> = extra_clang_args.iter().map(|s| s.as_ref()).collect_vec();
+
+    let default_gen_cmd = std::env::current_exe()?
+        .parent()
+        .unwrap()
+        .join("autocxx-gen")
+        .to_str()
+        .unwrap()
+        .to_string();
+    let gen_cmd = matches.value_of("gen-cmd").unwrap_or(&default_gen_cmd);
+    if !Path::new(gen_cmd).exists() {
+        panic!(
+            "autocxx-gen not found in {}. hint: autocxx-reduce --gen-cmd /path/to/autocxx-gen",
+            gen_cmd
+        );
+    }
+    run_sample_gen_cmd(gen_cmd, &rs_path, tmp_dir.path(), &extra_clang_args)?;
+    // Create and run an interestingness test which does not filter its output through grep.
+    let demo_interestingness_test_dir = tmp_dir.path().join("demo-interestingness-test");
+    std::fs::create_dir(&demo_interestingness_test_dir).unwrap();
+    let interestingness_test = demo_interestingness_test_dir.join("test-demo.sh");
+    create_interestingness_test(
+        gen_cmd,
+        &interestingness_test,
+        None,
+        &rs_path,
+        &extra_clang_args,
+        !matches.is_present("no-precompile"),
+        !matches.is_present("no-postcompile"),
+    )?;
+    let demo_dir_concat_path = demo_interestingness_test_dir.join("concat.h");
+    std::fs::copy(&concat_path, demo_dir_concat_path).unwrap();
+    run_demo_interestingness_test(&demo_interestingness_test_dir, &interestingness_test).unwrap();
+
+    // Now the main interestingness test
+    let interestingness_test = tmp_dir.path().join("test.sh");
+    create_interestingness_test(
+        gen_cmd,
+        &interestingness_test,
+        Some(matches.value_of("problem").unwrap()),
+        &rs_path,
+        &extra_clang_args,
+        !matches.is_present("no-precompile"),
+        !matches.is_present("no-postcompile"),
+    )?;
+    run_creduce(
+        matches.value_of("creduce").unwrap(),
+        &interestingness_test,
+        &concat_path,
+        matches.values_of("creduce-args").unwrap_or_default(),
+    );
+    announce_progress("creduce completed");
+    let output_path = matches.value_of("output");
+    match output_path {
+        None => print_minimized_case(&concat_path)?,
+        Some(output_path) => {
+            std::fs::copy(&concat_path, &PathBuf::from(output_path))?;
+        }
+    };
+    Ok(())
+}
+
+/// Try to detect whether the preprocessed source code already contains
+/// a preprocessed version of cxx.h. This is hard because all the comments
+/// and preprocessor symbols may have been removed, and in fact if we're
+/// part way through reduction, parts of the code may have been removed too.
+fn detect_cxx_h(concat_path: &Path) -> Result<bool, std::io::Error> {
+    let haystack = std::fs::read_to_string(concat_path)?;
+    Ok(["class Box", "class Vec", "class Slice"]
+        .iter()
+        .all(|needle| haystack.contains(needle)))
+}
+
+fn announce_progress(msg: &str) {
+    println!("=== {} ===", msg);
+}
+
+fn print_minimized_case(concat_path: &Path) -> Result<(), std::io::Error> {
+    announce_progress("Completed. Minimized test case:");
+    let contents = std::fs::read_to_string(concat_path)?;
+    println!("{}", contents);
+    Ok(())
+}
+
+/// Arguments we pass to creduce if supported. This pass always seems to cause a crash
+/// as far as I can tell, so always exclude it. It may be environment-dependent,
+/// of course, but as I'm the primary user of this tool I am ruthlessly removing it.
+const REMOVE_PASS_LINE_MARKERS: &[&str] = &["--remove-pass", "pass_line_markers", "*"];
+const SKIP_INITIAL_PASSES: &[&str] = &["--skip-initial-passes"];
+
+fn creduce_supports_remove_pass(creduce_cmd: &str) -> bool {
+    let cmd = std::process::Command::new(creduce_cmd)
+        .arg("--help")
+        .output();
+    let msg = match cmd {
+        Err(error) => panic!("failed to run creduce. creduce_cmd = {}. hint: autocxx-reduce --creduce /path/to/creduce. error = {}", creduce_cmd, error),
+        Ok(result) => result.stdout
+    };
+    let msg = std::str::from_utf8(&msg).unwrap();
+    msg.contains("--remove-pass")
+}
+
+fn run_creduce<'a>(
+    creduce_cmd: &str,
+    interestingness_test: &'a Path,
+    concat_path: &'a Path,
+    creduce_args: impl Iterator<Item = &'a str>,
+) {
+    announce_progress("creduce");
+    let args = std::iter::once(interestingness_test.to_str().unwrap())
+        .chain(std::iter::once(concat_path.to_str().unwrap()))
+        .chain(creduce_args)
+        .chain(
+            if creduce_supports_remove_pass(creduce_cmd) {
+                REMOVE_PASS_LINE_MARKERS
+            } else {
+                SKIP_INITIAL_PASSES
+            }
+            .iter()
+            .copied(),
+        )
+        .collect::<Vec<_>>();
+    println!("Command: {} {}", creduce_cmd, args.join(" "));
+    std::process::Command::new(creduce_cmd)
+        .args(args)
+        .status()
+        .expect("failed to creduce");
+}
+
+fn run_sample_gen_cmd(
+    gen_cmd: &str,
+    rs_file: &Path,
+    tmp_dir: &Path,
+    extra_clang_args: &[&str],
+) -> Result<(), std::io::Error> {
+    let args = format_gen_cmd(rs_file, tmp_dir.to_str().unwrap(), extra_clang_args);
+    let args = args.collect::<Vec<_>>();
+    let args_str = args.join(" ");
+    announce_progress(&format!("Running sample gen cmd: {} {}", gen_cmd, args_str));
+    std::process::Command::new(gen_cmd).args(args).status()?;
+    Ok(())
+}
+
+fn run_demo_interestingness_test(demo_dir: &Path, test: &Path) -> Result<(), std::io::Error> {
+    announce_progress(&format!(
+        "Running demo interestingness test in {}",
+        demo_dir.to_string_lossy()
+    ));
+    std::process::Command::new(test)
+        .current_dir(demo_dir)
+        .status()?;
+    Ok(())
+}
+
+fn format_gen_cmd<'a>(
+    rs_file: &Path,
+    dir: &str,
+    extra_clang_args: &'a [&str],
+) -> impl Iterator<Item = String> + 'a {
+    let args = [
+        "-o".to_string(),
+        dir.to_string(),
+        "-I".to_string(),
+        dir.to_string(),
+        rs_file.to_str().unwrap().to_string(),
+        "--gen-rs-include".to_string(),
+        "--gen-cpp".to_string(),
+        "--suppress-system-headers".to_string(),
+        "--".to_string(),
+    ]
+    .to_vec();
+    args.into_iter()
+        .chain(extra_clang_args.iter().map(|s| s.to_string()))
+}
+
+fn create_interestingness_test(
+    gen_cmd: &str,
+    test_path: &Path,
+    problem: Option<&str>,
+    rs_file: &Path,
+    extra_clang_args: &[&str],
+    precompile: bool,
+    postcompile: bool,
+) -> Result<(), std::io::Error> {
+    announce_progress("Creating interestingness test");
+    // Ensure we refer to the input header by relative path
+    // because creduce will invoke us in some other directory with
+    // a copy thereof.
+    let mut args = format_gen_cmd(rs_file, "$(pwd)", extra_clang_args);
+    let args = args.join(" ");
+    let precompile_step = make_compile_step(precompile, "concat.h", extra_clang_args);
+    // For the compile afterwards, we have to avoid including any system headers.
+    // We rely on equivalent content being hermetically inside concat.h.
+    let postcompile_step = make_compile_step(postcompile, "gen0.cc", extra_clang_args);
+    let problem_grep = problem
+        .map(|problem| format!("| grep \"{}\"  >/dev/null  2>&1", problem))
+        .unwrap_or_default();
+    let content = format!(
+        indoc! {"
+        #!/bin/sh
+        set -e
+        echo Precompile
+        {}
+        echo Move
+        mv concat.h concat-body.h
+        echo Codegen
+        (echo \"#ifndef __CONCAT_H__\"; echo \"#define __CONCAT_H__\"; echo '#include \"concat-body.h\"'; echo \"#endif\") > concat.h
+        ({} {} 2>&1 && cat autocxx-ffi-default-gen.rs && cat autocxxgen*.h && {} 2>&1 ) {}
+        echo Remove
+        rm concat.h
+        echo Swap back
+        mv concat-body.h concat.h
+        echo Done
+    "},
+        precompile_step, gen_cmd, args, postcompile_step, problem_grep
+    );
+    println!("Interestingness test:\n{}", content);
+    {
+        let mut file = File::create(test_path)?;
+        file.write_all(content.as_bytes())?;
+    }
+
+    let mut perms = std::fs::metadata(&test_path)?.permissions();
+    perms.set_mode(0o700);
+    std::fs::set_permissions(&test_path, perms)?;
+    Ok(())
+}
+
+fn make_compile_step(enabled: bool, file: &str, extra_clang_args: &[&str]) -> String {
+    if enabled {
+        format!(
+            "{} {} -c {}",
+            get_clang_path(),
+            make_clang_args(&[PathBuf::from(".")], extra_clang_args).join(" "),
+            file,
+        )
+    } else {
+        "echo 'Skipping compilation'".into()
+    }
+}
+
+fn create_rs_file(rs_path: &Path, directives: &[String]) -> Result<(), std::io::Error> {
+    announce_progress("Creating Rust input file");
+    let mut file = File::create(rs_path)?;
+    file.write_all("use autocxx::include_cpp;\ninclude_cpp! (\n".as_bytes())?;
+    for directive in directives {
+        file.write_all(directive.as_bytes())?;
+    }
+    file.write_all(");\n".as_bytes())?;
+    Ok(())
+}
+
+fn create_concatenated_header(headers: &[&str], listing_path: &Path) -> Result<(), std::io::Error> {
+    announce_progress("Creating preprocessed header");
+    let mut file = File::create(listing_path)?;
+    for header in headers {
+        file.write_all(format!("#include \"{}\"\n", header).as_bytes())?;
+    }
+    Ok(())
+}
+
+fn create_file(path: &Path, content: &str) -> Result<(), std::io::Error> {
+    let mut file = File::create(path)?;
+    write!(file, "{}", content)?;
+    Ok(())
+}
+
+fn get_cxx_suppressions() -> Vec<String> {
+    let defines: IndexSet<_> = Regex::new(r"\bCXXBRIDGE1_\w+\b")
+        .unwrap()
+        .find_iter(cxx_gen::HEADER)
+        .map(|m| m.as_str())
+        .collect(); // for uniqueness
+    defines
+        .into_iter()
+        .map(|def| format!("-D{}", def))
+        .collect()
+}
+
+#[test]
+fn test_get_cxx_suppressions() {
+    let defines = get_cxx_suppressions();
+    assert!(defines.contains(&"-DCXXBRIDGE1_RUST_BITCOPY_T".to_string()));
+    assert!(defines.contains(&"-DCXXBRIDGE1_RUST_STR".to_string()));
+}
diff --git a/tools/reduce/tests/reduce_test.rs b/tools/reduce/tests/reduce_test.rs
new file mode 100644
index 0000000..ceac5f4
--- /dev/null
+++ b/tools/reduce/tests/reduce_test.rs
@@ -0,0 +1,230 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use assert_cmd::Command;
+use proc_macro2::Span;
+use quote::quote;
+use std::{
+    borrow::Cow,
+    fs::File,
+    io::Write,
+    path::{Path, PathBuf},
+};
+use syn::Token;
+use tempdir::TempDir;
+
+static INPUT_H: &str = indoc::indoc! {"
+    inline int DoMath(int a) {
+        return a * 3;
+    }
+
+    struct First {
+        First() {}
+        int foo;
+    };
+
+    struct Second {
+        Second(const First& a) {}
+        int bar;
+    };
+
+    struct WithMethods {
+        First get_first();
+        Second get_second();
+        int a;
+    };
+"};
+
+enum Input {
+    Header(String),
+    ReproCase(PathBuf),
+}
+
+#[test]
+fn test_reduce_direct_header() -> Result<(), Box<dyn std::error::Error>> {
+    do_reduce(|header, _| Ok(Input::Header(header.into())), false)
+}
+
+#[test]
+fn test_reduce_direct_repro_case() -> Result<(), Box<dyn std::error::Error>> {
+    do_reduce(
+        |header, demo_code_dir| {
+            let config = format!(
+                "#include \"{}\" generate_all!() block!(\"First\")
+            safety!(unsafe_ffi)",
+                header
+            );
+            let json = serde_json::json!({
+                "header": INPUT_H,
+                "config": config
+            });
+            let repropath = demo_code_dir.join("repro.json");
+            let f = File::create(&repropath)?;
+            serde_json::to_writer(f, &json)?;
+            Ok(Input::ReproCase(repropath))
+        },
+        false,
+    )
+}
+
+#[test]
+#[ignore] // takes absolutely ages but you can run using cargo test -- --ignored
+fn test_reduce_preprocessed_repro_case() -> Result<(), Box<dyn std::error::Error>> {
+    do_reduce(
+        |header, demo_code_dir| {
+            write_minimal_rs_code(header, demo_code_dir);
+            let repro = demo_code_dir.join("autocxx-repro.json");
+            let mut cmd = Command::cargo_bin("autocxx-gen")?;
+            cmd.arg("--inc")
+                .arg(demo_code_dir.to_str().unwrap())
+                .arg(demo_code_dir.join("main.rs"))
+                .env("AUTOCXX_REPRO_CASE", repro.to_str().unwrap())
+                .arg("--outdir")
+                .arg(demo_code_dir.to_str().unwrap())
+                .arg("--gen-cpp")
+                .arg("--suppress-system-headers")
+                .assert()
+                .success();
+            Ok(Input::ReproCase(repro))
+        },
+        false,
+    )
+}
+
+#[test]
+#[ignore] // takes absolutely ages but you can run using cargo test -- --ignored
+fn test_reduce_preprocessed() -> Result<(), Box<dyn std::error::Error>> {
+    do_reduce(
+        |header, demo_code_dir| {
+            write_minimal_rs_code(header, demo_code_dir);
+            let prepro = demo_code_dir.join("autocxx-preprocessed.h");
+            let mut cmd = Command::cargo_bin("autocxx-gen")?;
+            cmd.arg("--inc")
+                .arg(demo_code_dir.to_str().unwrap())
+                .arg(demo_code_dir.join("main.rs"))
+                .env("AUTOCXX_PREPROCESS", prepro.to_str().unwrap())
+                .arg("--outdir")
+                .arg(demo_code_dir.to_str().unwrap())
+                .arg("--gen-cpp")
+                .arg("--suppress-system-headers")
+                .assert()
+                .success();
+            Ok(Input::Header("autocxx-preprocessed.h".into()))
+        },
+        false,
+    )
+}
+
+#[test]
+#[ignore] // takes absolutely ages but you can run using cargo test -- --ignored
+fn test_reduce_preprocessed_include_cxx_h() -> Result<(), Box<dyn std::error::Error>> {
+    do_reduce(
+        |header, demo_code_dir| {
+            write_minimal_rs_code(header, demo_code_dir);
+            let prepro = demo_code_dir.join("autocxx-preprocessed.h");
+            let mut cmd = Command::cargo_bin("autocxx-gen")?;
+            cmd.arg("--inc")
+                .arg(demo_code_dir.to_str().unwrap())
+                .arg(demo_code_dir.join("main.rs"))
+                .env("AUTOCXX_PREPROCESS", prepro.to_str().unwrap())
+                .arg("--outdir")
+                .arg(demo_code_dir.to_str().unwrap())
+                .arg("--gen-cpp")
+                .arg("--suppress-system-headers")
+                .assert()
+                .success();
+            Ok(Input::Header("autocxx-preprocessed.h".into()))
+        },
+        true,
+    )
+}
+
+fn write_minimal_rs_code(header: &str, demo_code_dir: &Path) {
+    let hexathorpe = Token![#](Span::call_site());
+    write_to_file(
+        demo_code_dir,
+        "main.rs",
+        quote! {
+            autocxx::include_cpp! {
+                #hexathorpe include #header
+                generate!("WithMethods")
+                block!("First")
+                safety!(unsafe_ffi)
+            }
+        }
+        .to_string()
+        .as_bytes(),
+    );
+}
+
+fn do_reduce<F>(get_repro_case: F, include_cxx_h: bool) -> Result<(), Box<dyn std::error::Error>>
+where
+    F: FnOnce(&str, &Path) -> Result<Input, Box<dyn std::error::Error>>,
+{
+    if creduce_is_broken() {
+        return Ok(());
+    }
+    let tmp_dir = TempDir::new("example")?;
+    let demo_code_dir = tmp_dir.path().join("demo");
+    std::fs::create_dir(&demo_code_dir).unwrap();
+    let input_header = if include_cxx_h {
+        Cow::Owned(format!("#include \"cxx.h\"\n{}", INPUT_H))
+    } else {
+        Cow::Borrowed(INPUT_H)
+    };
+    write_to_file(&demo_code_dir, "input.h", input_header.as_bytes());
+    write_to_file(&demo_code_dir, "cxx.h", cxx_gen::HEADER.as_bytes());
+    let output_path = tmp_dir.path().join("min.h");
+    let repro_case = get_repro_case("input.h", &demo_code_dir)?;
+    let mut cmd = Command::cargo_bin("autocxx-reduce")?;
+    let mut cmd = cmd
+        .arg("-o")
+        .arg(output_path.to_str().unwrap())
+        .arg("-p")
+        .arg("type marked as blocked")
+        .arg("-k");
+    match repro_case {
+        Input::Header(header_name) => {
+            cmd = cmd
+                .arg("file")
+                .arg("--inc")
+                .arg(demo_code_dir.to_str().unwrap())
+                .arg("--header")
+                .arg(header_name)
+                .arg("-d")
+                .arg("generate!(\"WithMethods\")")
+                .arg("-d")
+                .arg("block!(\"First\")");
+        }
+        Input::ReproCase(repro_case) => {
+            cmd = cmd.arg("repro").arg("-r").arg(repro_case);
+        }
+    }
+    eprintln!("Running {:?}", cmd);
+    let o = cmd.output()?;
+    println!("Reduce output: {}", std::str::from_utf8(&o.stdout).unwrap());
+    println!("Reduce error: {}", std::str::from_utf8(&o.stderr).unwrap());
+    if !o.status.success() {
+        panic!("autocxx-reduce returned non-zero result code");
+    }
+    let minimized = std::fs::read_to_string(output_path)?;
+    assert!(minimized.contains("First"));
+    assert!(!minimized.contains("DoMath"));
+    Ok(())
+}
+
+fn write_to_file(dir: &Path, filename: &str, content: &[u8]) {
+    let path = dir.join(filename);
+    let mut f = File::create(&path).expect("Unable to create file");
+    f.write_all(content).expect("Unable to write file");
+}
+
+fn creduce_is_broken() -> bool {
+    // On some machines, creduce immediately segfaults
+    Command::new("creduce").arg("--version").ok().is_err()
+}
diff --git a/tools/stress-test/Cargo.toml b/tools/stress-test/Cargo.toml
new file mode 100644
index 0000000..6f15e42
--- /dev/null
+++ b/tools/stress-test/Cargo.toml
@@ -0,0 +1,21 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+[package]
+name = "autocxx-stress-test"
+version = "0.22.0"
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
+edition = "2021"
+
+[dependencies]
+cxx = "1.0.54"
+autocxx = { path = "../..", version="0.22.0" }
+
+[build-dependencies]
+autocxx-build = { path = "../../gen/build", version="0.22.0" }
+miette = { version="4.3", features=["fancy"]}
diff --git a/tools/stress-test/README.md b/tools/stress-test/README.md
new file mode 100644
index 0000000..7a1801c
--- /dev/null
+++ b/tools/stress-test/README.md
@@ -0,0 +1,5 @@
+This directory contains a code example which tries to generate bindings to all the things
+in various STL headers.
+
+This currently is a long way from working, so there's a reduce.sh script in this directory
+which helps identify and minimize test cases for each new problem.
diff --git a/tools/stress-test/build.rs b/tools/stress-test/build.rs
new file mode 100644
index 0000000..bffd96f
--- /dev/null
+++ b/tools/stress-test/build.rs
@@ -0,0 +1,17 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() -> miette::Result<()> {
+    let path = std::path::PathBuf::from("src");
+    let mut b = autocxx_build::Builder::new("src/main.rs", &[&path]).build()?;
+    b.flag_if_supported("-std=c++14").compile("autocxx-stress-test");
+
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/input.h");
+    Ok(())
+}
diff --git a/tools/stress-test/reduce.sh b/tools/stress-test/reduce.sh
new file mode 100755
index 0000000..0722825
--- /dev/null
+++ b/tools/stress-test/reduce.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Using this stress test
+# 1. cargo build
+# 2. Spot what error message appears (because something will)
+# 3. Create a new directory and cd into it
+# 4. Run this script passing the error message as an argument
+# 5. Wait (consider running tail -f nohup.out)
+# 6. Several days later, a minimized test case should appear in nohup.out.
+
+set -e
+
+PROBLEM="$1"
+SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
+TEST_CASE_DIR=$(pwd)
+
+if [ !-n "$PROBLEM" ]; then
+  echo "Specify a compile error as an argument"
+  exit -1
+fi
+
+echo "About to minimize stress test. Problem is '$PROBLEM' and script dir is '$SCRIPT_DIR'. Test case dir is $TEST_CASE_DIR"
+
+REPRO_CASE="$TEST_CASE_DIR/repro.json"
+
+pushd $SCRIPT_DIR
+touch src/main.rs
+echo Building with repro case
+AUTOCXX_REPRO_CASE=$REPRO_CASE cargo build --release || true
+echo Built.
+popd
+
+echo Building autocxx-reduce and friends
+pushd $SCRIPT_DIR/../..
+cargo build --all --release
+popd
+
+echo Starting reduction
+nohup $SCRIPT_DIR/../../target/release/autocxx-reduce --problem "$PROBLEM" -k --clang-arg=-std=c++17 --creduce-arg=--n --creduce-arg=192 repro -r "$REPRO_CASE" &
+echo Reduction underway. Consider using tail -f nohup.out.
+
diff --git a/tools/stress-test/src/input.h b/tools/stress-test/src/input.h
new file mode 100644
index 0000000..31961d6
--- /dev/null
+++ b/tools/stress-test/src/input.h
@@ -0,0 +1,17 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#pragma once
+
+#include <cstdint>
+#include <sstream>
+#include <stdint.h>
+#include <string>
+
+inline void DoNothing() {
+}
diff --git a/tools/stress-test/src/main.rs b/tools/stress-test/src/main.rs
new file mode 100644
index 0000000..94d9bc0
--- /dev/null
+++ b/tools/stress-test/src/main.rs
@@ -0,0 +1,19 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use autocxx::prelude::*;
+include_cpp! {
+    #include "input.h"
+    safety!(unsafe_ffi)
+    generate_all!()
+}
+
+fn main() {
+    ffi::DoNothing();
+    println!("Gosh, it worked.");
+}
diff --git a/tools/upgrade-cxx.sh b/tools/upgrade-cxx.sh
new file mode 100755
index 0000000..eb01333
--- /dev/null
+++ b/tools/upgrade-cxx.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# Just specify the final numbers (e.g. 42 for 1.0.42)
+OLD=$1
+NEW=$2
+find . -type f -name "Cargo.toml" -print0 | xargs -0 sed -i -e "s/1.0.$OLD/1.0.$NEW/g" # cxx
+find . -type f -name "Cargo.toml" -print0 | xargs -0 sed -i -e "s/0.7.$OLD/0.7.$NEW/g" # cxx-gen
diff --git a/tools/upgrade-version.sh b/tools/upgrade-version.sh
new file mode 100755
index 0000000..58ed04a
--- /dev/null
+++ b/tools/upgrade-version.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+OLD=$1
+NEW=$2
+find . -type f -name "Cargo.toml" -print0 | xargs -0 sed -i '' -e "s/$OLD/$NEW/g"
+find . -type f -name "*.md" -print0 | xargs -0 sed -i '' -e "s/$OLD/$NEW/g"