user: 请将这段汇编代码片段转换成等效的C代码：

```asm
<protobuf_parse>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x50,%rsp
  mov    %rdi,-0x38(%rbp)
  mov    %rsi,-0x40(%rbp)
  mov    %edx,-0x44(%rbp)
  mov    %rcx,-0x50(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  movl   $0x0,-0x28(%rbp)
  movl   $0x0,-0x24(%rbp)
  movq   $0x0,-0x18(%rbp)
  lea    -0x28(%rbp),%rdx
  mov    -0x44(%rbp),%ecx
  mov    -0x40(%rbp),%rax
  mov    %ecx,%esi
  mov    %rax,%rdi
  call   <protobuf_read_varint@plt>
  mov    %rax,-0x10(%rbp)
  cmpq   $0x0,-0x10(%rbp)
  sete   %al
  movzbl %al,%eax
  mov    $0x0,%esi
  mov    %eax,%edi
  call   <__builtin_expect@plt>
  test   %rax,%rax
  je     L216
  mov    $0xffffffff,%eax
  jmp    L98
L216:
  mov    -0x28(%rbp),%eax
  and    $0x7,%eax
  mov    %eax,-0x20(%rbp)
  mov    -0x28(%rbp),%eax
  sar    $0x3,%eax
  mov    %eax,-0x1c(%rbp)
  mov    -0x44(%rbp),%edx
  mov    -0x10(%rbp),%rax
  sub    -0x40(%rbp),%rax
  mov    %eax,%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  mov    %eax,-0x44(%rbp)
  cmpl   $0x5,-0x20(%rbp)
  je     L49
  cmpl   $0x5,-0x20(%rbp)
  jg     L109
  cmpl   $0x2,-0x20(%rbp)
  je     L219
  cmpl   $0x2,-0x20(%rbp)
  jg     L109
  cmpl   $0x0,-0x20(%rbp)
  je     L24
  cmpl   $0x1,-0x20(%rbp)
  je     L36
  jmp    L109
L24:
  lea    -0x24(%rbp),%rdx
  mov    -0x44(%rbp),%ecx
  mov    -0x10(%rbp),%rax
  mov    %ecx,%esi
  mov    %rax,%rdi
  call   <protobuf_read_varint@plt>
  mov    %rax,-0x10(%rbp)
  cmpq   $0x0,-0x10(%rbp)
  sete   %al
  movzbl %al,%eax
  mov    $0x0,%esi
  mov    %eax,%edi
  call   <__builtin_expect@plt>
  test   %rax,%rax
  je     L171
  mov    $0xffffffff,%eax
  jmp    L98
L36:
  mov    -0x44(%rbp),%eax
  cmp    $0x3,%eax
  setbe  %al
  movzbl %al,%eax
  mov    $0x0,%esi
  mov    %eax,%edi
  call   <__builtin_expect@plt>
  test   %rax,%rax
  je     L230
  mov    $0xffffffff,%eax
  jmp    L98
L230:
  mov    -0x10(%rbp),%rax
  mov    (%rax),%eax
  mov    %eax,-0x24(%rbp)
  addq   $0x4,-0x10(%rbp)
  jmp    L12
L219:
  lea    -0x24(%rbp),%rdx
  mov    -0x44(%rbp),%ecx
  mov    -0x10(%rbp),%rax
  mov    %ecx,%esi
  mov    %rax,%rdi
  call   <protobuf_read_varint@plt>
  mov    %rax,-0x10(%rbp)
  cmpq   $0x0,-0x10(%rbp)
  sete   %al
  movzbl %al,%eax
  mov    $0x0,%esi
  mov    %eax,%edi
  call   <__builtin_expect@plt>
  test   %rax,%rax
  je     L229
  mov    $0xffffffff,%eax
  jmp    L98
L229:
  mov    -0x10(%rbp),%rax
  mov    %rax,-0x18(%rbp)
  mov    -0x24(%rbp),%eax
  cltq
  add    %rax,-0x10(%rbp)
  jmp    L12
L49:
  mov    -0x44(%rbp),%eax
  cmp    $0x3,%eax
  setbe  %al
  movzbl %al,%eax
  mov    $0x0,%esi
  mov    %eax,%edi
  call   <__builtin_expect@plt>
  test   %rax,%rax
  je     L115
  mov    $0xffffffff,%eax
  jmp    L98
L115:
  mov    -0x10(%rbp),%rax
  mov    (%rax),%eax
  mov    %eax,-0x24(%rbp)
  addq   $0x4,-0x10(%rbp)
  jmp    L12
L109:
  mov    $0xffffffff,%eax
  jmp    L98
L171:
  nop
L12:
  mov    -0x24(%rbp),%ecx
  mov    -0x18(%rbp),%rdi
  mov    -0x20(%rbp),%edx
  mov    -0x1c(%rbp),%esi
  mov    -0x38(%rbp),%rax
  mov    -0x50(%rbp),%r9
  mov    %rdi,%r8
  mov    %rax,%rdi
  call   *%r9
  cmp    $0x1,%eax
  sete   %al
  movzbl %al,%eax
  mov    $0x1,%esi
  mov    %eax,%edi
  call   <__builtin_expect@plt>
  test   %rax,%rax
  je     L199
  mov    -0x10(%rbp),%rax
  sub    -0x40(%rbp),%rax
  jmp    L98
L199:
  mov    $0xffffffff,%eax
L98:
  mov    -0x8(%rbp),%rdx
  sub    %fs:0x28,%rdx
  je     L174
  call   <__stack_chk_fail@plt>
L174:
  leave
  ret
```

assistant: ```c
int protobuf_parse(void *param, const char *restrict buf, int size, bool (*cb)(void *param, int field, int wire_type, uint64_t value, const char *restrict extra)) {
  uint64_t key = 0;
  uint64_t value = 0;
  const char *extra = NULL;
  const char *p = protobuf_read_varint(buf, size, &key);
  if (__builtin_expect(!!(p == NULL), 0)) {
    return -1;
  }
  int wire_type = key & 0x07;
  int field = key >> 3;
  size -= (p - buf);
  switch (wire_type) {
  case 0:
    p = protobuf_read_varint(p, size, &value);
    if (__builtin_expect(!!(p == NULL), 0)) {
      return -1;
    };
    break;
  case 1:
    if (__builtin_expect(!!(size < sizeof(uint64_t)), 0)) {
      return -1;
    }
    value = *(uint64_t *)p;
    p += sizeof(uint64_t);
    ;
    break;
  case 2:
    p = protobuf_read_varint(p, size, &value);
    if (__builtin_expect(!!(p == NULL), 0)) {
      return -1;
    };
    extra = p;
    p += value;
    break;
  case 5:
    if (__builtin_expect(!!(size < sizeof(uint32_t)), 0)) {
      return -1;
    }
    value = *(uint32_t *)p;
    p += sizeof(uint32_t);
    ;
    break;
  default:
    return -1;
  }
  return (__builtin_expect(!!(cb(param, field, wire_type, value, extra) == true), 1)) ? p - buf : -1;
}
```