// File: /workspace/github_c_makefile_star2_O0/sprt[P]lossless-transport/src/packet_implem.c
// Function: pkt_decode
pkt_status_code pkt_decode(const char *data, const size_t len, pkt_t *pkt) {
	if (data == NULL || len < HEADER_SIZE) {
		return E_NOHEADER;
	}

	size_t read = 0;

	memcpy(pkt, data + read, HEADER_SIZE);
	read += HEADER_SIZE;

	size_t payload_size = pkt_get_length(pkt) * sizeof (*pkt->payload);

	/* Field errors should be returned in the order those fields are
	 * declared in the struct. We could return E_UNCONSISTENT if the packet
	 * has a payload and isn't of type PTYPE_DATA, but we don't since it
	 * isn't specified and thus doing so might break other implementations
	 * (albeit buggy ones). */
	if (pkt_get_type(pkt) == 0) {
		return E_TYPE;
	} else if (pkt_get_type(pkt) != PTYPE_DATA && pkt_get_tr(pkt) != 0) {
		return E_TR;
	} else if (pkt_get_window(pkt) > MAX_WINDOW_SIZE) {
		return E_WINDOW;
	} else if (payload_size > MAX_PAYLOAD_SIZE) {
		/* FIXME: pkt_get_length returns 0 when the packet has been
		 * truncated, regardless of the value of length field. Thus, in
		 * that case we can't reliably check whether the length field
		 * overflows the maximum size given by the specification. */
		return E_LENGTH;
	} else if (len != pkt_get_total_size(pkt)) {
		// Return now in order to prevent a potential buffer overflow
		return E_UNCONSISTENT;
	} else if (pkt_get_crc1(pkt) != pkt_compute_crc1(pkt)) {
		return E_CRC;
	}

	// No-op if payload empty
	memcpy(pkt->payload, data + read, payload_size);
	read += payload_size;

	// Prevent memcpy from overflowing
	if (payload_size > 0) {
		memcpy(&pkt->crc2, data + read, sizeof (pkt->crc2));
		if (pkt_get_crc2(pkt) != pkt_compute_crc2(pkt, payload_size)) {
			return E_CRC;
		}
	}

	return PKT_OK;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x14c2
cmpq $0xc, -0x18(%rbp)
jae 0x14ce
movl $0x8, -0x4(%rbp)
jmp 0x1657
movq $0x0, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rdx
movq (%rcx,%rdx), %rsi
movq %rsi, (%rax)
movl 0x8(%rcx,%rdx), %ecx
movl %ecx, 0x8(%rax)
movq -0x28(%rbp), %rax
addq $0xc, %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rdi
callq 0x1460
movzwl %ax, %eax
shlq $0x0, %rax
movq %rax, -0x30(%rbp)
movq -0x20(%rbp), %rdi
callq 0x1660
cmpl $0x0, %eax
jne 0x152a
movl $0x1, -0x4(%rbp)
jmp 0x1657
movq -0x20(%rbp), %rdi
callq 0x1660
cmpl $0x1, %eax
je 0x1555
movq -0x20(%rbp), %rdi
callq 0x1680
movzbl %al, %eax
cmpl $0x0, %eax
je 0x1555
movl $0x2, -0x4(%rbp)
jmp 0x1657
movq -0x20(%rbp), %rdi
callq 0x16a0
movzbl %al, %eax
cmpl $0x1f, %eax
jle 0x1572
movl $0x5, -0x4(%rbp)
jmp 0x1657
cmpq $0x200, -0x30(%rbp)     # imm = 0x200
jbe 0x1588
movl $0x3, -0x4(%rbp)
jmp 0x1657
movq -0x18(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rdi
callq 0x1410
movq %rax, %rcx
movq -0x38(%rbp), %rax
cmpq %rcx, %rax
je 0x15b1
movl $0x9, -0x4(%rbp)
jmp 0x1657
movq -0x20(%rbp), %rdi
callq 0x16c0
movl %eax, -0x3c(%rbp)
movq -0x20(%rbp), %rdi
callq 0x1380
movl %eax, %ecx
movl -0x3c(%rbp), %eax
cmpl %ecx, %eax
je 0x15d8
movl $0x4, -0x4(%rbp)
jmp 0x1657
jmp 0x15da
jmp 0x15dc
jmp 0x15de
jmp 0x15e0
jmp 0x15e2
movq -0x20(%rbp), %rdi
addq $0xc, %rdi
movq -0x10(%rbp), %rsi
addq -0x28(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x1110
movq -0x30(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x30(%rbp)
jbe 0x1650
movq -0x20(%rbp), %rax
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rdx
movl (%rcx,%rdx), %ecx
movl %ecx, 0x20c(%rax)
movq -0x20(%rbp), %rdi
callq 0x16e0
movl %eax, -0x40(%rbp)
movq -0x20(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x13e0
movl %eax, %ecx
movl -0x40(%rbp), %eax
cmpl %ecx, %eax
je 0x164e
movl $0x4, -0x4(%rbp)
jmp 0x1657
jmp 0x1650
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq