text:
abstract AbstractFinancialID
abstract AbstractCurrency
abstract AbstractInstrument

type Ticker
    id::String
end

type CUSIP <: AbstractFinancialID
    id::String
end

type BloombergID <: AbstractFinancialID
    id::String
end

type ReutersID <: AbstractFinancialID
     id::String
end

type Currency <: AbstractCurrency
    origin::String
end

type CurrencyPair <: AbstractCurrency
    baseside::Currency
    quoteside::Currency
end

type Stock <: AbstractInstrument
    ticker::Ticker
    #cusip::CUSIP
#    id::Dict{typeof(AbstractInstrument),AbstractInstrument}
#    id::Dict(typeof(AbstractFinancialID)=>AbstractFinancialID)[]
    currency::Currency
    tick::Float64
    multiplier::Float64
end

#Stock(ticker::Ticker) = Stock(ticker, [CUSIP=>CUSIP("123")], USD, .01, 1)
Stock(ticker::Ticker) = Stock(ticker, USD, .01, 1)

############ const ################

const USD = Currency("USD")
const GBP = Currency("GBP")
const EUR = Currency("EUR")
const AUD = Currency("AUD")
const NZD = Currency("NZD")
const JPY = Currency("JPY")

const EURUSD = CurrencyPair(EUR,USD)
const EURJPY = CurrencyPair(EUR,JPY)
const AUDUSD = CurrencyPair(AUD,USD)
const NZDUSD = CurrencyPair(NZD,USD)
const GBPUSD = CurrencyPair(GBP,USD)
const USDJPY = CurrencyPair(USD,JPY)

const F = "Jan"
const G = "Feb"
const H = "Mar"
const J = "Apr"
const K = "May"
const M = "Jun"
const N = "Jul"
const Q = "Aug"
const U = "Sep"
const X = "Oct"
const V = "Nov"
const Z = "Dec"

############ show methods ################

function show(io::IO, c::CUSIP)
    print(io, @sprintf("%s", c.id))
end

function show(io::IO, c::ReutersID)
    print(io, @sprintf("%s", c.id))
end

function show(io::IO, c::BloombergID)
    print(io, @sprintf("%s", c.id))
end

function show(io::IO, t::Ticker)
    print(io, @sprintf("%s", t.id))
end

function show(io::IO, s::Stock)
    println(io, @sprintf("ticker:         %s", s.ticker))
#    println(io, @sprintf("cusip:          %s", s.cusip))
    println(io, @sprintf("currency:       %s", s.currency))
    println(io, @sprintf("tick:           %s", s.tick))
    println(io, @sprintf("multiplier:     %s", s.multiplier))
end

function show(io::IO, c::Currency)
    print(io, @sprintf("%s", c.origin))
end

function show(io::IO, c::CurrencyPair)
    print(io, @sprintf("%s/%s", string(c.baseside), string(c.quoteside)))
end


text:
push!(LOAD_PATH,"../")

using Documenter
using DescentMethods

makedocs(
    ;
    sitename="Documentation",
    modules=[DescentMethods],
    pages = [
        "index.md",
        "Optimization Methods" => "core_types.md",
        "Basic Functions" => "functions.md",
    ]
)

deploydocs(
    repo = "github.com/vvpisarev/DescentMethods.jl.git",
)

ext: jl


text:
module SimpleSDMDataSources

# Load the dependencies for this package
using HTTP,
      ZipFile,
      Dates

# Abstract types for the download
abstract type SDMDataSource end
abstract type SDMDataSet end

# List of data sources

struct WorldClim{X} <: SDMDataSource end
struct CHELSA{X} <: SDMDataSource end
struct EarthEnv{X} <: SDMDataSource end

export WorldClim, CHELSA, EarthEnv, AWAP, ALWB

# List of data sets
struct Weather <: SDMDataSet end
struct BioClim <: SDMDataSet end
struct LandCover <: SDMDataSet end
struct HabitatHeterogeneity <: SDMDataSet end

export BioClim, Weather, LandCover, HabitatHeterogeneity

# Using types to specify layers makes sense in some contexts
# These are exported for AWAP, but are experimental
export Temperature, VapourPressure, Solar, Rainfall, H09, H15, MinAve, MaxAve

export download_raster, rasterpath

# Create a path for the various assets
include("assets_path.jl")

# Download the files if they don't exist
include("download.jl")

# Download raster data
include("worldclim/shared.jl")
include("worldclim/bioclim.jl")
include("worldclim/weather.jl")
include("chelsa/bioclim.jl")
include("earthenv/shared.jl")
include("earthenv/landcover.jl")
include("earthenv/habitatheterogeneity.jl")
include("awap/awap.jl")
include("alwb/alwb.jl")

export download_raster

end # module


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule TMatrix_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("TMatrix")
JLLWrappers.@generate_main_file("TMatrix", UUID("f6676dc9-6ae6-5380-b4ed-33bd8634dc70"))
end  # module TMatrix_jll


text:
function build_LOModel_result(lom::LaplacianOptModel, solve_time::Number)
    # try-catch is needed until solvers reliably support ResultCount()
    result_count = 1
    try
        result_count = JuMP.result_count(lom.model)
    catch
        Memento.warn(_LOGGER, "the given optimizer does not provide the ResultCount() attribute, assuming the solver returned a solution which may be incorrect.");
    end

    solution = Dict{String,Any}()

    if result_count > 0
        solution = LOpt.build_LOModel_solution(lom)
    else
        Memento.warn(_LOGGER, "LaplacianOpt model has no results - solution cannot be built")
    end

    result = Dict{String,Any}(
        "optimizer" => JuMP.solver_name(lom.model),
        "termination_status" => JuMP.termination_status(lom.model),
        "primal_status" => JuMP.primal_status(lom.model),
        "objective" => get_objective_value(lom.model),
        "objective_ub" => get_objective_bound(lom.model),
        "solve_time" => solve_time,
        "solution" => solution,
    )

    return result
end

""
function get_objective_value(model::JuMP.Model)

    obj_val = NaN

    try
        obj_val = JuMP.objective_value(model)
    catch
        Memento.warn(_LOGGER, "Objective value is unbounded. Problem may be infeasible or not constrained properly");
    end

    return obj_val
end

""
function get_objective_bound(model::JuMP.Model)

    obj_lb = -Inf

    try
        obj_lb = JuMP.objective_bound(model)
    catch
    end

    return obj_lb
end

function build_LOModel_solution(lom::LaplacianOptModel)

    solution = Dict{String,Any}()

    for i in keys(lom.variables)
        solution[String(i)] = JuMP.value.(lom.variables[i])
    end

    return solution
end


text:
#helper.jl

using StructJuMP, JuMP
import MathProgBase

export get_nlp_evaluator, convert_to_lower, array_copy, write_mat_to_file, convert_to_c_idx, write_x
export @declare_second_stage, @timing, @message
export strip_x, build_x
export PIPSRetCodeToSolverInterfaceCode

const PIPSRetCode = Dict{Int, Symbol}(
    0=>:SUCCESSFUL_TERMINATION,
    1=>:NOT_FINISHED,
    2=>:MAX_ITS_EXCEEDED,
    3=>:INFEASIBLE,
    4=>:NEED_FEASIBILITY_RESTORATION,
    5=>:UNKNOWN
    )

const PIPSRetCodeToSolverInterfaceCode = Dict{Int, Int}(
    0=>0,
    1=>8,
    2=>-1,
    3=>2,
    4=>7,
    5=>8
    )

function strip_x(m,id,x,start_idx)
    mm = getModel(m,id)
    nx = getNumVars(m,id)
    new_x = Vector{Float64}(MathProgBase.numvar(mm))
    array_copy(x,start_idx,new_x,1,nx)

    othermap = getStructure(mm).othermap
    for i in othermap
        pid = i[1].col
        cid = i[2].col
        new_x[cid] = x[pid]
        @assert cid > nx
    end
    return new_x
end

function build_x(m,id,x0,x1)
    # @show "build_x", id, length(x0), length(x1)
    # @show x0, x1
    if id==0
        # @show x0
        return x0
    else
        #build x using index tracking info
        mm = getModel(m,id)
        othermap = getStructure(mm).othermap
        new_x = Vector{Float64}(MathProgBase.numvar(mm))
        unsafe_copy!(new_x,1,x1,1,length(x1))
        for e in othermap
            pidx = e[1].col
            cidx = e[2].col
            # @show pidx, cidx
            assert(cidx > length(x1))
            new_x[cidx] = x0[pidx]
        end
        # @show new_x
        return new_x
    end
end

function get_nlp_evaluator(m,id)
    # @show id,getScenarioIds(m)
    # @show getProcIdxSet(m)
    # assert(id == 0 || id in getProcIdxSet(m))
    e = JuMP.NLPEvaluator(getModel(m,id))
    MathProgBase.initialize(e,[:Grad,:Jac,:Hess])
    return e
end

function array_copy(src,os, dest, od, n)
    for i=0:n-1
        dest[i+od] = src[i+os]
    end
end

function write_mat_to_file(filename,mat)
    if(false)
        filename = string("./mat/",filename)
        pre_filename = string(filename,"_0")
        i = 0
        while isfile(pre_filename)
            i += 1
            pre_filename = string(filename,"_",i)
        end
        @show "output : ", pre_filename
        writedlm(pre_filename,mat,",")
    end
end

function convert_to_c_idx(indicies)
    for i in 1:length(indicies)
        indicies[i] = indicies[i] - 1
    end
end

function convert_to_lower(I,J,rI,rJ)
    @assert length(I) == length(J) == length(rI) == length(rJ)
    for i in 1:length(I)
        if I[i] < J[i]
            rI = I[i]
            rJ = J[i]
        else
            rI = J[i]
            rJ = I[i]
        end
    end
    return rI, rJ
end

function write_x(subdir,iter,x)
    @printf("writing x to ./%s/x%d \n",subdir,iter)
    run(`mkdir -p ./$subdir`)
    writedlm(string("./",subdir,"/x",iter),x,",")
end

macro message(s)
    return quote
        rank, nprocs = getMyRank()
        @printf("[%d/%d] [ %s ] \n", rank, nprocs, $(esc(s)))
    end
end

macro declare_second_stage(m,ind,code)
    return quote
        proc_idx_set = getLocalChildrenIds($(esc(m)))
        # @show proc_idx_set
        for $(esc(ind)) in proc_idx_set
            $(esc(code))
        end
    end
end

macro timing(cond,code)
    return quote
        if $(esc(cond))
            $(esc(code))
       end
    end
end

function SparseArrays.sparse(I,J,V, M, N;keepzeros=false)
    if(!keepzeros)
        return sparse(I,J,V,M,N)
    else
        full = sparse(I,J,ones(Float64,length(I)),M,N)
        actual = sparse(I,J,V,M,N)
        fill!(full.nzval,0.0)

        for c = 1:N
            for i=nzrange(actual,c)
                r = actual.rowval[i]
                v = actual.nzval[i]
                if(v!=0)
                    full[r,c] = v
                end
            end
            # full.nzval[crange] = actual.nzval[crange]
        end
        return full
    end
end


text:
module SpriteDumperWindow

using Maple, Cairo
using Gtk, Gtk.ShortNames
using ..Ahorn

# This will not dump original sprites if any of those are overwritten
function dumpSpritesDialog(w)
    celesteDir = get(Ahorn.config, "celeste_dir", "")
    targetDir = ispath(celesteDir) ? celesteDir : pwd()

    outdir = Ahorn.saveDialog("Save as", Ahorn.window, action=GtkFileChooserAction.SELECT_FOLDER, folder=targetDir)
    useRealSize = get(Ahorn.debug.config, "SPRITE_DUMPER_REAL_SIZE", true)

    if outdir != ""
        for (atlas, sprites) in Ahorn.atlases
            for (name, spriteHolder) in sprites
                sprite = spriteHolder.sprite

                if sprite.width == 0 && sprite.height == 0
                    continue
                end

                filename = joinpath(outdir, atlas, name) * ".png"

                width = useRealSize ? sprite.realWidth : sprite.width
                height = useRealSize ? sprite.realHeight : sprite.height

                offsetX = useRealSize ? -sprite.offsetX : 0
                offsetY = useRealSize ? -sprite.offsetY : 0

                surface = Cairo.CairoARGBSurface(width, height)
                ctx = Ahorn.getSurfaceContext(surface)

                Ahorn.drawImage(ctx, sprite, offsetX, offsetY, alpha=1.0)

                mkpath(dirname(filename))
                open(io -> Cairo.write_to_png(surface, io), filename, "w")

                Cairo.destroy(surface)
            end
        end
    end

    Ahorn.info_dialog("Done dumping sprites.", Ahorn.window)
end

end


text:
#unum-test-warlpiri.jl

#unit tests based on warlpiri mathematics.
#not part of the main test suite.

#some useful unsigned int constants

#create the warlpiri type.  This is a 0/0 unum.
Warlpiri = Unum{0,0}
#an external constructor will make things a bit easier, sadly we have to lower case this.
warlpiri(exp::UInt64, frac::UInt64, flags::UInt16) = Warlpiri(exp, frac, flags, z16, z16)

#create english words for each of the warlpiri unums
stop_ = Unums.nan(Warlpiri, Unums.UNUM_SIGN_MASK)
n_all = neg_inf(Warlpiri)
nmany = warlpiri(o64, z64, 0x0003)
n_two = warlpiri(o64, z64, 0x0002)
nsome = warlpiri(z64, t64, 0x0003)
n_one = Unums.additiveinverse!(one(Warlpiri))
n_few = warlpiri(z64, z64, 0x0003)
nnone = Unums.additiveinverse!(zero(Warlpiri))
none_ = zero(Warlpiri)
pfew_ = warlpiri(z64, z64, 0x0001)
pone_ = one(Warlpiri)
psome = warlpiri(z64, t64, 0x0001)
ptwo_ = warlpiri(o64, z64, 0x0000)
pmany = warlpiri(o64, z64, 0x0001)
pall_ = pos_inf(Warlpiri)
junk_ = Warlpiri(NaN)
#check the bits on all of the warpiri unums
@test "1111" == bits(stop_)
@test "1110" == bits(n_all)
@test "1101" == bits(nmany)
@test "1100" == bits(n_two)
@test "1011" == bits(nsome)
@test "1010" == bits(n_one)
@test "1001" == bits(n_few)
@test "1000" == bits(nnone)
@test "0000" == bits(none_)
@test "0001" == bits(pfew_)
@test "0010" == bits(pone_)
@test "0011" == bits(psome)
@test "0100" == bits(ptwo_)
@test "0101" == bits(pmany)
@test "0110" == bits(pall_)
@test "0111" == bits(junk_)

@test none_ == nnone #and also that negative zero equals zero.

#create the warlarray, simple ordered array of warlpiris, by bit representation, minus the stop_.
warlpiris = [none_, pfew_, pone_, psome, ptwo_, pmany, pall_, junk_, nnone, n_few, n_one, nsome, n_two, nmany, n_all]

#the complete set of warlpiri ubounds
na_nm = Ubound{0,0}(n_all, nmany)
na_nt = Ubound{0,0}(n_all, n_two)
na_ns = Ubound{0,0}(n_all, nsome)
na_no = Ubound{0,0}(n_all, n_one)
na_nf = Ubound{0,0}(n_all, n_few)
na_n_ = Ubound{0,0}(n_all, none_)
na_pf = Ubound{0,0}(n_all, pfew_)
na_po = Ubound{0,0}(n_all, pone_)
na_ps = Ubound{0,0}(n_all, psome)
na_pt = Ubound{0,0}(n_all, ptwo_)
na_pm = Ubound{0,0}(n_all, pmany)
na_pa = Ubound{0,0}(n_all, pall_)

nm_nt = Ubound{0,0}(nmany, n_two)
nm_ns = Ubound{0,0}(nmany, nsome)
nm_no = Ubound{0,0}(nmany, n_one)
nm_nf = Ubound{0,0}(nmany, n_few)
nm_n_ = Ubound{0,0}(nmany, none_)
nm_pf = Ubound{0,0}(nmany, pfew_)
nm_po = Ubound{0,0}(nmany, pone_)
nm_ps = Ubound{0,0}(nmany, psome)
nm_pt = Ubound{0,0}(nmany, ptwo_)
nm_pm = Ubound{0,0}(nmany, pmany)
nm_pa = Ubound{0,0}(nmany, pall_)

nt_ns = Ubound{0,0}(n_two, nsome)
nt_no = Ubound{0,0}(n_two, n_one)
nt_nf = Ubound{0,0}(n_two, n_few)
nt_n_ = Ubound{0,0}(n_two, none_)
nt_pf = Ubound{0,0}(n_two, pfew_)
nt_po = Ubound{0,0}(n_two, pone_)
nt_ps = Ubound{0,0}(n_two, psome)
nt_pt = Ubound{0,0}(n_two, ptwo_)
nt_pm = Ubound{0,0}(n_two, pmany)
nt_pa = Ubound{0,0}(n_two, pall_)

ns_no = Ubound{0,0}(nsome, n_one)
ns_nf = Ubound{0,0}(nsome, n_few)
ns_n_ = Ubound{0,0}(nsome, none_)
ns_pf = Ubound{0,0}(nsome, pfew_)
ns_po = Ubound{0,0}(nsome, pone_)
ns_ps = Ubound{0,0}(nsome, psome)
ns_pt = Ubound{0,0}(nsome, ptwo_)
ns_pm = Ubound{0,0}(nsome, pmany)
ns_pa = Ubound{0,0}(nsome, pall_)

no_nf = Ubound{0,0}(n_one, n_few)
no_n_ = Ubound{0,0}(n_one, none_)
no_pf = Ubound{0,0}(n_one, pfew_)
no_po = Ubound{0,0}(n_one, pone_)
no_ps = Ubound{0,0}(n_one, psome)
no_pt = Ubound{0,0}(n_one, ptwo_)
no_pm = Ubound{0,0}(n_one, pmany)
no_pa = Ubound{0,0}(n_one, pall_)

nf_n_ = Ubound{0,0}(n_few, none_)
nf_pf = Ubound{0,0}(n_few, pfew_)
nf_po = Ubound{0,0}(n_few, pone_)
nf_ps = Ubound{0,0}(n_few, psome)
nf_pt = Ubound{0,0}(n_few, ptwo_)
nf_pm = Ubound{0,0}(n_few, pmany)
nf_pa = Ubound{0,0}(n_few, pall_)

n__pf = Ubound{0,0}(none_, pfew_)
n__po = Ubound{0,0}(none_, pone_)
n__ps = Ubound{0,0}(none_, psome)
n__pt = Ubound{0,0}(none_, ptwo_)
n__pm = Ubound{0,0}(none_, pmany)
n__pa = Ubound{0,0}(none_, pall_)

pf_po = Ubound{0,0}(pfew_, pone_)
pf_ps = Ubound{0,0}(pfew_, psome)
pf_pt = Ubound{0,0}(pfew_, ptwo_)
pf_pm = Ubound{0,0}(pfew_, pmany)
pf_pa = Ubound{0,0}(pfew_, pall_)

po_ps = Ubound{0,0}(pone_, psome)
po_pt = Ubound{0,0}(pone_, ptwo_)
po_pm = Ubound{0,0}(pone_, pmany)
po_pa = Ubound{0,0}(pone_, pall_)

ps_pt = Ubound{0,0}(psome, ptwo_)
ps_pm = Ubound{0,0}(psome, pmany)
ps_pa = Ubound{0,0}(psome, pall_)

pt_pm = Ubound{0,0}(ptwo_, pmany)
pt_pa = Ubound{0,0}(ptwo_, pall_)

pm_pa = Ubound{0,0}(pmany, pall_)

#and a general purpose function for testing an operation,
function testop(op, expected)
  #now create a matrix of warlpiris
  fails = 0
  for i=1:15
    for j=1:15
      try
        res = op(warlpiris[i], warlpiris[j])
        if !isequal(res, expected[i, j])
          println("$i, $j: $(bits(warlpiris[i])) $op $(bits(warlpiris[j])) failed as $(bits(res)); should be $(bits(expected[i,j]))")
          fails += 1
        end
      catch e
        println("$i, $j: $(bits(warlpiris[i])) $op $(bits(warlpiris[j])) failed due to thrown error: $e")
        bt = catch_backtrace()
        s = sprint(io->Base.show_backtrace(io, bt))
        println("$s")
        fails += 1
      end
    end
  end
  println("$op $fails / 225 = $(100 * fails/225)% failure!")
end

include("./warlpiri/test-warlpiri-ordering.jl")
include("./warlpiri/test-warlpiri-addition.jl")
include("./warlpiri/test-warlpiri-multiplication.jl")
include("./warlpiri/test-warlpiri-division.jl")

max_stars_repo_name: REX-Computing/unumjl

max_issues_repo_name: REX-Computing/unumjl

max_forks_repo_name: REX-Computing/unumjl


text:
using Test, Lattices

lattice = Square(4, 5)

test_sites = []
for i = 1:5
    for j = 1:4
        push!(test_sites, (j, i))
    end
end
test_sites
@test collect(sites(lattice)) == test_sites
edges(lattice)

function check_index(lattice::Square{Tuple{h, w}, Periodic}) where {h, w}
    count = 1
    for i = 1:w
        for j = 1:h
            @test lattice[j, i] == count
            count += 1
        end
    end

    @test lattice[h+1, 2] == lattice[1, 2]
    @test lattice[2, w+1] == lattice[2, 1]

    true
end

function check_index(lattice::Square{Tuple{h, w}, Fixed}) where {h, w}
    count = 1
    for i = 1:w
        for j = 1:h
            @test lattice[j, i] == count
            count += 1
        end
    end
    true
end

@test check_index(Square(4, 5, boundary=Periodic))
@test check_index(Square(4, 5, boundary=Fixed))

lattice = Square(4, 5, boundary=Fixed)
@test_throws BoundsError lattice[1, 6]


text:
using PyCall

@pyimport matplotlib as mpl
mpl.use("Agg")
mpl.interactive(false)

using PyPlot

# rc("font", size=12)
rc("axes.formatter", use_mathtext=true)
rc("axes.formatter", useoffset=false)


text:
"Map from PCRaster LDD value to a CartesianIndex"
const pcr_dir = [
    CartesianIndex(-1, -1),  # 1
    CartesianIndex(0, -1),  # 2
    CartesianIndex(1, -1),  # 3
    CartesianIndex(-1, 0),  # 4
    CartesianIndex(0, 0),  # 5
    CartesianIndex(1, 0),  # 6
    CartesianIndex(-1, 1),  # 7
    CartesianIndex(0, 1),  # 8
    CartesianIndex(1, 1),  # 9
]

const mv = Float(NaN)

# timestep that the parameter units are defined in
const basetimestep = Second(Day(1))

"Set at indices pit values (default = 5) in a gridded local drainage direction vector"
function set_pit_ldd(pits_2d, ldd, indices; pit = 5)
    pits = pits_2d[indices]
    index = filter(i -> isequal(pits[i], true), 1:length(indices))
    ldd[index] .= pit
    return ldd
end

"Filter upstream neighbors of graph based on logical vector"
function filter_upsteam_nodes(graph, vec_logical::Vector{Bool})
    upstream_nodes = Vector{Int}[]
    for v in topological_sort_by_dfs(graph)
        ups_nodes = inneighbors(graph, v)
        push!(upstream_nodes, filter(i -> !vec_logical[i], ups_nodes))
    end
    return upstream_nodes
end

"""
    active_indices(subcatch_2d, nodata)

Takes a 2D array of the subcatchments. And derive forward and reverse indices.

1: Get a list of `CartesianIndex{2}`` that are active, based on a nodata value.
These map from the 1D internal domain to the 2D external domain.

2: Make a reverse index, a `Matrix{Int}``, which maps from the 2D external domain to
the 1D internal domain, providing an Int which can be used as a linear index. Values of 0
represent inactive cells.
"""
function active_indices(subcatch_2d::AbstractMatrix, nodata)
    A = subcatch_2d
    all_inds = CartesianIndices(size(A))
    indices = filter(i -> !isequal(A[i], nodata), all_inds)

    reverse_indices = zeros(Int, size(A))
    for (i, I) in enumerate(indices)
        reverse_indices[I] = i
    end

    return indices, reverse_indices
end

function active_indices(network::NamedTuple, key::Tuple)
    if :reservoir in key
        return network.reservoir.indices_outlet
    elseif :lake in key
        return network.lake.indices_outlet
    elseif :river in key
        return network.river.indices
    elseif :drain in key
        return network.drain.indices
    else
        return network.land.indices
    end
end

function lattometres(lat::Real)
    m1 = 111132.92     # latitude calculation term 1
    m2 = -559.82       # latitude calculation term 2
    m3 = 1.175         # latitude calculation term 3
    m4 = -0.0023       # latitude calculation term 4
    p1 = 111412.84     # longitude calculation term 1
    p2 = -93.5         # longitude calculation term 2
    p3 = 0.118         # longitude calculation term 3

    # Calculate the length of a degree of latitude and longitude in meters
    latlen = m1 + (m2 * cosd(2.0 * lat)) + (m3 * cosd(4.0 * lat)) + (m4 * cosd(6.0 * lat))
    longlen = (p1 * cosd(lat)) + (p2 * cosd(3.0 * lat)) + (p3 * cosd(5.0 * lat))

    return longlen, latlen
end

function cell_lengths(y::AbstractVector, cellength::Real, sizeinmetres::Bool)
    n = length(y)
    xl = fill(mv, n)
    yl = fill(mv, n)
    if sizeinmetres
        xl .= cellength
        yl .= cellength
    else
        for i = 1:n
            longlen, latlen = lattometres(y[i])
            xl[i] = longlen * cellength
            yl[i] = latlen * cellength
        end
    end
    return xl, yl
end

function river_fraction(
    river::AbstractVector,
    riverlength::AbstractVector,
    riverwidth::AbstractVector,
    xl::AbstractVector,
    yl::AbstractVector,
)
    n = length(river)
    riverfrac = fill(mv, n)
    for i = 1:n
        riverfrac[i] = if river[i]
            min((riverlength[i] * riverwidth[i]) / (xl[i] * yl[i]), 1.0)
        else
            0.0
        end
    end
    return riverfrac
end

"""
    set_states(instate_path, model, state_ncnames; <keyword arguments>)

Read states contained in `Dict` `state_ncnames` from NetCDF file located in `instate_path`,
and set states in `model` object. Active cells are selected with the corresponding network's
(`Vector{CartesianIndex}`) from the NetCDF file.

# Arguments
- `type = nothing`: type to convert data to after reading. By default no conversion is done.
"""
function set_states(instate_path, model, state_ncnames; type = nothing, dimname = nothing)
    @unpack network = model
    # states in NetCDF include dim time (one value) at index 3 or 4, 3 or 4 dims are allowed
    NCDataset(instate_path) do ds
        for (state, ncname) in state_ncnames
            @info "Setting initial state from NetCDF." ncpath = instate_path ncvarname =
                ncname state
            sel = active_indices(network, state)
            n = length(sel)
            dims = length(dimnames(ds[ncname]))
            # 4 dims, for example (x,y,layer,time) where dim layer is an SVector for soil layers
            if dims == 4
                if dimname == :layer
                    dimensions = (x = :, y = :, layer = :, time = 1)
                elseif dimname == :classes
                    dimensions = (x = :, y = :, classes = :, time = 1)
                else
                    error("Unrecognized dimension name $dimname")
                end
                A = read_standardized(ds, ncname, dimensions)
                A = permutedims(A[sel, :])
                # note that this array is allowed to have missings, since not every vertical
                # column is `maxlayers` layers deep
                if dimname == :layer
                    A = replace!(A, missing => NaN)
                end
                # Convert to desired type if needed
                if !isnothing(type)
                    if eltype(A) != type
                        A = map(type, A)
                    end
                end
                # set state in model object
                param(model, state) .= svectorscopy(A, Val{size(A)[1]}())
            # 3 dims (x,y,time)
            elseif dims == 3
                A = read_standardized(ds, ncname, (x = :, y = :, time = 1))
                A = A[sel]
                A = nomissing(A)
                # Convert to desired type if needed
                if !isnothing(type)
                    if eltype(A) != type
                        A = map(type, A)
                    end
                end
                # set state in model object, only set active cells ([1:n]) (ignore boundary conditions/ghost points)
                param(model, state)[1:n] .= A
            else
                error(
                    "Number of state dims should be 3 or 4, number of dims = ",
                    string(dims),
                )
            end
        end
    end
end

"""
    ncread(nc, config::Config, parameter::AbstractString; <keyword arguments>)

Read a NetCDF variable `var` from file `nc`, based on `config` (parsed TOML file) and the
model `parameter` specified in the TOML configuration file. Supports various keyword
arguments to get selections of data in desired types, with or without missing values.

# Arguments
- `alias`=nothing` : An `alias` for the TOML key, by default an `alias` is not expected.
- `optional=true` : By default specifying a model `parameter` in the TOML file is optional.
        Set to false if the model `parameter` is required.
- `sel=nothing`: A selection of indices, such as a `Vector{CartesianIndex}` of active cells,
        to return from the NetCDF. By default all cells are returned.
- `defaults=nothing`: A default value if `var` is not in `nc`. By default it gives an error
    in this case.
- `type=nothing`: Type to convert data to after reading. By default no conversion is done.
- `allow_missing=false`: Missing values within `sel` is not allowed by default. Set to
        `true` to allow missing values.
- `fill=nothing`: Missing values are replaced by this fill value if `allow_missing` is
  `false`.
- `dimname` : Name of third dimension of parameter `var`. By default no third dimension is
  expected.
"""
function ncread(
    nc,
    config::Config,
    parameter::AbstractString;
    alias = nothing,
    optional = true,
    sel = nothing,
    defaults = nothing,
    type = nothing,
    allow_missing = false,
    fill = nothing,
    dimname = nothing,
)
    # get var (NetCDF variable or type Config) from TOML file.
    # if var has type Config, input parameters can be changed.
    if isnothing(alias)
        if optional
            var = param(config.input, parameter, nothing)
        else
            var = param(config.input, parameter)
        end
    else
        var = get_alias(config.input, parameter, alias, nothing)
    end

    # dim `time` is also included in `dim_sel`: this allows for cyclic parameters (read
    # first timestep), that is later updated with the `update_cyclic!` function.
    if isnothing(dimname)
        dim_sel = (x = :, y = :, time = 1)
    elseif dimname == :classes
        dim_sel = (x = :, y = :, classes = :, time = 1)
    elseif dimname == :layer
        dim_sel = (x = :, y = :, layer = :, time = 1)
    else
        error("Unrecognized dimension name $dimname")
    end

    if isnothing(var)
        @info "Set `$parameter` using default value `$defaults`."
        @assert !isnothing(defaults)
        if !isnothing(type)
            defaults = convert(type, defaults)
        end
        if isnothing(dimname)
            return Base.fill(defaults, length(sel))
        else
            return Base.fill(defaults, (nc.dim[String(dimname)], length(sel)))
        end
    end

    # If var has type Config, input parameters can be changed (through scale, offset and
    # input NetCDF var) or set to a uniform value (providing a value). Otherwise, input
    # NetCDF var is read directly.
    var, mod = ncvar_name_modifier(var; config = config)

    if !isnothing(mod.value)
        @info "Set `$parameter` using default value `$(mod.value)`."
        if isnothing(dimname)
            return Base.fill(mod.value, length(sel))
        # set to one uniform value
        elseif length(mod.value) == 1
            return Base.fill(mod.value, (nc.dim[String(dimname)], length(sel)))
        # set to vector of values (should be equal to size dimname)
        elseif length(mod.value) > 1
            @assert length(mod.value) == nc.dim[String(dimname)]
            return repeat(mod.value, 1, length(sel))
        end
    else
        @info "Set `$parameter` using NetCDF variable `$var`."
        A = read_standardized(nc, var, dim_sel)
        if !isnothing(mod.index)
            # the modifier index is only set in combination with scale and offset for SVectors,
            # provided through the TOML file.
            if length(mod.index) > 1
                # if index, scale and offset is provided in the TOML as a list.
                for i = 1:length(mod.index)
                    A[:,:,mod.index[i]] =  A[:,:,mod.index[i]] .* mod.scale[i] .+ mod.offset[i]
                end
            else
                A[:,:,mod.index] =  A[:,:,mod.index] .* mod.scale .+ mod.offset
            end
        elseif mod.scale != 1.0 || mod.offset != 0.0
            A = A .* mod.scale .+ mod.offset
        end
    end

    # Take out only the active cells
    if !isnothing(sel)
        if isnothing(dimname)
            A = A[sel]
        else
            A = permutedims(A[sel, :])
        end
    end

    if !allow_missing
        if isnothing(fill)
            # errors if missings are found
            A = nomissing(A)
            if any(isnan, A)
                error("NaN not allowed in $var")
            end
        else
            # replaces missings with a fill value
            A = nomissing(A, fill)
            # replace also NaN values with the fill value
            replace!(x -> isnan(x) ? fill : x, A)
        end
    end

    # Convert to desired type if needed
    if !isnothing(type)
        if eltype(A) != type
            A = convert(Array{type}, A)
        end
    end

    return A
end

"""
    set_layerthickness(d::Real, sl::SVector)

Calculate actual soil thickness of layers based on a reference depth (e.g. soil depth or water table depth) `d`,
a SVector `sl` with cumulative soil depth starting at soil surface (0), and a SVector `tl` with actual thickness
per soil layer.
"""
function set_layerthickness(d::Real, sl::SVector, tl::SVector)

    act_d = tl .* mv
    for i = 1:length(act_d)
        if d > sl[i+1]
            act_d = setindex(act_d, tl[i], i)
        elseif d - sl[i] > 0.0
            act_d = setindex(act_d, d - sl[i], i)
        end
    end

    nlayers = length(act_d) - sum(isnan.(act_d))
    return act_d, nlayers
end

"""
    detdrainlength(ldd, xl, yl)

Determines the drainaige length for a non square grid. Input `ldd` (drainage network), `xl` (length of cells in x direction),
`yl` (length of cells in y direction). Output is drainage length.
"""
function detdrainlength(ldd, xl, yl)
    # take into account non-square cells
    # if ldd is 8 or 2 use ylength
    # if ldd is 4 or 6 use xlength
    if ldd == 2 || ldd == 8
        yl
    elseif ldd == 4 || ldd == 6
        xl
    else
        hypot(xl, yl)
    end
end

"""
    detdrainwidth(ldd, xl, yl)

Determines the drainaige width for a non square grid. Input `ldd` (drainage network), `xl`
(length of cells in x direction), `yl` (length of cells in y direction). Output is drainage
width.
"""
function detdrainwidth(ldd, xl, yl)
    # take into account non-square cells
    # if ldd is 8 or 2 use xlength
    # if ldd is 4 or 6 use ylength
    slantwidth = (xl + yl) * 0.5
    if ldd == 2 || ldd == 8
        xl
    elseif ldd == 4 || ldd == 6
        yl
    else
        slantwidth
    end
end

"""
    det_surfacewidth(ldd, xl, yl)

Determines the surface flow width. Input `dw` (drainage width), `riverwidth` and `river`
(boolean). Output is surface flow width `sw`.
"""
function det_surfacewidth(dw, riverwidth, river)
    sw = river ? max(dw - riverwidth, 0.0) : dw
    return sw
end

# 2.5x faster power method
"Faster method for exponentiation"
pow(x, y) = exp(y * log(x))

"Return the sum of the array `A` at indices `inds`"
function sum_at(A, inds)
    v = zero(eltype(A))
    for i in inds
        v += A[i]
    end
    return v
end

"Return the sum of the function `f` at indices `inds`"
function sum_at(f::Function, inds, T)
    v = zero(T)
    for i in inds
        v += f(i)
    end
    return v
end

# https://juliaarrays.github.io/StaticArrays.jl/latest/pages/api/#Arrays-of-static-arrays-1
function svectorscopy(x::Matrix{T}, ::Val{N}) where {T,N}
    size(x, 1) == N || error("sizes mismatch")
    isbitstype(T) || error("use for bitstypes only")
    copy(reinterpret(SVector{N,T}, vec(x)))
end

"""
    fraction_runoff_toriver(graph, ldd, index_river, slope, n)

Determine ratio `frac` between `slope` river cell `index_river` and `slope` of each upstream
neighbor (based on directed acyclic graph `graph`).
"""
function fraction_runoff_toriver(graph, ldd, index_river, slope, n)
    frac = zeros(n)
    for i in index_river
        nbs = inneighbors(graph, i)
        for j in nbs
            if ldd[j] != ldd[i]
                frac[j] = slope[j] / (slope[i] + slope[j])
            end
        end
    end
    return frac
end

"""
    equal_size_vectors(x)

Used in the structs of arrays to ensure all vectors are of equal length.

`equal_size_vectors(([1,2], [1,2,3]))` would throw an ArgumentError.
`equal_size_vectors(([4,5], [4,5]))` would pass.
`equal_size_vectors((1, [4,5], [4,5]))` would also pass, since `1` is not an AbstractVector.
"""
function equal_size_vectors(x)
    # all vectors in this struct should be the same size
    inds_vec = findall(arg -> isa(arg, AbstractVector), x)
    n = length(x[inds_vec[1]])
    x_vec = x[inds_vec]

    for arr in x_vec
        if length(arr) != n
            throw(ArgumentError("Not all vectors are of equal length"))
        end
    end
    return x
end

"""
    tosecond(x::Period)

Convert a Period into a Float64, which represents the number of seconds. Will fail if this
is not well defined, such as for Month.

# Examples
```julia-repl
julia> tosecond(Day(1))
86400.0
```
"""
tosecond(x::Hour) = Float64(Dates.value(Second(x)))
tosecond(x::Minute) = Float64(Dates.value(Second(x)))
tosecond(x::T) where {T<:DatePeriod} = Float64(Dates.value(Second(x)))
tosecond(x::T) where {T<:TimePeriod} = x / convert(T, Second(1))

"""
    adjacent_nodes_at_link(graph)

Return the source node `src` and destination node `dst` of each link of a directed `graph`.
"""
function adjacent_nodes_at_link(graph)
    links = collect(edges(graph))
    return (src = src.(links), dst = dst.(links))
end

"""
    adjacent_links_at_node(graph, nodes_at_link)

Return the source link `src` and destination link `dst` of each node of a directed `graph`.
"""
function adjacent_links_at_node(graph, nodes_at_link)
    nodes = vertices(graph)
    src_link = Vector{Int}[]
    dst_link = copy(src_link)
    for i = 1:nv(graph)
        push!(src_link, findall(isequal(nodes[i]), nodes_at_link.dst))
        push!(dst_link, findall(isequal(nodes[i]), nodes_at_link.src))
    end
    return (src = src_link, dst = dst_link)
end

"Add `vertex` and `edge` to `pits` of a directed `graph`"
function add_vertex_edge_graph!(graph, pits)
    n = nv(graph)
    for (i, v) in enumerate(pits)
        add_vertex!(graph)
        add_edge!(graph, v, n + i)
    end
end

"""
    set_effective_flowwidth!(we_x, we_y, indices, graph_riv, riverwidth, ldd_riv, inds_rev_riv)

For river cells (D8 flow direction) in a staggered grid the effective flow width at cell
edges (floodplain) 'we_x' in the x-direction and `we_y` in the y-direction is corrected by
subtracting the river width `riverwidth` from the cell edges. For diagonal directions, the
`riverwidth`` is split between the two adjacent cell edges. A cell edge at linear index
`idx` is defined as the edge between node `idx` and the adjacent node (+ CartesianIndex(1,
0)) for x and (+ CartesianIndex(0, 1)) for y.
"""
function set_effective_flowwidth!(
    we_x,
    we_y,
    indices,
    graph_riv,
    riverwidth,
    ldd_riv,
    inds_rev_riv,
)

    toposort = topological_sort_by_dfs(graph_riv)
    n = length(we_x)
    for v in toposort
        dst = outneighbors(graph_riv, v)
        isempty(dst) && continue
        w = min(riverwidth[v], riverwidth[only(dst)])
        dir = pcr_dir[ldd_riv[v]]
        idx = inds_rev_riv[v]
        # loop over river D8 directions
        if dir == CartesianIndex(1, 1)
            we_x[idx] = max(we_x[idx] - 0.5 * w, 0.0)
            we_y[idx] = max(we_y[idx] - 0.5 * w, 0.0)
        elseif dir == CartesianIndex(-1, -1)
            if indices.xd[idx] <= n
                we_y[indices.xd[idx]] = max(we_y[indices.xd[idx]] - 0.5 * w, 0.0)
            end
            if indices.yd[idx] <= n
                we_x[indices.yd[idx]] = max(we_x[indices.yd[idx]] - 0.5 * w, 0.0)
            end
        elseif dir == CartesianIndex(1, 0)
            we_y[idx] = max(we_y[idx] - w, 0.0)
        elseif dir == CartesianIndex(0, 1)
            we_x[idx] = max(we_x[idx] - w, 0.0)
        elseif dir == CartesianIndex(-1, 0)
            if indices.xd[idx] <= n
                we_y[indices.xd[idx]] = max(we_y[indices.xd[idx]] - w, 0.0)
            end
        elseif dir == CartesianIndex(0, -1)
            if indices.yd[idx] <= n
                we_x[indices.yd[idx]] = max(we_x[indices.yd[idx]] - w, 0.0)
            end
        elseif dir == CartesianIndex(1, -1)
            we_y[idx] = max(we_y[idx] - 0.5 * w, 0.0)
            if indices.yd[idx] <= n
                we_x[indices.yd[idx]] = max(we_x[indices.yd[idx]] - 0.5 * w, 0.0)
            end
        elseif dir == CartesianIndex(-1, 1)
            if indices.xd[idx] <= n
                we_y[indices.xd[idx]] = max(we_y[indices.xd[idx]] - 0.5 * w, 0.0)
            end
            we_x[idx] = max(we_x[idx] - 0.5 * w, 0.0)
        end
    end
end


text:
using DashBootstrapComponents

carousel = dbc_carousel(
    items=[
        Dict("key" => "1", "src" => "/static/images/slide1.svg"),
        Dict("key" => "2", "src" => "/static/images/slide2.svg"),
        Dict("key" => "3", "src" => "/static/images/slide3.svg"),
    ],
    controls=true,
    indicators=false,
);

max_stars_repo_name: harisbal/dash-bootstrap-components

max_issues_repo_name: harisbal/dash-bootstrap-components

max_forks_repo_name: harisbal/dash-bootstrap-components


text:
# MPI Declarations
push!(LOAD_PATH, "../src/")
push!(LOAD_PATH, joinpath(Pkg.dir("PumiInterface"), "src"))
push!(LOAD_PATH, joinpath(Pkg.dir("SummationByParts"), "src"))
push!(LOAD_PATH, joinpath(Pkg.dir("MeshMovement"), "src"))
push!(LOAD_PATH, joinpath(Pkg.dir("PDESolver"), "src/Utils"))

using PdePumiInterface
using PDESolver
using SummationByParts
using ODLCommonTools
using ArrayViews
using Utils
using MPI
# using MeshMovement
using FFD
using Base.Test

comm = MPI.COMM_WORLD
comm_world = MPI.MPI_COMM_WORLD
comm_self = MPI.COMM_SELF
my_rank = MPI.Comm_rank(comm)
comm_size = MPI.Comm_size(comm)

resize!(ARGS, 1)
ARGS[1] = "./input_vals_3d_parallel_np3and4.jl"

opts = PDESolver.read_input(ARGS[1])
sbp, mesh, pmesh, Tsol, Tres, Tmsh, mesh_time = createMeshAndOperator(opts, 1)
orig_vert_coords = deepcopy(mesh.vert_coords)
geom_faces = opts["BC2"]

@testset "--- Checking evaldXdControlPointProduct for 3D DG Mesh ---" begin

  # for i = 1:comm_size
  #   if my_rank == i-1
  #     println("mesh.vert_sharing.vert_nums = \n$(mesh.vert_sharing.vert_nums)")
  #     println("mesh.vert_sharing.rev_mapping = \n$(mesh.vert_sharing.rev_mapping)\n")
  #   end
  #   MPI.Barrier(comm)
  # end

  # for i = 1:comm_size
  #   if my_rank == i-1
  #     println("Rank $my_rank,\nmesh.peer_parts = \n$(mesh.peer_parts)")
  #     println("shared interfaces = \n$(mesh.shared_interfaces)\n")
  #   end
  #   MPI.Barrier(comm)
  # end

  ndim = mesh.dim
  order = [4,4,2]  # Order of B-splines in the 3 directions
  nControlPts = [4,4,2]
  offset = [0.5, 0.5, 0.5] # No offset in the X & Y direction
  geom_faces = opts["BC2"]

  # Create a mapping object using nonlinear mapping
  map, box = initializeFFD(mesh, sbp, order, nControlPts, offset, false, geom_faces)

  for i = 1:comm_size
    fname = string("controlPoints_rank", my_rank)
    writeControlPointsVTS(map, fname)
    MPI.Barrier(comm)
  end

  MPI.Barrier(comm)
  fill!(map.work, 0.0)

  # FFD.bndryMPIRanks(mesh, geom_faces)

  # Create seed vector
  # - Get original wall coordinates
  orig_wallCoords = FFD.getGlobalUniqueWallCorrdsArray(mesh, geom_faces)
  for i = 1:comm_size
    if my_rank == i-1
      println("on rank $my_rank, orig_wallCoords = \n$(orig_wallCoords)")
    end
    MPI.Barrier(comm)
  end

  Xs_bar = ones(3, size(orig_wallCoords,2))
  evaldXdControlPointProduct(map, mesh, vec(Xs_bar))

  fname = "./testvalues/evaldXdControlPointProduct_tet8cube.dat"

  test_values = readdlm(fname)
  @test ( length(map.work) )== length(test_values)
  for i = 1:length(map.work)
    err = abs.(test_values[i] - map.work[i])
    @test  err  < 1e-14
  end

  #=
  for i = 1:comm_size
    fname2 = string("./testvalues/evaldXdControlPointProduct_tet_cube_8el_rank",
                    my_rank, ".dat")
    f = open(fname2, "w")
    for j = 1:length(map.work)
      println(f, map.work[j])
    end
    close(f)
  end
  =#

end # End facts("--- Checking evaldXdControlPointProduct for 2D DG Mesh ---")


text:
using Test, FlatBuffers

const cppData = "monsterdata_test.mon"
const javaData = "monsterdata_java_wire.mon"
const outData = "out_data"
const fuzzFields = 4
const fuzzObjects = 10000

const overflowingInt32Val = read(IOBuffer(UInt8[0x83, 0x33, 0x33, 0x33]), Int32)
const overflowingInt64Val = read(IOBuffer(UInt8[0x84, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44]), Int64)

#   TestAll runs all checks, failing if any errors occur.
function TestAll(t)
    #   Verify that the Go FlatBuffers runtime library generates the
    #   expected bytes (does not use any schema):
    CheckByteLayout(t.Fatalf)
    CheckMutateMethods(t.Fatalf)

    #   Verify that panics are raised during exceptional conditions:
    CheckNotInObjectError(t.Fatalf)
    CheckStringIsNestedError(t.Fatalf)
    CheckByteStringIsNestedError(t.Fatalf)
    CheckStructIsNotInlineError(t.Fatalf)
    CheckFinishedBytesError(t.Fatalf)
    CheckSharedStrings(t.Fatalf)

    #   Verify that GetRootAs works for non-root tables
    CheckGetRootAsForNonRootTable(t.Fatalf)
    CheckTableAccessors(t.Fatalf)

    #   Verify that using the generated Go code builds a buffer without
    #   returning errors:
    generated, off = CheckGeneratedBuild(t.Fatalf)

    #   Verify that the buffer generated by Go code is readable by the
    #   generated Go code:
    CheckReadBuffer(generated, off, t.Fatalf)
    CheckMutateBuffer(generated, off, t.Fatalf)
    CheckObjectAPI(generated, off, t.Fatalf)

    #   Verify that the buffer generated by C++ code is readable by the
    #   generated Go code:
    monsterDataCpp = read(cppData)

    CheckReadBuffer(monsterDataCpp, 0, t.Fatalf)
    CheckMutateBuffer(monsterDataCpp, 0, t.Fatalf)
    CheckObjectAPI(monsterDataCpp, 0, t.Fatalf)

    #   Verify that vtables are deduplicated when written:
    CheckVtableDeduplication(t.Fatalf)

    #   Verify the enum names
    CheckEnumNames(t.Fatalf)

    #   Verify enum String methods
    CheckEnumString(t.Fatalf)

    #   Verify the enum values maps
    CheckEnumValues(t.Fatalf)

    #   Verify that the Go code used in FlatBuffers documentation passes
    #   some sanity checks:
    CheckDocExample(generated, off, t.Fatalf)

    #   Check Builder.CreateByteVector
    CheckCreateByteVector(t.Fatalf)

    #   Check a parent namespace import
    CheckParentNamespace(t.Fatalf)

    #   If the filename of the FlatBuffers file generated by the Java test
    #   is given, check that Go code can read it, and that Go code
    #   generates an identical buffer when used to create the example data:
    if javaData != ""
        monsterDataJava = read(javaData)
        CheckReadBuffer(monsterDataJava, 0, t.Fatalf)
        CheckByteEquality(generated[off:end], monsterDataJava, t.Fatalf)
    end

    #   Verify that various fuzzing scenarios produce a valid FlatBuffer.
    if fuzz
        checkFuzz(fuzzFields, fuzzObjects, t.Fatalf)
    end

    #   Write the generated buffer out to a file:
    open(outData, "w+") do io
        write(io, generated[off:end])
    end
end

#   CheckReadBuffer checks that the given buffer is evaluated correctly
#   as the example Monster.
function CheckReadBuffer(buf, offset)
    #   try the two ways of generating a monster
    #TODO
    monster1 = Example.GetRootAsMonster(buf, offset)
    monster2 = Monster()
    FlatBuffers.GetRootAs(buf, offset, monster2)
    for monster in (monster1, monster2)
        @test monster.hp == 80

        #   default
        @test monster.mana == 150
        @test monster.name == "MyMonster"
        @test monster.color == Example.ColorBlue
        @test monster.testbool

        #   initialize a Vec3 from Pos()
        @test !isempty(monster.pos)

        #   verify the properties of the Vec3
        @test monster.pos.x === Float32(1.0)
        @test monster.pos.y === Float32(2.0)
        @test monster.pos.z === Float32(3.0)
        @test monster.pos.test1 === Float64(3.0)
        @test monster.pos.test2 === Example.ColorGreen
        t = monster.pos.test3
        @test t !== nothing
        @test t.a === Int16(5)
        @test t.b === Int8(6)

        @test monster.testType == Example.AnyMonster

        table2 = monster.test
        @test table2 !== nothing
        monster2 = Monster(tabl2.bytes, table2.pos)
        @test monster2.name == "Fred"
        inventorySlice = monster.inventoryBytes
        @test length(inventorySlice) == monster.inventoryLength
        @test monster.inventoryLength == 5

        invsum = 0
        l = monster.inventoryLength
        for i = 1:l
            v = monster.inventory[i]
            @test v == inventorySlice[i]
            invsum += v
        end
        @test invsum == 10

        @test monster.test4Length == 2

        test0 = monster.test4[1]
        test1 = monster.test4[2]

        #   the position of test0 and test1 are swapped in monsterdata_java_wire
        #   and monsterdata_test_wire, so ignore ordering
        v0 = test0.a
        v1 = test0.b
        v2 = test1.a
        v3 = test1.b
        @test v0 + v1 + v2 + v3 == 100

        @test monster.testArrayOfStringLength == 2
        @test monster.testArrayOfString[1] == "test1"
        @test monster.testArrayOfString[2] == "test2"
    end
end

#   CheckMutateBuffer checks that the given buffer can be mutated correctly
#   as the example Monster. Only available scalar values are mutated.
# function CheckMutateBuffer(org, offset)
#     #   make a copy to mutate
#     buf = make([]byte, len(org))
#     copy(buf, org)

#     #   load monster data from the buffer
#     monster = Example.GetRootAsMonster(buf, offset)

#     #   test case struct
#     type testcase struct {
#         field  string
#         testfn func() bool
#     end

#     testForOriginalValues = []testcase{
#         testcase{"Hp", func() bool { return monster.Hp() == 80 }end,
#         testcase{"Mana", func() bool { return monster.Mana() == 150 }end,
#         testcase{"Testbool", func() bool { return monster.Testbool() == true }end,
#         testcase{"Pos.X'", func() bool { return monster.Pos(nil).X() == float32(1.0) }end,
#         testcase{"Pos.Y'", func() bool { return monster.Pos(nil).Y() == float32(2.0) }end,
#         testcase{"Pos.Z'", func() bool { return monster.Pos(nil).Z() == float32(3.0) }end,
#         testcase{"Pos.Test1'", func() bool { return monster.Pos(nil).Test1() == float64(3.0) }end,
#         testcase{"Pos.Test2'", func() bool { return monster.Pos(nil).Test2() == Example.ColorGreen }end,
#         testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).A() == int16(5) }end,
#         testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).B() == int8(6) }end,
#         testcase{"Inventory[2]", func() bool { return monster.Inventory(2) == byte(2) }end,
#     end

#     testMutability = []testcase{
#         testcase{"Hp", func() bool { return monster.MutateHp(70) }end,
#         testcase{"Mana", func() bool { return !monster.MutateMana(140) }end,
#         testcase{"Testbool", func() bool { return monster.MutateTestbool(false) }end,
#         testcase{"Pos.X", func() bool { return monster.Pos(nil).MutateX(10.0) }end,
#         testcase{"Pos.Y", func() bool { return monster.Pos(nil).MutateY(20.0) }end,
#         testcase{"Pos.Z", func() bool { return monster.Pos(nil).MutateZ(30.0) }end,
#         testcase{"Pos.Test1", func() bool { return monster.Pos(nil).MutateTest1(30.0) }end,
#         testcase{"Pos.Test2", func() bool { return monster.Pos(nil).MutateTest2(Example.ColorBlue) }end,
#         testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).MutateA(50) }end,
#         testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).MutateB(60) }end,
#         testcase{"Inventory[2]", func() bool { return monster.MutateInventory(2, 200) }end,
#     end

#     testForMutatedValues = []testcase{
#         testcase{"Hp", func() bool { return monster.Hp() == 70 }end,
#         testcase{"Mana", func() bool { return monster.Mana() == 150 }end,
#         testcase{"Testbool", func() bool { return monster.Testbool() == false }end,
#         testcase{"Pos.X'", func() bool { return monster.Pos(nil).X() == float32(10.0) }end,
#         testcase{"Pos.Y'", func() bool { return monster.Pos(nil).Y() == float32(20.0) }end,
#         testcase{"Pos.Z'", func() bool { return monster.Pos(nil).Z() == float32(30.0) }end,
#         testcase{"Pos.Test1'", func() bool { return monster.Pos(nil).Test1() == float64(30.0) }end,
#         testcase{"Pos.Test2'", func() bool { return monster.Pos(nil).Test2() == Example.ColorBlue }end,
#         testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).A() == int16(50) }end,
#         testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).B() == int8(60) }end,
#         testcase{"Inventory[2]", func() bool { return monster.Inventory(2) == byte(200) }end,
#     end

#     testInvalidEnumValues = []testcase{
#         testcase{"Pos.Test2", func() bool { return monster.Pos(nil).MutateTest2(Example.Color(20)) }end,
#         testcase{"Pos.Test2", func() bool { return monster.Pos(nil).Test2() == Example.Color(20) }end,
#     end

#     #   make sure original values are okay
#     for _, t = range testForOriginalValues {
#         if !t.testfn()
#             fail("field '" + t.field + "' doesn't have the expected original value")
#         end
#     end

#     #   try to mutate fields and check mutability
#     for _, t = range testMutability {
#         if !t.testfn()
#             error(string("field '"+t.field+"' failed mutability test", true, false))
#         end
#     end

#     #   test whether values have changed
#     for _, t = range testForMutatedValues {
#         if !t.testfn()
#             fail("field '" + t.field + "' doesn't have the expected mutated value")
#         end
#     end

#     #   make sure the buffer has changed
#     if reflect.DeepEqual(buf, org)
#         fail("mutate buffer failed")
#     end

#     #   To make sure the buffer has changed accordingly
#     #   Read data from the buffer and verify all fields
#     monster = Example.GetRootAsMonster(buf, offset)
#     for _, t = range testForMutatedValues {
#         if !t.testfn()
#             fail("field '" + t.field + "' doesn't have the expected mutated value")
#         end
#     end

#     #   a couple extra tests for "invalid" enum values, which don't correspond to
#     #   anything in the schema, but are allowed
#     for _, t = range testInvalidEnumValues {
#         if !t.testfn()
#             fail("field '" + t.field + "' doesn't work with an invalid enum value")
#         end
#     end

#     #   reverting all fields to original values should
#     #   re-create the original buffer. Mutate all fields
#     #   back to their original values and compare buffers.
#     #   This test is done to make sure mutations do not do
#     #   any unnecessary changes to the buffer.
#     monster = Example.GetRootAsMonster(buf, offset)
#     monster.MutateHp(80)
#     monster.MutateTestbool(true)
#     monster.Pos(nil).MutateX(1.0)
#     monster.Pos(nil).MutateY(2.0)
#     monster.Pos(nil).MutateZ(3.0)
#     monster.Pos(nil).MutateTest1(3.0)
#     monster.Pos(nil).MutateTest2(Example.ColorGreen)
#     monster.Pos(nil).Test3(nil).MutateA(5)
#     monster.Pos(nil).Test3(nil).MutateB(6)
#     monster.MutateInventory(2, 2)

#     for _, t = range testForOriginalValues {
#         if !t.testfn()
#             fail("field '" + t.field + "' doesn't have the expected original value")
#         end
#     end

#     #   buffer should have original values
#     if !reflect.DeepEqual(buf, org)
#         fail("revert changes failed")
#     end
# end

# function CheckObjectAPI(buf, offset)
#     #TODO
#     monster = Example.GetRootAsMonster(buf, offset).UnPack()

#     @test monster.hp == 80

#     #   default
#     @test monster.mana == 150

#     builder = FlatBuffers.Builder()
#     finish!(builder, monster.Pack(builder))
#     monster2 = Example.GetRootAsMonster(finishedbytes(builder), 0).UnPack()
#     if !reflect.DeepEqual(monster, monster2)
#         error(string("Pack/Unpack()", monster, monster2))
#     end
# end

#   Low level stress/fuzz test: serialize/deserialize a variety of
#   different kinds of data in different combinations
@testset "checkFuzz" begin

    #   Values we're testing against: chosen to ensure no bits get chopped
    #   off anywhere, and also be different from eachother.
    boolVal = true
    int8Val = Int8(-127) #   0x81
    uint8Val = UInt8(0xFF)
    int16Val = Int16(-32222) #   0x8222
    uint16Val = UInt16(0xFEEE)
    int32Val = Int32(overflowingInt32Val)
    uint32Val = UInt32(0xFDDDDDDD)
    int64Val = Int64(overflowingInt64Val)
    uint64Val = UInt64(0xFCCCCCCCCCCCCCCC)
    float32Val = Float32(3.14159)
    float64Val = Float64(3.14159265359)

    testValuesMax = 11 #   hardcoded to the number of scalar types

    builder = FlatBuffers.Builder()
    l = NewLCG()

    objects = Vector{FlatBuffers.UOffsetT}(undef, fuzzObjects)

    #   Generate fuzzObjects random objects each consisting of
    #   fuzzFields fields, each of a random type.
    for i = 1:fuzzObjects
        builder.startobject!(fuzzFields)

        for f = 1:fuzzFields
            choice = next!(l) % UInt32(testValuesMax)
            if choice == 0
                prependslot!(builder, Int(f), boolVal, false)
            elseif choice == 1
                prependslot!(builder, Int(f), int8Val, 0)
            elseif choice == 2
                prependslot!(builder, Int(f), uint8Val, 0)
            elseif choice == 3
                prependslot!(builder, Int(f), int16Val, 0)
            elseif choice == 4
                prependslot!(builder, Int(f), uint16Val, 0)
            elseif choice == 5
                prependslot!(builder, Int(f), int32Val, 0)
            elseif choice == 6
                prependslot!(builder, Int(f), uint32Val, 0)
            elseif choice == 7
                prependslot!(builder, Int(f), int64Val, 0)
            elseif choice == 8
                prependslot!(builder, Int(f), uint64Val, 0)
            elseif choice == 9
                prependslot!(builder, Int(f), float32Val, 0)
            elseif choice == 10
                prependslot!(builder, Int(f), float64Val, 0)
            end
        end

        off = endobject!(builder)

        #   store the offset from the end of the builder buffer,
        #   since it will keep growing:
        objects[i] = off
    end

    #   Do some bookkeeping to generate stats on fuzzes:
    stats = Dict{String, Int}()
    check = function(desc, want, got)
        stats[desc] += 1
        @test want == got
    end

    l = NewLCG() #   Reset.

    #   Test that all objects we generated are readable and return the
    #   expected values. We generate random objects in the same order
    #   so this is deterministic.
    for i = 1:fuzzObjects

        table = FlatBuffers.Table(
            builder.bytes,
            FlatBuffers.UOffsetT(length(builder.bytes)) - objects[i]
        )

        for j = 1:fuzzFields
            f = FlatBuffers.VOffsetT((FlatBuffers.VtableMetadataFields + j) * sizeof(FlatBuffers.VOffsetT))
            choice = next!(l) % UInt32(testValuesMax)

            if choice == 0
                check("bool", boolVal, getslot(table, f, false))
            elseif choice == 1
                check("int8", int8Val, getslot(table, f, 0))
            elseif choice == 2
                check("uint8", uint8Val, getslot(table, f, 0))
            elseif choice == 3
                check("int16", int16Val, getslot(table, f, 0))
            elseif choice == 4
                check("uint16", uint16Val, getslot(table, f, 0))
            elseif choice == 5
                check("int32", int32Val, getslot(table, f, 0))
            elseif choice == 6
                check("UInt32", uint32Val, getslot(table, f, 0))
            elseif choice == 7
                check("int64", int64Val, getslot(table, f, 0))
            elseif choice == 8
                check("uint64", uint64Val, getslot(table, f, 0))
            elseif choice == 9
                check("float32", float32Val, getslot(table, f, 0))
            elseif choice == 10
                check("float64", float64Val, getslot(table, f, 0))
            end
        end
    end

    #   If enough checks were made, verify that all scalar types were used:
    if fuzzFields * fuzzObjects >= testValuesMax
        @test length(stats) == testValuesMax
    end

    #   Print some counts, if needed:
    if fuzzFields == 0 || fuzzObjects == 0
        println("fuzz\tfields: $fuzzFields\tobjects: $fuzzObjects\t[none]\t0")
    else
        keys = collect(keys(stats))
        sort!(keys)
        for k in keys
            println("fuzz\tfields: $fuzzFields\tobjects: $fuzzObjects\t$k\t$(stats[k])\n")
        end
    end

    return
end

#   CheckByteLayout verifies the bytes of a Builder in various scenarios.
function CheckByteLayout()
    b::FlatBuffers.Builder
    check = function(want)
        i += 1
        @test want == b.bytes[b.head:end]
    end

    #   test 1: numbers

    b = FlatBuffers.Builder()
    check(UInt8[])
    prepend!(b, true)
    check(UInt8[1])
    prepend!(b, -127)
    check(UInt8[129, 1])
    prepend!(b, 255)
    check(UInt8[255, 129, 1])
    prepend!(b, -32222)
    check(UInt8[0x22, 0x82, 0, 255, 129, 1]) #   first pad
    prepend!(b, 0xFEEE)
    check(UInt8[0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]) #   no pad this time
    prepend!(b, -53687092)
    check(UInt8[204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1])
    prepend!(b, 0x98765432)
    check(UInt8[0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1])

    #   test 1b: numbers 2

    b = FlatBuffers.Builder()
    prepend!(b, 0x1122334455667788)
    check(UInt8[0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11])

    #   test 2: 1xbyte vector

    b = FlatBuffers.Builder()
    check(UInt8[])
    startvector!(b, sizeof(UInt8), 1, 1)
    check(UInt8[0, 0, 0]) #   align to 4bytes
    prepend!(b, UInt8(1))
    check(UInt8[1, 0, 0, 0])
    endvector!(b, 1)
    check(UInt8[1, 0, 0, 0, 1, 0, 0, 0]) #   padding

    #   test 3: 2xbyte vector

    b = FlatBuffers.Builder()
    startvector!(b, sizeof(UInt8), 2, 1)
    check(UInt8[0, 0]) #   align to 4bytes
    prepend!(b, UInt8(1))
    check(UInt8[1, 0, 0])
    prepend!(b, UInt8(2))
    check(UInt8[2, 1, 0, 0])
    endvector!(b, 2)
    check(UInt8[2, 0, 0, 0, 2, 1, 0, 0]) #   padding

    #   test 3b: 11xbyte vector matches builder size

    b = FlatBuffers.Builder(12)
    startvector!(b, sizeof(UInt8), 8, 1)
    start = UInt8[]
    check(start)
    for i = 1:11
        prepend!(b, UInt8(i))
        pushfirst!(start, UInt8(i))
        check(start)
    end
    endvector!(b, 8)
    check(append!(UInt8[8, 0, 0, 0], start))

    #   test 4: 1xuint16 vector

    b = FlatBuffers.Builder()
    startvector!(b, sizeof(UInt16), 1, 1)
    check(UInt8[0, 0]) #   align to 4bytes
    prepend!(b, 1)
    check(UInt8[1, 0, 0, 0])
    endvector!(b, 1)
    check(UInt8[1, 0, 0, 0, 1, 0, 0, 0]) #   padding

    #   test 5: 2xuint16 vector

    b = FlatBuffers.Builder()
    startvector!(b, sizeof(UInt16), 2, 1)
    check(UInt8[]) #   align to 4bytes
    prepend!(b, 0xABCD)
    check(UInt8[0xCD, 0xAB])
    prepend!(b, 0xDCBA)
    check(UInt8[0xBA, 0xDC, 0xCD, 0xAB])
    endvector!(b, 2)
    check(UInt8[2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB])

    #   test 6: CreateString

    b = FlatBuffers.Builder()
    createstring!(b, "foo")
    check(UInt8[3, 0, 0, 0, 'f', 'o', 'o', 0]) #   0-terminated, no pad
    createstring!(b, "moop")
    check(UInt8[4, 0, 0, 0, 'm', 'o', 'o', 'p', 0, 0, 0, 0, #   0-terminated, 3-byte pad
        3, 0, 0, 0, 'f', 'o', 'o', 0])

    #   test 6b: CreateString unicode

    b = FlatBuffers.Builder()
    #   These characters are chinese from blog.golang.org/strings
    #   We use escape codes here so that editors without unicode support
    #   aren't bothered:
    uni_str = "\u65e5\u672c\u8a9e"
    createstring!(b, uni_str)
    check(UInt8[9, 0, 0, 0, 230, 151, 165, 230, 156, 172, 232, 170, 158, 0, #    null-terminated, 2-byte pad
        0, 0])

    #   test 6c: CreateByteString

    b = FlatBuffers.Builder()
    createstring!(b, "foo")
    check(UInt8[3, 0, 0, 0, 'f', 'o', 'o', 0]) #   0-terminated, no pad
    createstring!(b, "moop")
    check(UInt8[4, 0, 0, 0, 'm', 'o', 'o', 'p', 0, 0, 0, 0, #   0-terminated, 3-byte pad
        3, 0, 0, 0, 'f', 'o', 'o', 0])

    #   test 7: empty vtable
    b = FlatBuffers.Builder()
    startobject!(b, 0)
    check(UInt8[])
    endobject!(b)
    check(UInt8[4, 0, 4, 0, 4, 0, 0, 0])

    #   test 8: vtable with one true bool
    b = FlatBuffers.Builder()
    check(UInt8[])
    startobject!(b, 1)
    check(UInt8[])
    prependslot!(b, 0, true, false)
    endobject!(b)
    check(UInt8[
        6, 0, #   vtable bytes
        8, 0, #   length of object including vtable offset
        7, 0, #   start of bool value
        6, 0, 0, 0, #   offset for start of vtable (int32)
        0, 0, 0, #   padded to 4 bytes
        1, #   bool value
    ])

    #   test 9: vtable with one default bool
    b = FlatBuffers.Builder()
    check(UInt8[])
    startobject!(b, 1)
    check(UInt8[])
    prependslot!(b, 0, false, false)
    endobject!(b)
    check(UInt8[
        4, 0, #   vtable bytes
        4, 0, #   end of object from here
        #   entry 1 is zero and not stored.
        4, 0, 0, 0, #   offset for start of vtable (int32)
    ])

    #   test 10: vtable with one int16
    b = FlatBuffers.Builder()
    startobject!(b, 1)
    prependslot!(b, 0, 0x789A, 0)
    endobject!(b)
    check(UInt8[
        6, 0, #   vtable bytes
        8, 0, #   end of object from here
        6, 0, #   offset to value
        6, 0, 0, 0, #   offset for start of vtable (int32)
        0, 0, #   padding to 4 bytes
        0x9A, 0x78,
    ])

    #   test 11: vtable with two int16
    b = FlatBuffers.Builder()
    startobject!(b, 2)
    prependslot!(b, 0, 0x3456, 0)
    prependslot!(b, 1, 0x789A, 0)
    endobject!(b)
    check(UInt8[
        8, 0, #   vtable bytes
        8, 0, #   end of object from here
        6, 0, #   offset to value 0
        4, 0, #   offset to value 1
        8, 0, 0, 0, #   offset for start of vtable (int32)
        0x9A, 0x78, #   value 1
        0x56, 0x34, #   value 0
    ])

    #   test 12: vtable with int16 and bool
    b = FlatBuffers.Builder()
    startobject!(b, 2)
    prependslot!(b, 0, 0x3456, 0)
    prependslot!(b, 1, true, false)
    endobject!(b)
    check(UInt8[
        8, 0, #   vtable bytes
        8, 0, #   end of object from here
        6, 0, #   offset to value 0
        5, 0, #   offset to value 1
        8, 0, 0, 0, #   offset for start of vtable (int32)
        0,          #   padding
        1,          #   value 1
        0x56, 0x34, #   value 0
    ])

    #   test 12: vtable with empty vector
    b = FlatBuffers.Builder()
    startvector!(b, sizeof(UInt8), 0, 1)
    vecend = endvector!(b, 0)
    startobject!(b, 1)
    prependslot!(b, 0, vecend, 0)
    endobject!(b)
    check(UInt8[
        6, 0, #   vtable bytes
        8, 0,
        4, 0, #   offset to vector offset
        6, 0, 0, 0, #   offset for start of vtable (int32)
        4, 0, 0, 0,
        0, 0, 0, 0, #   length of vector (not in struct)
    ])

    #   test 12b: vtable with empty vector of byte and some scalars
    b = FlatBuffers.Builder()
    startvector!(b, sizeof(UInt8), 0, 1)
    vecend = endvector!(b, 0)
    startobject!(b, 2)
    prependslot!(b, 0, 55, 0)
    prependslot!(b, 1, vecend, 0)
    endobject!(b)
    check(UInt8[
        8, 0, #   vtable bytes
        12, 0,
        10, 0, #   offset to value 0
        4, 0, #   offset to vector offset
        8, 0, 0, 0, #   vtable loc
        8, 0, 0, 0, #   value 1
        0, 0, 55, 0, #   value 0

        0, 0, 0, 0, #   length of vector (not in struct)
    ])

    #   test 13: vtable with 1 int16 and 2-vector of int16
    b = FlatBuffers.Builder()
    startvector!(b, sizeof(Int16), 2, 1)
    prepend!(b, 0x1234)
    prepend!(b, 0x5678)
    vecend = endvector!(b, 2)
    startobject!(b, 2)
    prependslot!(b, 1, vecend, 0)
    prependslot!(b, 0, 55, 0)
    endobject!(b)
    check(UInt8[
        8, 0, #   vtable bytes
        12, 0, #   length of object
        6, 0, #   start of value 0 from end of vtable
        8, 0, #   start of value 1 from end of buffer
        8, 0, 0, 0, #   offset for start of vtable (int32)
        0, 0, #   padding
        55, 0, #   value 0
        4, 0, 0, 0, #   vector position from here
        2, 0, 0, 0, #   length of vector (UInt32)
        0x78, 0x56, #   vector value 1
        0x34, 0x12, #   vector value 0
    ])

    #   test 14: vtable with 1 struct of 1 int8, 1 int16, 1 int32
    b = FlatBuffers.Builder()
    startobject!(b, 1)
    prep!(b, 4+4+4, 0)
    prepend!(b, 55)
    pad!(b, 3)
    prepend!(b, 0x1234)
    pad!(b, 2)
    prepend!(b, 0x12345678)
    structStart = offset(b)
    prependstructslot!(b, 0, structStart, 0)
    endobject!(b)
    check(UInt8[
        6, 0, #   vtable bytes
        16, 0, #   end of object from here
        4, 0, #   start of struct from here
        6, 0, 0, 0, #   offset for start of vtable (int32)
        0x78, 0x56, 0x34, 0x12, #   value 2
        0, 0, #   padding
        0x34, 0x12, #   value 1
        0, 0, 0, #   padding
        55, #   value 0
    ])

    #   test 15: vtable with 1 vector of 2 struct of 2 int8
    b = FlatBuffers.Builder()
    startvector!(b, sizeof(Int8) * 2, 2, 1)
    prepend!(b, 33)
    prepend!(b, 44)
    prepend!(b, 55)
    prepend!(b, 66)
    vecend = endvector!(b, 2)
    startobject!(b, 1)
    prependslot!(b, 0, vecend, 0)
    endobject!(b)
    check(UInt8[
        6, 0, #   vtable bytes
        8, 0,
        4, 0, #   offset of vector offset
        6, 0, 0, 0, #   offset for start of vtable (int32)
        4, 0, 0, 0, #   vector start offset

        2, 0, 0, 0, #   vector length
        66, #   vector value 1,1
        55, #   vector value 1,0
        44, #   vector value 0,1
        33, #   vector value 0,0
    ])

    #   test 16: table with some elements
    b = FlatBuffers.Builder()
    startobject!(b, 2)
    prependslot!(b, 0, 33, 0)
    prependslot!(b, 1, 66, 0)
    off = endobject!(b)
    finish!(b, off)

    check(UInt8[
        12, 0, 0, 0, #   root of table: points to vtable offset

        8, 0, #   vtable bytes
        8, 0, #   end of object from here
        7, 0, #   start of value 0
        4, 0, #   start of value 1

        8, 0, 0, 0, #   offset for start of vtable (int32)

        66, 0, #   value 1
        0,  #   padding
        33, #   value 0
    ])

    #   test 17: one unfinished table and one finished table
    b = FlatBuffers.Builder()
    startobject!(b, 2)
    prependslot!(b, 0, 33, 0)
    prependslot!(b, 1, 44, 0)
    off = endobject!(b)
    finish!(b, off)

    startobject!(b, 3)
    prependslot!(b, 0, 55, 0)
    prependslot!(b, 1, 66, 0)
    prependslot!(b, 2, 77, 0)
    off = endobject!(b)
    finish!(b, off)

    check(UInt8[
        16, 0, 0, 0, #   root of table: points to object
        0, 0, #   padding

        10, 0, #   vtable bytes
        8, 0, #   size of object
        7, 0, #   start of value 0
        6, 0, #   start of value 1
        5, 0, #   start of value 2
        10, 0, 0, 0, #   offset for start of vtable (int32)
        0,  #   padding
        77, #   value 2
        66, #   value 1
        55, #   value 0

        12, 0, 0, 0, #   root of table: points to object

        8, 0, #   vtable bytes
        8, 0, #   size of object
        7, 0, #   start of value 0
        6, 0, #   start of value 1
        8, 0, 0, 0, #   offset for start of vtable (int32)
        0, 0, #   padding
        44, #   value 1
        33, #   value 0
    ])

    #   test 18: a bunch of bools
    b = FlatBuffers.Builder()
    startobject!(b, 8)
    prependslot!(b, 0, true, false)
    prependslot!(b, 1, true, false)
    prependslot!(b, 2, true, false)
    prependslot!(b, 3, true, false)
    prependslot!(b, 4, true, false)
    prependslot!(b, 5, true, false)
    prependslot!(b, 6, true, false)
    prependslot!(b, 7, true, false)
    off = endobject!(b)
    finish!(b, off)

    check(UInt8[
        24, 0, 0, 0, #   root of table: points to vtable offset

        20, 0, #   vtable bytes
        12, 0, #   size of object
        11, 0, #   start of value 0
        10, 0, #   start of value 1
        9, 0, #   start of value 2
        8, 0, #   start of value 3
        7, 0, #   start of value 4
        6, 0, #   start of value 5
        5, 0, #   start of value 6
        4, 0, #   start of value 7
        20, 0, 0, 0, #   vtable offset

        1, #   value 7
        1, #   value 6
        1, #   value 5
        1, #   value 4
        1, #   value 3
        1, #   value 2
        1, #   value 1
        1, #   value 0
    ])

    #   test 19: three bools
    b = FlatBuffers.Builder()
    startobject!(b, 3)
    prependslot!(b, 0, true, false)
    prependslot!(b, 1, true, false)
    prependslot!(b, 2, true, false)
    off = endobject!(b)
    finish!(b, off)

    check(UInt8[
        16, 0, 0, 0, #   root of table: points to vtable offset

        0, 0, #   padding

        10, 0, #   vtable bytes
        8, 0, #   size of object
        7, 0, #   start of value 0
        6, 0, #   start of value 1
        5, 0, #   start of value 2
        10, 0, 0, 0, #   vtable offset from here

        0, #   padding
        1, #   value 2
        1, #   value 1
        1, #   value 0
    ])

    #   test 20: some floats
    b = FlatBuffers.Builder()
    startobject!(b, 1)
    prependslot!(b, 0, 1.0, 0.0)
    off = endobject!(b)

    check(UInt8[
        6, 0, #   vtable bytes
        8, 0, #   size of object
        4, 0, #   start of value 0
        6, 0, 0, 0, #   vtable offset

        0, 0, 128, 63, #   value 0
    ])
end

#   CheckManualBuild builds a Monster manually.
function CheckManualBuild()
    b = FlatBuffers.Builder()
    str = createstring!(b, "MyMonster")

    startvector!(b, 1, 5, 1)
    prepend!(b, UInt8(4))
    prepend!(b, UInt8(3))
    prepend!(b, UInt8(2))
    prepend!(b, UInt8(1))
    prepend!(b, UInt8(0))
    inv = endvector!(b, 5)

    startobject!(b, 13)
    prependslot!(b, 2, 20, 100)
    mon2 = endobject!(b)

    #   Test4Vector
    startvector!(b, 4, 2, 1)

    #   Test 0
    prep!(b, 2, 4)
    pad!(b, 1)
    place!(b, Int8(20))
    place!(b, Int16(10)

    #   Test 1
    prep!(b, 2, 4)
    pad!(b, 1)
    place!(b, Int8(40))
    place!(b, Int16(30)

    #   end testvector
    test4 = endvector!(b, 2)

    startobject!(b, 13)

    #   a vec3
    prep!(b, 16, 32)
    pad!(b, 2)
    prep!(b, 2, 4)
    pad!(b, 1)
    place!(b, UInt8(6))
    place!(b, Int16(5)
    pad!(b, 1)
    place!(b, UInt8(4))
    place!(b, 3.0)
    pad!(b, 4)
    place!(b, Float32(3.0))
    place!(b, Float32(2.0))
    place!(b, Float32(1.0))
    vec3Loc = offset(b)
    #   end vec3

    prependstructslot!(b, 0, vec3Loc, 0) #   vec3. noop
    prependslot!(b, 2, 80, 100)     #   hp
    prependslot!(b, 3, str, 0)
    prependslot!(b, 5, inv, 0) #   inventory
    prependslot!(b, 7, UInt8(1), 0)
    prependslot!(b, 8, mon2, 0)
    prependslot!(b, 9, test4, 0)
    mon = endobject!(b)

    finish!(b, mon)

    return b.bytes, b.head
end

function CheckGetRootAsForNonRootTable()
    b = FlatBuffers.Builder()
    str = createstring!(b, "MyStat")
    Example.StatStart(b)
    Example.StatAddId(b, str)
    Example.StatAddVal(b, 12345678)
    Example.StatAddCount(b, 12345)
    stat_end = Example.StatEnd(b)
    finish!(b, stat_end)

    stat = Example.GetRootAsStat(b.bytes, b.head)

    @test stat.id == "MyStat"
    @test stat.val == 12345678
    @test stat.count == 12345
end

#   CheckGeneratedBuild uses generated code to build the example Monster.
function CheckGeneratedBuild()
    #TODO
    b = FlatBuffers.Builder()
    str = createstring!(b, "MyMonster")
    test1 = createstring!(b, "test1")
    test2 = createstring!(b, "test2")
    fred = createstring!(b, "Fred")

    Example.MonsterStartInventoryVector(b, 5)
    prepend!(b, UInt8(4))
    prepend!(b, UInt8(3))
    prepend!(b, UInt8(2))
    prepend!(b, UInt8(1))
    prepend!(b, UInt8(0))
    inv = endvector!(b, 5)

    Example.MonsterStart(b)
    Example.MonsterAddName(b, fred)
    mon2 = Example.MonsterEnd(b)

    Example.MonsterStartTest4Vector(b, 2)
    Example.CreateTest(b, 10, 20)
    Example.CreateTest(b, 30, 40)
    test4 = endvector!(b, 2)

    Example.MonsterStartTestarrayofstringVector(b, 2)
    prepend!(b, FlatBuffers.UOffsetT(test2))
    prepend!(b, FlatBuffers.UOffsetT(test1))
    testArrayOfString = endvector!(b, 2)

    Example.MonsterStart(b)

    pos = Example.CreateVec3(b, 1.0, 2.0, 3.0, 3.0, Example.ColorGreen, 5, 6)
    Example.MonsterAddPos(b, pos)

    Example.MonsterAddHp(b, 80)
    Example.MonsterAddName(b, str)
    Example.MonsterAddTestbool(b, true)
    Example.MonsterAddInventory(b, inv)
    Example.MonsterAddTestType(b, 1)
    Example.MonsterAddTest(b, mon2)
    Example.MonsterAddTest4(b, test4)
    Example.MonsterAddTestarrayofstring(b, testArrayOfString)
    mon = Example.MonsterEnd(b)

    finish!(b, mon)

    return b.bytes, b.head
end

#   CheckTableAccessors checks that the table accessors work as expected.
function CheckTableAccessors()
    #   test struct accessor
    b = FlatBuffers.Builder()
    pos = Example.CreateVec3(b, 1.0, 2.0, 3.0, 3.0, 4, 5, 6)
    finish!(b, pos)
    vec3Bytes = finishedbytes(b)
    vec3 = Example.Vec3()
    FlatBuffers.GetRootAs(vec3Bytes, 0, vec3)

    @test vec3Bytes == table(vec3).bytes

    #   test table accessor
    b = FlatBuffers.Builder()
    str = createstring!(b, "MyStat")
    Example.StatStart(b)
    Example.StatAddId(b, str)
    Example.StatAddVal(b, 12345678)
    Example.StatAddCount(b, 12345)
    pos = Example.StatEnd(b)
    finish!(b, pos)
    statBytes = finishedbytes(b)
    stat = Example.Stat()
    FlatBuffers.GetRootAs(statBytes, 0, stat)

    @test statBytes == table(stat).bytes
end

#   CheckVtableDeduplication verifies that vtables are deduplicated.
function CheckVtableDeduplication()
    b = FlatBuffers.Builder()

    startobject!(b, 4)
    prependslot!(b, 0, UInt8(0), 0)
    prependslot!(b, 1, UInt8(11), 0)
    prependslot!(b, 2, UInt8(22), 0)
    prependslot!(b, 3, Int16(33), 0)
    obj0 = endobject!(b)

    startobject!(b, 4)
    prependslot!(b, 0, UInt8(0), 0)
    prependslot!(b, 1, UInt8(44), 0)
    prependslot!(b, 2, UInt8(55), 0)
    prependslot!(b, 3, Int16(66), 0)
    obj1 = endobject!(b)

    startobject!(b, 4)
    prependslot!(b, 0, UInt8(0), 0)
    prependslot!(b, 1, UInt8(77), 0)
    prependslot!(b, 2, UInt8(88), 0)
    prependslot!(b, 3, Int16(99), 0)
    obj2 = endobject!(b)

    got = b.bytes[b.head:end]

    want = UInt8[
        240, 255, 255, 255, #   == -12. offset to dedupped vtable.
        99, 0,
        88,
        77,
        248, 255, 255, 255, #   == -8. offset to dedupped vtable.
        66, 0,
        55,
        44,
        12, 0,
        8, 0,
        0, 0,
        7, 0,
        6, 0,
        4, 0,
        12, 0, 0, 0,
        33, 0,
        22,
        11,
    ]

    @test want == got

    table0 = FlatBuffers.Table(b.bytes, FlatBuffers.UOffsetT(length(b.bytes)) - obj0)
    table1 = FlatBuffers.Table(b.bytes, FlatBuffers.UOffsetT(length(b.bytes)) - obj1)
    table2 = FlatBuffers.Table(b.bytes, FlatBuffers.UOffsetT(length(b.bytes)) - obj2)

    testTable = function(tab, a, b, c, d)
        #   vtable size
        @test got ==
        if got = tab.GetVOffsetTSlot(0, 0); 12 != got
            fail("failed 0, 0: %d", got)
        end
        #   object size
        if got = tab.GetVOffsetTSlot(2, 0); 8 != got
            fail("failed 2, 0: %d", got)
        end
        #   default value
        if got = tab.GetVOffsetTSlot(4, 0); a != got
            fail("failed 4, 0: %d", got)
        end
        if got = tab.GetByteSlot(6, 0); b != got
            fail("failed 6, 0: %d", got)
        end
        if val = tab.GetByteSlot(8, 0); c != val
            fail("failed 8, 0: %d", got)
        end
        if got = tab.GetByteSlot(10, 0); d != got
            fail("failed 10, 0: %d", got)
        end
    end

    testTable(table0, 0, 11, 22, 33)
    testTable(table1, 0, 44, 55, 66)
    testTable(table2, 0, 77, 88, 99)
end

#   CheckNotInObjectError verifies that `EndObject` fails if not inside an
#   object.
function CheckNotInObjectError(fail)
    b = FlatBuffers.Builder()

    defer func()
        r = recover()
        if r == nil
            fail("expected panic in CheckNotInObjectError")
        end
    end()
    endobject!(b)
end

#   CheckStringIsNestedError verifies that a string can not be created inside
#   another object.
function CheckStringIsNestedError(fail)
    b = FlatBuffers.Builder()
    startobject!(b, 0)
    defer func()
        r = recover()
        if r == nil
            fail("expected panic in CheckStringIsNestedError")
        end
    end()
    createstring!(b, "foo")
end

function CheckSharedStrings(fail)
    f = func(strings []string) bool {
        b = FlatBuffers.Builder()
        for _, s1 = range strings {
            for _, s2 = range strings {
                off1 = b.CreateSharedString(s1)
                off2 = b.CreateSharedString(s2)

                if (s1 == s2) && (off1 != off2)
                    return false
                end
                if (s1 != s2) && (off1 == off2)
                    return false
                end
            end
        end
        return true
    end
    if err = quick.Check(f, nil); err != nil
        fail("expected same offset")
    end
end

#   CheckByteStringIsNestedError verifies that a bytestring can not be created
#   inside another object.
function CheckByteStringIsNestedError(fail)
    b = FlatBuffers.Builder()
    startobject!(b, 0)
    defer func()
        r = recover()
        if r == nil
            fail("expected panic in CheckByteStringIsNestedError")
        end
    end()
    createstring!(b, []byte("foo"))
end

#   CheckStructIsNotInlineError verifies that writing a struct in a location
#   away from where it is used will cause a panic.
function CheckStructIsNotInlineError(fail)
    b = FlatBuffers.Builder()
    startobject!(b, 0)
    defer func()
        r = recover()
        if r == nil
            fail("expected panic in CheckStructIsNotInlineError")
        end
    end()
    prependstructslot!(b, 0, 1, 0)
end

#   CheckFinishedBytesError verifies that `FinishedBytes` panics if the table
#   is not finished.
function CheckFinishedBytesError(fail)
    b = FlatBuffers.Builder()

    defer func()
        r = recover()
        if r == nil
            fail("expected panic in CheckFinishedBytesError")
        end
    end()
    finishedbytes(b)
end

#   CheckEnumNames checks that the generated enum names are correct.
function CheckEnumNames(fail)
    {
        want = map[Example.Any]string{
            Example.AnyNONE:                    "NONE",
            Example.AnyMonster:                 "Monster",
            Example.AnyTestSimpleTableWithEnum: "TestSimpleTableWithEnum",
            Example.AnyMyGame_Example2_Monster: "MyGame_Example2_Monster",
        end
        got = Example.EnumNamesAny
        if !reflect.DeepEqual(got, want)
            fail("enum name is not equal")
        end
    end
    {
        want = map[Example.Color]string{
            Example.ColorRed:   "Red",
            Example.ColorGreen: "Green",
            Example.ColorBlue:  "Blue",
        end
        got = Example.EnumNamesColor
        if !reflect.DeepEqual(got, want)
            fail("enum name is not equal")
        end
    end
end

#   CheckEnumString checks the String method on generated enum types.
function CheckEnumString(fail)
    if got = Example.AnyMonster.String(); got != "Monster"
        fail("Monster.String: %q != %q", got, "Monster")
    end
    if got = fmt.Sprintf("color: %s", Example.ColorGreen); got != "color: Green"
        fail("color.String: %q != %q", got, "color: Green")
    end
end

#   CheckEnumValues checks that the generated enum values maps are correct.
function CheckEnumValues(fail)
    {
        want = map[string]Example.Any{
            "NONE":                    Example.AnyNONE,
            "Monster":                 Example.AnyMonster,
            "TestSimpleTableWithEnum": Example.AnyTestSimpleTableWithEnum,
            "MyGame_Example2_Monster": Example.AnyMyGame_Example2_Monster,
        end
        got = Example.EnumValuesAny
        if !reflect.DeepEqual(got, want)
            fail("enum name is not equal")
        end
    end
    {
        want = map[string]Example.Color{
            "Red":   Example.ColorRed,
            "Green": Example.ColorGreen,
            "Blue":  Example.ColorBlue,
        end
        got = Example.EnumValuesColor
        if !reflect.DeepEqual(got, want)
            fail("enum name is not equal")
        end
    end
end

#   CheckDocExample checks that the code given in FlatBuffers documentation
#   is syntactically correct.
function CheckDocExample(buf, off)
    monster = Example.GetRootAsMonster(buf, off)
    _ = monster.Hp()
    _ = monster.Pos(nil)
    for i = 0; i < monster.InventoryLength(); i++ {
        _ = monster.Inventory(i) #   do something here
    end

    builder = FlatBuffers.Builder()

    Example.MonsterStartInventoryVector(builder, 5)
    for i = 4; i >= 0; i-- {
        prepend!(b, UInt8(byte)(i))
    end
    inv = builder.EndVector(5)

    str = builder.CreateString("MyMonster")
    Example.MonsterStart(builder)
    Example.MonsterAddPos(builder, Example.CreateVec3(builder, 1.0, 2.0, 3.0, 3.0, Example.Color(4), 5, 6))
    Example.MonsterAddHp(builder, 80)
    Example.MonsterAddName(builder, str)
    Example.MonsterAddInventory(builder, inv)
    Example.MonsterAddTestType(builder, 1)
    Example.MonsterAddColor(builder, Example.ColorRed)
    #   Example.MonsterAddTest(builder, mon2)
    #   Example.MonsterAddTest4(builder, test4s)
    _ = Example.MonsterEnd(builder)
end

function CheckCreateByteVector(fail)
    raw = [30]byte{end
    for i = 0; i < len(raw); i++ {
        raw[i] = byte(i)
    end

    for size = 0; size < len(raw); size++ {
        b1 = FlatBuffers.Builder()
        b2 = FlatBuffers.Builder()
        b1.startvector!(1, size, 1)
        for i = size - 1; i >= 0; i-- {
            prepend!(b, UInt8(raw)[i])
        end
        b1.EndVector(size)
        b2.CreateByteVector(raw[:size])
        CheckByteEquality(b1.Bytes, b2.Bytes)
    end
end

function CheckParentNamespace(fail)
    var empty, nonempty []byte

    #   create monster with an empty parent namespace field
    {
        builder = FlatBuffers.Builder()

        Example.MonsterStart(builder)
        m = Example.MonsterEnd(builder)
        finish!(builder, m)

        empty = make([]byte, len(finishedbytes(builder)))
        copy(empty, finishedbytes(builder))
    end

    #   create monster with a non-empty parent namespace field
    {
        builder = FlatBuffers.Builder()
        mygame.InParentNamespaceStart(builder)
        pn = mygame.InParentNamespaceEnd(builder)

        Example.MonsterStart(builder)
        Example.MonsterAddParentNamespaceTest(builder, pn)
        m = Example.MonsterEnd(builder)

        finish!(builder, m)

        nonempty = make([]byte, len(finishedbytes(builder)))
        copy(nonempty, finishedbytes(builder))
    end

    #   read monster with empty parent namespace field
    {
        m = Example.GetRootAsMonster(empty, 0)
        if m.ParentNamespaceTest(nil) != nil
            fail("expected nil ParentNamespaceTest for empty field")
        end
    end

    #   read monster with non-empty parent namespace field
    {
        m = Example.GetRootAsMonster(nonempty, 0)
        if m.ParentNamespaceTest(nil) == nil
            fail("expected non-nil ParentNamespaceTest for non-empty field")
        end
    end
end

#   Include simple random number generator to ensure results will be the
#   same cross platform.
#   http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator
type LCG UInt32

const InitialLCGSeed = 48271

function NewLCG() *LCG {
    n = UInt32(InitialLCGSeed)
    l = LCG(n)
    return &l
end

function (lcg *LCG) Reset()
    *lcg = InitialLCGSeed
end

function (lcg *LCG) Next() UInt32 {
    n = UInt32((uint64(*lcg) * uint64(279470273)) % uint64(4294967291))
    *lcg = LCG(n)
    return n
end

#   CheckByteEquality verifies that two byte buffers are the same.
function CheckByteEquality(a, b)
    if !bytes.Equal(a, b)
        fail("objects are not byte-wise equal")
    end
end

#   CheckMutateMethods checks all mutate methods one by one
function CheckMutateMethods(fail)
    b = FlatBuffers.Builder()
    startobject!(b, 15)
    prependslot!(b, 0, true, false)
    prependslot!(b, 1, UInt8(1), 0)
    prependslot!(b, 2, 2, 0)
    prependslot!(b, 3, 3, 0)
    prependslot!(b, 4, 4, 0)
    prependslot!(b, 5, 5, 0)
    prependslot!(b, 6, 6, 0)
    prependslot!(b, 7, 7, 0)
    prependslot!(b, 8, 8, 0)
    prependslot!(b, 9, 9, 0)
    prependslot!(b, 10, 10, 0)
    prependslot!(b, 11, 11, 0)

    prependslot!(b, 12, 12, 0)
    uoVal = offset(b) - 12

    b.PrependVOffsetT(13)
    b.Slot(13)

    b.PrependSOffsetT(14)
    b.Slot(14)
    soVal = FlatBuffers.SOffsetT(offset(b) - 14)

    offset = endobject!(b)

    t = FlatBuffers.Table(
        Bytes: b.bytes,
        Pos:   FlatBuffers.UOffsetT(len(b.bytes)) - offset,
    end

    calcVOffsetT = func(slot int) (vtableOffset FlatBuffers.VOffsetT)
        return FlatBuffers.VOffsetT((FlatBuffers.VtableMetadataFields + slot) * FlatBuffers.SizeVOffsetT)
    end
    calcUOffsetT = func(vtableOffset FlatBuffers.VOffsetT) (valueOffset FlatBuffers.UOffsetT)
        return t.Pos + FlatBuffers.UOffsetT(t.Offset(vtableOffset))
    end

    type testcase struct {
        field  string
        testfn func() bool
    end

    testForOriginalValues = []testcase{
        testcase{"BoolSlot", func() bool { return t.getslot(calcVOffsetT(0), true) == true }end,
        testcase{"ByteSlot", func() bool { return t.GetByteSlot(calcVOffsetT(1), 1) == 1 }end,
        testcase{"Uint8Slot", func() bool { return t.getslot(calcVOffsetT(2), 2) == 2 }end,
        testcase{"Uint16Slot", func() bool { return t.getslot(calcVOffsetT(3), 3) == 3 }end,
        testcase{"Uint32Slot", func() bool { return t.getslot(calcVOffsetT(4), 4) == 4 }end,
        testcase{"Uint64Slot", func() bool { return t.getslot(calcVOffsetT(5), 5) == 5 }end,
        testcase{"Int8Slot", func() bool { return t.getslot(calcVOffsetT(6), 6) == 6 }end,
        testcase{"Int16Slot", func() bool { return t.getslot(calcVOffsetT(7), 7) == 7 }end,
        testcase{"Int32Slot", func() bool { return t.getslot(calcVOffsetT(8), 8) == 8 }end,
        testcase{"Int64Slot", func() bool { return t.getslot(calcVOffsetT(9), 9) == 9 }end,
        testcase{"Float32Slot", func() bool { return t.getslot(calcVOffsetT(10), 10) == 10 }end,
        testcase{"Float64Slot", func() bool { return t.getslot(calcVOffsetT(11), 11) == 11 }end,
        testcase{"UOffsetTSlot", func() bool { return t.GetUOffsetT(calcUOffsetT(calcVOffsetT(12))) == uoVal }end,
        testcase{"VOffsetTSlot", func() bool { return t.GetVOffsetT(calcUOffsetT(calcVOffsetT(13))) == 13 }end,
        testcase{"SOffsetTSlot", func() bool { return t.GetSOffsetT(calcUOffsetT(calcVOffsetT(14))) == soVal }end,
    end

    testMutability = []testcase{
        testcase{"BoolSlot", func() bool { return t.MutateBoolSlot(calcVOffsetT(0), false) }end,
        testcase{"ByteSlot", func() bool { return t.MutateByteSlot(calcVOffsetT(1), 2) }end,
        testcase{"Uint8Slot", func() bool { return t.MutateUint8Slot(calcVOffsetT(2), 4) }end,
        testcase{"Uint16Slot", func() bool { return t.MutateUint16Slot(calcVOffsetT(3), 6) }end,
        testcase{"Uint32Slot", func() bool { return t.MutateUint32Slot(calcVOffsetT(4), 8) }end,
        testcase{"Uint64Slot", func() bool { return t.MutateUint64Slot(calcVOffsetT(5), 10) }end,
        testcase{"Int8Slot", func() bool { return t.MutateInt8Slot(calcVOffsetT(6), 12) }end,
        testcase{"Int16Slot", func() bool { return t.MutateInt16Slot(calcVOffsetT(7), 14) }end,
        testcase{"Int32Slot", func() bool { return t.MutateInt32Slot(calcVOffsetT(8), 16) }end,
        testcase{"Int64Slot", func() bool { return t.MutateInt64Slot(calcVOffsetT(9), 18) }end,
        testcase{"Float32Slot", func() bool { return t.MutateFloat32Slot(calcVOffsetT(10), 20) }end,
        testcase{"Float64Slot", func() bool { return t.MutateFloat64Slot(calcVOffsetT(11), 22) }end,
        testcase{"UOffsetTSlot", func() bool { return t.MutateUOffsetT(calcUOffsetT(calcVOffsetT(12)), 24) }end,
        testcase{"VOffsetTSlot", func() bool { return t.MutateVOffsetT(calcUOffsetT(calcVOffsetT(13)), 26) }end,
        testcase{"SOffsetTSlot", func() bool { return t.MutateSOffsetT(calcUOffsetT(calcVOffsetT(14)), 28) }end,
    end

    testMutabilityWithoutSlot = []testcase{
        testcase{"BoolSlot", func() bool { return t.MutateBoolSlot(calcVOffsetT(16), false) }end,
        testcase{"ByteSlot", func() bool { return t.MutateByteSlot(calcVOffsetT(16), 2) }end,
        testcase{"Uint8Slot", func() bool { return t.MutateUint8Slot(calcVOffsetT(16), 2) }end,
        testcase{"Uint16Slot", func() bool { return t.MutateUint16Slot(calcVOffsetT(16), 2) }end,
        testcase{"Uint32Slot", func() bool { return t.MutateUint32Slot(calcVOffsetT(16), 2) }end,
        testcase{"Uint64Slot", func() bool { return t.MutateUint64Slot(calcVOffsetT(16), 2) }end,
        testcase{"Int8Slot", func() bool { return t.MutateInt8Slot(calcVOffsetT(16), 2) }end,
        testcase{"Int16Slot", func() bool { return t.MutateInt16Slot(calcVOffsetT(16), 2) }end,
        testcase{"Int32Slot", func() bool { return t.MutateInt32Slot(calcVOffsetT(16), 2) }end,
        testcase{"Int64Slot", func() bool { return t.MutateInt64Slot(calcVOffsetT(16), 2) }end,
        testcase{"Float32Slot", func() bool { return t.MutateFloat32Slot(calcVOffsetT(16), 2) }end,
        testcase{"Float64Slot", func() bool { return t.MutateFloat64Slot(calcVOffsetT(16), 2) }end,
    end

    testForMutatedValues = []testcase{
        testcase{"BoolSlot", func() bool { return t.getslot(calcVOffsetT(0), true) == false }end,
        testcase{"ByteSlot", func() bool { return t.GetByteSlot(calcVOffsetT(1), 1) == 2 }end,
        testcase{"Uint8Slot", func() bool { return t.getslot(calcVOffsetT(2), 1) == 4 }end,
        testcase{"Uint16Slot", func() bool { return t.getslot(calcVOffsetT(3), 1) == 6 }end,
        testcase{"Uint32Slot", func() bool { return t.getslot(calcVOffsetT(4), 1) == 8 }end,
        testcase{"Uint64Slot", func() bool { return t.getslot(calcVOffsetT(5), 1) == 10 }end,
        testcase{"Int8Slot", func() bool { return t.getslot(calcVOffsetT(6), 1) == 12 }end,
        testcase{"Int16Slot", func() bool { return t.getslot(calcVOffsetT(7), 1) == 14 }end,
        testcase{"Int32Slot", func() bool { return t.getslot(calcVOffsetT(8), 1) == 16 }end,
        testcase{"Int64Slot", func() bool { return t.getslot(calcVOffsetT(9), 1) == 18 }end,
        testcase{"Float32Slot", func() bool { return t.getslot(calcVOffsetT(10), 1) == 20 }end,
        testcase{"Float64Slot", func() bool { return t.getslot(calcVOffsetT(11), 1) == 22 }end,
        testcase{"UOffsetTSlot", func() bool { return t.GetUOffsetT(calcUOffsetT(calcVOffsetT(12))) == 24 }end,
        testcase{"VOffsetTSlot", func() bool { return t.GetVOffsetT(calcUOffsetT(calcVOffsetT(13))) == 26 }end,
        testcase{"SOffsetTSlot", func() bool { return t.GetSOffsetT(calcUOffsetT(calcVOffsetT(14))) == 28 }end,
    end

    #   make sure original values are okay
    for _, t = range testForOriginalValues {
        if !t.testfn()
            fail(t.field + "' field doesn't have the expected original value")
        end
    end

    #   try to mutate fields and check mutability
    for _, t = range testMutability {
        if !t.testfn()
            error(string(t.field+"' field failed mutability test", "passed", "failed"))
        end
    end

    #   try to mutate fields and check mutability
    #   these have wrong slots so should fail
    for _, t = range testMutabilityWithoutSlot {
        if t.testfn()
            error(string(t.field+"' field failed no slot mutability test", "failed", "passed"))
        end
    end

    #   test whether values have changed
    for _, t = range testForMutatedValues {
        if !t.testfn()
            fail(t.field + "' field doesn't have the expected mutated value")
        end
    end
end

#   BenchmarkVtableDeduplication measures the speed of vtable deduplication
#   by creating prePop vtables, then populating b.N objects with a
#   different single vtable.
//
#   When b.N is large (as in long benchmarks), memory usage may be high.
function BenchmarkVtableDeduplication(b *testing.B)
    prePop = 10
    builder = FlatBuffers.Builder()

    #   pre-populate some vtables:
    for i = 0; i < prePop; i++ {
        builder.startobject!(i)
        for j = 0; j < i; j++ {
            prependslot!(builder, j, int16(j), 0)
        end
        builder.EndObject()
    end

    #   benchmark deduplication of a new vtable:
    b.ResetTimer()
    for i = 0; i < b.N; i++ {
        lim = prePop

        builder.startobject!(lim)
        for j = 0; j < lim; j++ {
            prependslot!(builder, j, int16(j), 0)
        end
        builder.EndObject()
    end
end

#   BenchmarkParseGold measures the speed of parsing the 'gold' data
#   used throughout this test suite.
function BenchmarkParseGold(b *testing.B)
    buf, offset = CheckGeneratedBuild(b.Fatalf)
    monster = Example.GetRootAsMonster(buf, offset)

    #   use these to prevent allocations:
    reuse_pos = Example.Vec3{end
    reuse_test3 = Example.Test{end
    reuse_table2 = FlatBuffers.Table{end
    reuse_monster2 = Example.Monster{end
    reuse_test4_0 = Example.Test{end
    reuse_test4_1 = Example.Test{end

    b.SetBytes(int64(len(buf[offset:])))
    b.ReportAllocs()
    b.ResetTimer()
    for i = 0; i < b.N; i++ {
        monster.Hp()
        monster.Mana()
        name = monster.Name()
        _ = name[0]
        _ = name[len(name)-1]

        monster.Pos(&reuse_pos)
        reuse_pos.X()
        reuse_pos.Y()
        reuse_pos.Z()
        reuse_pos.Test1()
        reuse_pos.Test2()
        reuse_pos.Test3(&reuse_test3)
        reuse_test3.A()
        reuse_test3.B()
        monster.TestType()
        monster.Test(&reuse_table2)
        reuse_monster2.Init(reuse_table2.Bytes, reuse_table2.Pos)
        name2 = reuse_monster2.Name()
        _ = name2[0]
        _ = name2[len(name2)-1]
        monster.InventoryLength()
        l = monster.InventoryLength()
        for i = 0; i < l; i++ {
            monster.Inventory(i)
        end
        monster.Test4Length()
        monster.Test4(&reuse_test4_0, 0)
        monster.Test4(&reuse_test4_1, 1)

        reuse_test4_0.A()
        reuse_test4_0.B()
        reuse_test4_1.A()
        reuse_test4_1.B()

        monster.TestarrayofstringLength()
        str0 = monster.Testarrayofstring(0)
        _ = str0[0]
        _ = str0[len(str0)-1]
        str1 = monster.Testarrayofstring(1)
        _ = str1[0]
        _ = str1[len(str1)-1]
    end
end

#   BenchmarkBuildGold uses generated code to build the example Monster.
function BenchmarkBuildGold(b *testing.B)
    buf, offset = CheckGeneratedBuild(b.Fatalf)
    bytes_length = int64(len(buf[offset:]))

    reuse_str = "MyMonster"
    reuse_test1 = "test1"
    reuse_test2 = "test2"
    reuse_fred = "Fred"

    b.SetBytes(bytes_length)
    bldr = FlatBuffers.Builder()
    b.ResetTimer()
    b.ReportAllocs()
    for i = 0; i < b.N; i++ {
        bldr.Reset()

        str = bldr.CreateString(reuse_str)
        test1 = bldr.CreateString(reuse_test1)
        test2 = bldr.CreateString(reuse_test2)
        fred = bldr.CreateString(reuse_fred)

        Example.MonsterStartInventoryVector(bldr, 5)
        prepend!(b, UInt8(4))
        prepend!(b, UInt8(3))
        prepend!(b, UInt8(2))
        prepend!(b, UInt8(1))
        prepend!(b, UInt8(0))
        inv = bldr.EndVector(5)

        Example.MonsterStart(bldr)
        Example.MonsterAddName(bldr, fred)
        mon2 = Example.MonsterEnd(bldr)

        Example.MonsterStartTest4Vector(bldr, 2)
        Example.CreateTest(bldr, 10, 20)
        Example.CreateTest(bldr, 30, 40)
        test4 = bldr.EndVector(2)

        Example.MonsterStartTestarrayofstringVector(bldr, 2)
        bldr.PrependUOffsetT(test2)
        bldr.PrependUOffsetT(test1)
        testArrayOfString = bldr.EndVector(2)

        Example.MonsterStart(bldr)

        pos = Example.CreateVec3(bldr, 1.0, 2.0, 3.0, 3.0, Example.ColorGreen, 5, 6)
        Example.MonsterAddPos(bldr, pos)

        Example.MonsterAddHp(bldr, 80)
        Example.MonsterAddName(bldr, str)
        Example.MonsterAddInventory(bldr, inv)
        Example.MonsterAddTestType(bldr, 1)
        Example.MonsterAddTest(bldr, mon2)
        Example.MonsterAddTest4(bldr, test4)
        Example.MonsterAddTestarrayofstring(bldr, testArrayOfString)
        mon = Example.MonsterEnd(bldr)

        finish!(bldr, mon)
    end
end