// File: williewillus[P]panda_scratchpad/src/wrapper/DiskMod.cpp
// Function: wrapper::DiskMod::Serialize(wrapper::DiskMod&, unsigned long long*)
shared_ptr<char> DiskMod::Serialize(DiskMod &dm, unsigned long long *size) {
  // Standard code to serialize the front part of the DiskMod.
  // Get a block large enough for this DiskMod.
  const uint64_t mod_size = dm.GetSerializeSize();
  if (size != nullptr) {
    *size = mod_size;
  }
  // TODO(ashmrtn): May want to split this if it is very large.
  shared_ptr<char> res_ptr(new (std::nothrow) char[mod_size],
      [](char *c) {delete[] c;});
  char *buf = res_ptr.get();
  if (buf == nullptr) {
    return res_ptr;
  }

  const uint64_t mod_size_be = htobe64(mod_size);
  memcpy(buf, &mod_size_be, sizeof(uint64_t));
  unsigned int buf_offset = sizeof(uint64_t);

  int res = SerializeHeader(buf, buf_offset, dm);
  if (res < 0) {
    return shared_ptr<char>(nullptr);
  }
  buf_offset += res;

  // kCheckpointMod and kSyncMod don't need anything done after the type.
  if (!(dm.mod_type == DiskMod::kCheckpointMod ||
      dm.mod_type == DiskMod::kSyncMod)) {
    res = SerializeChangeHeader(buf, buf_offset, dm);
    if (res < 0) {
      return shared_ptr<char>(nullptr);
    }

    if (dm.mod_type == DiskMod::kFsyncMod ||
        dm.mod_type == DiskMod::kCreateMod) {
      return res_ptr;
    }

    buf_offset += res;
    if (dm.directory_mod) {
      // We changed a directory, only put that down.
      res = SerializeDirectoryMod(buf, buf_offset, dm);
      if (res < 0) {
        return shared_ptr<char>(nullptr);
      }
      buf_offset += res;
    } else {
      // TODO(ashmrtn): *Technically* fallocate and friends can be called on a
      // directory file descriptor. The current code will not play well with
      // that.
      // We changed a file, only put that down.
      res = SerializeDataRange(buf, buf_offset, dm);
      if (res < 0) {
        return shared_ptr<char>(nullptr);
      }
      buf_offset += res;
    }
  }

  return res_ptr;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x78(%rbp)
movq %rdi, %rax
movq %rax, -0x70(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x10(%rbp), %rdi
callq 0xdb10
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0xdca1
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x20(%rbp), %rdi
movq 0x272dc(%rip), %rsi     # 0x34f88
callq 0x6810
movq %rax, %rsi
leaq -0x30(%rbp), %rdi
callq 0xdee0
leaq -0x30(%rbp), %rdi
callq 0xf430
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0xdcea
movq -0x78(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0xf450
movl $0x1, -0x44(%rbp)
jmp 0xdeb9
movq -0x20(%rbp), %rdi
callq 0xdf10
movq %rax, -0x80(%rbp)
jmp 0xdcf9
movq -0x80(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x40(%rbp), %rax
movq -0x50(%rbp), %rcx
movq %rcx, (%rax)
movl $0x8, -0x60(%rbp)
movq -0x40(%rbp), %rdi
movl -0x60(%rbp), %esi
movq -0x10(%rbp), %rdx
callq 0xdfc0
movl %eax, -0x84(%rbp)
jmp 0xdd2b
movl -0x84(%rbp), %eax
movl %eax, -0x64(%rbp)
cmpl $0x0, -0x64(%rbp)
jge 0xdd6d
movq -0x78(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xf480
movl $0x1, -0x44(%rbp)
jmp 0xdeb9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x30(%rbp), %rdi
callq 0xbfa0
jmp 0xdecf
movl -0x64(%rbp), %eax
addl -0x60(%rbp), %eax
movl %eax, -0x60(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x6, 0x20(%rax)
je 0xdea5
movq -0x10(%rbp), %rax
cmpl $0x8, 0x20(%rax)
je 0xdea5
movq -0x40(%rbp), %rdi
movl -0x60(%rbp), %esi
movq -0x10(%rbp), %rdx
callq 0xe040
movl %eax, -0x88(%rbp)
jmp 0xddaa
movl -0x88(%rbp), %eax
movl %eax, -0x64(%rbp)
cmpl $0x0, -0x64(%rbp)
jge 0xddd2
movq -0x78(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xf480
movl $0x1, -0x44(%rbp)
jmp 0xdeb9
movq -0x10(%rbp), %rax
cmpl $0x7, 0x20(%rax)
je 0xdde6
movq -0x10(%rbp), %rax
cmpl $0x0, 0x20(%rax)
jne 0xddff
movq -0x78(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0xf450
movl $0x1, -0x44(%rbp)
jmp 0xdeb9
movl -0x64(%rbp), %eax
addl -0x60(%rbp), %eax
movl %eax, -0x60(%rbp)
movq -0x10(%rbp), %rax
testb $0x1, 0xb8(%rax)
je 0xde5d
movq -0x40(%rbp), %rdi
movl -0x60(%rbp), %esi
movq -0x10(%rbp), %rdx
callq 0xe0d0
movl %eax, -0x8c(%rbp)
jmp 0xde2d
movl -0x8c(%rbp), %eax
movl %eax, -0x64(%rbp)
cmpl $0x0, -0x64(%rbp)
jge 0xde52
movq -0x78(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xf480
movl $0x1, -0x44(%rbp)
jmp 0xdeb9
movl -0x64(%rbp), %eax
addl -0x60(%rbp), %eax
movl %eax, -0x60(%rbp)
jmp 0xdea3
movq -0x40(%rbp), %rdi
movl -0x60(%rbp), %esi
movq -0x10(%rbp), %rdx
callq 0xe110
movl %eax, -0x90(%rbp)
jmp 0xde75
movl -0x90(%rbp), %eax
movl %eax, -0x64(%rbp)
cmpl $0x0, -0x64(%rbp)
jge 0xde9a
movq -0x78(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xf480
movl $0x1, -0x44(%rbp)
jmp 0xdeb9
movl -0x64(%rbp), %eax
addl -0x60(%rbp), %eax
movl %eax, -0x60(%rbp)
jmp 0xdea5
movq -0x78(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0xf450
movl $0x1, -0x44(%rbp)
leaq -0x30(%rbp), %rdi
callq 0xbfa0
movq -0x70(%rbp), %rax
addq $0x90, %rsp
popq %rbp
retq
movq -0x58(%rbp), %rdi
callq 0x68a0
nopl (%rax,%rax)