// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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
//
//     http://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 "cobalt/storage/virtual_file.h"

#include <algorithm>

#include "base/logging.h"

namespace cobalt {
namespace storage {
namespace {

// We must use forward declarations to be able to specify the
// WARN_UNUSED_RESULT attribute.

// Read size bytes from buffer into dest. Updates buffer and buffer_remaining
// on success.
// Returns true on success, false on buffer overrun
bool ReadBuffer(uint8* dest, const uint8** buffer, size_t size,
                size_t* buffer_remaining) WARN_UNUSED_RESULT;

// Write size bytes from source into buffer. Return # of bytes written.
size_t WriteBuffer(uint8* buffer, const uint8* source, size_t size,
                   bool dry_run) WARN_UNUSED_RESULT;

bool ReadBuffer(uint8* dest, const uint8** buffer, size_t size,
                size_t* buffer_remaining) {
  if (size > *buffer_remaining) {
    return false;
  }
  memcpy(dest, *buffer, size);
  *buffer_remaining -= size;
  *buffer += size;
  return true;
}

size_t WriteBuffer(uint8* buffer, const uint8* source, size_t size,
                   bool dry_run) {
  if (!dry_run) {
    memcpy(buffer, source, size);
  }
  return size;
}

}  // namespace

VirtualFile::VirtualFile(const std::string& name) : name_(name) {}
VirtualFile::~VirtualFile() {}

int VirtualFile::Read(void* dest, int bytes_in, int offset_in) const {
  DCHECK_GE(offset_in, 0);
  DCHECK_GE(bytes_in, 0);
  size_t offset = static_cast<size_t>(offset_in);
  size_t bytes = static_cast<size_t>(bytes_in);
  size_t size = buffer_.size();
  if (offset > size) {
    return 0;
  }
  size_t bytes_to_read = std::min(static_cast<size_t>(size - offset), bytes);
  if (bytes_to_read == 0) {
    return 0;
  }
  memcpy(dest, &buffer_[offset], bytes_to_read);
  return static_cast<int>(bytes_to_read);
}

int VirtualFile::Write(const void* source, int bytes_in, int offset_in) {
  DCHECK_GE(offset_in, 0);
  DCHECK_GE(bytes_in, 0);
  size_t bytes = static_cast<size_t>(bytes_in);
  size_t offset = static_cast<size_t>(offset_in);
  if (buffer_.size() < offset + bytes) {
    buffer_.resize(offset + bytes);
  }

  if (!buffer_.empty()) {
    // std::vector does not define access to underlying array when empty
    memcpy(&buffer_[offset], source, bytes);
  }
  return bytes_in;
}

int VirtualFile::Truncate(int size) {
  size_t newsize = std::min(buffer_.size(), static_cast<size_t>(size));
  buffer_.resize(newsize);
  return static_cast<int>(newsize);
}

int VirtualFile::Serialize(uint8* dest, bool dry_run) {
  uint8* cur_buffer = dest;

  // Write filename length
  uint64 name_length = name_.length();
  DCHECK_LT(name_length, kMaxVfsPathname);
  cur_buffer +=
      WriteBuffer(cur_buffer, reinterpret_cast<const uint8*>(&name_length),
                  sizeof(name_length), dry_run);

  // Write the filename
  cur_buffer +=
      WriteBuffer(cur_buffer, reinterpret_cast<const uint8*>(name_.c_str()),
                  static_cast<size_t>(name_length), dry_run);

  // NOTE: Ensure the file size is 64-bit for compatibility
  // with any existing serialized files.
  uint64 file_size = static_cast<uint64>(buffer_.size());
  // Write the file contents size
  cur_buffer +=
      WriteBuffer(cur_buffer, reinterpret_cast<const uint8*>(&file_size),
                  sizeof(file_size), dry_run);

  // Write the file contents
  if (!buffer_.empty()) {
    // std::vector does not define access to underlying array when empty
    cur_buffer += WriteBuffer(cur_buffer, &buffer_[0], buffer_.size(), dry_run);
  }

  // Return the number of bytes written
  return static_cast<int>(std::distance(dest, cur_buffer));
}

int VirtualFile::Deserialize(const uint8* source, size_t buffer_remaining) {
  // Read in filename length
  const uint8* cur_buffer = source;
  uint64 name_length;
  bool success = ReadBuffer(reinterpret_cast<uint8*>(&name_length), &cur_buffer,
                            sizeof(name_length), &buffer_remaining);
  if (!success) {
    DLOG(ERROR) << "Buffer overrun";
    return -1;
  }

  if (name_length >= kMaxVfsPathname) {
    DLOG(ERROR) << "Filename was longer than the maximum allowed.";
    return -1;
  }
  // Read in filename
  char name[kMaxVfsPathname];
  success = ReadBuffer(reinterpret_cast<uint8*>(name), &cur_buffer,
                       static_cast<size_t>(name_length), &buffer_remaining);
  if (!success) {
    DLOG(ERROR) << "Buffer overrun";
    return -1;
  }
  name_.assign(name, static_cast<size_t>(name_length));

  // Read in file contents size.
  uint64 file_size;
  success = ReadBuffer(reinterpret_cast<uint8*>(&file_size), &cur_buffer,
                       sizeof(file_size), &buffer_remaining);
  if (!success) {
    DLOG(ERROR) << "Buffer overrun";
    return -1;
  }
  // Read in the file contents
  buffer_.resize(static_cast<size_t>(file_size));

  if (!buffer_.empty()) {
    // std::vector does not define access to underlying array when empty
    success =
        ReadBuffer(&buffer_[0], &cur_buffer, buffer_.size(), &buffer_remaining);
    if (!success) {
      DLOG(ERROR) << "Buffer overrun";
      return -1;
    }
  }

  // Return the number of bytes read
  return static_cast<int>(std::distance(source, cur_buffer));
}

}  // namespace storage
}  // namespace cobalt
