// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "dice/cbor_writer.h"

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

enum CborType {
  CBOR_TYPE_UINT = 0,
  CBOR_TYPE_NINT = 1,
  CBOR_TYPE_BSTR = 2,
  CBOR_TYPE_TSTR = 3,
  CBOR_TYPE_ARRAY = 4,
  CBOR_TYPE_MAP = 5,
  // Type 6, tags, are not supported.
  CBOR_TYPE_SIMPLE = 7,
};

static bool CborWriteWouldOverflowCursor(size_t size, struct CborOut* out) {
  return size > SIZE_MAX - out->cursor;
}

static bool CborWriteFitsInBuffer(size_t size, struct CborOut* out) {
  return out->cursor <= out->buffer_size &&
         size <= out->buffer_size - out->cursor;
}

static void CborWriteType(enum CborType type, uint64_t val,
                          struct CborOut* out) {
  size_t size;
  if (val <= 23) {
    size = 1;
  } else if (val <= 0xff) {
    size = 2;
  } else if (val <= 0xffff) {
    size = 3;
  } else if (val <= 0xffffffff) {
    size = 5;
  } else {
    size = 9;
  }
  if (CborWriteWouldOverflowCursor(size, out)) {
    out->cursor = SIZE_MAX;
    return;
  }
  if (CborWriteFitsInBuffer(size, out)) {
    if (size == 1) {
      out->buffer[out->cursor] = (type << 5) | val;
    } else if (size == 2) {
      out->buffer[out->cursor] = (type << 5) | 24;
      out->buffer[out->cursor + 1] = val & 0xff;
    } else if (size == 3) {
      out->buffer[out->cursor] = (type << 5) | 25;
      out->buffer[out->cursor + 1] = (val >> 8) & 0xff;
      out->buffer[out->cursor + 2] = val & 0xff;
    } else if (size == 5) {
      out->buffer[out->cursor] = (type << 5) | 26;
      out->buffer[out->cursor + 1] = (val >> 24) & 0xff;
      out->buffer[out->cursor + 2] = (val >> 16) & 0xff;
      out->buffer[out->cursor + 3] = (val >> 8) & 0xff;
      out->buffer[out->cursor + 4] = val & 0xff;
    } else if (size == 9) {
      out->buffer[out->cursor] = (type << 5) | 27;
      out->buffer[out->cursor + 1] = (val >> 56) & 0xff;
      out->buffer[out->cursor + 2] = (val >> 48) & 0xff;
      out->buffer[out->cursor + 3] = (val >> 40) & 0xff;
      out->buffer[out->cursor + 4] = (val >> 32) & 0xff;
      out->buffer[out->cursor + 5] = (val >> 24) & 0xff;
      out->buffer[out->cursor + 6] = (val >> 16) & 0xff;
      out->buffer[out->cursor + 7] = (val >> 8) & 0xff;
      out->buffer[out->cursor + 8] = val & 0xff;
    }
  }
  out->cursor += size;
}

static void* CborAllocStr(enum CborType type, size_t data_size,
                          struct CborOut* out) {
  CborWriteType(type, data_size, out);
  bool overflow = CborWriteWouldOverflowCursor(data_size, out);
  bool fit = CborWriteFitsInBuffer(data_size, out);
  void* ptr = (overflow || !fit) ? NULL : &out->buffer[out->cursor];
  out->cursor = overflow ? SIZE_MAX : out->cursor + data_size;
  return ptr;
}

static void CborWriteStr(enum CborType type, size_t data_size, const void* data,
                         struct CborOut* out) {
  uint8_t* ptr = CborAllocStr(type, data_size, out);
  if (ptr && data_size) {
    memcpy(ptr, data, data_size);
  }
}

void CborWriteInt(int64_t val, struct CborOut* out) {
  if (val < 0) {
    CborWriteType(CBOR_TYPE_NINT, (-1 - val), out);
  } else {
    CborWriteType(CBOR_TYPE_UINT, val, out);
  }
}

void CborWriteUint(uint64_t val, struct CborOut* out) {
  CborWriteType(CBOR_TYPE_UINT, val, out);
}

void CborWriteBstr(size_t data_size, const uint8_t* data, struct CborOut* out) {
  CborWriteStr(CBOR_TYPE_BSTR, data_size, data, out);
}

uint8_t* CborAllocBstr(size_t data_size, struct CborOut* out) {
  return CborAllocStr(CBOR_TYPE_BSTR, data_size, out);
}

void CborWriteTstr(const char* str, struct CborOut* out) {
  CborWriteStr(CBOR_TYPE_TSTR, strlen(str), str, out);
}

char* CborAllocTstr(size_t size, struct CborOut* out) {
  return CborAllocStr(CBOR_TYPE_TSTR, size, out);
}

void CborWriteArray(size_t num_elements, struct CborOut* out) {
  CborWriteType(CBOR_TYPE_ARRAY, num_elements, out);
}

void CborWriteMap(size_t num_pairs, struct CborOut* out) {
  CborWriteType(CBOR_TYPE_MAP, num_pairs, out);
}

void CborWriteFalse(struct CborOut* out) {
  CborWriteType(CBOR_TYPE_SIMPLE, /*val=*/20, out);
}

void CborWriteTrue(struct CborOut* out) {
  CborWriteType(CBOR_TYPE_SIMPLE, /*val=*/21, out);
}

void CborWriteNull(struct CborOut* out) {
  CborWriteType(CBOR_TYPE_SIMPLE, /*val=*/22, out);
}
