/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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 "format/Container.h"

#include "android-base/scopeguard.h"
#include "android-base/stringprintf.h"

using ::android::base::StringPrintf;
using ::google::protobuf::io::CodedInputStream;
using ::google::protobuf::io::CodedOutputStream;
using ::google::protobuf::io::ZeroCopyOutputStream;

namespace aapt {

constexpr const static uint32_t kContainerFormatMagic = 0x54504141u;
constexpr const static uint32_t kContainerFormatVersion = 1u;

ContainerWriter::ContainerWriter(ZeroCopyOutputStream* out, size_t entry_count)
    : out_(out), total_entry_count_(entry_count), current_entry_count_(0u) {
  CodedOutputStream coded_out(out_);

  // Write the magic.
  coded_out.WriteLittleEndian32(kContainerFormatMagic);

  // Write the version.
  coded_out.WriteLittleEndian32(kContainerFormatVersion);

  // Write the total number of entries.
  coded_out.WriteLittleEndian32(static_cast<uint32_t>(total_entry_count_));

  if (coded_out.HadError()) {
    error_ = "failed writing container format header";
  }
}

inline static void WritePadding(int padding, CodedOutputStream* out) {
  if (padding < 4) {
    const uint32_t zero = 0u;
    out->WriteRaw(&zero, padding);
  }
}

bool ContainerWriter::AddResTableEntry(const pb::ResourceTable& table) {
  if (current_entry_count_ >= total_entry_count_) {
    error_ = "too many entries being serialized";
    return false;
  }
  current_entry_count_++;

  CodedOutputStream coded_out(out_);

  // Write the type.
  coded_out.WriteLittleEndian32(kResTable);

  // Write the aligned size.
  const ::google::protobuf::uint64 size = table.ByteSize();
  const int padding = 4 - (size % 4);
  coded_out.WriteLittleEndian64(size);

  // Write the table.
  table.SerializeWithCachedSizes(&coded_out);

  // Write the padding.
  WritePadding(padding, &coded_out);

  if (coded_out.HadError()) {
    error_ = "failed writing to output";
    return false;
  }
  return true;
}

bool ContainerWriter::AddResFileEntry(const pb::internal::CompiledFile& file,
                                      io::KnownSizeInputStream* in) {
  if (current_entry_count_ >= total_entry_count_) {
    error_ = "too many entries being serialized";
    return false;
  }
  current_entry_count_++;

  constexpr const static int kResFileEntryHeaderSize = 12;

  CodedOutputStream coded_out(out_);

  // Write the type.
  coded_out.WriteLittleEndian32(kResFile);

  // Write the aligned size.
  const ::google::protobuf::uint32 header_size = file.ByteSize();
  const int header_padding = 4 - (header_size % 4);
  const ::google::protobuf::uint64 data_size = in->TotalSize();
  const int data_padding = 4 - (data_size % 4);
  coded_out.WriteLittleEndian64(kResFileEntryHeaderSize + header_size + header_padding + data_size +
                                data_padding);

  // Write the res file header size.
  coded_out.WriteLittleEndian32(header_size);

  // Write the data payload size.
  coded_out.WriteLittleEndian64(data_size);

  // Write the header.
  file.SerializeToCodedStream(&coded_out);

  WritePadding(header_padding, &coded_out);

  // Write the data payload. We need to call Trim() since we are going to write to the underlying
  // ZeroCopyOutputStream.
  coded_out.Trim();

  // Check at this point if there were any errors.
  if (coded_out.HadError()) {
    error_ = "failed writing to output";
    return false;
  }

  if (!io::Copy(out_, in)) {
    if (in->HadError()) {
      std::ostringstream error;
      error << "failed reading from input: " << in->GetError();
      error_ = error.str();
    } else {
      error_ = "failed writing to output";
    }
    return false;
  }
  WritePadding(data_padding, &coded_out);

  if (coded_out.HadError()) {
    error_ = "failed writing to output";
    return false;
  }
  return true;
}

bool ContainerWriter::HadError() const {
  return !error_.empty();
}

std::string ContainerWriter::GetError() const {
  return error_;
}

static bool AlignRead(CodedInputStream* in) {
  const int padding = 4 - (in->CurrentPosition() % 4);
  if (padding < 4) {
    return in->Skip(padding);
  }
  return true;
}

ContainerReaderEntry::ContainerReaderEntry(ContainerReader* reader) : reader_(reader) {
}

ContainerEntryType ContainerReaderEntry::Type() const {
  return type_;
}

bool ContainerReaderEntry::GetResTable(pb::ResourceTable* out_table) {
  CHECK(type_ == ContainerEntryType::kResTable) << "reading a kResTable when the type is kResFile";
  if (length_ > std::numeric_limits<int>::max()) {
    reader_->error_ = StringPrintf("entry length %zu is too large", length_);
    return false;
  }

  CodedInputStream& coded_in = reader_->coded_in_;

  const CodedInputStream::Limit limit = coded_in.PushLimit(static_cast<int>(length_));
  auto guard = ::android::base::make_scope_guard([&]() { coded_in.PopLimit(limit); });

  if (!out_table->ParseFromCodedStream(&coded_in)) {
    reader_->error_ = "failed to parse ResourceTable";
    return false;
  }
  return true;
}

bool ContainerReaderEntry::GetResFileOffsets(pb::internal::CompiledFile* out_file,
                                             off64_t* out_offset, size_t* out_len) {
  CHECK(type_ == ContainerEntryType::kResFile) << "reading a kResFile when the type is kResTable";

  CodedInputStream& coded_in = reader_->coded_in_;

  // Read the ResFile header.
  ::google::protobuf::uint32 header_length;
  if (!coded_in.ReadLittleEndian32(&header_length)) {
    std::ostringstream error;
    error << "failed to read header length from input: " << reader_->in_->GetError();
    reader_->error_ = error.str();
    return false;
  }

  ::google::protobuf::uint64 data_length;
  if (!coded_in.ReadLittleEndian64(&data_length)) {
    std::ostringstream error;
    error << "failed to read data length from input: " << reader_->in_->GetError();
    reader_->error_ = error.str();
    return false;
  }

  if (header_length > std::numeric_limits<int>::max()) {
    std::ostringstream error;
    error << "header length " << header_length << " is too large";
    reader_->error_ = error.str();
    return false;
  }

  if (data_length > std::numeric_limits<size_t>::max()) {
    std::ostringstream error;
    error << "data length " << data_length << " is too large";
    reader_->error_ = error.str();
    return false;
  }

  {
    const CodedInputStream::Limit limit = coded_in.PushLimit(static_cast<int>(header_length));
    auto guard = ::android::base::make_scope_guard([&]() { coded_in.PopLimit(limit); });

    if (!out_file->ParseFromCodedStream(&coded_in)) {
      reader_->error_ = "failed to parse CompiledFile header";
      return false;
    }
  }

  AlignRead(&coded_in);

  *out_offset = coded_in.CurrentPosition();
  *out_len = data_length;

  coded_in.Skip(static_cast<int>(data_length));
  AlignRead(&coded_in);
  return true;
}

bool ContainerReaderEntry::HadError() const {
  return reader_->HadError();
}

std::string ContainerReaderEntry::GetError() const {
  return reader_->GetError();
}

ContainerReader::ContainerReader(io::InputStream* in)
    : in_(in),
      adaptor_(in),
      coded_in_(&adaptor_),
      total_entry_count_(0u),
      current_entry_count_(0u),
      entry_(this) {
  ::google::protobuf::uint32 magic;
  if (!coded_in_.ReadLittleEndian32(&magic)) {
    std::ostringstream error;
    error << "failed to read magic from input: " << in_->GetError();
    error_ = error.str();
    return;
  }

  if (magic != kContainerFormatMagic) {
    error_ =
        StringPrintf("magic value is 0x%08x but AAPT expects 0x%08x", magic, kContainerFormatMagic);
    return;
  }

  ::google::protobuf::uint32 version;
  if (!coded_in_.ReadLittleEndian32(&version)) {
    std::ostringstream error;
    error << "failed to read version from input: " << in_->GetError();
    error_ = error.str();
    return;
  }

  if (version != kContainerFormatVersion) {
    error_ = StringPrintf("container version is 0x%08x but AAPT expects version 0x%08x", version,
                          kContainerFormatVersion);
    return;
  }

  ::google::protobuf::uint32 total_entry_count;
  if (!coded_in_.ReadLittleEndian32(&total_entry_count)) {
    std::ostringstream error;
    error << "failed to read entry count from input: " << in_->GetError();
    error_ = error.str();
    return;
  }

  total_entry_count_ = total_entry_count;
}

ContainerReaderEntry* ContainerReader::Next() {
  if (current_entry_count_ >= total_entry_count_) {
    return nullptr;
  }
  current_entry_count_++;

  // Ensure the next read is aligned.
  AlignRead(&coded_in_);

  ::google::protobuf::uint32 entry_type;
  if (!coded_in_.ReadLittleEndian32(&entry_type)) {
    std::ostringstream error;
    error << "failed reading entry type from input: " << in_->GetError();
    error_ = error.str();
    return nullptr;
  }

  ::google::protobuf::uint64 entry_length;
  if (!coded_in_.ReadLittleEndian64(&entry_length)) {
    std::ostringstream error;
    error << "failed reading entry length from input: " << in_->GetError();
    error_ = error.str();
    return nullptr;
  }

  if (entry_type == ContainerEntryType::kResFile || entry_type == ContainerEntryType::kResTable) {
    entry_.type_ = static_cast<ContainerEntryType>(entry_type);
  } else {
    error_ = StringPrintf("entry type 0x%08x is invalid", entry_type);
    return nullptr;
  }

  if (entry_length > std::numeric_limits<size_t>::max()) {
    std::ostringstream error;
    error << "entry length " << entry_length << " is too large";
    error_ = error.str();
    return nullptr;
  }

  entry_.length_ = entry_length;
  return &entry_;
}

bool ContainerReader::HadError() const {
  return !error_.empty();
}

std::string ContainerReader::GetError() const {
  return error_;
}

}  // namespace aapt
