// File: /workspace/github_c_makefile_star2_O3/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, %r12
movq %rsi, %r15
movq %rdi, %r14
callq 0x20a0
movq %rax, %rbx
movl $0x0, (%rax)
movb 0x1c(%r14), %bpl
movl %ebp, %eax
notb %al
testb $0x3, %al
jne 0xaac5
testb $0xc, %bpl
jne 0xaae4
movq %r12, %rdi
callq 0x22a0
movq %rax, %r13
movq %rax, 0x50(%r14)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
testq %r13, %r13
je 0xa871
movq %r13, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x2280
cmpq $0x6, %r12
jae 0xa747
movq 0x50(%r14), %rdi
callq 0x2040
movq $0x0, 0x50(%r14)
cmpl $0x0, (%rbx)
je 0xa858
leaq 0xafa0(%rip), %rdi      # 0x156db
xorl %eax, %eax
callq 0xffd0
jmp 0xa866
movq %r12, %rax
andq $-0x2, %rax
cmpq $0x6, %rax
je 0xa71a
movl $0x444c564b, %eax       # imm = 0x444C564B
xorl (%r13), %eax
movzwl 0x4(%r13), %ecx
xorl $0x53, %ecx
orl %eax, %ecx
jne 0xa71a
movzbl 0x6(%r13), %r9d
movzbl 0x7(%r13), %r10d
movl %r9d, %r15d
shll $0x8, %r15d
leaq (%r15,%r10), %r8
movq %r8, 0x38(%r14)
cmpq $0x8, %r12
je 0xa71a
movb 0x8(%r13), %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(%r13), %dl
movb %dl, 0x1e(%r14)
andb $0x10, %cl
movl %ecx, %edx
shrb $0x4, %dl
xorl %esi, %esi
testb %cl, %cl
sete %sil
leaq (%r12,%rsi,8), %rbp
addq $-0x12, %rbp
movzbl %dl, %ecx
leaq 0xa(%r13,%rcx,8), %r13
testb $0x1, %al
jne 0xa880
testq %r8, %r8
je 0xa973
leal (,%r8,8), %edi
movq %r8, (%rsp)
movq %r10, %r12
callq 0x22a0
movq (%rsp), %r8
movq %rax, 0x40(%r14)
testq %rax, %rax
je 0xa71a
movq %r12, %rcx
leaq 0x40(%r14), %r12
addq %rcx, %r15
xorl %ecx, %ecx
testq %rbp, %rbp
je 0xaaaf
movq %r13, (%rax,%rcx,8)
movq (%r12), %rax
movq (%rax,%rcx,8), %rdx
movzbl (%rdx), %edx
cmpq %rdx, %rbp
jbe 0xaaaf
addq %rdx, %r13
incq %r13
incq %rdx
subq %rdx, %rbp
incq %rcx
cmpq %rcx, %r15
jne 0xa81e
jmp 0xa97f
leaq 0xae8f(%rip), %rdi      # 0x156ee
xorl %eax, %eax
callq 0x100ef
movl $0x0, (%rbx)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testq %r8, %r8
je 0xaa4e
movl %r8d, %edi
shll $0x4, %edi
movq %r8, %r15
movq %r9, %r12
movq %r10, (%rsp)
callq 0x22a0
movq (%rsp), %r9
movq %rax, 0x40(%r14)
testq %rax, %rax
je 0xa71a
movq %r12, %r8
movq %r15, %rsi
movq %rax, %rdi
leaq 0x40(%r14), %r12
movl %r9d, %ecx
shll $0x4, %ecx
movl %r8d, %eax
shll $0xc, %eax
orl %ecx, %eax
xorl %ecx, %ecx
testq %rbp, %rbp
je 0xaab3
movq %r13, (%rdi,%rcx)
movq (%r12), %rdi
movq (%rdi,%rcx), %rdx
movzbl (%rdx), %edx
cmpq %rdx, %rbp
jbe 0xaab3
addq %rdx, %r13
incq %r13
incq %rdx
subq %rdx, %rbp
addq $0x10, %rcx
cmpq %rcx, %rax
jne 0xa8cc
movb $-0x1, %al
testq %rsi, %rsi
je 0xaa5c
shll $0x4, %r9d
shll $0xc, %r8d
orl %r9d, %r8d
xorl %ecx, %ecx
testq %rbp, %rbp
je 0xaab3
movq %r13, 0x8(%rdi,%rcx)
movq (%r12), %rdi
movq 0x8(%rdi,%rcx), %rdx
movzbl (%rdx), %edx
cmpq %rdx, %rbp
jbe 0xaab3
addq %rdx, %r13
incq %r13
incq %rdx
subq %rdx, %rbp
addq $0x10, %rcx
cmpq %rcx, %r8
jne 0xa91a
testq %rsi, %rsi
je 0xaa5c
movq (%rdi), %rax
shll $0x4, %esi
movq -0x10(%rdi,%rsi), %rsi
movq %rax, %rdi
callq 0x1032f
jmp 0xaa5c
leaq 0x40(%r14), %r12
movq $0x0, 0x40(%r14)
incq %r8
movl $0x8, %esi
movq %r8, %rdi
callq 0xab03
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 0xaaaf
leaq 0x1(%rax), %rcx
cmpq $0x1, %rcx
adcq $0x1, %rax
xorl %ecx, %ecx
movq 0x48(%r14), %rdx
movq $0x0, (%rdx,%rcx,8)
incq %rcx
cmpq %rcx, %rax
jne 0xa9bd
movq $-0x1, %r15
subq $0x14, %rbp
jb 0xaa85
movq (%r13), %rdi
movq 0x8(%r13), %rsi
bswapq %rdi
bswapq %rsi
movl 0x10(%r13), %edx
bswapl %edx
callq 0xab58
movq 0x48(%r14), %rcx
movq %rax, 0x8(%rcx,%r15,8)
testq %rax, %rax
je 0xaa85
movq 0x48(%r14), %rax
movq 0x8(%rax,%r15,8), %rax
movq %r14, 0x28(%rax)
movq 0x48(%r14), %rax
movq 0x8(%rax,%r15,8), %rax
movq %r14, 0x20(%rax)
addq $0x14, %r13
incq %r15
cmpq 0x38(%r14), %r15
jb 0xa9d8
testq %rbp, %rbp
je 0xaa7e
xorl %ecx, %ecx
xorl %eax, %eax
cmpb $0x0, (%r13,%rcx)
jne 0xaa85
incq %rcx
cmpq %rcx, %rbp
jne 0xaa39
jmp 0xa871
leaq 0x40(%r14), %r12
movq $0x0, 0x40(%r14)
movb $-0x1, %al
movb %al, 0x1f(%r14)
testq %rbp, %rbp
je 0xaa7e
xorl %ecx, %ecx
xorl %eax, %eax
cmpb $0x0, (%r13,%rcx)
jne 0xaaaf
incq %rcx
cmpq %rcx, %rbp
jne 0xaa69
jmp 0xa871
xorl %eax, %eax
jmp 0xa871
xorl %r15d, %r15d
movq 0x48(%r14), %rax
movq (%rax,%r15,8), %rdi
callq 0xab9b
incq %r15
cmpq 0x38(%r14), %r15
jbe 0xaa88
movq 0x48(%r14), %rdi
callq 0x2040
movq $0x0, 0x48(%r14)
movq (%r12), %rdi
callq 0x2040
movq $0x0, (%r12)
jmp 0xa71a
leaq 0xabbd(%rip), %rdi      # 0x15689
leaq 0xaaf0(%rip), %rsi      # 0x155c3
leaq 0xabc9(%rip), %rcx      # 0x156a3
movl $0xc9, %edx
callq 0x21c0
leaq 0xa66c(%rip), %rdi      # 0x15157
leaq 0xaad1(%rip), %rsi      # 0x155c3
leaq 0xabaa(%rip), %rcx      # 0x156a3
movl $0xca, %edx
callq 0x21c0