// File: jBlinden[P]private-codis/protocol.cpp
// Function: ReceiveLargePacked(CSocket*, unsigned char, unsigned long, unsigned char*)
void ReceiveLargePacked(CSocket* socket, uint8_t bitsPerMsg, uint64_t length, uint8_t* out){
  //Assumes bitsPerMsg <= 8
  uint64_t newLength = packLength(length, bitsPerMsg);
  uint8_t* buffer = new uint8_t[newLength];

#if LOGGING
  struct timespec start, stop;
  uint64_t duration;
  clock_gettime(CLOCK_REALTIME, &start);
#endif

  socket->ReceiveLarge(buffer, newLength);

#if LOGGING
  clock_gettime(CLOCK_REALTIME, &stop);
  duration = (stop.tv_sec - start.tv_sec) * BILLION + stop.tv_nsec - start.tv_nsec;
  cout << "Time to receive: " << duration << " ns with size: " << newLength << endl;
#endif
  
  uint8_t bitPointer = 0;
  uint64_t index = 0;

  uint8_t mask = (1 << bitsPerMsg) - 1;

  for (int i = 0; i < length; i++){
    if (bitPointer + bitsPerMsg <= 8){
      //REGULAR CASE
      out[i] = (buffer[index] >> bitPointer) & mask;
      bitPointer += bitsPerMsg;
      if (bitPointer == 8){
        index += 1;
        bitPointer = 0;
      }
    }
    else{
      //OVERLAP CASE
      uint8_t reconstructedValue = 0;

      uint8_t rightBits = 8 - bitPointer;
      reconstructedValue += buffer[index] >> bitPointer;

      index += 1;
      uint8_t leftBits = bitsPerMsg - rightBits;
      uint8_t newMask = (1 << leftBits) - 1;
      reconstructedValue += (buffer[index] & newMask) << rightBits;
      out[i] = reconstructedValue;

      bitPointer = leftBits;
    }
  }
  delete[] buffer;
}

// Assembly:
subq $0x58, %rsp
movb %sil, %al
movq %rdi, 0x50(%rsp)
movb %al, 0x4f(%rsp)
movq %rdx, 0x40(%rsp)
movq %rcx, 0x38(%rsp)
movq 0x40(%rsp), %rdi
movzbl 0x4f(%rsp), %esi
callq 0x6f20
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rdi
callq 0x3030
movq %rax, 0x28(%rsp)
movq 0x50(%rsp), %rdi
movq 0x28(%rsp), %rsi
movq 0x30(%rsp), %rdx
callq 0x8410
movb $0x0, 0x27(%rsp)
movq $0x0, 0x18(%rsp)
movzbl 0x4f(%rsp), %ecx
movl $0x1, %eax
shll %cl, %eax
subl $0x1, %eax
movb %al, 0x17(%rsp)
movl $0x0, 0x10(%rsp)
movslq 0x10(%rsp), %rax
cmpq 0x40(%rsp), %rax
jae 0x8014
movzbl 0x27(%rsp), %eax
movzbl 0x4f(%rsp), %ecx
addl %ecx, %eax
cmpl $0x8, %eax
jg 0x7f58
movq 0x28(%rsp), %rax
movq 0x18(%rsp), %rcx
movzbl (%rax,%rcx), %eax
movzbl 0x27(%rsp), %ecx
sarl %cl, %eax
movzbl 0x17(%rsp), %ecx
andl %ecx, %eax
movb %al, %dl
movq 0x38(%rsp), %rax
movslq 0x10(%rsp), %rcx
movb %dl, (%rax,%rcx)
movzbl 0x4f(%rsp), %ecx
movzbl 0x27(%rsp), %eax
addl %ecx, %eax
movb %al, 0x27(%rsp)
movzbl 0x27(%rsp), %eax
cmpl $0x8, %eax
jne 0x7f53
movq 0x18(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x18(%rsp)
movb $0x0, 0x27(%rsp)
jmp 0x8002
movb $0x0, 0xf(%rsp)
movzbl 0x27(%rsp), %ecx
movl $0x8, %eax
subl %ecx, %eax
movb %al, 0xe(%rsp)
movq 0x28(%rsp), %rax
movq 0x18(%rsp), %rcx
movzbl (%rax,%rcx), %eax
movzbl 0x27(%rsp), %ecx
sarl %cl, %eax
movl %eax, %ecx
movzbl 0xf(%rsp), %eax
addl %ecx, %eax
movb %al, 0xf(%rsp)
movq 0x18(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x18(%rsp)
movzbl 0x4f(%rsp), %eax
movzbl 0xe(%rsp), %ecx
subl %ecx, %eax
movb %al, 0xd(%rsp)
movzbl 0xd(%rsp), %ecx
movl $0x1, %eax
shll %cl, %eax
subl $0x1, %eax
movb %al, 0xc(%rsp)
movq 0x28(%rsp), %rax
movq 0x18(%rsp), %rcx
movzbl (%rax,%rcx), %eax
movzbl 0xc(%rsp), %ecx
andl %ecx, %eax
movzbl 0xe(%rsp), %ecx
shll %cl, %eax
movl %eax, %ecx
movzbl 0xf(%rsp), %eax
addl %ecx, %eax
movb %al, 0xf(%rsp)
movb 0xf(%rsp), %dl
movq 0x38(%rsp), %rax
movslq 0x10(%rsp), %rcx
movb %dl, (%rax,%rcx)
movb 0xd(%rsp), %al
movb %al, 0x27(%rsp)
jmp 0x8004
movl 0x10(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10(%rsp)
jmp 0x7eda
movq 0x28(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x802c
movq (%rsp), %rdi
callq 0x3370
addq $0x58, %rsp
retq
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)