// File: /workspace/github_c_makefile_star2_O2/agl[P]obstcp/libobstcp.c
// Function: obstcp_rbuf_read
ssize_t EXPORTED
obstcp_rbuf_read(struct obstcp_rbuf *rbuf, uint8_t *buffer, size_t len,
                 ssize_t (*read) (void *ctx, uint8_t *buffer, size_t len),
                 void *ctx) {

  size_t copied = varbuf_copy_out(buffer, len, &rbuf->out);
  len -= copied;
  off_t j = copied;

  if (!len)
    return j;

  static const size_t rbuflen = OBSTCP_MAX_FRAME + OBSTCP_MAX_PREFIX;
  uint8_t rbuffer[rbuflen];

  const ssize_t n = read(ctx, rbuffer, rbuflen);
  if (n < 1)
    return n;

  struct varbuf_cursor inc;
  varbuf_cursor_init(&inc, &rbuf->in, rbuffer, n);

  size_t consumed;
  struct iovec outiov[8];
  unsigned outlen = 8;

  if (rbuf->is_server) {
    if (obstcp_server_read((struct obstcp_server_ctx *) rbuf->ctx,
                           outiov, &outlen, &consumed,
                           (struct obstcp_cursor *) &inc) == -1)
      return -1;
  } else {
    if (obstcp_client_read((struct obstcp_client_ctx *) rbuf->ctx,
                           outiov, &outlen, &consumed,
                           (struct obstcp_cursor *) &inc) == -1)
      return -1;
  }

  // Walk the output iovec and copy into the output buffer
  struct iovec_cursor outc;
  iovec_cursor_init(&outc, outiov, outlen);

  while (len && !iovec_cursor_full(&outc)) {
    struct iovec iov;
    iovec_cursor_get(&iov, &outc, len);
    memcpy(buffer + j, iov.iov_base, iov.iov_len);
    j += iov.iov_len;
    len -= iov.iov_len;
  }

  // Buffer any remaining output
  if (!varbuf_copy_iovec_cursor(&rbuf->out, &outc) == -1)
    return -1;

  // Discard all buffered input that was consumed
  const size_t remaining = varbuf_discard(&rbuf->in, consumed);

  if (remaining < n) {
    // Not all of @buffer was consumed
    varbuf_copy_in(&rbuf->in, rbuffer + remaining, n - remaining);
  }

  if (!j) {
    errno = EAGAIN;
    return -1;
  }

  return j;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x128, %rsp            # imm = 0x128
movq %r8, -0x48(%rbp)
movq %rcx, -0x50(%rbp)
movq %rdx, %r13
movq %rsi, -0x40(%rbp)
leaq 0x18(%rdi), %rax
movq %rax, -0x60(%rbp)
movq %rdi, -0x38(%rbp)
movq 0x18(%rdi), %r12
xorl %ebx, %ebx
movq %rdx, -0x58(%rbp)
testq %r12, %r12
je 0x2f26
movq %r12, %r14
movq 0x20(%r12), %r12
movq 0x8(%r14), %r15
movq 0x10(%r14), %rax
subq %rax, %r15
cmpq %r13, %r15
cmovaeq %r13, %r15
movq -0x40(%rbp), %rcx
leaq (%rcx,%rbx), %rdi
leaq (%r14,%rax), %rsi
addq $0x28, %rsi
movq %r15, %rdx
callq 0x10b0
subq %r15, %r13
addq %r15, %rbx
addq 0x10(%r14), %r15
movq %r15, 0x10(%r14)
cmpq 0x8(%r14), %r15
jne 0x2ebc
movq %r14, %rdi
callq 0x1030
movq -0x60(%rbp), %rax
movq %r12, (%rax)
testq %r12, %r12
jne 0x2ebc
movq -0x38(%rbp), %rax
andq $0x0, 0x20(%rax)
jmp 0x2ebc
movq -0x58(%rbp), %r15
subq %rbx, %r15
je 0x3147
movq %rsp, %r14
movq %rsp, %r12
addq $-0x2040, %r12          # imm = 0xDFC0
movq %r12, %rsp
movl $0x2040, %edx           # imm = 0x2040
movq -0x48(%rbp), %rdi
movq %r12, %rsi
callq *-0x50(%rbp)
movq %rax, %r13
testq %rax, %rax
jle 0x3141
movq %r14, -0x58(%rbp)
leaq 0x4d4(%rip), %rax       # 0x343d
movq %rax, -0xa8(%rbp)
leaq 0x53a(%rip), %rax       # 0x34b1
movq %rax, -0xa0(%rbp)
movq -0x38(%rbp), %rcx
movq 0x8(%rcx), %rax
movq %rax, -0x98(%rbp)
movq %r12, -0x88(%rbp)
movq %r13, -0x80(%rbp)
andq $0x0, -0x90(%rbp)
movl $0x8, -0x2c(%rbp)
cmpb $0x0, 0x28(%rcx)
movq (%rcx), %rdi
pushq $-0x1
popq %r14
leaq -0x150(%rbp), %rsi
leaq -0x2c(%rbp), %rdx
leaq -0x68(%rbp), %rcx
leaq -0xa8(%rbp), %r8
je 0x2fd1
callq 0x1cea
jmp 0x2fd6
callq 0x274a
cmpl $-0x1, %eax
je 0x313a
movq %r13, -0x50(%rbp)
movq -0x38(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x48(%rbp)
movl -0x2c(%rbp), %eax
leaq 0x329(%rip), %rcx       # 0x3322
leaq -0xd0(%rbp), %rdx
movq %rcx, (%rdx)
leaq 0x36a(%rip), %rcx       # 0x3374
movq %rcx, 0x8(%rdx)
leaq -0x150(%rbp), %rcx
movq %rcx, 0x10(%rdx)
movl %eax, 0x18(%rdx)
andl $0x0, 0x1c(%rdx)
movq %rdx, %r13
andq $0x0, 0x20(%rdx)
testq %r15, %r15
je 0x306a
movl -0xb4(%rbp), %eax
cmpl -0xb8(%rbp), %eax
je 0x306a
leaq -0x78(%rbp), %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x2cd9
movq -0x40(%rbp), %rax
leaq (%rax,%rbx), %rdi
movq -0x78(%rbp), %rsi
movq -0x70(%rbp), %r14
movq %r14, %rdx
callq 0x10b0
addq %r14, %rbx
subq %r14, %r15
jmp 0x3028
movq %r12, -0x40(%rbp)
leaq -0x78(%rbp), %r14
leaq -0xd0(%rbp), %r13
pushq $-0x1
popq %r12
movl -0xb4(%rbp), %eax
cmpl -0xb8(%rbp), %eax
je 0x30af
movq %r14, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0x2cd9
movq -0x78(%rbp), %rsi
movq -0x70(%rbp), %rdx
movq -0x60(%rbp), %rdi
callq 0x3159
cmpl $-0x1, %eax
jne 0x307d
movq -0x68(%rbp), %r14
movq -0x38(%rbp), %rax
movq 0x8(%rax), %r13
movq -0x48(%rbp), %r15
testq %r13, %r13
je 0x310c
testq %r14, %r14
je 0x310c
movq %r13, %rdi
movq 0x20(%r13), %r13
movq 0x8(%rdi), %rax
movq 0x10(%rdi), %rcx
movq %rax, %rdx
subq %rcx, %rdx
cmpq %rdx, %r14
cmovbq %r14, %rdx
addq %rdx, %rcx
movq %rcx, 0x10(%rdi)
subq %rdx, %r14
cmpq %rax, %rcx
jne 0x30bf
movq %r13, (%r15)
testq %r13, %r13
jne 0x3105
movq -0x38(%rbp), %rax
andq $0x0, 0x10(%rax)
callq 0x1030
jmp 0x30bf
movq -0x50(%rbp), %rdx
subq %r14, %rdx
jbe 0x3124
movq -0x40(%rbp), %rsi
addq %r14, %rsi
movq %r15, %rdi
callq 0x3159
testq %rbx, %rbx
jne 0x3137
callq 0x1050
movl $0xb, (%rax)
movq %r12, %rbx
movq %rbx, %r14
movq %r14, %r13
movq -0x58(%rbp), %r14
movq %r14, %rsp
movq %r13, %rbx
movq %rbx, %rax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq