text:
/*******************************************************************************
 memorymanager.cpp - GameOS reference pseudo code

 MechCommander;source code

 2014-07-24 Jerker Back, created

*******************************************************************************/

#include "stdinc.h"

#include "memorymanager.hpp"

typedef struct _MemStack
{
	PVOID unk1;
	PVOID startaddress;
	size_t nsize;
	PVOID unk4;
} MemStack;
typedef MemStack* PMemStack;

// -----------------------------------------------------------------------------
// Global data exported from this module

// extern HGOSHEAP HeapList[256];
// extern HGOSHEAP gCurrentHeapStack[64];
extern PMEMORYPOOL gMemoryPool[MemoryPools];
size_t MemoryLeaks;
size_t LeakedMemory;
size_t LargeMemorySize;
size_t LargeMemoryAllocations;
HANDLE HWSProcess;
size_t MemoryAllocated;
size_t SystemMemoryAllocated;
size_t SystemMemoryAllocs;
HGOSHEAP Heap_Font;
HGOSHEAP ParentGameOSHeap;
HGOSHEAP ParentClientHeap;
HGOSHEAP DefaultHeap;
HGOSHEAP CurrentHeap;
HGOSHEAP ClientHeap;
HGOSHEAP Heap_Network;
HGOSHEAP Heap_Texture;
HGOSHEAP Heap_Texture32;
HGOSHEAP Heap_Texture16;
HGOSHEAP Heap_TextureOther;
HGOSHEAP AllHeaps;
PLARGEBLOCKHEADER gMemoryBigAllocList;
size_t gCurrentHeapStackLevel;
size_t gMemoryStackWalkLevel;
HGOSHEAP gExaminingHeap; // not used
PMEMORYPOOL gExaminingPool; // not used
size_t VirtualMemoryAllocated;
size_t MemoryUsed;
size_t MemoryAllocations;
PPSAPI_WS_WATCH_INFORMATION pMemBlockInfo;

// initialized data
uint16_t AgressiveManager = 1; // unknown purpose
extern uint16_t PoolSizes[MemoryPools] = {
	0x000C,
	0x0010,
	0x0014,
	0x0018,
	0x001C,
	0x0020,
	0x0028,
	0x0030,
	0x0044,
	0x0058,
	0x0080,
	0x00C4,
	0x0100,
	0x015C,
	0x0180,
	0x0200,
	0x0300,
	0x0400,
};
uint32_t gMemoryBlockOverhead = 0xFF81FF81; // not used

// global referenced data not listed in headers
bool gViaNew;

// local data
size_t MemoryFreed;
PMemStack pMemoryStack;

// -----------------------------------------------------------------------------
// global implemented functions in this module listed in headers
void __stdcall SetupVirtualMemory(void);
void __stdcall MM_Startup(void);
void __stdcall MM_UpdateStatistics(HGOSHEAP Heap);
void __stdcall MM_Shutdown(void);
PVOID __stdcall gos_Malloc(size_t nbytes, HGOSHEAP Heap = nullptr);
PVOID __stdcall gos_Realloc(HGOSHEAP Heap, size_t nbytes);
void __stdcall gos_Free(PVOID ptr);
HGOSHEAP __stdcall gos_CreateMemoryHeap(
	PSTR HeapName, size_t MaximumSize /* = 0*/, HGOSHEAP parentHeap /* = ParentClientHeap*/);
void __stdcall gos_DestroyMemoryHeap(HGOSHEAP Heap, uint8_t shouldBeEmpty = 1);
void __stdcall gos_ChangeHeapSize(HGOSHEAP Heap, size_t Change, uint8_t SystemAllocation = 0);
void __stdcall gos_PushCurrentHeap(HGOSHEAP Heap);
HGOSHEAP __stdcall gos_GetCurrentHeap(void);
void __stdcall gos_PopCurrentHeap(void);
void __stdcall gos_WalkMemoryHeap(HGOSHEAP pHeap, uint8_t vociferous = 0);
void __stdcall AnalyzeWS(PSTR Title);

// global implemented functions not listed in headers

// local functions
PMEMORYPOOL __stdcall MM_CreateMemoryPool(uint16_t);
void __stdcall MM_DestroyMemoryPool(PMEMORYPOOL pAddress);
void __stdcall DisplayLeakInformation(PLARGEBLOCKHEADER, PPOOLBLOCK, PSMALLPOOLBLOCK,
	uint8_t*) void __stdcall SpewAndFreeHeapAllocs(HGOSHEAP heap,
	bool) void __stdcall DestroySelfAndChildren(HGOSHEAP heap, bool);
void __stdcall WalkSelfAndChildren(HGOSHEAP heap, bool);
void __stdcall WalkHeapAllocs(HGOSHEAP heap, bool);

// -----------------------------------------------------------------------------
// externals referenced in this file not specified in headers
extern size_t MemoryFrees;
extern size_t MemoryAllocs;
extern bool g_MMInitialized;


text:
<!DOCTYPE html>

<meta charset="utf-8">
<meta name="description"
      content="So I came across a situation where I needed to boot up an https server to host some files and guess what its really v..." >
<meta name="author" content="Pankaj Malhotra">

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">

<title>Simple HTTPS Server In Python Using Self Signed Certs · Pankaj Malhotra</title>

<link rel="shortcut icon" href="/public/images/favicon.ico" />

<link rel="stylesheet" href="/public/css/responsive.gs.12col.css">
<link rel="stylesheet" href="/public/css/animate.min.css">
<link rel="stylesheet" href="/public/css/main.css">
<link rel="stylesheet" href="/public/css/share-page.css">
<link rel="stylesheet" href="/public/css/social.css">
<link rel="stylesheet" href="/public/css/console.css">
<link rel="stylesheet" href="/public/css/til.css">

<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic&subset=latin-ext">
<link href='https://fonts.googleapis.com/css?family=Give+You+Glory' rel='stylesheet' type='text/css'>

<link rel="alternate" href="/feed.xml" type="application/rss+xml" title="">

  Blog

  Live

  Til

  CV

  <time class="published" datetime="2015-06-08">08 June 2015</time>

Simple HTTPS Server In Python Using Self Signed Certs

So I came across a situation where I needed to boot up an https server to host some files and guess what its really very easy to do than what I imagined.

Generate self signed certificates using OpenSSL

Generate your server key

$ openssl genrsa -des3 -out server.key 1024

You will be prompted for a password for your key. Enter, confirm and continue.

Generate your Certificate Signing Request (CSR)

$ openssl req -new -key server.key -out server.csr

You will be prompted again for your key password. Enter the one you created from step 1 above. You can then accept the defaults for all of the prompts you are presented with except the Common Name. This is key, and what makes the enhanced certificate validation happy. Since we are doing local development your common name will be localhost.

Common Name (e.g. server FQDN or YOUR name) []:localhost

Generate your Certificate

Lastly we need to create our certificate. Again, use your key password and you will be all set.

$ openssl x509 -req -days 1024 -in server.csr -signkey server.key -out server.crt

Generate a pem file

$ cat server.crt server.key > server.pem

Python implementation of server:

#!/usr/bin/python

import BaseHTTPServer, SimpleHTTPServer
import ssl

httpd = BaseHTTPServer.HTTPServer(('localhost', 4443), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='/path/to/server.pem', server_side=True)
httpd.serve_forever()

Run $ python server.py

Default host here is localhost and port is 4443.

That's it ! You have finally deployed an https server.
Go to https://localhost:4443 and click Advanced > Proceed to localhost(unsafe) to accept certificates and see the serverd files.

Sources:

Generating valid self signed certificates for localhost development

Creating an HTTPS server in Python

    Please enable JavaScript to view the comments powered by Disqus.
    comments powered by Disqus

          Subscribe to: Posts(Atom)

	  No Attributions, It's all yours under  Creative Commons CC0.

redpajama_set_name: RedPajamaGithub


text:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef nsLookAndFeel_h_
#define nsLookAndFeel_h_
#include "nsXPLookAndFeel.h"

class nsLookAndFeel: public nsXPLookAndFeel {
public:
  nsLookAndFeel();
  virtual ~nsLookAndFeel();

  virtual nsresult NativeGetColor(ColorID aID, nscolor &aResult);
  virtual nsresult GetIntImpl(IntID aID, int32_t &aResult);
  virtual nsresult GetFloatImpl(FloatID aID, float &aResult);
  virtual bool GetFontImpl(FontID aID, nsString& aFontName,
                           gfxFontStyle& aFontStyle,
                           float aDevPixPerCSSPixel);
  virtual PRUnichar GetPasswordCharacterImpl()
  {
    // unicode value for the bullet character, used for password textfields.
    return 0x2022;
  }

protected:

  // Apple hasn't defined a constant for scollbars with two arrows on each end, so we'll use this one.
  static const int kThemeScrollBarArrowsBoth = 2;
  static const int kThemeScrollBarArrowsUpperLeft = 3;
};

#endif // nsLookAndFeel_h_


text:
#include "jemalloc/internal/jemalloc_preamble.h"
#include "jemalloc/internal/jemalloc_internal_includes.h"

#include "jemalloc/internal/psset.h"

#include "jemalloc/internal/flat_bitmap.h"

void
psset_init(psset_t *psset) {
	for (unsigned i = 0; i < PSSET_NPSIZES; i++) {
		hpdata_age_heap_new(&psset->pageslabs[i]);
	}
	fb_init(psset->pageslab_bitmap, PSSET_NPSIZES);
	memset(&psset->merged_stats, 0, sizeof(psset->merged_stats));
	memset(&psset->stats, 0, sizeof(psset->stats));
	hpdata_empty_list_init(&psset->empty);
	for (int i = 0; i < PSSET_NPURGE_LISTS; i++) {
		hpdata_purge_list_init(&psset->to_purge[i]);
	}
	fb_init(psset->purge_bitmap, PSSET_NPURGE_LISTS);
	hpdata_hugify_list_init(&psset->to_hugify);
}

static void
psset_bin_stats_accum(psset_bin_stats_t *dst, psset_bin_stats_t *src) {
	dst->npageslabs += src->npageslabs;
	dst->nactive += src->nactive;
	dst->ndirty += src->ndirty;
}

void
psset_stats_accum(psset_stats_t *dst, psset_stats_t *src) {
	psset_bin_stats_accum(&dst->full_slabs[0], &src->full_slabs[0]);
	psset_bin_stats_accum(&dst->full_slabs[1], &src->full_slabs[1]);
	psset_bin_stats_accum(&dst->empty_slabs[0], &src->empty_slabs[0]);
	psset_bin_stats_accum(&dst->empty_slabs[1], &src->empty_slabs[1]);
	for (pszind_t i = 0; i < PSSET_NPSIZES; i++) {
		psset_bin_stats_accum(&dst->nonfull_slabs[i][0],
		    &src->nonfull_slabs[i][0]);
		psset_bin_stats_accum(&dst->nonfull_slabs[i][1],
		    &src->nonfull_slabs[i][1]);
	}
}

/*
 * The stats maintenance strategy is to remove a pageslab's contribution to the
 * stats when we call psset_update_begin, and re-add it (to a potentially new
 * bin) when we call psset_update_end.
 */
JEMALLOC_ALWAYS_INLINE void
psset_bin_stats_insert_remove(psset_t *psset, psset_bin_stats_t *binstats,
    hpdata_t *ps, bool insert) {
	size_t mul = insert ? (size_t)1 : (size_t)-1;
	size_t huge_idx = (size_t)hpdata_huge_get(ps);

	binstats[huge_idx].npageslabs += mul * 1;
	binstats[huge_idx].nactive += mul * hpdata_nactive_get(ps);
	binstats[huge_idx].ndirty += mul * hpdata_ndirty_get(ps);

	psset->merged_stats.npageslabs += mul * 1;
	psset->merged_stats.nactive += mul * hpdata_nactive_get(ps);
	psset->merged_stats.ndirty += mul * hpdata_ndirty_get(ps);

	if (config_debug) {
		psset_bin_stats_t check_stats = {0};
		for (size_t huge = 0; huge <= 1; huge++) {
			psset_bin_stats_accum(&check_stats,
			    &psset->stats.full_slabs[huge]);
			psset_bin_stats_accum(&check_stats,
			    &psset->stats.empty_slabs[huge]);
			for (pszind_t pind = 0; pind < PSSET_NPSIZES; pind++) {
				psset_bin_stats_accum(&check_stats,
				    &psset->stats.nonfull_slabs[pind][huge]);
			}
		}
		assert(psset->merged_stats.npageslabs
		    == check_stats.npageslabs);
		assert(psset->merged_stats.nactive == check_stats.nactive);
		assert(psset->merged_stats.ndirty == check_stats.ndirty);
	}
}

static void
psset_bin_stats_insert(psset_t *psset, psset_bin_stats_t *binstats,
    hpdata_t *ps) {
	psset_bin_stats_insert_remove(psset, binstats, ps, true);
}

static void
psset_bin_stats_remove(psset_t *psset, psset_bin_stats_t *binstats,
    hpdata_t *ps) {
	psset_bin_stats_insert_remove(psset, binstats, ps, false);
}

static void
psset_hpdata_heap_remove(psset_t *psset, pszind_t pind, hpdata_t *ps) {
	hpdata_age_heap_remove(&psset->pageslabs[pind], ps);
	if (hpdata_age_heap_empty(&psset->pageslabs[pind])) {
		fb_unset(psset->pageslab_bitmap, PSSET_NPSIZES, (size_t)pind);
	}
}

static void
psset_hpdata_heap_insert(psset_t *psset, pszind_t pind, hpdata_t *ps) {
	if (hpdata_age_heap_empty(&psset->pageslabs[pind])) {
		fb_set(psset->pageslab_bitmap, PSSET_NPSIZES, (size_t)pind);
	}
	hpdata_age_heap_insert(&psset->pageslabs[pind], ps);
}

static void
psset_stats_insert(psset_t* psset, hpdata_t *ps) {
	if (hpdata_empty(ps)) {
		psset_bin_stats_insert(psset, psset->stats.empty_slabs, ps);
	} else if (hpdata_full(ps)) {
		psset_bin_stats_insert(psset, psset->stats.full_slabs, ps);
	} else {
		size_t longest_free_range = hpdata_longest_free_range_get(ps);

		pszind_t pind = sz_psz2ind(sz_psz_quantize_floor(
		    longest_free_range << LG_PAGE));
		assert(pind < PSSET_NPSIZES);

		psset_bin_stats_insert(psset, psset->stats.nonfull_slabs[pind],
		    ps);
	}
}

static void
psset_stats_remove(psset_t *psset, hpdata_t *ps) {
	if (hpdata_empty(ps)) {
		psset_bin_stats_remove(psset, psset->stats.empty_slabs, ps);
	} else if (hpdata_full(ps)) {
		psset_bin_stats_remove(psset, psset->stats.full_slabs, ps);
	} else {
		size_t longest_free_range = hpdata_longest_free_range_get(ps);

		pszind_t pind = sz_psz2ind(sz_psz_quantize_floor(
		    longest_free_range << LG_PAGE));
		assert(pind < PSSET_NPSIZES);

		psset_bin_stats_remove(psset, psset->stats.nonfull_slabs[pind],
		    ps);
	}
}

/*
 * Put ps into some container so that it can be found during future allocation
 * requests.
 */
static void
psset_alloc_container_insert(psset_t *psset, hpdata_t *ps) {
	assert(!hpdata_in_psset_alloc_container_get(ps));
	hpdata_in_psset_alloc_container_set(ps, true);
	if (hpdata_empty(ps)) {
		/*
		 * This prepend, paired with popping the head in psset_fit,
		 * means we implement LIFO ordering for the empty slabs set,
		 * which seems reasonable.
		 */
		hpdata_empty_list_prepend(&psset->empty, ps);
	} else if (hpdata_full(ps)) {
		/*
		 * We don't need to keep track of the full slabs; we're never
		 * going to return them from a psset_pick_alloc call.
		 */
	} else {
		size_t longest_free_range = hpdata_longest_free_range_get(ps);

		pszind_t pind = sz_psz2ind(sz_psz_quantize_floor(
		    longest_free_range << LG_PAGE));
		assert(pind < PSSET_NPSIZES);

		psset_hpdata_heap_insert(psset, pind, ps);
	}
}

/* Remove ps from those collections. */
static void
psset_alloc_container_remove(psset_t *psset, hpdata_t *ps) {
	assert(hpdata_in_psset_alloc_container_get(ps));
	hpdata_in_psset_alloc_container_set(ps, false);

	if (hpdata_empty(ps)) {
		hpdata_empty_list_remove(&psset->empty, ps);
	} else if (hpdata_full(ps)) {
		/* Same as above -- do nothing in this case. */
	} else {
		size_t longest_free_range = hpdata_longest_free_range_get(ps);

		pszind_t pind = sz_psz2ind(sz_psz_quantize_floor(
		    longest_free_range << LG_PAGE));
		assert(pind < PSSET_NPSIZES);

		psset_hpdata_heap_remove(psset, pind, ps);
	}
}

static size_t
psset_purge_list_ind(hpdata_t *ps) {
	size_t ndirty = hpdata_ndirty_get(ps);
	/* Shouldn't have something with no dirty pages purgeable. */
	assert(ndirty > 0);
	pszind_t pind = sz_psz2ind(sz_psz_quantize_floor(ndirty << LG_PAGE));
	/*
	 * Higher indices correspond to lists we'd like to purge earlier;
	 * increment the index for the nonhugified hpdatas first, so that we'll
	 * pick them before picking hugified ones.
	 */
	return (size_t)pind * 2 + (hpdata_huge_get(ps) ? 0 : 1);
}

static void
psset_maybe_remove_purge_list(psset_t *psset, hpdata_t *ps) {
	/*
	 * Remove the hpdata from its purge list (if it's in one).  Even if it's
	 * going to stay in the same one, by appending it during
	 * psset_update_end, we move it to the end of its queue, so that we
	 * purge LRU within a given dirtiness bucket.
	 */
	if (hpdata_purge_allowed_get(ps)) {
		size_t ind = psset_purge_list_ind(ps);
		hpdata_purge_list_t *purge_list = &psset->to_purge[ind];
		hpdata_purge_list_remove(purge_list, ps);
		if (hpdata_purge_list_empty(purge_list)) {
			fb_unset(psset->purge_bitmap, PSSET_NPURGE_LISTS, ind);
		}
	}
}

static void
psset_maybe_insert_purge_list(psset_t *psset, hpdata_t *ps) {
	if (hpdata_purge_allowed_get(ps)) {
		size_t ind = psset_purge_list_ind(ps);
		hpdata_purge_list_t *purge_list = &psset->to_purge[ind];
		if (hpdata_purge_list_empty(purge_list)) {
			fb_set(psset->purge_bitmap, PSSET_NPURGE_LISTS, ind);
		}
		hpdata_purge_list_append(purge_list, ps);
	}

}

void
psset_update_begin(psset_t *psset, hpdata_t *ps) {
	hpdata_assert_consistent(ps);
	assert(hpdata_in_psset_get(ps));
	hpdata_updating_set(ps, true);
	psset_stats_remove(psset, ps);
	if (hpdata_in_psset_alloc_container_get(ps)) {
		/*
		 * Some metadata updates can break alloc container invariants
		 * (e.g. the longest free range determines the hpdata_heap_t the
		 * pageslab lives in).
		 */
		assert(hpdata_alloc_allowed_get(ps));
		psset_alloc_container_remove(psset, ps);
	}
	psset_maybe_remove_purge_list(psset, ps);
	/*
	 * We don't update presence in the hugify list; we try to keep it FIFO,
	 * even in the presence of other metadata updates.  We'll update
	 * presence at the end of the metadata update if necessary.
	 */
}

void
psset_update_end(psset_t *psset, hpdata_t *ps) {
	assert(hpdata_in_psset_get(ps));
	hpdata_updating_set(ps, false);
	psset_stats_insert(psset, ps);

	/*
	 * The update begin should have removed ps from whatever alloc container
	 * it was in.
	 */
	assert(!hpdata_in_psset_alloc_container_get(ps));
	if (hpdata_alloc_allowed_get(ps)) {
		psset_alloc_container_insert(psset, ps);
	}
	psset_maybe_insert_purge_list(psset, ps);

	if (hpdata_hugify_allowed_get(ps)
	    && !hpdata_in_psset_hugify_container_get(ps)) {
		hpdata_in_psset_hugify_container_set(ps, true);
		hpdata_hugify_list_append(&psset->to_hugify, ps);
	} else if (!hpdata_hugify_allowed_get(ps)
	    && hpdata_in_psset_hugify_container_get(ps)) {
		hpdata_in_psset_hugify_container_set(ps, false);
		hpdata_hugify_list_remove(&psset->to_hugify, ps);
	}
	hpdata_assert_consistent(ps);
}

hpdata_t *
psset_pick_alloc(psset_t *psset, size_t size) {
	assert((size & PAGE_MASK) == 0);
	assert(size <= HUGEPAGE);

	pszind_t min_pind = sz_psz2ind(sz_psz_quantize_ceil(size));
	pszind_t pind = (pszind_t)fb_ffs(psset->pageslab_bitmap, PSSET_NPSIZES,
	    (size_t)min_pind);
	if (pind == PSSET_NPSIZES) {
		return hpdata_empty_list_first(&psset->empty);
	}
	hpdata_t *ps = hpdata_age_heap_first(&psset->pageslabs[pind]);
	if (ps == NULL) {
		return NULL;
	}

	hpdata_assert_consistent(ps);

	return ps;
}

hpdata_t *
psset_pick_purge(psset_t *psset) {
	ssize_t ind_ssz = fb_fls(psset->purge_bitmap, PSSET_NPURGE_LISTS,
	    PSSET_NPURGE_LISTS - 1);
	if (ind_ssz < 0) {
		return NULL;
	}
	pszind_t ind = (pszind_t)ind_ssz;
	assert(ind < PSSET_NPSIZES);
	hpdata_t *ps = hpdata_purge_list_first(&psset->to_purge[ind]);
	assert(ps != NULL);
	return ps;
}

hpdata_t *
psset_pick_hugify(psset_t *psset) {
	return hpdata_hugify_list_first(&psset->to_hugify);
}

void
psset_insert(psset_t *psset, hpdata_t *ps) {
	hpdata_in_psset_set(ps, true);

	psset_stats_insert(psset, ps);
	if (hpdata_alloc_allowed_get(ps)) {
		psset_alloc_container_insert(psset, ps);
	}
	psset_maybe_insert_purge_list(psset, ps);

	if (hpdata_hugify_allowed_get(ps)) {
		hpdata_in_psset_hugify_container_set(ps, true);
		hpdata_hugify_list_append(&psset->to_hugify, ps);
	}
}

void
psset_remove(psset_t *psset, hpdata_t *ps) {
	hpdata_in_psset_set(ps, false);

	psset_stats_remove(psset, ps);
	if (hpdata_in_psset_alloc_container_get(ps)) {
		psset_alloc_container_remove(psset, ps);
	}
	psset_maybe_remove_purge_list(psset, ps);
	if (hpdata_in_psset_hugify_container_get(ps)) {
		hpdata_in_psset_hugify_container_set(ps, false);
		hpdata_hugify_list_remove(&psset->to_hugify, ps);
	}
}


text:
<?php

namespace Sonata\TimelineBundle\DependencyInjection;

use Sonata\EasyExtendsBundle\Mapper\DoctrineCollector;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

/**
 * SonataTimelineExtension.
 *
 * @author Thomas Rabaix <thomas.rabaix@sonata-project.org>
 */
class SonataTimelineExtension extends Extension
{
    /**
     * Loads the url shortener configuration.
     *
     * @param array            $configs   An array of configuration settings
     * @param ContainerBuilder $container A ContainerBuilder instance
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $processor = new Processor();
        $configuration = new Configuration();
        $config = $processor->processConfiguration($configuration, $configs);

        $config = $this->addDefaults($config);

        if ('orm' !== $config['manager_type']) {
            throw new \RuntimeException('Only ORM manager is implemented');
        }

        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('timeline.xml');

        $this->configureClass($config, $container);
        $this->registerDoctrineMapping($config);
    }

    /**
     * @param array $config
     *
     * @return array
     */
    public function addDefaults(array $config)
    {
        if ('orm' === $config['manager_type']) {
            $modelType = 'Entity';
        } elseif ('mongodb' === $config['manager_type']) {
            $modelType = 'Document';
        }

        $defaultConfig['class']['timeline']         = sprintf('Application\\Sonata\\TimelineBundle\\%s\\Timeline', $modelType);
        $defaultConfig['class']['action']           = sprintf('Application\\Sonata\\TimelineBundle\\%s\\Action', $modelType);
        $defaultConfig['class']['action_component'] = sprintf('Application\\Sonata\\TimelineBundle\\%s\\ActionComponent', $modelType);
        $defaultConfig['class']['component']        = sprintf('Application\\Sonata\\TimelineBundle\\%s\\Component', $modelType);

        return array_replace_recursive($defaultConfig, $config);
    }

    /**
     * @param array            $config
     * @param ContainerBuilder $container
     */
    public function configureClass($config, ContainerBuilder $container)
    {
        if ('orm' === $config['manager_type']) {
            $modelType = 'entity';
        } elseif ('mongodb' === $config['manager_type']) {
            $modelType = 'document';
        }

        $container->setParameter(sprintf('sonata.timeline.admin.timeline.%s', $modelType),           $config['class']['timeline']);
        $container->setParameter(sprintf('sonata.timeline.admin.action.%s', $modelType),            $config['class']['action']);
        $container->setParameter(sprintf('sonata.timeline.admin.action_component.%s', $modelType),  $config['class']['action_component']);
        $container->setParameter(sprintf('sonata.timeline.admin.component.%s', $modelType),         $config['class']['component']);
    }

    /**
     * @param array $config
     */
    public function registerDoctrineMapping(array $config)
    {
        foreach ($config['class'] as $type => $class) {
            if (!class_exists($class)) {
                return;
            }
        }

        $collector = DoctrineCollector::getInstance();

        $collector->addAssociation($config['class']['timeline'], 'mapManyToOne', array(
            'fieldName'    => 'action',
            'targetEntity' => $config['class']['action'],
            'cascade'      => array(),
            'mappedBy'     => null,
            'inversedBy'   => 'timelines',
            'joinColumns'  => array(
                array(
                    'name'                 => 'action_id',
                    'referencedColumnName' => 'id',
                ),
            ),
            'orphanRemoval' => false,
        ));

        $collector->addAssociation($config['class']['timeline'], 'mapManyToOne', array(
            'fieldName'    => 'subject',
            'targetEntity' => $config['class']['component'],
            'cascade'      => array(),
            'mappedBy'     => null,
            'inversedBy'   => null,
            'joinColumns'  => array(
                array(
                    'name'                 => 'subject_id',
                    'referencedColumnName' => 'id',
                    'onDelete'             => 'CASCADE',
                ),
            ),
            'orphanRemoval' => false,
        ));

        $collector->addAssociation($config['class']['action'], 'mapOneToMany', array(
             'fieldName'    => 'actionComponents',
             'targetEntity' => $config['class']['action_component'],
             'cascade'      => array(
                 1 => 'persist',
             ),
             'mappedBy' => 'action',
        ));

        $collector->addAssociation($config['class']['action'], 'mapOneToMany', array(
             'fieldName'    => 'timelines',
             'targetEntity' => $config['class']['timeline'],
             'cascade'      => array(),
             'mappedBy'     => 'action',
        ));

        $collector->addAssociation($config['class']['action_component'], 'mapManyToOne', array(
            'fieldName'    => 'action',
            'targetEntity' => $config['class']['action'],
            'cascade'      => array(),
            'mappedBy'     => null,
            'inversedBy'   => 'actionComponents',
            'joinColumns'  => array(
                array(
                    'name'                 => 'action_id',
                    'referencedColumnName' => 'id',
                    'onDelete'             => 'CASCADE',
                ),
            ),
            'orphanRemoval' => false,
        ));

        $collector->addAssociation($config['class']['action_component'], 'mapManyToOne', array(
            'fieldName'    => 'component',
            'targetEntity' => $config['class']['component'],
            'cascade'      => array(),
            'mappedBy'     => null,
            'joinColumns'  => array(
                array(
                    'name'                 => 'component_id',
                    'referencedColumnName' => 'id',
                    'onDelete'             => 'CASCADE',
                ),
            ),
            'orphanRemoval' => false,
        ));
    }
}


text:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace EncriptografadorEnigma
{
    public partial class Encriptografador : Form
    {
        string entrada = "";
        string saida = "";
        int processamentoItem = new int();
        int rotacao1 = new int();
        int rotacao2 = new int();
        int rotacao3 = new int();
        char testChar = ' ';
        static int comprimento = 94;
        Rotor chave1 = new Rotor(comprimento, 1);
        Rotor chave2 = new Rotor(comprimento, 2);
        Rotor chave3 = new Rotor(comprimento, 3);
        Auxiliares auxiliares = new Auxiliares();

        public Encriptografador()
        {
            InitializeComponent();
        }

        private void botaoEncriptaClique(object sender, EventArgs e)
        {
            rotacao1 = Convert.ToInt32(inicioTextoChave1.Text);
            rotacao2 = Convert.ToInt32(inicioTextoChave2.Text);
            rotacao3 = Convert.ToInt32(inicioTextoChave3.Text);
            entrada = rxtInput.Text;
            while (entrada.Length > 0)
            {
                //Pega o primeiro caracter e o muda para numero
                processamentoItem = decodificaLetraParaNumero(entrada.Substring(0, 1));
                //Encripta processamentoItem
                processamentoItem = rodaEncriptacao(processamentoItem);
                //Adiciona processamentoItem, muda para letra e adiciona para saida
                saida = saida + encodificaNumeroParaLetra(processamentoItem);
                //Remove o caracter transformado da sequência de caracteres
                entrada = entrada.Remove(0,1);
            }

            rxtSaida.Text = saida;
            saida = "";
        }

        private void botaoDecriptarClique(object sender, EventArgs e)
        {
            rotacao1 = Convert.ToInt32(inicioTextoChave1.Text);
            rotacao2 = Convert.ToInt32(inicioTextoChave2.Text);
            rotacao3 = Convert.ToInt32(inicioTextoChave3.Text);
            entrada = rxtInput.Text;
            while (entrada.Length > 0)
            {
                //Pega o primeiro caracter e o muda para numero
                processamentoItem = decodificaLetraParaNumero(entrada.Substring(0, 1));
                //Decripta processamentoItem
                processamentoItem = rodaDecriptacao(processamentoItem);
                //Adiciona processamentoItem, muda para letra e adiciona para saida
                saida = saida + encodificaNumeroParaLetra(processamentoItem);
                //Remove caracter processado pra String
                entrada = entrada.Remove(0, 1);
            }

            rxtSaida.Text = saida;
            saida = "";
        }

        public int rodaEncriptacao(int entradaDeEncriptacao)
        {
            int processoDeEncriptacaoDoItem = entradaDeEncriptacao;

            // Adiciona rotação a chave1
            processoDeEncriptacaoDoItem = (processoDeEncriptacaoDoItem + rotacao1) % comprimento;
            // Encripta chave1
            processoDeEncriptacaoDoItem = chave1.encripta(processoDeEncriptacaoDoItem);
            // Adiciona rotação a chave2
            processoDeEncriptacaoDoItem = (processoDeEncriptacaoDoItem + rotacao2) % comprimento;
            // Encripta chave2
            processoDeEncriptacaoDoItem = chave2.encripta(processoDeEncriptacaoDoItem);
            // Adiciona rotação a chave3
            processoDeEncriptacaoDoItem = (processoDeEncriptacaoDoItem + rotacao3) % comprimento;
            // Encripta chave2
            processoDeEncriptacaoDoItem = chave3.encripta(processoDeEncriptacaoDoItem);
            // Aumenta rotação a Chave1
            rotacao1++;
            // Aumenta rotação a chave2 se a chave1 for divisivel por 2
            if ((rotacao1 % 2) == 0)
                rotacao2++;
            // Aumenta rotação a chave3 se a chave2 for divisivel por 3
            if ((rotacao2 % 3) == 0)
                rotacao3++;
            // Se rotacao1 > 1 rotação total, reseta rotacao1
            if (rotacao1 > (comprimento - 1))
                rotacao1 = 0;
            // Se rotacao2 > 1 rotação total, reseta rotacao1
            if (rotacao2 > (comprimento - 1))
                rotacao2 = 0;
            // Se rotacao3 > 1 rotação total, reseta rotacao1
            if (rotacao3 > (comprimento - 1))
                rotacao3 = 0;
            // Saida
            return processoDeEncriptacaoDoItem;
        }

        public int rodaDecriptacao(int entradaDeDecriptacao)
        {
            int processoDeDecriptacaoDoItem = entradaDeDecriptacao;

            // Decripta chave3
            processoDeDecriptacaoDoItem = chave3.decripta(processoDeDecriptacaoDoItem);
            // Subtrai rotação da chave3
            if ((processoDeDecriptacaoDoItem - rotacao3) >= 0)
                processoDeDecriptacaoDoItem = processoDeDecriptacaoDoItem - rotacao3;
            else
                processoDeDecriptacaoDoItem = (processoDeDecriptacaoDoItem - rotacao3) + comprimento;
            // Decripta chave2
            processoDeDecriptacaoDoItem = chave2.decripta(processoDeDecriptacaoDoItem);
            // Subtrai rotação da chave2
            if ((processoDeDecriptacaoDoItem - rotacao2) >= 0)
                processoDeDecriptacaoDoItem = processoDeDecriptacaoDoItem - rotacao2;
            else
                processoDeDecriptacaoDoItem = (processoDeDecriptacaoDoItem - rotacao2) + comprimento;
            // Decripta chave1
            processoDeDecriptacaoDoItem = chave1.decripta(processoDeDecriptacaoDoItem);
            // Subtrai rotação da chave1
            if ((processoDeDecriptacaoDoItem - rotacao1) >= 0)
                processoDeDecriptacaoDoItem = processoDeDecriptacaoDoItem - rotacao1;
            else
                processoDeDecriptacaoDoItem = (processoDeDecriptacaoDoItem - rotacao1) + comprimento;
            // Aumenta rotação na chave1
            rotacao1++;
            // Aumenta rotação a chave2 se a chave1 for divisivel por 2
            if ((rotacao1 % 2) == 0)
                rotacao2++;
            // Aumenta rotação a chave3 se a chave2 for divisivel por 3
            if ((rotacao2 % 3) == 0)
                rotacao3++;
            // Se rotacao1 > 1 rotação total, reseta rotacao1
            if (rotacao1 > (comprimento - 1))
                rotacao1 = 0;
            // Se rotacao2 > 1 rotação total, reseta rotacao2
            if (rotacao2 > (comprimento - 1))
                rotacao2 = 0;
            // Se rotacao3 > 1 rotação total, reseta rotacao1
            if (rotacao3 > (comprimento - 1))
                rotacao3 = 0;
            //saida
            return processoDeDecriptacaoDoItem;
        }

        public int decodificaLetraParaNumero(string letra)
        {
            int numero = new int();
            char letraChar = Convert.ToChar(letra);
            numero = (Convert.ToInt32(letraChar)) - 32;

            return numero;
        }

        public string encodificaNumeroParaLetra(int numero)
        {
            string letra = "";
            char numeroChar = Convert.ToChar(numero);
            letra = (Convert.ToString((char) (numeroChar + 32)));

            return letra;
        }

        private void botaoResetClique(object sender, EventArgs e)
        {
            rotacao1 = 0;
            rotacao2 = 0;
        }

        private void rxtEntradaTextoAlterado(object sender, EventArgs e)
        {

        }

    }

}


text:
1. What is it?
    DEMO
2. Technical details
3. How to?
    3.1 Generate your own PLT
    3.2 Use your own PLT
    3.3 See some results on the command line
4. Weak points and future solutions

# 1. WHAT IS IT?

Have you ever tried Hoogle? http://www.haskell.org/hoogle/

If you haven't, here's a brief description.

Quite often you don't know the name of a function, or the name of the module it resides in, but you know what types you'd like this function to accept and what types this function will output.

Hoogle let's you search based on type signatures of functions. One small problem though... It's Haskell only, no Erlang.

Wouldn't it be nice to type in something like

       proplists:?(any(), list()) -> any()

and get back

       proplists:get_value

Or type in

       "(erlang:timestamp(),erlang:timestamp())->integer()"

and get back

       erlang:now_diff

?

That's the goal of HINT: to provide you with a way to search for function definitions and documentation by function type signatures.

# DEMO

1. Start web.sh
2. Go to http://127.0.0.1/52012

Give some time for web.sh to start completely. If it doesn't work, clean && compile && run.

3. Demo URLs (on Monday):
- http://memorici.de:52012
- http://booktu.com

One of these will work :)

# 4. HOW TO

## 4.1 Generate your own PLT

The problem with PLTs is that they are slow to generate and that they contain hard-coded links to .beam files on you system, so we cannot provide you with one.

We recommend you generate a "tiny version" of PLT. Otherwise you might end up waiting for search results forever (or run out of memory).

In order to generate a tiny PLT, run the following in your shell:
       dialyzer --build_plt --apps kernel stdlib erts crypto sasl --output_plt tiny_plt

## 4.2 Use your own PLT

Make sure that application environment contains

           {env, [{plt_path, PATH/TO/YOUR/PLT]}
or
           {env, [{plt_path, {priv_dir, PLT}}]}

## 4.3 See some results on the command line

In PROJECT_ROOT:

       bash> erl -pa apps/hint_search/ebin
       > hint_search:start().
       > hint_search:q("(erlang:timestamp(),erlang:timestamp())->integer()").
       {ok,[{{timer,now_diff,2},1.5},
            {{dets,init,2},0.9},
            {{crypto,dh_generate_parameters,2},0.9},
            {{dets,next,2},0.9},
       ...

# 2. Technical details

Frontend:
- Cowboy web-server
- Custom controllers
- Regular web stuff
- Fuzzy search on provided names

Backend:
- derive Module, Funciton, Arity from user request
- create possible permutations of these
- call Dialyzer to check types
- create a ranking of Module-Function pairs based on Dialyzer output
- return these to the user

On startup we read from a supplied PLT file and cache information on all available MFAs in the PLT (plt_cache_server)

Once we receive a request, we do the following:

1. Derive Module, Funciton, Arity
2. For each MFA in cache where A = Arity:
    2.1 For each possible permutation of parameters in MFA
    2.2 Write custom functions:

            -spec func_permutation_1(UserProvidedSpecs...
            func_permutation_1(Param1, Param2, Param3, ..., ParamArity) ->
                       M:F(permutation 1 of Param1, Param2, Param3, ..., ParamArity).

            -spec func_permutation_2(UserProvidedSpecs...
            func_permutation_2(Param1, Param2, Param3, ..., ParamArity) ->
                      M:F(permutation 2 of Param1, Param2, Param3, ..., ParamArity).
            ...
3. Once the file with custom functions is complete, run Dialyzer over it
4. For each warning generated by Dialyzer:
      4.1 Match permutation and warning against MFA
      4.2 Store warnings with MFA
5. For each MFA for which there are no warnings (full type match):
      5.1 Store the MFA with no warnings
6. For each MFA that we have
      6.1 Rank based on module name (extremely long and extremely short names decrease the rank)
      6.2 Rank based on function name (extremely long names decrease the rank)
      6.3 Rank based on warnings
      - Various diyalizer warnings decrease rank
      - If there are less warnings than permutations, it means that some of the permutations matched, increase rank
      - If there are no warnings, all permutations matched, increase rank
7. Final rank for each MFA is the sum all ranks for that MFA
8. Reverse sort MFAs based on rank
9. Return list of MFAs

# 3. Weak points and future solutions

1. Requires PLT
    1.1 Takes insane amounts of time to build
    Solution: build several smaller PLTs, search across them
    1.2 Takes insane amounts of memory for Dialyzer to process
    Solution:
    - build several smaller PLTs, search across them cache
    - search result for common searches

2. Permutations
    2.1 Take a long time to generate on each search
    Solution:
    - precompute permutations when loading PLT on startup
    - save files with premutations for more common searches


text:
<?php

namespace ZendService\Apple\Apns\Client;

use ZendService\Apple\Exception;
use ZendService\Apple\Exception\StreamSocketClientException;

/**
 * Apple Push Notification Abstract Client
 */
abstract class AbstractClient
{
    /**
     * APNS URI Constants
     * @var int
     */
    const SANDBOX_URI = 0;
    const PRODUCTION_URI = 1;

    /**
     * APNS URIs
     * @var array
     */
    protected $uris = array();

    /**
     * Is Connected
     * @var boolean
     */
    protected $isConnected = false;

    /**
     * Stream Socket
     * @var Resource
     */
    protected $socket;

    /**
     * Open Connection to APNS Service
     *
     * @param  int                                $environment
     * @param  string                             $certificate
     * @param  string                             $passPhrase
     * @throws Exception\RuntimeException
     * @throws Exception\InvalidArgumentException
     * @return AbstractClient
     */
    public function open($environment, $certificate, $passPhrase = null)
    {
        if ($this->isConnected) {
            throw new Exception\RuntimeException('Connection has already been opened and must be closed');
        }

        if (!array_key_exists($environment, $this->uris)) {
            throw new Exception\InvalidArgumentException('Environment must be one of PRODUCTION_URI or SANDBOX_URI');
        }

        if (!is_string($certificate) || !file_exists($certificate)) {
            throw new Exception\InvalidArgumentException('Certificate must be a valid path to a APNS certificate');
        }

        $sslOptions = array(
            'local_cert' => $certificate,
        );
        if ($passPhrase !== null) {
            if (!is_scalar($passPhrase)) {
                throw new Exception\InvalidArgumentException('SSL passphrase must be a scalar');
            }
            $sslOptions['passphrase'] = $passPhrase;
        }
        $this->connect($this->uris[$environment], $sslOptions);
        $this->isConnected = true;

        return $this;
    }

    /**
     * Connect to Host
     *
     * @param  string         $host
     * @param  array          $ssl
     * @return AbstractClient
     */
    protected function connect($host, array $ssl)
    {
        set_error_handler(function($errno, $errstr, $errfile, $errline){
            throw new StreamSocketClientException($errstr, $errno, 1, $errfile, $errline);
        });

        try {
            $this->socket = stream_socket_client(
                $host,
                $errno,
                $errstr,
                ini_get('default_socket_timeout'),
                STREAM_CLIENT_CONNECT,
                stream_context_create(
                    array(
                        'ssl' => $ssl,
                    )
                )
            );
        } catch (StreamSocketClientException $e) {
            throw new Exception\RuntimeException(sprintf(
                'Unable to connect: %s: %d (%s)',
                $host,
                $e->getCode(),
                $e->getMessage()
            ));
        }

        restore_error_handler();

        if (!$this->socket) {
            throw new Exception\RuntimeException(sprintf(
                'Unable to connect: %s: %d (%s)',
                $host,
                $errno,
                $errstr
            ));
        }
        stream_set_blocking($this->socket, 0);
        stream_set_write_buffer($this->socket, 0);

        return $this;
    }

    /**
     * Close Connection
     *
     * @return AbstractClient
     */
    public function close()
    {
        if ($this->isConnected && is_resource($this->socket)) {
            fclose($this->socket);
        }
        $this->isConnected = false;

        return $this;
    }

    /**
     * Is Connected
     *
     * @return boolean
     */
    public function isConnected()
    {
        return $this->isConnected;
    }

    /**
     * Read from the Server
     *
     * @param  int    $length
     * @return string
     */
    protected function read($length = 1024)
    {
        if (!$this->isConnected()) {
            throw new Exception\RuntimeException('You must open the connection prior to reading data');
        }
        $data = false;
        $stream_meta_data = stream_get_meta_data($this->socket);
        if ($stream_meta_data['unread_bytes'] > 0) {
            $data = fread($this->socket, (int) $length);
        }

        return $data;
    }

    /**
     * Write Payload to the Server
     *
     * @param  string $payload
     * @return int
     */
    protected function write($payload)
    {
        if (!$this->isConnected()) {
            throw new Exception\RuntimeException('You must open the connection prior to writing data');
        }

        return @fwrite($this->socket, $payload);
    }

    /**
     * Destructor
     *
     * @return void
     */
    public function __destruct()
    {
        $this->close();
    }
}


text:
USERNAME=$1

if [ "${USERNAME}" == "" ]; then
  echo "Please provide a SVN username."
  echo -e "\nUsage:\n\t$0 <username>\n"
  exit 1
fi

read -s -p "Password for SVN user ${USERNAME}: " PASSWORD
echo

SVN_CMD="svn --no-auth-cache --username=${USERNAME} --password=${PASSWORD}"
VERSION=$(cat pom.xml | grep -A1 '<artifactId>tinkerpop</artifactId>' | grep '<version>' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}')

rm -rf target/svn

bin/process-docs.sh || exit 1
mvn process-resources -Djavadoc

mkdir -p target/svn
${SVN_CMD} co --depth immediates https://svn.apache.org/repos/asf/tinkerpop/site target/svn

pushd target/svn
${SVN_CMD} update --depth empty "docs/${VERSION}"
${SVN_CMD} update --depth empty "javadocs/${VERSION}"
${SVN_CMD} rm "docs/${VERSION}"
${SVN_CMD} rm "javadocs/${VERSION}"
${SVN_CMD} commit . -m "Docs for TinkerPop ${VERSION} are being replaced."
popd

mkdir -p "target/svn/docs/${VERSION}"
mkdir -p "target/svn/javadocs/${VERSION}/core"
mkdir -p "target/svn/javadocs/${VERSION}/full"

cp -R target/docs/htmlsingle/.   "target/svn/docs/${VERSION}"
cp -R target/site/apidocs/core/. "target/svn/javadocs/${VERSION}/core"
cp -R target/site/apidocs/full/. "target/svn/javadocs/${VERSION}/full"

pushd target/svn
rm "docs/${VERSION}/images/tinkerpop3.graffle"
${SVN_CMD} update --depth empty "docs/${VERSION}"
${SVN_CMD} update --depth empty "javadocs/${VERSION}"

${SVN_CMD} add * --force
${SVN_CMD} commit -m "Deploy docs for TinkerPop ${VERSION}"
popd


text:
import {connect} from 'react-redux';
import {CurrencySelect} from '../../dumb/selects/CurrencySelect';
import {changeCurrency} from '../../actions';
import {Currencies} from "../../entities/Currencies";

const mapStateToProps = (state) => {
    return {
        selectedCurrency: Currencies.find(x => x.getName() === state.currency)
    };
};

const mapDispatchToProps = (dispatch) => {
    return {
        onChange: (currency) => dispatch(changeCurrency(currency))
    };
};

export const ItemsCurrencySelect = connect(
    mapStateToProps,
    mapDispatchToProps
)(CurrencySelect);


text:
<?php
require_once __DIR__ . '/../vendor/autoload.php';

use Lcobucci\ActionMapper2\Config\ApplicationBuilder;

$app = ApplicationBuilder::build(
    __DIR__ . '/../config/routes.xml',
    require __DIR__ . '/../config/di-config.php',
    null,
    'cache.apc'
);

$app->run();


text:
<?php

// @namespace
namespace Rock\OnSymfony\WATBundle\Event;
// @base
use Rock\OnSymfony\WATBundle\Event\IEvent;

/**
 * TypeSafeInterface
 */
interface IEvent
{
}


text:
#include <bitset>

#include "gapii/cc/vulkan_layer_extras.h"
#include "gapii/cc/vulkan_spy.h"
#include "gapis/api/vulkan/vulkan_pb/extras.pb.h"
#include "spirv_reflect.h"

namespace gapii {

namespace {

bool hasAndroidExternalFormat(const VkImageCreateInfo* pCreateInfo) {
  const VulkanStructHeader* header =
      reinterpret_cast<const VulkanStructHeader*>(pCreateInfo->mpNext);
  while (header != nullptr) {
    if (header->mSType ==
        VkStructureType::VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID) {
      const VkExternalFormatANDROID* externalFormat =
          reinterpret_cast<const VkExternalFormatANDROID*>(header);
      return externalFormat->mexternalFormat != 0;
    }
    header = reinterpret_cast<const VulkanStructHeader*>(header->mPNext);
  }
  return false;
}

}  // namespace

struct destroyer {
  destroyer(const std::function<void(void)>& f) { destroy = f; }
  ~destroyer() { destroy(); }
  std::function<void(void)> destroy;
};

static inline void set_dispatch_from_parent(void* child, void* parent) {
  *((const void**)child) = *((const void**)parent);
}

// Declared in api_spy.h.tmpl
bool VulkanSpy::observeFramebuffer(CallObserver* observer, uint32_t* w,
                                   uint32_t* h, std::vector<uint8_t>* data) {
  gapil::Ref<ImageObject> image;
  uint32_t frame_buffer_img_level = 0;
  uint32_t frame_buffer_img_layer = 0;
  if (mState.LastSubmission == LastSubmissionType::SUBMIT) {
    if (!mState.LastBoundQueue) {
      return false;
    }
    if (!mState.LastDrawInfos.contains(mState.LastBoundQueue->mVulkanHandle)) {
      return false;
    }
    auto& lastDrawInfo =
        *mState.LastDrawInfos[mState.LastBoundQueue->mVulkanHandle];
    if (!lastDrawInfo.mRenderPass) {
      return false;
    }
    if (!lastDrawInfo.mFramebuffer) {
      return false;
    }
    if (lastDrawInfo.mLastSubpass >=
        lastDrawInfo.mRenderPass->mSubpassDescriptions.count()) {
      return false;
    }
    if (lastDrawInfo.mRenderPass
            ->mSubpassDescriptions[lastDrawInfo.mLastSubpass]
            .mColorAttachments.empty()) {
      return false;
    }

    uint32_t color_attachment_index =
        lastDrawInfo.mRenderPass
            ->mSubpassDescriptions[lastDrawInfo.mLastSubpass]
            .mColorAttachments[0]
            .mAttachment;
    if (!lastDrawInfo.mFramebufferAttachments.contains(
            color_attachment_index)) {
      return false;
    }

    auto& imageView =
        lastDrawInfo.mFramebufferAttachments[color_attachment_index];
    image = imageView->mImage;
    *w = lastDrawInfo.mFramebuffer->mWidth;
    *h = lastDrawInfo.mFramebuffer->mHeight;
    // If the image view is to be used as framebuffer attachment, it must
    // contains only one level.
    frame_buffer_img_level = imageView->mSubresourceRange.mbaseMipLevel;
    // There might be more layers, but we only show the first layer.
    // TODO: support multi-layer rendering.
    frame_buffer_img_layer = imageView->mSubresourceRange.mbaseArrayLayer;
  } else {
    if (mState.LastPresentInfo.mPresentImageCount == 0) {
      return false;
    }
    image = mState.LastPresentInfo.mPresentImages[0];
    *w = image->mInfo.mExtent.mwidth;
    *h = image->mInfo.mExtent.mheight;
    // Swapchain images have only one miplevel.
    frame_buffer_img_level = 0;
    // There might be more than one array layers for swapchain images,
    // currently we only show the data at layer 0
    // TODO: support multi-layer swapchain images.
    frame_buffer_img_layer = 0;
  }

  // TODO: Handle multisampled images. This is only a concern for
  // draw-level observations.

  VkDevice device = image->mDevice;
  VkPhysicalDevice physical_device = mState.Devices[device]->mPhysicalDevice;
  VkInstance instance = mState.PhysicalDevices[physical_device]->mInstance;
  VkQueue queue = mState.LastPresentInfo.mQueue;
  uint32_t queue_family = mState.Queues[queue]->mFamily;
  auto& instance_fn = mImports.mVkInstanceFunctions[instance];

  VkPhysicalDeviceMemoryProperties memory_properties(arena());
  instance_fn.vkGetPhysicalDeviceMemoryProperties(physical_device,
                                                  &memory_properties);

  auto& fn = mImports.mVkDeviceFunctions[device];

  VkImageCreateInfo create_info{
      VkStructureType::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,  // sType
      nullptr,                                               // pNext
      0,                                                     // flags
      VkImageType::VK_IMAGE_TYPE_2D,                         // imageType
      VkFormat::VK_FORMAT_R8G8B8A8_UNORM,                    // format
      VkExtent3D{*w, *h, 1},                                 // extent
      1,                                                     // mipLevels
      1,                                                     // arrayLayers
      VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT,          // samples
      VkImageTiling::VK_IMAGE_TILING_OPTIMAL,                // tiling
      VkImageUsageFlagBits::VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
          VkImageUsageFlagBits::VK_IMAGE_USAGE_TRANSFER_DST_BIT,  // usage
      VkSharingMode::VK_SHARING_MODE_EXCLUSIVE,                   // sharingMode
      0,                                        // queueFamilyIndexCount
      nullptr,                                  // queueFamilyIndices
      VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED  // layout
  };

  VkImage resolve_image;
  VkDeviceMemory image_memory;

  if (VkResult::VK_SUCCESS !=
      fn.vkCreateImage(device, &create_info, nullptr, &resolve_image)) {
    return false;
  }
  destroyer image_destroyer(
      [&]() { fn.vkDestroyImage(device, resolve_image, nullptr); });

  VkMemoryRequirements image_reqs(arena());
  fn.vkGetImageMemoryRequirements(device, resolve_image, &image_reqs);

  uint32_t image_memory_req = 0xFFFFFFFF;
  for (size_t i = 0; i < 32; ++i) {
    if (image_reqs.mmemoryTypeBits & (1 << i)) {
      image_memory_req = i;
      break;
    }
  }

  if (image_memory_req == 0xFFFFFFFF) {
    return false;
  }

  VkMemoryAllocateInfo allocate{
      VkStructureType::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,  // sType
      nullptr,                                                  // pNext
      image_reqs.msize,  // allocationSize
      image_memory_req   // memoryTypeIndex
  };
  if (VkResult::VK_SUCCESS !=
      fn.vkAllocateMemory(device, &allocate, nullptr, &image_memory)) {
    return false;
  }
  destroyer image_memory_destroyer(
      [&]() { fn.vkFreeMemory(device, image_memory, nullptr); });

  fn.vkBindImageMemory(device, resolve_image, image_memory, 0);

  VkBuffer buffer;
  VkDeviceMemory buffer_memory;
  VkBufferCreateInfo buffer_info = {
      VkStructureType::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,    // sType
      nullptr,                                                  // pNext
      0,                                                        // flags
      *w * *h * 4,                                              // size
      VkBufferUsageFlagBits::VK_BUFFER_USAGE_TRANSFER_DST_BIT,  // usage
      VkSharingMode::VK_SHARING_MODE_EXCLUSIVE,                 // sharingMode
      0,       // queueFamilyIndexCountg
      nullptr  // queueFamilyIndices
  };

  if (VkResult::VK_SUCCESS !=
      fn.vkCreateBuffer(device, &buffer_info, nullptr, &buffer)) {
    return false;
  }
  destroyer buffer_destroyer(
      [&]() { fn.vkDestroyBuffer(device, buffer, nullptr); });

  VkMemoryRequirements buffer_reqs(arena());
  fn.vkGetBufferMemoryRequirements(device, buffer, &buffer_reqs);

  uint32_t buffer_memory_req = 0;
  while (buffer_reqs.mmemoryTypeBits) {
    if (buffer_reqs.mmemoryTypeBits & 0x1) {
      if (memory_properties.mmemoryTypes[buffer_memory_req].mpropertyFlags &
          VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
        break;
      }
    }
    buffer_reqs.mmemoryTypeBits >>= 1;
    ++buffer_memory_req;
  }
  if (!buffer_reqs.mmemoryTypeBits) {
    return false;
  }
  allocate.mallocationSize = buffer_reqs.msize;
  allocate.mmemoryTypeIndex = buffer_memory_req;
  if (VkResult::VK_SUCCESS !=
      fn.vkAllocateMemory(device, &allocate, nullptr, &buffer_memory)) {
    return false;
  }
  destroyer buffer_memory_destroyer(
      [&]() { fn.vkFreeMemory(device, buffer_memory, nullptr); });

  fn.vkBindBufferMemory(device, buffer, buffer_memory, 0);

  VkCommandPoolCreateInfo command_pool_info = {
      VkStructureType::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,  // sType
      nullptr,                                                      // pNext
      0,                                                            // flags
      queue_family  // queueFamilyIndex
  };

  VkCommandPool command_pool;
  if (VkResult::VK_SUCCESS != fn.vkCreateCommandPool(device, &command_pool_info,
                                                     nullptr, &command_pool)) {
    return false;
  }
  destroyer command_pool_destroyer(
      [&]() { fn.vkDestroyCommandPool(device, command_pool, nullptr); });

  VkCommandBufferAllocateInfo command_buffer_info = {
      VkStructureType::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,  // sType
      nullptr,                                                          // pNext
      command_pool,                                                     // pool
      VkCommandBufferLevel::VK_COMMAND_BUFFER_LEVEL_PRIMARY,            // level
      1  // commandBufferCount
  };

  VkCommandBuffer command_buffer;
  if (VkResult::VK_SUCCESS != fn.vkAllocateCommandBuffers(device,
                                                          &command_buffer_info,
                                                          &command_buffer)) {
    return false;
  }
  set_dispatch_from_parent((void*)command_buffer, (void*)device);

  VkCommandBufferBeginInfo command_buffer_begin_info = {
      VkStructureType::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
      nullptr,
      VkCommandBufferUsageFlagBits::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
      nullptr,
  };
  fn.vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info);

  VkImageMemoryBarrier barriers[2] = {
      {VkStructureType::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,  // sType
       nullptr,                                                  // pNext
       VkAccessFlagBits::VK_ACCESS_MEMORY_WRITE_BIT,   // srcAccessMask
       VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT,  // dstAccessMask
       image->mAspects[VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT]
           ->mLayers[frame_buffer_img_layer]
           ->mLevels[frame_buffer_img_level]
           ->mLayout,                                        // srcLayout
       VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,  // dstLayout
       0xFFFFFFFF,                                           // srcQueueFamily
       0xFFFFFFFF,                                           // dstQueueFamily
       image->mVulkanHandle,                                 // image
       {
           // subresourcerange
           VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT,  // aspectMask
           0,                                                 // baseMipLevel
           1,                                                 // mipLevelCount
           0,                                                 // baseArrayLayer
           1,                                                 // layerCount
       }},
      {VkStructureType::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,  // sType
       nullptr,                                                  // pNext
       VkAccessFlagBits::VK_ACCESS_MEMORY_WRITE_BIT,         // srcAccessMask
       VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT,       // dstAccessMask
       VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED,             // srcLayout
       VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,  // dstLayout
       0xFFFFFFFF,                                           // srcQueueFamily
       0xFFFFFFFF,                                           // dstQueueFamily
       resolve_image,                                        // image
       {
           // subresourcerange
           VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT,  // aspectMask
           0,                                                 // baseMipLevel
           1,                                                 // mipLevelCount
           0,                                                 // baseArrayLayer
           1,                                                 // layerCount
       }},
  };

  fn.vkCmdPipelineBarrier(
      command_buffer,
      VkPipelineStageFlagBits::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
      VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0,
      nullptr, 2, barriers);
  VkImageBlit blit = {
      {VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
      core::StaticArray<VkOffset3D, 2>::create(
          {{0, 0, 0}, {static_cast<int32_t>(*w), static_cast<int32_t>(*h), 1}}),
      {VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
      core::StaticArray<VkOffset3D, 2>::create(
          {{0, 0, 0},
           {static_cast<int32_t>(*w), static_cast<int32_t>(*h), 1}})};
  fn.vkCmdBlitImage(command_buffer, image->mVulkanHandle,
                    VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                    resolve_image,
                    VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
                    &blit, VkFilter::VK_FILTER_NEAREST);

  barriers[0].msrcAccessMask = VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT;
  barriers[0].mdstAccessMask = VkAccessFlagBits::VK_ACCESS_MEMORY_WRITE_BIT |
                               VkAccessFlagBits::VK_ACCESS_MEMORY_READ_BIT;
  barriers[0].moldLayout = VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  barriers[0].mnewLayout =
      image->mAspects[VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT]
          ->mLayers[frame_buffer_img_layer]
          ->mLevels[frame_buffer_img_level]
          ->mLayout;
  barriers[1].msrcAccessMask = VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT;
  barriers[1].mdstAccessMask = VkAccessFlagBits::VK_ACCESS_TRANSFER_READ_BIT;
  barriers[1].moldLayout = VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  barriers[1].mnewLayout = VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;

  fn.vkCmdPipelineBarrier(
      command_buffer, VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT,
      VkPipelineStageFlagBits::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0,
      nullptr, 0, nullptr, 2, barriers);

  VkBufferImageCopy copy_region = {
      0,  // bufferOffset
      0,  // bufferRowLength
      0,  // bufferImageHeight
      {VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
      {0, 0, 0},
      {*w, *h, 1}};
  fn.vkCmdCopyImageToBuffer(command_buffer, resolve_image,
                            VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                            buffer, 1, &copy_region);

  VkBufferMemoryBarrier buffer_barrier = {
      VkStructureType::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,  // sType
      nullptr,                                                   // pNext
      VkAccessFlagBits::VK_ACCESS_TRANSFER_WRITE_BIT,  // srcAccessMask
      VkAccessFlagBits::VK_ACCESS_HOST_READ_BIT,       // dstAccessMask
      0xFFFFFFFF,                                      // srcqueueFamily
      0xFFFFFFFF,                                      // dstQueueFamily
      buffer,                                          // buffer
      0,                                               // offset
      0xFFFFFFFFFFFFFFFF                               // size
  };
  fn.vkCmdPipelineBarrier(
      command_buffer, VkPipelineStageFlagBits::VK_PIPELINE_STAGE_TRANSFER_BIT,
      VkPipelineStageFlagBits::VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1,
      &buffer_barrier, 0, nullptr);

  fn.vkEndCommandBuffer(command_buffer);

  VkSubmitInfo submit_info = {VkStructureType::VK_STRUCTURE_TYPE_SUBMIT_INFO,
                              nullptr,
                              0,
                              nullptr,
                              nullptr,
                              1,
                              &command_buffer,
                              0,
                              nullptr};
  if (VkResult::VK_SUCCESS != fn.vkQueueSubmit(queue, 1, &submit_info, 0)) {
    return false;
  }
  fn.vkQueueWaitIdle(queue);
  char* image_data;
  if (VkResult::VK_SUCCESS !=
      fn.vkMapMemory(device, buffer_memory, 0, 0xFFFFFFFFFFFFFFFF, 0,
                     reinterpret_cast<void**>(&image_data))) {
    return false;
  }
  VkMappedMemoryRange range = {
      VkStructureType::VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,  // sType
      nullptr,                                                 // pNext
      buffer_memory,                                           // memory
      0,                                                       // offset
      0xFFFFFFFFFFFFFFFF                                       // size
  };
  fn.vkInvalidateMappedMemoryRanges(device, 1, &range);
  data->resize(*w * *h * 4);
  // Flip the image because vulkan renders upside-down.
  for (size_t i = 0; i < *h; ++i) {
    memcpy(data->data() + i * (*w * 4), image_data + ((*h - i - 1) * (*w * 4)),
           *w * 4);
  }

  return true;
}

// Extern functions
void VulkanSpy::trackMappedCoherentMemory(CallObserver*, uint64_t start,
                                          size_val size) {
  // If the tracing not started yet, do not track the coherent memory
  if (is_suspended()) {
    return;
  }
#if COHERENT_TRACKING_ENABLED
  if (m_coherent_memory_tracking_enabled) {
    void* start_addr = reinterpret_cast<void*>(start);
    if (!mMemoryTracker.TrackRange(start_addr, size)) {
      GAPID_ERROR(
          "Failed at adding tracking range: (%p - %p) to coherent memory "
          "tracker",
          (void*)start, (void*)(start + size));
    }
  }
#endif  // COHERENT_TRACKING_ENABLED
}

void VulkanSpy::readMappedCoherentMemory(CallObserver* observer,
                                         VkDeviceMemory memory,
                                         uint64_t offset_in_mapped,
                                         size_val readSize) {
  auto& memory_object = mState.DeviceMemories[memory];
  const auto mapped_location = (uint64_t)(memory_object->mMappedLocation);
  void* offset_addr = (void*)(offset_in_mapped + mapped_location);
#if COHERENT_TRACKING_ENABLED
  if (m_coherent_memory_tracking_enabled) {
    // Read the valid mapped range
    if (!mMemoryTracker.HandleAndClearDirtyIntersects(
            offset_addr, readSize, [observer, this](void* addr, size_val size) {
              observer->read(slice((uint8_t*)addr, 0ULL, size));
            })) {
      GAPID_ERROR(
          "Failed at resetting memory page permissions when observing range: "
          "(%p - %p)",
          (void*)offset_addr, (void*)((uintptr_t)offset_addr + readSize));
    }
    return;
  }
#endif  // COHERENT_TRACKING_ENABLED
  observer->read(slice((uint8_t*)offset_addr, 0ULL, readSize));
}

void VulkanSpy::untrackMappedCoherentMemory(CallObserver*, uint64_t start,
                                            size_val size) {
#if COHERENT_TRACKING_ENABLED
  if (m_coherent_memory_tracking_enabled) {
    void* start_addr = reinterpret_cast<void*>(start);
    mMemoryTracker.UntrackRange(start_addr, size);
  }
#endif  // COHERENT_TRACKING_ENABLED
}

void VulkanSpy::mapMemory(CallObserver*, VkDeviceMemory, void**,
                          gapil::Slice<uint8_t>) {}
void VulkanSpy::unmapMemory(CallObserver*, VkDeviceMemory,
                            gapil::Slice<uint8_t>) {}
void VulkanSpy::recordEventWait(CallObserver*, VkEvent) {}
void VulkanSpy::recordEventSet(CallObserver*, VkEvent) {}
void VulkanSpy::recordFenceSignal(CallObserver*, uint64_t) {}
void VulkanSpy::recordFenceWait(CallObserver*, uint64_t) {}
void VulkanSpy::recordFenceReset(CallObserver*, uint64_t) {}
void VulkanSpy::recordAcquireNextImage(CallObserver*, uint64_t, uint32_t) {}
void VulkanSpy::recordPresentSwapchainImage(CallObserver*, uint64_t, uint32_t) {
}
void VulkanSpy::recordBeginCommandBuffer(CallObserver*, VkCommandBuffer) {}
void VulkanSpy::recordEndCommandBuffer(CallObserver*, VkCommandBuffer) {}

void VulkanSpy::resetCmd(CallObserver* observer, VkCommandBuffer cmdBuf) {}
void VulkanSpy::enterSubcontext(CallObserver*) {}
void VulkanSpy::leaveSubcontext(CallObserver*) {}
void VulkanSpy::nextSubcontext(CallObserver*) {}
void VulkanSpy::resetSubcontext(CallObserver*) {}
void VulkanSpy::onPreSubcommand(CallObserver*, gapil::Ref<CommandReference>) {}

void VulkanSpy::onPostSubcommand(CallObserver*, gapil::Ref<CommandReference>) {}
void VulkanSpy::onCommandAdded(CallObserver*, VkCommandBuffer) {}
uint32_t VulkanSpy::onesCount(CallObserver*, uint32_t x) {
  return std::bitset<32>(x).count();
}

gapil::Ref<PhysicalDevicesAndProperties>
VulkanSpy::fetchPhysicalDeviceProperties(CallObserver* observer,
                                         VkInstance instance,
                                         gapil::Slice<VkPhysicalDevice> devs) {
  auto props = gapil::Ref<PhysicalDevicesAndProperties>::create(arena());
  for (VkPhysicalDevice dev : devs) {
    props->mPhyDevToProperties[dev] = VkPhysicalDeviceProperties(arena());
    mImports.mVkInstanceFunctions[instance].vkGetPhysicalDeviceProperties(
        dev, &props->mPhyDevToProperties[dev]);
  }
  observer->encode(*props.get());
  return props;
}

gapil::Ref<PhysicalDevicesMemoryProperties>
VulkanSpy::fetchPhysicalDeviceMemoryProperties(
    CallObserver* observer, VkInstance instance,
    gapil::Slice<VkPhysicalDevice> devs) {
  auto props = gapil::Ref<PhysicalDevicesMemoryProperties>::create(arena());
  for (VkPhysicalDevice dev : devs) {
    props->mPhyDevToMemoryProperties[dev] =
        VkPhysicalDeviceMemoryProperties(arena());
    mImports.mVkInstanceFunctions[instance].vkGetPhysicalDeviceMemoryProperties(
        dev, &props->mPhyDevToMemoryProperties[dev]);
  }
  observer->encode(*props.get());
  return props;
}

gapil::Ref<PhysicalDevicesAndQueueFamilyProperties>
VulkanSpy::fetchPhysicalDeviceQueueFamilyProperties(
    CallObserver* observer, VkInstance instance,
    gapil::Slice<VkPhysicalDevice> devs) {
  auto all_props =
      gapil::Ref<PhysicalDevicesAndQueueFamilyProperties>::create(arena());
  for (VkPhysicalDevice dev : devs) {
    uint32_t propCount = 0;
    mImports.mVkInstanceFunctions[instance]
        .vkGetPhysicalDeviceQueueFamilyProperties(dev, &propCount, nullptr);
    std::vector<VkQueueFamilyProperties> props(
        propCount, VkQueueFamilyProperties(arena()));
    mImports.mVkInstanceFunctions[instance]
        .vkGetPhysicalDeviceQueueFamilyProperties(dev, &propCount,
                                                  props.data());
    for (uint32_t i = 0; i < props.size(); i++) {
      all_props->mPhyDevToQueueFamilyProperties[dev][i] = props[i];
    }
  }
  observer->encode(*all_props.get());
  return all_props;
}

gapil::Ref<PhysicalDevicesFormatProperties>
VulkanSpy::fetchPhysicalDeviceFormatProperties(
    CallObserver* observer, VkInstance instance,
    gapil::Slice<VkPhysicalDevice> devs) {
  auto props = gapil::Ref<PhysicalDevicesFormatProperties>::create(arena());
  for (VkPhysicalDevice dev : devs) {
    for (uint32_t format : VkFormat::values()) {
      VkFormatProperties prop(arena());
      mImports.mVkInstanceFunctions[instance]
          .vkGetPhysicalDeviceFormatProperties(dev, format, &prop);
      props->mPhyDevToFormatProperties[dev][format] = prop;
    }
  }
  observer->encode(*props.get());
  return props;
}

gapil::Ref<FetchedImageMemoryRequirements>
VulkanSpy::fetchImageMemoryRequirements(CallObserver* observer, VkDevice device,
                                        gapil::Ref<ImageObject> image,
                                        bool hasSparseBit) {
  auto reqs = gapil::Ref<FetchedImageMemoryRequirements>::create(arena());
  VkMemoryRequirements rawReq{0};
  mImports.mVkDeviceFunctions[device].vkGetImageMemoryRequirements(
      device, image->mVulkanHandle, &rawReq);
  // TODO: Handle multi-planar images
  reqs->mPlaneBitsToMemoryRequirements[0] = rawReq;
  if (hasSparseBit) {
    uint32_t sparse_mem_req_count = 0;
    mImports.mVkDeviceFunctions[device].vkGetImageSparseMemoryRequirements(
        device, image->mVulkanHandle, &sparse_mem_req_count, nullptr);
    core::Arena arena;
    std::vector<VkSparseImageMemoryRequirements> sparse_mem_reqs(
        sparse_mem_req_count, VkSparseImageMemoryRequirements(&arena));
    mImports.mVkDeviceFunctions[device].vkGetImageSparseMemoryRequirements(
        device, image->mVulkanHandle, &sparse_mem_req_count,
        sparse_mem_reqs.data());
    for (VkSparseImageMemoryRequirements& req : sparse_mem_reqs) {
      auto aspect_map = subUnpackImageAspectFlags(
          nullptr, nullptr, image, req.mformatProperties.maspectMask);
      for (auto aspect : aspect_map) {
        reqs->mAspectBitsToSparseMemoryRequirements[aspect.second] = req;
      }
    }
  }
  observer->encode(*reqs.get());
  return reqs;
}

VkMemoryRequirements VulkanSpy::fetchBufferMemoryRequirements(
    CallObserver* observer, VkDevice device, VkBuffer buffer) {
  auto reqs = VkMemoryRequirements(arena());
  mImports.mVkDeviceFunctions[device].vkGetBufferMemoryRequirements(
      device, buffer, &reqs);
  observer->encode(reqs);
  return reqs;
}

gapil::Ref<LinearImageLayouts> VulkanSpy::fetchLinearImageSubresourceLayouts(
    CallObserver* observer, VkDevice device, gapil::Ref<ImageObject> image,
    VkImageSubresourceRange rng) {
  auto layouts = gapil::Ref<LinearImageLayouts>::create(arena());
  walkImageSubRng(
      image, rng,
      [&layouts, device, &image, this](uint32_t aspect_bit, uint32_t layer,
                                       uint32_t level) {
        VkImageSubresource subres(VkImageAspectFlags(aspect_bit),  // aspectMask
                                  level,                           // mipLevel
                                  layer                            // arrayLayer
        );
        auto aspect_i = layouts->mAspectLayouts.find(aspect_bit);
        if (aspect_i == layouts->mAspectLayouts.end()) {
          layouts->mAspectLayouts[aspect_bit] =
              gapil::Ref<LinearImageAspectLayouts>::create(arena());
          aspect_i = layouts->mAspectLayouts.find(aspect_bit);
        }
        auto layer_i = aspect_i->second->mLayerLayouts.find(layer);
        if (layer_i == aspect_i->second->mLayerLayouts.end()) {
          aspect_i->second->mLayerLayouts[layer] =
              gapil::Ref<LinearImageLayerLayouts>::create(arena());
          layer_i = aspect_i->second->mLayerLayouts.find(layer);
        }
        layer_i->second->mLevelLayouts[level] =
            gapil::Ref<VkSubresourceLayout>::create(arena());
        mImports.mVkDeviceFunctions[device].vkGetImageSubresourceLayout(
            device, image->mVulkanHandle, &subres,
            &*layer_i->second->mLevelLayouts[level]);
      });
  observer->encode(*layouts.get());
  return layouts;
}

gapil::Ref<DescriptorInfo> VulkanSpy::fetchUsedDescriptors(
    CallObserver* observer, gapil::Ref<ShaderModuleObject> module) {
  auto descriptors = gapil::Ref<DescriptorInfo>::create(arena());

  spv_reflect::ShaderModule smod(module->mWords.size(), &module->mWords[0]);
  if (smod.GetResult() != SPV_REFLECT_RESULT_SUCCESS) {
    GAPID_INFO("spirv reflect failed on shader module %" PRIu64,
               module->mVulkanHandle);
    return nullptr;
  }

  for (uint32_t i = 0; i < smod.GetEntryPointCount(); ++i) {
    const char* epName = smod.GetEntryPointName(i);
    uint32_t count = 0;

    if (SPV_REFLECT_RESULT_SUCCESS !=
        smod.EnumerateEntryPointDescriptorSets(epName, &count, nullptr)) {
      continue;
    }
    if (count == 0) {
      continue;
    }
    std::vector<SpvReflectDescriptorSet*> sets;
    sets.resize(count);
    if (SPV_REFLECT_RESULT_SUCCESS !=
        smod.EnumerateEntryPointDescriptorSets(epName, &count, sets.data())) {
      continue;
    }
    descriptors->mDescriptors[gapil::String(arena(), epName)] =
        U32ToDescriptorUsage(arena());
    auto& desc = descriptors->mDescriptors[gapil::String(arena(), epName)];
    for (auto& set : sets) {
      for (size_t i = 0; i < set->binding_count; ++i) {
        auto binding = set->bindings[i];
        uint32_t count = 1;
        for (size_t j = 0; j < binding->array.dims_count; ++j) {
          count *= binding->array.dims[j];
        }

        desc[desc.count()] =
            DescriptorUsage(binding->set, binding->binding, count);
      }
    }
  }
  observer->encode(*descriptors.get());
  return descriptors;
}

// Override API functions
// SpyOverride_vkGetInstanceProcAddr(), SpyOverride_vkGetDeviceProcAddr(),
// SpyOverride_vkCreateInstance() and SpyOverride_vkCreateDevice() require
// the their function table to be created through the template system, so they
// won't be defined here, but vk_spy_helpers.cpp.tmpl
uint32_t VulkanSpy::SpyOverride_vkEnumerateInstanceLayerProperties(
    CallObserver*, uint32_t* pCount, VkLayerProperties* pProperties) {
  if (pProperties == NULL) {
    *pCount = 1;
    return VkResult::VK_SUCCESS;
  }
  if (pCount == 0) {
    return VkResult::VK_INCOMPLETE;
  }
  *pCount = 1;
  pProperties = {nullptr};
  strcpy((char*)pProperties->mlayerName, "GraphicsSpy");
  pProperties->mspecVersion = VK_VERSION_MAJOR(1) | VK_VERSION_MINOR(0) | 5;
  pProperties->mimplementationVersion = 1;
  strcpy((char*)pProperties->mdescription, "vulkan_trace");
  return VkResult::VK_SUCCESS;
}

uint32_t VulkanSpy::SpyOverride_vkEnumerateDeviceLayerProperties(
    CallObserver*, VkPhysicalDevice dev, uint32_t* pCount,
    VkLayerProperties* pProperties) {
  if (pProperties == NULL) {
    *pCount = 1;
    return VkResult::VK_SUCCESS;
  }
  if (pCount == 0) {
    return VkResult::VK_INCOMPLETE;
  }
  *pCount = 1;
  pProperties = {nullptr};
  strcpy((char*)pProperties->mlayerName, "GraphicsSpy");
  pProperties->mspecVersion = VK_VERSION_MAJOR(1) | VK_VERSION_MINOR(0) | 5;
  pProperties->mimplementationVersion = 1;
  strcpy((char*)pProperties->mdescription, "vulkan_trace");
  return VkResult::VK_SUCCESS;
}
uint32_t VulkanSpy::SpyOverride_vkEnumerateInstanceExtensionProperties(
    CallObserver*, const char* pLayerName, uint32_t* pCount,
    VkExtensionProperties* pProperties) {
  *pCount = 0;
  return VkResult::VK_SUCCESS;
}

uint32_t VulkanSpy::SpyOverride_vkEnumeratePhysicalDeviceGroups(
    CallObserver*, VkInstance instance, uint32_t* pPhysicalDeviceGroupCount,
    VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
  auto inst_func_iter = mImports.mVkInstanceFunctions.find(instance);
  gapii::VulkanImports::PFNVKENUMERATEPHYSICALDEVICEGROUPS next =
      inst_func_iter->second.vkEnumeratePhysicalDeviceGroups;

  auto ret =
      next(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
  if (!pPhysicalDeviceGroupProperties) {
    return ret;
  }
  for (size_t i = 0; i < *pPhysicalDeviceGroupCount; ++i) {
    pPhysicalDeviceGroupProperties[i].mphysicalDeviceCount = 1;
    pPhysicalDeviceGroupProperties[i].msubsetAllocation = 0;
  }
  return ret;
}

uint32_t VulkanSpy::SpyOverride_vkEnumeratePhysicalDeviceGroupsKHR(
    CallObserver*, VkInstance instance, uint32_t* pPhysicalDeviceGroupCount,
    VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
  auto inst_func_iter = mImports.mVkInstanceFunctions.find(instance);
  gapii::VulkanImports::PFNVKENUMERATEPHYSICALDEVICEGROUPSKHR next =
      inst_func_iter->second.vkEnumeratePhysicalDeviceGroupsKHR;

  auto ret =
      next(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
  if (!pPhysicalDeviceGroupProperties) {
    return ret;
  }
  for (size_t i = 0; i < *pPhysicalDeviceGroupCount; ++i) {
    pPhysicalDeviceGroupProperties[i].mphysicalDeviceCount = 1;
    pPhysicalDeviceGroupProperties[i].msubsetAllocation = 0;
  }
  return ret;
}

uint32_t VulkanSpy::SpyOverride_vkEnumerateDeviceExtensionProperties(
    CallObserver*, VkPhysicalDevice physicalDevice, const char* pLayerName,
    uint32_t* pCount, VkExtensionProperties* pProperties) {
  gapii::VulkanImports::PFNVKENUMERATEDEVICEEXTENSIONPROPERTIES
      next_layer_enumerate_extensions = NULL;
  auto phy_dev_iter = mState.PhysicalDevices.find(physicalDevice);
  if (phy_dev_iter != mState.PhysicalDevices.end()) {
    auto inst_func_iter =
        mImports.mVkInstanceFunctions.find(phy_dev_iter->second->mInstance);
    if (inst_func_iter != mImports.mVkInstanceFunctions.end()) {
      next_layer_enumerate_extensions = reinterpret_cast<
          gapii::VulkanImports::PFNVKENUMERATEDEVICEEXTENSIONPROPERTIES>(
          inst_func_iter->second.vkEnumerateDeviceExtensionProperties);
    }
  }

  uint32_t next_layer_count = 0;
  uint32_t next_layer_result;
  if (next_layer_enumerate_extensions) {
    next_layer_result = next_layer_enumerate_extensions(
        physicalDevice, pLayerName, &next_layer_count, NULL);
    if (next_layer_result != VkResult::VK_SUCCESS) {
      return next_layer_result;
    }
  }
  std::vector<VkExtensionProperties> properties(next_layer_count,
                                                VkExtensionProperties{arena()});
  if (next_layer_enumerate_extensions) {
    next_layer_result = next_layer_enumerate_extensions(
        physicalDevice, pLayerName, &next_layer_count, properties.data());
    if (next_layer_result != VkResult::VK_SUCCESS) {
      return next_layer_result;
    }
  }

  bool has_debug_marker_ext = false;
  for (VkExtensionProperties& ext : properties) {
    // TODO: Check the spec version and emit warning if not match.
    // TODO: refer to VK_EXT_DEBUG_MARKER_EXTENSION_NAME
    if (!strcmp(ext.mextensionName, "VK_EXT_debug_marker")) {
      has_debug_marker_ext = true;
      break;
    }
  }
  if (!has_debug_marker_ext) {
    // TODO: refer to VK_EXT_DEBUG_MARKER_EXTENSION_NAME and
    // VK_EXT_DEBUG_MARKER_SPEC_VERSION
    char debug_marker_extension_name[] = "VK_EXT_debug_marker";
    uint32_t debug_marker_spec_version = 4;
    properties.emplace_back(VkExtensionProperties{debug_marker_extension_name,
                                                  debug_marker_spec_version});
  }

  auto extension = subSupportedDeviceExtensions(nullptr, nullptr);
  std::vector<VkExtensionProperties> all_properties;
  for (VkExtensionProperties& ext : properties) {
    gapil::String name(arena(), &ext.mextensionName[0]);
    if (!mHideUnknownExtensions || (extension->mExtensionNames.find(name) !=
                                    extension->mExtensionNames.end())) {
      all_properties.push_back(ext);
    }
  }

  // AGI implements VK_ANDROID_frame_boundary itself
  char frame_boundary_extension_name[] = "VK_ANDROID_frame_boundary";
  uint32_t frame_boundary_spec_version = 1;
  all_properties.push_back(VkExtensionProperties{frame_boundary_extension_name,
                                                 frame_boundary_spec_version});

  if (pProperties == NULL) {
    *pCount = all_properties.size();
    return VkResult::VK_SUCCESS;
  }
  uint32_t copy_count =
      all_properties.size() < *pCount ? all_properties.size() : *pCount;
  memcpy(pProperties, all_properties.data(),
         copy_count * sizeof(VkExtensionProperties));
  if (*pCount < all_properties.size()) {
    return VkResult::VK_INCOMPLETE;
  }
  *pCount = all_properties.size();
  return VkResult::VK_SUCCESS;
}

template <typename T>
static void SuppressUnsupportedFeatures2(T* pFeatures) {
  auto next = reinterpret_cast<VulkanStructHeader*>(pFeatures->mpNext);
  while (next) {
    // Filter out protected memory device feature
    if (next->mSType ==
        VkStructureType::
            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES) {
      reinterpret_cast<VkPhysicalDeviceProtectedMemoryFeatures*>(next)
          ->mprotectedMemory = 0;
    }
    next = reinterpret_cast<VulkanStructHeader*>(next->mPNext);
  }
}

void VulkanSpy::SpyOverride_vkGetPhysicalDeviceFeatures2(
    CallObserver*, VkPhysicalDevice physicalDevice,
    VkPhysicalDeviceFeatures2* pFeatures) {
  auto instance = mState.PhysicalDevices[physicalDevice]->mInstance;
  mImports.mVkInstanceFunctions[instance].vkGetPhysicalDeviceFeatures2(
      physicalDevice, pFeatures);
  SuppressUnsupportedFeatures2(pFeatures);
}

void VulkanSpy::SpyOverride_vkGetPhysicalDeviceFeatures2KHR(
    CallObserver*, VkPhysicalDevice physicalDevice,
    VkPhysicalDeviceFeatures2KHR* pFeatures) {
  auto instance = mState.PhysicalDevices[physicalDevice]->mInstance;
  mImports.mVkInstanceFunctions[instance].vkGetPhysicalDeviceFeatures2KHR(
      physicalDevice, pFeatures);
  SuppressUnsupportedFeatures2(pFeatures);
}

static void SuppressUnsupportedQueueFamilyProperties(
    VkQueueFamilyProperties& queue_family_props) {
  // Filter out protected queue property
  queue_family_props.mqueueFlags &= ~VkQueueFlagBits::VK_QUEUE_PROTECTED_BIT;
}

template <typename T>
static void SuppressUnsupportedQueueFamilyProperties2(T& queueFamilyProps2) {
  SuppressUnsupportedQueueFamilyProperties(
      queueFamilyProps2.mqueueFamilyProperties);
}

void VulkanSpy::SpyOverride_vkGetPhysicalDeviceQueueFamilyProperties(
    CallObserver*, VkPhysicalDevice physicalDevice,
    uint32_t* pQueueFamilyPropertyCount,
    VkQueueFamilyProperties* pQueueFamilyProperties) {
  auto instance = mState.PhysicalDevices[physicalDevice]->mInstance;
  mImports.mVkInstanceFunctions[instance]
      .vkGetPhysicalDeviceQueueFamilyProperties(
          physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
  if (pQueueFamilyProperties != nullptr) {
    for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; i++) {
      SuppressUnsupportedQueueFamilyProperties(pQueueFamilyProperties[i]);
    }
  }
}

void VulkanSpy::SpyOverride_vkGetPhysicalDeviceQueueFamilyProperties2(
    CallObserver*, VkPhysicalDevice physicalDevice,
    uint32_t* pQueueFamilyPropertyCount,
    VkQueueFamilyProperties2* pQueueFamilyProperties) {
  auto instance = mState.PhysicalDevices[physicalDevice]->mInstance;
  mImports.mVkInstanceFunctions[instance]
      .vkGetPhysicalDeviceQueueFamilyProperties2(
          physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
  if (pQueueFamilyProperties != nullptr) {
    for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; i++) {
      SuppressUnsupportedQueueFamilyProperties2(pQueueFamilyProperties[i]);
    }
  }
}

void VulkanSpy::SpyOverride_vkGetPhysicalDeviceQueueFamilyProperties2KHR(
    CallObserver*, VkPhysicalDevice physicalDevice,
    uint32_t* pQueueFamilyPropertyCount,
    VkQueueFamilyProperties2KHR* pQueueFamilyProperties) {
  auto instance = mState.PhysicalDevices[physicalDevice]->mInstance;
  mImports.mVkInstanceFunctions[instance]
      .vkGetPhysicalDeviceQueueFamilyProperties2KHR(
          physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
  if (pQueueFamilyProperties != nullptr) {
    for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; i++) {
      SuppressUnsupportedQueueFamilyProperties2(pQueueFamilyProperties[i]);
    }
  }
}

void VulkanSpy::SpyOverride_vkDestroyInstance(
    CallObserver*, VkInstance instance,
    const VkAllocationCallbacks* pAllocator) {
  // First we have to find the function to chain to, then we have to
  // remove this instance from our list, then we forward the call.
  auto it = mImports.mVkInstanceFunctions.find(instance);
  gapii::VulkanImports::PFNVKDESTROYINSTANCE destroy_instance =
      it == mImports.mVkInstanceFunctions.end() ? nullptr
                                                : it->second.vkDestroyInstance;
  if (destroy_instance) {
    destroy_instance(instance, pAllocator);
  }
  mImports.mVkInstanceFunctions.erase(
      mImports.mVkInstanceFunctions.find(instance));
}

uint32_t VulkanSpy::SpyOverride_vkCreateBuffer(
    CallObserver*, VkDevice device, const VkBufferCreateInfo* pCreateInfo,
    const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) {
  if (is_suspended()) {
    VkBufferCreateInfo override_create_info = *pCreateInfo;
    override_create_info.musage |=
        VkBufferUsageFlagBits::VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
    return mImports.mVkDeviceFunctions[device].vkCreateBuffer(
        device, &override_create_info, pAllocator, pBuffer);
  } else {
    return mImports.mVkDeviceFunctions[device].vkCreateBuffer(
        device, pCreateInfo, pAllocator, pBuffer);
  }
}

// SpyOverride_vkCreateImage adds the TRANSFER_SRC_BIT to images such that we
// can retrieve them when we serialize the initial state.
uint32_t VulkanSpy::SpyOverride_vkCreateImage(
    CallObserver*, VkDevice device, const VkImageCreateInfo* pCreateInfo,
    const VkAllocationCallbacks* pAllocator, VkImage* pImage) {
  VkImageCreateInfo override_create_info = *pCreateInfo;
  // Image with an Android external format cannot have the transfer bit, this
  // is forbidden and in practice it can cause driver crashes.
  if (!hasAndroidExternalFormat(pCreateInfo)) {
    // TODO(b/148857112): do not set TRANSFER_SRC_BIT on images with
    // TRANSIENT_ATTACHMENT_BIT set (this is invalid). For now, while this is
    // invalid, it seems to work fine in practice.
    override_create_info.musage |=
        VkImageUsageFlagBits::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
  }
  return mImports.mVkDeviceFunctions[device].vkCreateImage(
      device, &override_create_info, pAllocator, pImage);
}

uint32_t VulkanSpy::SpyOverride_vkCreateSwapchainKHR(
    CallObserver*, VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo,
    const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pImage) {
  if (is_observing() || is_suspended()) {
    VkSwapchainCreateInfoKHR override_create_info = *pCreateInfo;
    override_create_info.mimageUsage |=
        VkImageUsageFlagBits::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
    return mImports.mVkDeviceFunctions[device].vkCreateSwapchainKHR(
        device, &override_create_info, pAllocator, pImage);
  } else {
    return mImports.mVkDeviceFunctions[device].vkCreateSwapchainKHR(
        device, pCreateInfo, pAllocator, pImage);
  }
}

void VulkanSpy::SpyOverride_vkDestroyDevice(
    CallObserver*, VkDevice device, const VkAllocationCallbacks* pAllocator) {
  // First we have to find the function to chain to, then we have to
  // remove this instance from our list, then we forward the call.
  auto it = mImports.mVkDeviceFunctions.find(device);
  gapii::VulkanImports::PFNVKDESTROYDEVICE destroy_device =
      it == mImports.mVkDeviceFunctions.end() ? nullptr
                                              : it->second.vkDestroyDevice;
  if (destroy_device) {
    destroy_device(device, pAllocator);
  }
  mImports.mVkDeviceFunctions.erase(mImports.mVkDeviceFunctions.find(device));
}

uint32_t VulkanSpy::SpyOverride_vkAllocateMemory(
    CallObserver*, VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo,
    const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) {
  uint32_t r = mImports.mVkDeviceFunctions[device].vkAllocateMemory(
      device, pAllocateInfo, pAllocator, pMemory);
  auto l_physical_device =
      mState.PhysicalDevices[mState.Devices[device]->mPhysicalDevice];
  if (0 !=
      (l_physical_device->mMemoryProperties
           .mmemoryTypes[pAllocateInfo->mmemoryTypeIndex]
           .mpropertyFlags &
       ((uint32_t)(
           VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)))) {
    // This is host-coherent memory. Some drivers actually allocate these pages
    // on-demand. This forces all of the pages to be created. This is needed as
    // our coherent memory tracker relies on page-faults which interferes with
    // the on-demand allocation.
    char* memory;
    mImports.mVkDeviceFunctions[device].vkMapMemory(
        device, *pMemory, 0, pAllocateInfo->mallocationSize, 0,
        reinterpret_cast<void**>(&memory));
    memset(memory, 0x00, pAllocateInfo->mallocationSize);
    mImports.mVkDeviceFunctions[device].vkUnmapMemory(device, *pMemory);
  }
  return r;
}

// Utility functions
uint32_t VulkanSpy::numberOfPNext(CallObserver* observer, const void* pNext) {
  uint32_t counter = 0;
  while (pNext) {
    counter++;
    pNext = reinterpret_cast<const void*>(
        reinterpret_cast<const uintptr_t*>(pNext)[1]);
  }
  return counter;
}

void VulkanSpy::walkImageSubRng(
    gapil::Ref<ImageObject> img, VkImageSubresourceRange rng,
    std::function<void(uint32_t aspect_bit, uint32_t layer, uint32_t level)>
        f) {
  uint32_t layer_count =
      subImageSubresourceLayerCount(nullptr, nullptr, img, rng);
  uint32_t level_count =
      subImageSubresourceLevelCount(nullptr, nullptr, img, rng);
  auto aspect_map =
      subUnpackImageAspectFlags(nullptr, nullptr, img, rng.maspectMask);
  for (auto b : aspect_map) {
    auto ai = img->mAspects.find(b.second);
    if (ai == img->mAspects.end()) {
      continue;
    }
    for (uint32_t layer = rng.mbaseArrayLayer;
         layer < rng.mbaseArrayLayer + layer_count; layer++) {
      auto layi = ai->second->mLayers.find(layer);
      if (layi == ai->second->mLayers.end()) {
        continue;
      }
      for (uint32_t level = rng.mbaseMipLevel;
           level < rng.mbaseMipLevel + level_count; level++) {
        auto levi = layi->second->mLevels.find(level);
        if (levi == layi->second->mLevels.end()) {
          continue;
        }
        f(b.second, layer, level);
      }
    }
  }
}

void VulkanSpy::recordWaitedFences(CallObserver* observer, VkDevice device,
                                   uint32_t fenceCount,
                                   VkFence const* pFences) {
  auto it = mImports.mVkDeviceFunctions.find(device);

  vulkan_pb::FenceState state;

  for (size_t i = 0; i < fenceCount; ++i) {
    state.add_fences(pFences[i]);
    state.add_statuses(it->second.vkGetFenceStatus(device, pFences[i]));
  }

  observer->encode_message(&state);
}

}  // namespace gapii


text: export { default } from './container';


text:
'use strict';

var db = require('../models/schema');

var actions = {
  index: function(req, res) {
    res.render('index', { cookieValid: req.signedCookies.rememberToken === process.env.ZENODOTUS_REMEMBER_TOKEN
                        , currentUser: req.session.currentUser });
  }

, login: function(req, res) {
    var userName  = req.body.firstName + ' ' + req.body.lastName
      , userEmail = req.body.email.toLowerCase();

    // Look up the user if (s)he exists...
    db.user.findOne({ email: userEmail }, function(err, user) {
      if (err) {
        console.log(err.message);
        res.render('500', { message: err.message });
      }
      // ...or create a new user on first login.
      if (!user) {
        var newUser = new db.user({ name: userName
                                  , email: userEmail
                                  , admin: false
                                  , books: [] });

        newUser.save(function(err) {
          if (err) {
            console.log(err.message);
            res.render('500', { message: err.message });
          }
        });
      }

      res.cookie('rememberToken', process.env.ZENODOTUS_REMEMBER_TOKEN, { maxAge: 36000000, signed: true, httpOnly: true });
      req.session.currentUser = user || newUser;
      res.cookie('user', req.session.currentUser.email, { maxAge: 36000000, signed: true, httpOnly: true });

      res.redirect('/');
    });
  }

, logout: function(req, res) {
    res.clearCookie('rememberToken');
    res.clearCookie('user');
    req.session.destroy();
    res.redirect('/');
  }

, getBooks: function(req, res) {
    var query = db.book.find(function(err) {
      if (err) { console.log('An error occurred: ' + err.message); }
    }).sort('title');

    query.select('-_id -__v');

    query.exec(function(err, books) {
      if (err) {
        console.log('An error occurred: ' + err.message);
        res.render('500', { message: err });
      }
      res.json(books);
    });
  }

, addBook: function(req, res) {
    var bookTitle = req.body.title.trim()
      , bookIsbn  = +req.body.isbn.trim()
      , bookQty   = +req.body.quantity.trim();

    var newBook = new db.book({ title: bookTitle
                              , isbn: bookIsbn
                              , quantity: bookQty
                              , available: bookQty });

    // TODO: Check if book is already in the DB
    // & tell user to ++ qty rather than add new
    newBook.save(function(err) {
      if (err) {
        console.log(err.message);
        res.render('500', { message: err.message });
      }
    });

    res.redirect('/');
  }

, getUsers: function(req, res) {
    if (!isLoggedIn(req)) {
      res.status(401).send('Unauthorized');
      return;
    }
    var query = db.user.find(function(err) {
      if (err) { console.log('An error occurred: ' + err.message); }
    }).sort('name');

    query.select('name email books -_id');

    query.exec(function(err, users) {
      if (err) { console.log('An error occurred: ' + err.message); }
      res.json(users);
    });
  }

, getUsersBooks: function(req, res) {
    if (req.signedCookies.user) {
      db.user.findOne({ email: req.signedCookies.user }, function(err, user) {
        if (err) { console.log('An error occurred: ' + error); }
        res.json(user.books);
      });
    } else {
      res.json('Not logged in.');
    }
  }

, checkout: function(req, res) {
    var bookIsbn  = +req.body.ISBN
      , bookTitle = req.body.title
      , user      = req.signedCookies.user;

    // !!! Potentially unsafe !!!
    db.book.update({ isbn: bookIsbn }, { $inc : { available: -1 } }, function(err) {
      if (err) { console.log('An error occurred: ' + err); }
    });

    db.user.findOneAndUpdate({ email : user }
                           , { $push : { books: { title: bookTitle, isbn: bookIsbn } } }
                           , { new : true }
                           , function(err, user) {
                               if (err) { console.log('An error occurred: ' + err); }
                           });
    res.redirect('/');
  }

, return: function(req, res) {
    var bookTitle = req.body.title
      , bookIsbn  = +req.body.isbn
      , user      = req.signedCookies.user;

    // !!! Potentially unsafe !!!
    db.book.update({ isbn: bookIsbn }, { $inc : { available: 1 } }, function(err) {
      if (err) { console.log('An error occurred: ' + err); }
    });

    db.user.findOneAndUpdate( { email : user }
                            , { $pull : { books: { title: bookTitle, isbn: bookIsbn } } }
                            , { new : true }
                            , function(err, user) {
                                if (err) { console.log('An error occurred: ' + err); }
                            });
    res.redirect('/');
  }
};

// Login helper function
var isLoggedIn = function(req) {
  return !!req.signedCookies.rememberToken;
};

module.exports = actions;


text:
package io.crate.sql.tree;

import java.util.List;
import java.util.Objects;
import java.util.function.Function;

public class ColumnType<T> extends Expression {

    private final String name;
    private final List<Integer> parameters;

    public ColumnType(String name) {
        this(name, List.of());
    }

    public ColumnType(String name, List<Integer> parameters) {
        this.name = name;
        this.parameters = parameters;
    }

    public String name() {
        return name;
    }

    public List<Integer> parameters() {
        return parameters;
    }

    public boolean parametrized() {
        return !parameters.isEmpty();
    }

    @Override
    public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
        return visitor.visitColumnType(this, context);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        ColumnType<?> that = (ColumnType<?>) o;
        return Objects.equals(name, that.name) &&
               Objects.equals(parameters, that.parameters);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, parameters);
    }

    public <U> ColumnType<U> map(Function<? super T, ? extends U> mapper) {
        return new ColumnType<>(name, parameters);
    }

    public <U> ColumnType<U> mapExpressions(ColumnType<U> mappedType,
                                            Function<? super T, ? extends U> mapper) {
        return mappedType;
    }
}