// Copyright 2020 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 "src/storage/volume_image/utils/guid.h"

#include <zircon/assert.h>

#include <algorithm>
#include <array>
#include <cstdint>
#include <iterator>
#include <string>

#include <safemath/safe_conversions.h>

namespace storage::volume_image {
namespace {

// GuidSection represents a sequence of bytes within a representation of a GUID,
// that treated as a unit. This unit may be represented as little/big endian
// independently of the platform.
//
// Offsets and lengths are defined with respect to the byte sequence.
struct GuidSection {
  // Returns the offset of the first element in the section.
  constexpr ptrdiff_t begin() const {
    return static_cast<ptrdiff_t>(multiplier) * (reversed ? start + length - 1 : start);
  }

  // Returns the offset of the last element in the section.
  constexpr ptrdiff_t end() const {
    return static_cast<ptrdiff_t>(multiplier) * (reversed ? start - 1 : start + length);
  }

  // Returns the distance between two consecutive elements in the section, measured in bytes.
  constexpr ptrdiff_t next() const {
    return static_cast<ptrdiff_t>(multiplier) * (reversed ? -1 : +1);
  }

  // Start of the section.
  uint8_t start;

  // End of the section.
  uint8_t length;

  // Whether this section should be iterated in a particular order.
  bool reversed;

  // Byte size of elements.
  uint8_t multiplier = 1;
};

// Defines the different sections of the GUID to match the following format:
//
// Byte-Format: {section_0}....{section_N}
// String Format: {String(section_0)}-....-{String(section_N)}
//
//  Example:
//    Byte-Format: {0xA0, 0xA1, 0xA2, 0xA3, 0xB0, 0xB1, 0xC0, 0xC1, 0xD0, 0xD1, 0xE0, 0xE1, 0xE2,
//                  0xE3, 0xE4, 0xE5}
//    String-Format: A3A2A1A0-B1B0-C1C0-D0D1-E0E1E2E3E4E5
constexpr std::array<GuidSection, 5> kGuidSections = {
    {
        // section: 0
        // Bytes: {0xA0, 0xA1, 0xA2, 0xA3}
        // String: A3A2A1A0
        {.start = 0, .length = 4, .reversed = true},
        // section: 1
        // Bytes: {0xB0, 0xB1}
        // String: B1B0
        {4, 2, true},
        // section: 2
        // Bytes: {0xC0, 0xC1}
        // String C1C0
        {6, 2, true},
        // section: 3
        // Bytes: {0xD0, 0xD1}
        // D0D1
        {8, 2, false},
        // section 4
        // Bytes: {0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5}
        // String E0E1E2E3E4E5
        {10, 6, false},
    },
};

// Separator used for string representation of the GUID.
constexpr char kSeparator = '-';

// Returns the Hex equivalent of |value|.
//
// Precondition:
//  * |value| is less than 16 or |F| + 1.
constexpr char GetHex(uint8_t value) {
  ZX_ASSERT(value < 16);
  constexpr std::string_view kHexTable = "0123456789ABCDEF";
  return kHexTable[value];
}

// Returns the numeric value of |hex|.
//
// Precondition:
//  * |hex| is either a digit(0-9) or [a-fA-F].
uint8_t GetValue(char hex) {
  constexpr uint8_t kHexAlphaOffset = 0xA;
  if (hex >= 'a') {
    return hex - 'a' + kHexAlphaOffset;
  }
  if (hex >= 'A') {
    return hex - 'A' + kHexAlphaOffset;
  }
  return hex - '0';
}

constexpr uint64_t kHighMask = 0xF0;
constexpr uint64_t kLowMask = 0x0F;

}  // namespace

fpromise::result<std::string, std::string> Guid::ToString(cpp20::span<const uint8_t> guid) {
  if (guid.size() != kGuidLength) {
    std::string error = "Input GUID size must be equal to |kGuidLength|. Input Size: ";
    error.append(std::to_string(guid.size())).append(".\n");
    return fpromise::error(error);
  }
  std::array<char, kGuidStrLength> out_guid;

  uint8_t current_section = 0;
  uint8_t current_byte = 0;

  for (auto section : kGuidSections) {
    section.multiplier = sizeof(uint8_t);
    const uint8_t* begin = guid.data() + section.begin();
    const uint8_t* end = guid.data() + section.end();

    for (const uint8_t* it = begin; it != end; it = it + section.next()) {
      uint8_t high = (kHighMask & *it) >> 4;
      uint8_t low = (kLowMask & *it);
      out_guid[2 * current_byte + current_section] = GetHex(high);
      out_guid[2 * current_byte + current_section + 1] = GetHex(low);
      current_byte++;
    }
    // We dont need a separator after last section.
    if (current_section < kGuidSections.size() - 1) {
      out_guid[2 * (section.start + section.length) + current_section] = kSeparator;
    }
    current_section++;
  }
  return fpromise::ok(std::string(out_guid.data(), out_guid.size()));
}

fpromise::result<std::array<uint8_t, kGuidLength>, std::string> Guid::FromString(
    cpp20::span<const char> guid) {
  if (guid.size() != kGuidStrLength) {
    std::string error = "Input GUID size must be equal to |kGuidStrLength|. Input Size: ";
    error.append(std::to_string(guid.size())).append(".\n");
    return fpromise::error(error);
  }
  std::array<uint8_t, kGuidLength> out_guid;

  uint64_t current_byte = 0;
  uint64_t current_section = 0;

  for (auto section : kGuidSections) {
    // We iterate 2 characters at a time.
    section.multiplier = kGuidCharactersPerByte * sizeof(char);
    const char* begin = guid.data() + section.begin() + current_section;
    const char* end = guid.data() + section.end() + current_section;

    for (const char* it = begin; it != end; it = it + section.next()) {
      uint8_t high = GetValue(*it);
      uint8_t low = GetValue(*(it + 1));
      out_guid[current_byte] = safemath::checked_cast<uint8_t>((high << 4) | low);
      current_byte++;
    }
    current_section++;
  }

  return fpromise::ok(out_guid);
}

}  // namespace storage::volume_image
