// File: /workspace/github_cpp_makefile_star2_O3/cybozu[P]yrmcds/src/counter/counter.cpp
// Function: yrmcds::counter::request::parse(char const*, unsigned long)
void request::parse(const char* p, std::size_t len) noexcept {
    if( len < HEADER_SIZE ) return;  // incomplete
    std::uint32_t body_length;
    cybozu::ntoh(p + 4, body_length);
    if( len < HEADER_SIZE + body_length ) return;  // incomplete

    m_command = (counter::command)*(const uint8_t*)(p + 1);
    m_flags = *(const uint8_t*)(p + 2);
    m_body_length = body_length;
    m_opaque = p + 8;

    m_request_length = HEADER_SIZE + body_length;
    const char* body = p + HEADER_SIZE;
    std::uint16_t name_len;

    if( *(const std::uint8_t*)p != REQUEST_MAGIC )
        return;  // invalid

    switch( m_command ) {
    case counter::command::Noop:
    case counter::command::Stats:
    case counter::command::Dump:
        // no body
        break;

    case counter::command::Get:
        if( body_length < 2 )
            return;     // invalid
        cybozu::ntoh(body, name_len);
        if( name_len == 0 || 2U + name_len > body_length )
            return;     // invalid
        m_name.len = name_len;
        m_name.p = body + 2;
        break;

    case counter::command::Acquire:
        if( body_length < 10 )
            return;     // invalid
        cybozu::ntoh(body, m_resources);
        if( m_resources == 0 )
            return;     // invalid
        cybozu::ntoh(body + 4, m_maximum);
        if( m_maximum < m_resources )
            return;
        cybozu::ntoh(body + 8, name_len);
        if( name_len == 0 || 10U + name_len > body_length )
            return;     // invalid
        m_name.len = name_len;
        m_name.p = body + 10;
        break;

    case counter::command::Release:
        if( body_length < 6 )
            return;     // invalid
        cybozu::ntoh(body, m_resources);
        cybozu::ntoh(body + 4, name_len);
        if( name_len == 0 || 6U + name_len > body_length )
            return;     // invalid
        m_name.len = name_len;
        m_name.p = body + 6;
        break;

    default:
        m_command = counter::command::Unknown;
        m_status = counter::status::UnknownCommand;
        return;
    }

    m_status = counter::status::OK;
}

// Assembly:
cmpq $0xc, %rdx
jb 0x21b9a
movl 0x4(%rsi), %eax
bswapl %eax
leaq 0xc(%rax), %rcx
cmpq %rdx, %rcx
ja 0x21b9a
movzbl 0x1(%rsi), %edx
movb %dl, 0x8(%rdi)
movb 0x2(%rsi), %r8b
movb %r8b, 0x9(%rdi)
movl %eax, 0xc(%rdi)
leaq 0x8(%rsi), %r8
movq %r8, 0x10(%rdi)
movq %rcx, (%rdi)
cmpb $-0x70, (%rsi)
jne 0x21b9a
xorl %ecx, %ecx
cmpl $0x3, %edx
ja 0x21b10
movl %edx, %edx
leaq 0x14de2(%rip), %r8      # 0x368c0
movslq (%r8,%rdx,4), %rdx
addq %r8, %rdx
jmpq *%rdx
cmpl $0x2, %eax
jb 0x21b9a
movzwl 0xc(%rsi), %ecx
testw %cx, %cx
je 0x21b9a
rolw $0x8, %cx
movzwl %cx, %r8d
addl $0x2, %r8d
movl $0xe, %edx
jmp 0x21b82
addl $-0x10, %edx
cmpl $0x2, %edx
jb 0x21b97
movb $0x12, 0x8(%rdi)
movb $-0x7f, %cl
jmp 0x21b97
cmpl $0xa, %eax
jb 0x21b9a
movl 0xc(%rsi), %edx
movl %edx, %ecx
bswapl %ecx
movl %ecx, 0x18(%rdi)
testl %edx, %edx
je 0x21b9a
movl 0x10(%rsi), %edx
bswapl %edx
movl %edx, 0x1c(%rdi)
cmpl %ecx, %edx
jb 0x21b9a
movzwl 0x14(%rsi), %ecx
testw %cx, %cx
je 0x21b9a
rolw $0x8, %cx
movzwl %cx, %r8d
addl $0xa, %r8d
movl $0x16, %edx
jmp 0x21b82
cmpl $0x6, %eax
jb 0x21b9a
movl 0xc(%rsi), %ecx
bswapl %ecx
movl %ecx, 0x18(%rdi)
movzwl 0x10(%rsi), %ecx
testw %cx, %cx
je 0x21b9a
rolw $0x8, %cx
movzwl %cx, %r8d
addl $0x6, %r8d
movl $0x12, %edx
cmpl %eax, %r8d
ja 0x21b9a
movzwl %cx, %eax
movq %rax, 0x28(%rdi)
addq %rdx, %rsi
movq %rsi, 0x20(%rdi)
xorl %ecx, %ecx
movb %cl, 0x30(%rdi)
retq
nop