// File: /workspace/github_c_makefile_star2_O2/Tarsnap[P]kivaloo/kvlds/serialize.c
// Function: deserialize
int
deserialize(struct node * N, const uint8_t * buf, size_t buflen)
{
	uint8_t * p;
	size_t i;

	/*
	 * Clear errno; we will use it to distinguish between internal errors
	 * (i.e., ENOMEM) and invalid page data.
	 */
	errno = 0;

	/*
	 * Sanity check: We can only deserialize a page into a node which is
	 * being fetched (NODE_TYPE_READ) and clean (NODE_STATE_CLEAN).
	 */
	assert(N->type == NODE_TYPE_READ);
	assert(N->state == NODE_STATE_CLEAN);

	/* Copy the serialized page. */
	if ((N->pagebuf = malloc(buflen)) == NULL)
		goto err0;
	memcpy(N->pagebuf, buf, buflen);
	p = N->pagebuf;

	/* Check magic. */
	if (buflen < 6)
		goto err1;
	if (memcmp(p, "KVLDS\0", 6))
		goto err1;
	p += 6; buflen -= 6;

	/* Parse # of keys. */
	if (buflen < 2)
		goto err1;
	N->nkeys = be16dec(p);
	p += 2; buflen -= 2;

	/* Parse height and rootedness. */
	if (buflen < 1)
		goto err1;
	if (p[0] & 0x80)
		N->root = 1;
	else
		N->root = 0;
	N->height = p[0] & 0x7f;
	if (N->height)
		N->type = NODE_TYPE_PARENT;
	else
		N->type = NODE_TYPE_LEAF;
	p += 1; buflen -= 1;

	/* Parse matching prefix length. */
	N->mlen_t = p[0];
	p += 1; buflen -= 1;

	/* Skip root data if appropriate. */
	if (N->root) {
		p += 8;
		buflen -= 8;
	}

	/* Parse node data. */
	if (N->type == NODE_TYPE_LEAF) {
		/* Allocate array of key-value pairs. */
		if (IMALLOC(N->u.pairs, N->nkeys, struct kvpair_const))
			goto err1;

		/* Parse keys. */
		for (i = 0; i < N->nkeys; i++) {
			if (buflen == 0)
				goto err2;
			N->u.pairs[i].k = (struct kvldskey *)p;
			if (buflen < kvldskey_serial_size(N->u.pairs[i].k))
				goto err2;
			p += kvldskey_serial_size(N->u.pairs[i].k);
			buflen -= kvldskey_serial_size(N->u.pairs[i].k);
		}

		/* Parse values. */
		for (i = 0; i < N->nkeys; i++) {
			if (buflen == 0)
				goto err2;
			N->u.pairs[i].v = (struct kvldskey *)p;
			if (buflen < kvldskey_serial_size(N->u.pairs[i].v))
				goto err2;
			p += kvldskey_serial_size(N->u.pairs[i].v);
			buflen -= kvldskey_serial_size(N->u.pairs[i].v);
		}

		/* Figure out how far the keys match. */
		if (N->nkeys > 0) {
			N->mlen_n = (uint8_t)kvldskey_mlen(N->u.pairs[0].k,
			    N->u.pairs[N->nkeys - 1].k);
		} else {
			N->mlen_n = 255;
		}

		/* Make sure that the rest of the page is zeros. */
		while (buflen) {
			if (*p != 0)
				goto err2;
			p++; buflen--;
		}
	} else {
		/* Allocate array of keys. */
		if (IMALLOC(N->u.keys, N->nkeys, const struct kvldskey *))
			goto err1;

		/* Parse keys. */
		for (i = 0; i < N->nkeys; i++) {
			if (buflen == 0)
				goto err3;
			N->u.keys[i] = (struct kvldskey *)p;
			if (buflen < kvldskey_serial_size(N->u.keys[i]))
				goto err3;
			p += kvldskey_serial_size(N->u.keys[i]);
			buflen -= kvldskey_serial_size(N->u.keys[i]);
		}

		/* Allocate array of children. */
		if (IMALLOC(N->v.children, N->nkeys + 1, struct node *))
			goto err3;

		/* Initialize children to NULL to simplify error path. */
		for (i = 0; i <= N->nkeys; i++)
			N->v.children[i] = NULL;

		/* Parse children. */
		for (i = 0; i <= N->nkeys; i++) {
			/* Create child node. */
			if (buflen < SERIALIZE_PERCHILD)
				goto err4;
			if ((N->v.children[i] = node_alloc(be64dec(&p[0]),
			    be64dec(&p[8]), be32dec(&p[16]))) == NULL)
				goto err4;
			N->v.children[i]->p_shadow =
			    N->v.children[i]->p_dirty = N;
			p += SERIALIZE_PERCHILD;
			buflen -= SERIALIZE_PERCHILD;
		}

		/* Make sure that the rest of the page is zeros. */
		while (buflen) {
			if (*p != 0)
				goto err4;
			p++; buflen--;
		}
	}

	/* Success! */
	return (0);

	/*
	 * PARENT parsing error handling path.
	 */
err4:
	for (i = 0; i <= N->nkeys; i++)
		node_free(N->v.children[i]);
	free(N->v.children);
	N->v.children = NULL;

err3:
	free(N->u.keys);
	N->u.keys = NULL;
	goto err1;

	/*
	 * LEAF parsing error handling path.
	 */
err2:
	free(N->u.pairs);
	N->u.pairs = NULL;

	/*
	 * LEAF+PARENT merged error handling path.
	 */
err1:
	free(N->pagebuf);
	N->pagebuf = NULL;
	if (errno != 0)
		warnp("Error parsing page");
	else
		warn0("Invalid page read");
err0:
	/* Failure! */
	return (-1);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdx, %r15
movq %rsi, %r13
movq %rdi, %r14
callq 0x20a0
movq %rax, %rbx
andl $0x0, (%rax)
movb 0x1c(%r14), %bpl
movl %ebp, %eax
notb %al
testb $0x3, %al
jne 0x92aa
testb $0xc, %bpl
jne 0x92c9
movq %r15, %rdi
callq 0x22a0
movq %rax, %r12
movq %rax, 0x50(%r14)
pushq $-0x1
popq %rax
testq %r12, %r12
je 0x90b4
movq %r12, %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x2280
cmpq $0x6, %r15
jae 0x8fa1
movq 0x50(%r14), %rdi
callq 0x2040
andq $0x0, 0x50(%r14)
cmpl $0x0, (%rbx)
je 0x90a0
leaq 0x9766(%rip), %rdi      # 0x126fb
xorl %eax, %eax
callq 0xdf55
jmp 0x90ae
leaq 0x97b0(%rip), %rsi      # 0x12758
pushq $0x6
popq %rdx
movq %r12, %rdi
callq 0x22e0
movq %r15, %rcx
andq $-0x2, %rcx
cmpq $0x6, %rcx
je 0x8f77
testl %eax, %eax
jne 0x8f77
movzwl 0x6(%r12), %eax
rolw $0x8, %ax
movzwl %ax, %edi
movq %rdi, 0x38(%r14)
cmpq $0x8, %r15
je 0x8f77
movb 0x8(%r12), %al
movl %ebp, %ecx
andb $-0x1d, %cl
orb $0x10, %bpl
testb %al, %al
movzbl %bpl, %edx
movzbl %cl, %ecx
cmovsl %edx, %ecx
andb $0x7f, %al
movb %al, 0x1d(%r14)
sete %al
orb $-0x10, %al
movl %eax, %edx
andb %cl, %dl
movb %dl, 0x1c(%r14)
movb 0x9(%r12), %dl
movb %dl, 0x1e(%r14)
andb $0x10, %cl
movl %ecx, %edx
shrb $0x4, %dl
xorl %esi, %esi
testb %cl, %cl
sete %sil
leaq (%r15,%rsi,8), %r13
addq $-0x12, %r13
movzbl %dl, %ecx
leaq (%r12,%rcx,8), %r15
addq $0xa, %r15
testb $0x1, %al
jne 0x90c3
pushq $0x8
popq %rsi
callq 0x92e8
movq %rax, 0x40(%r14)
testq %rax, %rax
setne %cl
movq 0x38(%r14), %rdi
testq %rdi, %rdi
sete %dl
orb %cl, %dl
cmpb $0x1, %dl
jne 0x8f77
xorl %ecx, %ecx
cmpq %rcx, %rdi
je 0x912b
testq %r13, %r13
je 0x9274
movq %r15, (%rax,%rcx,8)
movq 0x40(%r14), %rax
movq (%rax,%rcx,8), %rdx
movzbl (%rdx), %edx
cmpq %rdx, %r13
jbe 0x9274
addq %rdx, %r15
incq %r15
incq %rdx
subq %rdx, %r13
incq %rcx
jmp 0x9065
leaq 0x9667(%rip), %rdi      # 0x1270e
xorl %eax, %eax
callq 0xe0e4
andl $0x0, (%rbx)
pushq $-0x1
popq %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x10
popq %rsi
callq 0x92e8
movq %rax, 0x40(%r14)
testq %rax, %rax
setne %dl
movq 0x38(%r14), %rcx
testq %rcx, %rcx
sete %sil
orb %dl, %sil
cmpb $0x1, %sil
jne 0x8f77
xorl %edx, %edx
movq %rcx, %rsi
subq $0x1, %rsi
jb 0x916d
testq %r13, %r13
je 0x9278
movq %r15, (%rax,%rdx)
movq 0x40(%r14), %rax
movq (%rax,%rdx), %rdi
movzbl (%rdi), %edi
cmpq %rdi, %r13
jbe 0x9278
addq %rdi, %r15
incq %r15
incq %rdi
subq %rdi, %r13
addq $0x10, %rdx
jmp 0x90f2
incq %rdi
pushq $0x8
popq %rsi
callq 0x92e8
movq %rax, 0x48(%r14)
testq %rax, %rax
setne %cl
movq 0x38(%r14), %rax
cmpq $-0x1, %rax
sete %dl
orb %cl, %dl
cmpb $0x1, %dl
jne 0x9274
pushq $-0x1
popq %rcx
cmpq %rcx, %rax
je 0x91b0
movq 0x48(%r14), %rdx
andq $0x0, 0x8(%rdx,%rcx,8)
incq %rcx
jmp 0x9159
pushq $0x8
popq %rdx
movq %rcx, %rsi
subq $0x1, %rsi
jb 0x9224
testq %r13, %r13
je 0x9278
movq %r15, (%rax,%rdx)
movq 0x40(%r14), %rax
movq (%rax,%rdx), %rdi
movzbl (%rdi), %edi
cmpq %rdi, %r13
jbe 0x9278
addq %rdi, %r15
incq %r15
incq %rdi
subq %rdi, %r13
addq $0x10, %rdx
jmp 0x9173
xorl %ebp, %ebp
cmpq %rax, %rbp
ja 0x923c
subq $0x14, %r13
jb 0x924f
movq %r15, %rdi
callq 0x9314
movq %rax, (%rsp)
leaq 0x8(%r15), %r12
movq %r12, %rdi
callq 0x9314
movl 0x10(%r15), %edx
bswapl %edx
movq (%rsp), %rdi
movq %rax, %rsi
callq 0x934c
movq 0x48(%r14), %rcx
movq %rax, (%rcx,%rbp,8)
testq %rax, %rax
je 0x924f
movq 0x48(%r14), %rax
movq (%rax,%rbp,8), %rax
movq %r14, 0x28(%rax)
movq 0x48(%r14), %rax
movq (%rax,%rbp,8), %rax
movq %r14, 0x20(%rax)
incq %rbp
movq 0x38(%r14), %rax
addq $0xc, %r12
movq %r12, %r15
jmp 0x91b2
testq %rcx, %rcx
je 0x928a
movq (%rax), %rdi
shlq $0x4, %rcx
movq -0x10(%rax,%rcx), %rsi
callq 0xe34c
jmp 0x928c
xorl %eax, %eax
cmpq %rax, %r13
je 0x92a3
cmpb $0x0, (%r15,%rax)
jne 0x924f
incq %rax
jmp 0x923e
xorl %r15d, %r15d
movq 0x48(%r14), %rdi
cmpq 0x38(%r14), %r15
ja 0x926a
movq (%rdi,%r15,8), %rdi
callq 0x9388
incq %r15
jmp 0x9252
callq 0x2040
andq $0x0, 0x48(%r14)
movq 0x40(%r14), %rax
movq %rax, %rdi
callq 0x2040
andq $0x0, 0x40(%r14)
jmp 0x8f77
movb $-0x1, %al
movb %al, 0x1f(%r14)
xorl %eax, %eax
cmpq %rax, %r13
je 0x92a3
cmpb $0x0, (%r15,%rax)
jne 0x9274
incq %rax
jmp 0x9292
xorl %eax, %eax
jmp 0x90b4
leaq 0x93f8(%rip), %rdi      # 0x126a9
leaq 0x932b(%rip), %rsi      # 0x125e3
leaq 0x9404(%rip), %rcx      # 0x126c3
movl $0xc9, %edx
callq 0x21c0
leaq 0x8ea7(%rip), %rdi      # 0x12177
leaq 0x930c(%rip), %rsi      # 0x125e3
leaq 0x93e5(%rip), %rcx      # 0x126c3
movl $0xca, %edx
callq 0x21c0