// File: /workspace/github_c_makefile_star2_O1/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 0xabe9
testb $0xc, %bpl
jne 0xac08
movq %r12, %rdi
callq 0x22a0
movq %rax, %r13
movq %rax, 0x50(%r14)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
testq %r13, %r13
je 0xa937
movq %r13, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x2280
cmpq $0x6, %r12
jae 0xa863
movq 0x50(%r14), %rdi
callq 0x2040
movq $0x0, 0x50(%r14)
cmpl $0x0, (%rbx)
je 0xa91e
leaq 0xaec9(%rip), %rdi      # 0x15720
xorl %eax, %eax
callq 0x10048
jmp 0xa92c
movq %r12, %rax
andq $-0x2, %rax
cmpq $0x6, %rax
je 0xa836
movl $0x444c564b, %eax       # imm = 0x444C564B
xorl (%r13), %eax
movzwl 0x4(%r13), %ecx
xorl $0x53, %ecx
orl %eax, %ecx
jne 0xa836
movzbl 0x7(%r13), %r9d
movzbl 0x6(%r13), %edi
movl %edi, %r15d
shll $0x8, %r15d
leaq (%r15,%r9), %r8
movq %r8, 0x38(%r14)
cmpq $0x8, %r12
je 0xa836
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), %r12
addq $-0x12, %r12
movzbl %dl, %ecx
leaq 0xa(%r13,%rcx,8), %r13
testb $0x1, %al
jne 0xa946
testq %r8, %r8
je 0xa973
leal (,%r8,8), %edi
movq %r8, (%rsp)
movq %r9, %rbp
callq 0x22a0
movq %rbp, %r9
movq (%rsp), %r8
jmp 0xa975
leaq 0xae0e(%rip), %rdi      # 0x15733
xorl %eax, %eax
callq 0x10167
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 0xaaa0
movq %rdi, (%rsp)
movl %r8d, %edi
shll $0x4, %edi
movq %r8, %r15
movq %r9, %rbp
callq 0x22a0
movq %rbp, %r9
movq (%rsp), %rdi
movq %r15, %r8
jmp 0xaaa2
xorl %eax, %eax
testq %r8, %r8
setne %cl
movq %rax, 0x40(%r14)
testq %rax, %rax
sete %al
testb %al, %cl
jne 0xa836
leaq 0x40(%r14), %rbp
testq %r8, %r8
je 0xa9d4
addq %r9, %r15
xorl %eax, %eax
testq %r12, %r12
je 0xaba8
movq (%rbp), %rcx
movq %r13, (%rcx,%rax,8)
movq (%rbp), %rcx
movq (%rcx,%rax,8), %rcx
movzbl (%rcx), %ecx
cmpq %rcx, %r12
jbe 0xaba8
addq %rcx, %r13
incq %r13
incq %rcx
subq %rcx, %r12
incq %rax
cmpq %rax, %r15
jne 0xa99b
incq %r8
movl $0x8, %esi
movq %r8, %rdi
callq 0xac27
movq %rax, 0x48(%r14)
testq %rax, %rax
je 0xab9d
movq 0x38(%r14), %rax
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 0xaa03
movq $-0x1, %r15
subq $0x14, %r12
jb 0xab71
movq (%r13), %rdi
movq 0x8(%r13), %rsi
bswapq %rdi
bswapq %rsi
movl 0x10(%r13), %edx
bswapl %edx
callq 0xac7c
movq 0x48(%r14), %rcx
movq %rax, 0x8(%rcx,%r15,8)
testq %rax, %rax
je 0xab71
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 0xaa1e
testq %r12, %r12
je 0xabe2
xorl %ecx, %ecx
xorl %eax, %eax
cmpb $0x0, (%r13,%rcx)
jne 0xab71
incq %rcx
cmpq %rcx, %r12
jne 0xaa87
jmp 0xa937
xorl %eax, %eax
testq %r8, %r8
setne %cl
movq %rax, 0x40(%r14)
testq %rax, %rax
sete %al
testb %al, %cl
jne 0xa836
leaq 0x40(%r14), %rbp
testq %r8, %r8
je 0xab0c
movl %r9d, %ecx
shll $0x4, %ecx
movl %edi, %eax
shll $0xc, %eax
orl %ecx, %eax
xorl %ecx, %ecx
testq %r12, %r12
je 0xaba8
movq (%rbp), %rdx
movq %r13, (%rdx,%rcx)
movq (%rbp), %rdx
movq (%rdx,%rcx), %rdx
movzbl (%rdx), %edx
cmpq %rdx, %r12
jbe 0xaba8
addq %rdx, %r13
incq %r13
incq %rdx
subq %rdx, %r12
addq $0x10, %rcx
cmpq %rcx, %rax
jne 0xaad2
testq %r8, %r8
je 0xab55
shll $0x4, %r9d
shll $0xc, %edi
orl %r9d, %edi
xorl %eax, %eax
testq %r12, %r12
je 0xaba8
movq (%rbp), %rcx
movq %r13, 0x8(%rcx,%rax)
movq (%rbp), %rcx
movq 0x8(%rcx,%rax), %rcx
movzbl (%rcx), %ecx
cmpq %rcx, %r12
jbe 0xaba8
addq %rcx, %r13
incq %r13
incq %rcx
subq %rcx, %r12
addq $0x10, %rax
cmpq %rax, %rdi
jne 0xab1d
testq %r8, %r8
je 0xabbe
movq (%rbp), %rax
movq (%rax), %rdi
shll $0x4, %r8d
movq -0x10(%rax,%r8), %rsi
callq 0x103ab
jmp 0xabc0
xorl %r15d, %r15d
movq 0x48(%r14), %rax
movq (%rax,%r15,8), %rdi
callq 0xace6
incq %r15
cmpq 0x38(%r14), %r15
jbe 0xab74
movq 0x48(%r14), %rdi
callq 0x2040
movq $0x0, 0x48(%r14)
jmp 0xaba8
cmpq $-0x1, 0x38(%r14)
je 0xa9f1
movq (%rbp), %rdi
callq 0x2040
movq $0x0, (%rbp)
jmp 0xa836
movb $-0x1, %al
movb %al, 0x1f(%r14)
testq %r12, %r12
je 0xabe2
xorl %ecx, %ecx
xorl %eax, %eax
cmpb $0x0, (%r13,%rcx)
jne 0xaba8
incq %rcx
cmpq %rcx, %r12
jne 0xabcd
jmp 0xa937
xorl %eax, %eax
jmp 0xa937
leaq 0xaade(%rip), %rdi      # 0x156ce
leaq 0xaa11(%rip), %rsi      # 0x15608
leaq 0xaaea(%rip), %rcx      # 0x156e8
movl $0xc9, %edx
callq 0x21c0
leaq 0xa58d(%rip), %rdi      # 0x1519c
leaq 0xa9f2(%rip), %rsi      # 0x15608
leaq 0xaacb(%rip), %rcx      # 0x156e8
movl $0xca, %edx
callq 0x21c0