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

#ifndef APPS_DART_RUNNER_MAPPED_RESOURCE_H_
#define APPS_DART_RUNNER_MAPPED_RESOURCE_H_

#include <fuchsia/mem/cpp/fidl.h>
#include <lib/fdio/namespace.h>
#include <third_party/dart/runtime/bin/elf_loader.h>

namespace dart_utils {

class ElfSnapshot {
 public:
  ElfSnapshot() {}
  ~ElfSnapshot();
  ElfSnapshot(ElfSnapshot&& other) : handle_(other.handle_) {
    other.handle_ = nullptr;
  }
  ElfSnapshot& operator=(ElfSnapshot&& other) {
    std::swap(handle_, other.handle_);
    return *this;
  }

  bool Load(fdio_ns_t* namespc, const std::string& path);
  bool Load(int dirfd, const std::string& path);

  const uint8_t* VmData() const { return vm_data_; }
  const uint8_t* VmInstrs() const { return vm_instrs_; }
  const uint8_t* IsolateData() const { return isolate_data_; }
  const uint8_t* IsolateInstrs() const { return isolate_instrs_; }

 private:
  bool Load(int fd);

  Dart_LoadedElf* handle_ = nullptr;

  const uint8_t* vm_data_ = nullptr;
  const uint8_t* vm_instrs_ = nullptr;
  const uint8_t* isolate_data_ = nullptr;
  const uint8_t* isolate_instrs_ = nullptr;

  // Disallow copy and assignment.
  ElfSnapshot(const ElfSnapshot&) = delete;
  ElfSnapshot& operator=(const ElfSnapshot&) = delete;
};

class MappedResource {
 public:
  MappedResource() : address_(nullptr), size_(0) {}
  MappedResource(MappedResource&& other)
      : address_(other.address_), size_(other.size_) {
    other.address_ = nullptr;
    other.size_ = 0;
  }
  MappedResource& operator=(MappedResource&& other) {
    address_ = other.address_;
    size_ = other.size_;
    other.address_ = nullptr;
    other.size_ = 0;
    return *this;
  }
  ~MappedResource();

  // Loads the content of a file from the given namespace and maps it into the
  // current process's address space. If namespace is null, the fdio "global"
  // namespace is used (in which case, ./pkg means the dart_runner's package).
  // The content is unmapped when the MappedResource goes out of scope. Returns
  // true on success.
  static bool LoadFromNamespace(fdio_ns_t* namespc,
                                const std::string& path,
                                MappedResource& resource,
                                bool executable = false);

  // Same as LoadFromNamespace, but takes a file descriptor to an opened
  // directory instead of a namespace.
  static bool LoadFromDir(int dirfd,
                          const std::string& path,
                          MappedResource& resource,
                          bool executable = false);

  // Maps a VMO into the current process's address space. The content is
  // unmapped when the MappedResource goes out of scope. Returns true on
  // success. The path is used only for error messages.
  static bool LoadFromVmo(const std::string& path,
                          fuchsia::mem::Buffer resource_vmo,
                          MappedResource& resource,
                          bool executable = false);

  const uint8_t* address() const {
    return reinterpret_cast<const uint8_t*>(address_);
  }
  size_t size() const { return size_; }

 private:
  void* address_;
  size_t size_;

  // Disallow copy and assignment.
  MappedResource(const MappedResource&) = delete;
  MappedResource& operator=(const MappedResource&) = delete;
};

}  // namespace dart_utils

#endif  // APPS_DART_RUNNER_MAPPED_RESOURCE_H_
