// File: /workspace/github_c_makefile_star2_O3/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, -0x50(%rbp)
movq %rcx, -0x58(%rbp)
movq %rsi, -0x48(%rbp)
leaq 0x18(%rdi), %rax
movq %rax, -0x60(%rbp)
movq %rdi, -0x40(%rbp)
movq 0x18(%rdi), %r14
testq %r14, %r14
movq %rdx, -0x38(%rbp)
je 0x31cd
xorl %ebx, %ebx
movq %rdx, %r12
movq 0x20(%r14), %r13
movq 0x8(%r14), %r15
movq 0x10(%r14), %rax
subq %rax, %r15
cmpq %r12, %r15
cmovaeq %r12, %r15
movq -0x48(%rbp), %rcx
leaq (%rcx,%rbx), %rdi
leaq (%r14,%rax), %rsi
addq $0x28, %rsi
movq %r15, %rdx
callq 0x10b0
subq %r15, %r12
addq %r15, %rbx
addq 0x10(%r14), %r15
movq %r15, 0x10(%r14)
cmpq 0x8(%r14), %r15
jne 0x31c3
movq %r14, %rdi
callq 0x1030
movq -0x60(%rbp), %rax
movq %r13, (%rax)
movq %r13, %r14
testq %r13, %r13
jne 0x3168
jmp 0x31d1
movq %r13, %r14
testq %r13, %r13
jne 0x3168
jmp 0x31dd
xorl %ebx, %ebx
jmp 0x31dd
movq -0x40(%rbp), %rax
movq $0x0, 0x20(%rax)
movq -0x38(%rbp), %r13
subq %rbx, %r13
je 0x3418
movq %rsp, %r14
movq %rsp, %r12
addq $-0x2040, %r12          # imm = 0xDFC0
movq %r12, %rsp
movl $0x2040, %edx           # imm = 0x2040
movq -0x50(%rbp), %rdi
movq %r12, %rsi
callq *-0x58(%rbp)
movq %rax, %r15
testq %rax, %rax
jle 0x3412
movq -0x40(%rbp), %rdx
movq 0x8(%rdx), %rax
leaq 0x468(%rip), %rcx       # 0x368c
movq %rcx, -0xa8(%rbp)
leaq 0x4d2(%rip), %rcx       # 0x3704
movq %rcx, -0xa0(%rbp)
movq %rax, -0x98(%rbp)
movq %r12, -0x88(%rbp)
movq %r15, -0x80(%rbp)
movq $0x0, -0x90(%rbp)
movl $0x8, -0x2c(%rbp)
cmpb $0x0, 0x28(%rdx)
movq (%rdx), %rdi
leaq -0x150(%rbp), %rsi
leaq -0x2c(%rbp), %rdx
leaq -0x68(%rbp), %rcx
leaq -0xa8(%rbp), %r8
je 0x3283
callq 0x1d0e
jmp 0x3288
callq 0x281f
cmpl $-0x1, %eax
je 0x340b
movq %r15, -0x50(%rbp)
movq %r14, -0x58(%rbp)
movq -0x40(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x38(%rbp)
movl -0x2c(%rbp), %eax
leaq 0x2c2(%rip), %rcx       # 0x3571
leaq -0xd0(%rbp), %r14
movq %rcx, (%r14)
leaq 0x308(%rip), %rcx       # 0x35c8
movq %rcx, 0x8(%r14)
leaq -0x150(%rbp), %rcx
movq %rcx, 0x10(%r14)
movl %eax, 0x18(%r14)
movl $0x0, 0x1c(%r14)
movq $0x0, 0x20(%r14)
movl -0xb4(%rbp), %eax
cmpl -0xb8(%rbp), %eax
je 0x3320
leaq -0x78(%rbp), %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x2f5b
movq -0x48(%rbp), %rax
leaq (%rax,%rbx), %rdi
movq -0x78(%rbp), %rsi
movq -0x70(%rbp), %r15
movq %r15, %rdx
callq 0x10b0
addq %r15, %rbx
subq %r15, %r13
jne 0x32e3
movq %r12, -0x48(%rbp)
leaq -0x78(%rbp), %r14
leaq -0xd0(%rbp), %r12
movl -0xb4(%rbp), %eax
cmpl -0xb8(%rbp), %eax
je 0x3365
movq %r14, %rdi
movq %r12, %rsi
movq $-0x1, %rdx
callq 0x2f5b
movq -0x78(%rbp), %rsi
movq -0x70(%rbp), %rdx
movq -0x60(%rbp), %rdi
callq 0x342a
cmpl $-0x1, %eax
jne 0x332f
movq -0x68(%rbp), %r14
movq -0x38(%rbp), %rax
movq (%rax), %rdi
testq %rdi, %rdi
sete %al
testq %r14, %r14
sete %cl
orb %al, %cl
movq -0x40(%rbp), %r13
jne 0x33d2
movq 0x8(%rdi), %rax
movq 0x10(%rdi), %rcx
movq %rax, %r12
subq %rcx, %r12
cmpq %r12, %r14
cmovbq %r14, %r12
movq 0x20(%rdi), %r15
addq %r12, %rcx
movq %rcx, 0x10(%rdi)
cmpq %rax, %rcx
jne 0x33c2
movq -0x38(%rbp), %rax
movq %r15, (%rax)
testq %r15, %r15
jne 0x33bd
movq $0x0, 0x10(%r13)
callq 0x1030
subq %r12, %r14
testq %r15, %r15
je 0x33d2
movq %r15, %rdi
testq %r14, %r14
jne 0x3384
movq -0x50(%rbp), %rdx
subq %r14, %rdx
jbe 0x33eb
movq -0x48(%rbp), %rsi
addq %r14, %rsi
movq -0x38(%rbp), %rdi
callq 0x342a
testq %rbx, %rbx
jne 0x3402
callq 0x1050
movl $0xb, (%rax)
movq $-0x1, %rbx
movq %rbx, %r15
movq -0x58(%rbp), %r14
jmp 0x3412
movq $-0x1, %r15
movq %r14, %rsp
movq %r15, %rbx
movq %rbx, %rax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq