// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string.h>

#include <ldmsg/ldmsg.h>

static_assert(sizeof(ldmsg_req_t) == 1024, "Loader service requests can be at most 1024 bytes.");

static uint64_t FidlAlign(uint32_t offset) {
  const uint64_t alignment_mask = FIDL_ALIGNMENT - 1;
  return (offset + alignment_mask) & ~alignment_mask;
}

zx_status_t ldmsg_req_encode(ldmsg_req_t* req, size_t* req_len_out, const char* data, size_t len) {
  size_t offset = 0;
  switch (req->header.ordinal) {
    case LDMSG_OP_DONE:
      *req_len_out = sizeof(fidl_message_header_t);
      return ZX_OK;
    case LDMSG_OP_CLONE:
      *req_len_out = sizeof(fidl_message_header_t) + sizeof(ldmsg_clone_t);
      req->clone.object = FIDL_HANDLE_PRESENT;
      return ZX_OK;
    case LDMSG_OP_LOAD_OBJECT:
    case LDMSG_OP_CONFIG:
      offset = sizeof(fidl_string_t);
      break;
    default:
      return ZX_ERR_INVALID_ARGS;
  }

  // Reserve one byte for the null terminator on the receiving side.
  if (LDMSG_MAX_PAYLOAD - offset - 1 < len)
    return ZX_ERR_OUT_OF_RANGE;

  req->common.string.size = len;
  req->common.string.data = (char*)FIDL_ALLOC_PRESENT;
  memcpy(req->data + offset, data, len);

  // Make sure to zero out the extra bytes required by alignment constraints.
  size_t req_len_unaligned = sizeof(fidl_message_header_t) + offset + len;
  *req_len_out = FidlAlign(req_len_unaligned);
  memset((char*)req + req_len_unaligned, 0, *req_len_out - req_len_unaligned);
  return ZX_OK;
}

zx_status_t ldmsg_req_decode(ldmsg_req_t* req, size_t req_len, const char** data_out,
                             size_t* len_out) {
  size_t offset = 0;
  switch (req->header.ordinal) {
    case LDMSG_OP_DONE:
      if (req_len != sizeof(fidl_message_header_t))
        return ZX_ERR_INVALID_ARGS;
      *data_out = 0;
      *len_out = 0;
      return ZX_OK;
    case LDMSG_OP_CLONE:
      if (req_len != sizeof(fidl_message_header_t) + sizeof(ldmsg_clone_t) ||
          req->clone.object != FIDL_HANDLE_PRESENT)
        return ZX_ERR_INVALID_ARGS;
      *data_out = 0;
      *len_out = 0;
      return ZX_OK;
    case LDMSG_OP_LOAD_OBJECT:
    case LDMSG_OP_CONFIG:
      if ((uintptr_t)req->common.string.data != FIDL_ALLOC_PRESENT)
        return ZX_ERR_INVALID_ARGS;
      offset = sizeof(fidl_string_t);
      break;
    default:
      return ZX_ERR_INVALID_ARGS;
  }

  size_t size = req->common.string.size;
  if (LDMSG_MAX_PAYLOAD - offset - 1 < size ||
      req_len != FidlAlign(sizeof(fidl_message_header_t) + offset + size))
    return ZX_ERR_INVALID_ARGS;

  // Null terminate the string. The message isn't required to have a null
  // terminated string, but we have enough space in our buffer for the null
  // terminator and adding it makes life easier for our caller.
  req->data[offset + size] = '\0';

  *data_out = req->data + offset;
  *len_out = size;
  return ZX_OK;
}

size_t ldmsg_rsp_get_size(ldmsg_rsp_t* rsp) {
  switch (rsp->header.ordinal) {
    case LDMSG_OP_LOAD_OBJECT:
    case LDMSG_OP_CONFIG:
    case LDMSG_OP_CLONE:
      return sizeof(ldmsg_rsp_t);
    case LDMSG_OP_DONE:
    default:
      return 0;
  }
}
