// Copyright 2014 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/fpdfapi/parser/cpdf_document.h"

#include <algorithm>
#include <functional>
#include <optional>
#include <utility>

#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_linearized_header.h"
#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_null.h"
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_parser.h"
#include "core/fpdfapi/parser/cpdf_read_validator.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxcodec/jbig2/JBig2_DocumentContext.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/containers/contains.h"
#include "core/fxcrt/fx_codepage.h"
#include "core/fxcrt/scoped_set_insertion.h"
#include "core/fxcrt/span.h"
#include "core/fxcrt/stl_util.h"

namespace {

const int kMaxPageLevel = 1024;

enum class NodeType : bool {
  kBranch,  // /Type /Pages, AKA page tree node.
  kLeaf,    // /Type /Page, AKA page object.
};

// Note that this function may modify `kid_dict` to correct PDF spec violations.
// Same reasoning as CountPages() below.
NodeType GetNodeType(RetainPtr<CPDF_Dictionary> kid_dict) {
  const ByteString kid_type_value = kid_dict->GetNameFor("Type");
  if (kid_type_value == "Pages") {
    return NodeType::kBranch;
  }
  if (kid_type_value == "Page") {
    return NodeType::kLeaf;
  }

  // Even though /Type is required for page tree nodes and page objects, PDFs
  // may not have them or have the wrong type. Tolerate these errors and guess
  // the type. Then fix the in-memory representation.
  const bool has_kids = kid_dict->KeyExist("Kids");
  kid_dict->SetNewFor<CPDF_Name>("Type", has_kids ? "Pages" : "Page");
  return has_kids ? NodeType::kBranch : NodeType::kLeaf;
}

// Returns a value in the range [0, `CPDF_Document::kPageMaxNum`), or nullopt on
// error. Note that this function may modify `pages_dict` to correct PDF spec
// violations. By normalizing the in-memory representation, other code that
// reads the object do not have to deal with the same spec violations again.
// If the PDF gets saved, the saved copy will also be more spec-compliant.
std::optional<int> CountPages(
    RetainPtr<CPDF_Dictionary> pages_dict,
    std::set<RetainPtr<CPDF_Dictionary>>* visited_pages) {
  // Required. See ISO 32000-1:2008 spec, table 29, but tolerate page tree nodes
  // that violate the spec.
  int count_from_dict = pages_dict->GetIntegerFor("Count");
  if (count_from_dict > 0 && count_from_dict < CPDF_Document::kPageMaxNum) {
    return count_from_dict;
  }

  RetainPtr<CPDF_Array> kids_array = pages_dict->GetMutableArrayFor("Kids");
  if (!kids_array) {
    return 0;
  }

  int count = 0;
  for (size_t i = 0; i < kids_array->size(); i++) {
    RetainPtr<CPDF_Dictionary> kid_dict = kids_array->GetMutableDictAt(i);
    if (!kid_dict || pdfium::Contains(*visited_pages, kid_dict)) {
      continue;
    }

    NodeType kid_type = GetNodeType(kid_dict);
    if (kid_type == NodeType::kBranch) {
      // Use |visited_pages| to help detect circular references of pages.
      ScopedSetInsertion local_add(visited_pages, kid_dict);
      std::optional<int> local_count =
          CountPages(std::move(kid_dict), visited_pages);
      if (!local_count.has_value()) {
        return std::nullopt;  // Propagate error.
      }
      count += local_count.value();
    } else {
      CHECK_EQ(kid_type, NodeType::kLeaf);
      count++;
    }

    if (count >= CPDF_Document::kPageMaxNum) {
      return std::nullopt;  // Error: too many pages.
    }
  }
  // Fix the in-memory representation for page tree nodes that violate the spec.
  pages_dict->SetNewFor<CPDF_Number>("Count", count);
  return count;
}

int FindPageIndex(const CPDF_Dictionary* pNode,
                  uint32_t* skip_count,
                  uint32_t objnum,
                  int* index,
                  int level) {
  if (!pNode->KeyExist("Kids")) {
    if (objnum == pNode->GetObjNum()) {
      return *index;
    }

    if (*skip_count != 0) {
      (*skip_count)--;
    }

    (*index)++;
    return -1;
  }

  RetainPtr<const CPDF_Array> pKidList = pNode->GetArrayFor("Kids");
  if (!pKidList) {
    return -1;
  }

  if (level >= kMaxPageLevel) {
    return -1;
  }

  size_t count = pNode->GetIntegerFor("Count");
  if (count <= *skip_count) {
    (*skip_count) -= count;
    (*index) += count;
    return -1;
  }

  if (count && count == pKidList->size()) {
    for (size_t i = 0; i < count; i++) {
      RetainPtr<const CPDF_Reference> pKid =
          ToReference(pKidList->GetObjectAt(i));
      if (pKid && pKid->GetRefObjNum() == objnum) {
        return static_cast<int>(*index + i);
      }
    }
  }

  for (size_t i = 0; i < pKidList->size(); i++) {
    RetainPtr<const CPDF_Dictionary> pKid = pKidList->GetDictAt(i);
    if (!pKid || pKid == pNode) {
      continue;
    }

    int found_index =
        FindPageIndex(pKid.Get(), skip_count, objnum, index, level + 1);
    if (found_index >= 0) {
      return found_index;
    }
  }
  return -1;
}

}  // namespace

CPDF_Document::CPDF_Document(std::unique_ptr<RenderDataIface> pRenderData,
                             std::unique_ptr<PageDataIface> pPageData)
    : doc_render_(std::move(pRenderData)),
      doc_page_(std::move(pPageData)),
      stock_font_clearer_(doc_page_.get()) {
  doc_render_->SetDocument(this);
  doc_page_->SetDocument(this);
}

CPDF_Document::~CPDF_Document() {
  // Be absolutely certain that |extension_| is null before destroying
  // the extension, to avoid re-entering it while being destroyed. clang
  // seems to already do this for us, but the C++ standards seem to
  // indicate the opposite.
  extension_.reset();
}

// static
bool CPDF_Document::IsValidPageObject(const CPDF_Object* obj) {
  // See ISO 32000-1:2008 spec, table 30.
  return ValidateDictType(ToDictionary(obj), "Page");
}

RetainPtr<CPDF_Object> CPDF_Document::ParseIndirectObject(uint32_t objnum) {
  return parser_ ? parser_->ParseIndirectObject(objnum) : nullptr;
}

bool CPDF_Document::TryInit() {
  SetLastObjNum(parser_->GetLastObjNum());

  RetainPtr<CPDF_Object> pRootObj =
      GetOrParseIndirectObject(parser_->GetRootObjNum());
  if (pRootObj) {
    root_dict_ = pRootObj->GetMutableDict();
  }

  LoadPages();
  return GetRoot() && GetPageCount() > 0;
}

CPDF_Parser::Error CPDF_Document::LoadDoc(
    RetainPtr<IFX_SeekableReadStream> pFileAccess,
    const ByteString& password) {
  if (!parser_) {
    SetParser(std::make_unique<CPDF_Parser>(this));
  }

  return HandleLoadResult(
      parser_->StartParse(std::move(pFileAccess), password));
}

CPDF_Parser::Error CPDF_Document::LoadLinearizedDoc(
    RetainPtr<CPDF_ReadValidator> validator,
    const ByteString& password) {
  if (!parser_) {
    SetParser(std::make_unique<CPDF_Parser>(this));
  }

  return HandleLoadResult(
      parser_->StartLinearizedParse(std::move(validator), password));
}

void CPDF_Document::LoadPages() {
  const CPDF_LinearizedHeader* linearized_header =
      parser_->GetLinearizedHeader();
  if (!linearized_header) {
    page_list_.resize(RetrievePageCount());
    return;
  }

  uint32_t objnum = linearized_header->GetFirstPageObjNum();
  if (!IsValidPageObject(GetOrParseIndirectObject(objnum).Get())) {
    page_list_.resize(RetrievePageCount());
    return;
  }

  uint32_t first_page_num = linearized_header->GetFirstPageNo();
  uint32_t page_count = linearized_header->GetPageCount();
  DCHECK(first_page_num < page_count);
  page_list_.resize(page_count);
  page_list_[first_page_num] = objnum;
}

RetainPtr<CPDF_Dictionary> CPDF_Document::TraversePDFPages(int iPage,
                                                           int* nPagesToGo,
                                                           size_t level) {
  if (*nPagesToGo < 0 || reached_max_page_level_) {
    return nullptr;
  }

  RetainPtr<CPDF_Dictionary> pPages = tree_traversal_[level].pages_dict;
  RetainPtr<CPDF_Array> pKidList = pPages->GetMutableArrayFor("Kids");
  if (!pKidList) {
    tree_traversal_.pop_back();
    if (*nPagesToGo != 1) {
      return nullptr;
    }
    if (GetNodeType(pPages) == NodeType::kBranch) {
      return nullptr;
    }
    page_list_[iPage] = pPages->GetObjNum();
    return pPages;
  }
  if (level >= kMaxPageLevel) {
    tree_traversal_.pop_back();
    reached_max_page_level_ = true;
    return nullptr;
  }
  RetainPtr<CPDF_Dictionary> page;
  for (size_t i = tree_traversal_[level].child_index; i < pKidList->size();
       i++) {
    if (*nPagesToGo == 0) {
      break;
    }
    pKidList->ConvertToIndirectObjectAt(i, this);
    RetainPtr<CPDF_Dictionary> pKid = pKidList->GetMutableDictAt(i);
    if (!pKid) {
      (*nPagesToGo)--;
      tree_traversal_[level].child_index++;
      continue;
    }
    if (pKid == pPages) {
      tree_traversal_[level].child_index++;
      continue;
    }
    if (!pKid->KeyExist("Kids")) {
      page_list_[iPage - (*nPagesToGo) + 1] = pKid->GetObjNum();
      (*nPagesToGo)--;
      tree_traversal_[level].child_index++;
      if (*nPagesToGo == 0) {
        page = std::move(pKid);
        break;
      }
    } else {
      // If the vector has size level+1, the child is not in yet
      if (tree_traversal_.size() == level + 1) {
        tree_traversal_.emplace_back(std::move(pKid));
      }
      // Now tree_traversal_[level+1] should exist and be equal to pKid.
      RetainPtr<CPDF_Dictionary> pPageKid =
          TraversePDFPages(iPage, nPagesToGo, level + 1);
      // Check if child was completely processed, i.e. it popped itself out
      if (tree_traversal_.size() == level + 1) {
        tree_traversal_[level].child_index++;
      }
      // If child did not finish, no pages to go, or max level reached, end
      if (tree_traversal_.size() != level + 1 || *nPagesToGo == 0 ||
          reached_max_page_level_) {
        page = std::move(pPageKid);
        break;
      }
    }
  }
  if (tree_traversal_[level].child_index == pKidList->size()) {
    tree_traversal_.pop_back();
  }
  return page;
}

void CPDF_Document::ResetTraversal() {
  next_page_to_traverse_ = 0;
  reached_max_page_level_ = false;
  tree_traversal_.clear();
}

void CPDF_Document::SetParser(std::unique_ptr<CPDF_Parser> pParser) {
  DCHECK(!parser_);
  parser_ = std::move(pParser);
}

CPDF_Parser::Error CPDF_Document::HandleLoadResult(CPDF_Parser::Error error) {
  if (error == CPDF_Parser::SUCCESS) {
    has_valid_cross_reference_table_ = !parser_->xref_table_rebuilt();
  }
  return error;
}

RetainPtr<const CPDF_Dictionary> CPDF_Document::GetPagesDict() const {
  const CPDF_Dictionary* pRoot = GetRoot();
  return pRoot ? pRoot->GetDictFor("Pages") : nullptr;
}

RetainPtr<CPDF_Dictionary> CPDF_Document::GetMutablePagesDict() {
  return pdfium::WrapRetain(
      const_cast<CPDF_Dictionary*>(this->GetPagesDict().Get()));
}

bool CPDF_Document::IsPageLoaded(int iPage) const {
  return !!page_list_[iPage];
}

RetainPtr<const CPDF_Dictionary> CPDF_Document::GetPageDictionary(int iPage) {
  if (!fxcrt::IndexInBounds(page_list_, iPage)) {
    return nullptr;
  }

  const uint32_t objnum = page_list_[iPage];
  if (objnum) {
    RetainPtr<CPDF_Dictionary> result =
        ToDictionary(GetOrParseIndirectObject(objnum));
    if (result) {
      return result;
    }
  }

  RetainPtr<CPDF_Dictionary> pPages = GetMutablePagesDict();
  if (!pPages) {
    return nullptr;
  }

  if (tree_traversal_.empty()) {
    ResetTraversal();
    tree_traversal_.emplace_back(std::move(pPages));
  }
  int nPagesToGo = iPage - next_page_to_traverse_ + 1;
  RetainPtr<CPDF_Dictionary> pPage = TraversePDFPages(iPage, &nPagesToGo, 0);
  next_page_to_traverse_ = iPage + 1;
  return pPage;
}

RetainPtr<CPDF_Dictionary> CPDF_Document::GetMutablePageDictionary(int iPage) {
  return pdfium::WrapRetain(
      const_cast<CPDF_Dictionary*>(GetPageDictionary(iPage).Get()));
}

void CPDF_Document::SetPageObjNum(int iPage, uint32_t objNum) {
  page_list_[iPage] = objNum;
}

JBig2_DocumentContext* CPDF_Document::GetOrCreateCodecContext() {
  if (!codec_context_) {
    codec_context_ = std::make_unique<JBig2_DocumentContext>();
  }
  return codec_context_.get();
}

RetainPtr<CPDF_Stream> CPDF_Document::CreateModifiedAPStream(
    RetainPtr<CPDF_Dictionary> dict) {
  auto stream = NewIndirect<CPDF_Stream>(std::move(dict));
  modified_apstream_ids_.insert(stream->GetObjNum());
  return stream;
}

bool CPDF_Document::IsModifiedAPStream(const CPDF_Stream* stream) const {
  return stream &&
         pdfium::Contains(modified_apstream_ids_, stream->GetObjNum());
}

int CPDF_Document::GetPageIndex(uint32_t objnum) {
  uint32_t skip_count = 0;
  bool bSkipped = false;
  for (uint32_t i = 0; i < page_list_.size(); ++i) {
    if (page_list_[i] == objnum) {
      return i;
    }

    if (!bSkipped && page_list_[i] == 0) {
      skip_count = i;
      bSkipped = true;
    }
  }
  RetainPtr<const CPDF_Dictionary> pPages = GetPagesDict();
  if (!pPages) {
    return -1;
  }

  int start_index = 0;
  int found_index = FindPageIndex(pPages, &skip_count, objnum, &start_index, 0);

  // Corrupt page tree may yield out-of-range results.
  if (!fxcrt::IndexInBounds(page_list_, found_index)) {
    return -1;
  }

  // Only update |page_list_| when |objnum| points to a /Page object.
  if (IsValidPageObject(GetOrParseIndirectObject(objnum).Get())) {
    page_list_[found_index] = objnum;
  }
  return found_index;
}

int CPDF_Document::GetPageCount() const {
  return fxcrt::CollectionSize<int>(page_list_);
}

int CPDF_Document::RetrievePageCount() {
  RetainPtr<CPDF_Dictionary> pPages = GetMutablePagesDict();
  if (!pPages) {
    return 0;
  }

  if (!pPages->KeyExist("Kids")) {
    return 1;
  }

  std::set<RetainPtr<CPDF_Dictionary>> visited_pages = {pPages};
  return CountPages(std::move(pPages), &visited_pages).value_or(0);
}

uint32_t CPDF_Document::GetUserPermissions(bool get_owner_perms) const {
  return parser_ ? parser_->GetPermissions(get_owner_perms) : 0;
}

RetainPtr<CPDF_StreamAcc> CPDF_Document::GetFontFileStreamAcc(
    RetainPtr<const CPDF_Stream> font_stream) {
  return doc_page_->GetFontFileStreamAcc(std::move(font_stream));
}

void CPDF_Document::MaybePurgeFontFileStreamAcc(
    RetainPtr<CPDF_StreamAcc>&& stream_acc) {
  doc_page_->MaybePurgeFontFileStreamAcc(std::move(stream_acc));
}

void CPDF_Document::MaybePurgeImage(uint32_t objnum) {
  doc_page_->MaybePurgeImage(objnum);
}

void CPDF_Document::CreateNewDoc() {
  DCHECK(!root_dict_);
  DCHECK(!info_dict_);
  root_dict_ = NewIndirect<CPDF_Dictionary>();
  root_dict_->SetNewFor<CPDF_Name>("Type", "Catalog");

  auto pPages = NewIndirect<CPDF_Dictionary>();
  pPages->SetNewFor<CPDF_Name>("Type", "Pages");
  pPages->SetNewFor<CPDF_Number>("Count", 0);
  pPages->SetNewFor<CPDF_Array>("Kids");
  root_dict_->SetNewFor<CPDF_Reference>("Pages", this, pPages->GetObjNum());
  info_dict_ = NewIndirect<CPDF_Dictionary>();
}

RetainPtr<CPDF_Dictionary> CPDF_Document::CreateNewPage(int iPage) {
  auto dict = NewIndirect<CPDF_Dictionary>();
  dict->SetNewFor<CPDF_Name>("Type", "Page");
  uint32_t dwObjNum = dict->GetObjNum();
  if (!InsertNewPage(iPage, dict)) {
    DeleteIndirectObject(dwObjNum);
    return nullptr;
  }
  return dict;
}

bool CPDF_Document::InsertDeletePDFPage(
    RetainPtr<CPDF_Dictionary> pages_dict,
    int pages_to_go,
    RetainPtr<CPDF_Dictionary> page_dict,
    bool is_insert,
    std::set<RetainPtr<CPDF_Dictionary>>* visited) {
  RetainPtr<CPDF_Array> kids_list = pages_dict->GetMutableArrayFor("Kids");
  if (!kids_list) {
    return false;
  }

  for (size_t i = 0; i < kids_list->size(); i++) {
    RetainPtr<CPDF_Dictionary> kid_dict = kids_list->GetMutableDictAt(i);
    NodeType kid_type = GetNodeType(kid_dict);
    if (kid_type == NodeType::kLeaf) {
      if (pages_to_go != 0) {
        pages_to_go--;
        continue;
      }
      if (is_insert) {
        kids_list->InsertNewAt<CPDF_Reference>(i, this, page_dict->GetObjNum());
        page_dict->SetNewFor<CPDF_Reference>("Parent", this,
                                             pages_dict->GetObjNum());
      } else {
        kids_list->RemoveAt(i);
      }
      pages_dict->SetNewFor<CPDF_Number>(
          "Count", pages_dict->GetIntegerFor("Count") + (is_insert ? 1 : -1));
      ResetTraversal();
      break;
    }

    CHECK_EQ(kid_type, NodeType::kBranch);
    int page_count = kid_dict->GetIntegerFor("Count");
    if (pages_to_go >= page_count) {
      pages_to_go -= page_count;
      continue;
    }
    if (pdfium::Contains(*visited, kid_dict)) {
      return false;
    }

    ScopedSetInsertion insertion(visited, kid_dict);
    if (!InsertDeletePDFPage(std::move(kid_dict), pages_to_go, page_dict,
                             is_insert, visited)) {
      return false;
    }
    pages_dict->SetNewFor<CPDF_Number>(
        "Count", pages_dict->GetIntegerFor("Count") + (is_insert ? 1 : -1));
    break;
  }
  return true;
}

bool CPDF_Document::InsertNewPage(int iPage,
                                  RetainPtr<CPDF_Dictionary> pPageDict) {
  RetainPtr<CPDF_Dictionary> pRoot = GetMutableRoot();
  if (!pRoot) {
    return false;
  }

  RetainPtr<CPDF_Dictionary> pPages = pRoot->GetMutableDictFor("Pages");
  if (!pPages) {
    return false;
  }

  int nPages = GetPageCount();
  if (iPage < 0 || iPage > nPages) {
    return false;
  }

  if (iPage == nPages) {
    RetainPtr<CPDF_Array> pPagesList = pPages->GetOrCreateArrayFor("Kids");
    pPagesList->AppendNew<CPDF_Reference>(this, pPageDict->GetObjNum());
    pPages->SetNewFor<CPDF_Number>("Count", nPages + 1);
    pPageDict->SetNewFor<CPDF_Reference>("Parent", this, pPages->GetObjNum());
    ResetTraversal();
  } else {
    std::set<RetainPtr<CPDF_Dictionary>> stack = {pPages};
    if (!InsertDeletePDFPage(std::move(pPages), iPage, pPageDict, true,
                             &stack)) {
      return false;
    }
  }
  page_list_.insert(page_list_.begin() + iPage, pPageDict->GetObjNum());
  return true;
}

RetainPtr<CPDF_Dictionary> CPDF_Document::GetInfo() {
  if (info_dict_) {
    return info_dict_;
  }

  if (!parser_) {
    return nullptr;
  }

  uint32_t info_obj_num = parser_->GetInfoObjNum();
  if (info_obj_num == 0) {
    return nullptr;
  }

  auto ref = pdfium::MakeRetain<CPDF_Reference>(this, info_obj_num);
  info_dict_ = ToDictionary(ref->GetMutableDirect());
  return info_dict_;
}

RetainPtr<const CPDF_Array> CPDF_Document::GetFileIdentifier() const {
  return parser_ ? parser_->GetIDArray() : nullptr;
}

uint32_t CPDF_Document::DeletePage(int iPage) {
  RetainPtr<CPDF_Dictionary> pPages = GetMutablePagesDict();
  if (!pPages) {
    return 0;
  }

  int nPages = pPages->GetIntegerFor("Count");
  if (iPage < 0 || iPage >= nPages) {
    return 0;
  }

  RetainPtr<const CPDF_Dictionary> page_dict = GetPageDictionary(iPage);
  if (!page_dict) {
    return 0;
  }

  std::set<RetainPtr<CPDF_Dictionary>> stack = {pPages};
  if (!InsertDeletePDFPage(std::move(pPages), iPage, nullptr, false, &stack)) {
    return 0;
  }

  page_list_.erase(page_list_.begin() + iPage);
  return page_dict->GetObjNum();
}

void CPDF_Document::SetPageToNullObject(uint32_t page_obj_num) {
  if (!page_obj_num || page_list_.empty()) {
    return;
  }

  // Load all pages so `page_list_` has all the object numbers.
  for (size_t i = 0; i < page_list_.size(); ++i) {
    GetPageDictionary(i);
  }

  if (pdfium::Contains(page_list_, page_obj_num)) {
    return;
  }

  // If `page_dict` is no longer in the page tree, replace it with an object of
  // type null.
  //
  // Delete the object first from this container, so the conditional in the
  // replacement call always evaluates to true.
  DeleteIndirectObject(page_obj_num);
  const bool replaced = ReplaceIndirectObjectIfHigherGeneration(
      page_obj_num, pdfium::MakeRetain<CPDF_Null>());
  CHECK(replaced);
}

void CPDF_Document::SetRootForTesting(RetainPtr<CPDF_Dictionary> root) {
  root_dict_ = std::move(root);
}

bool CPDF_Document::MovePages(pdfium::span<const int> page_indices,
                              int dest_page_index) {
  const CPDF_Dictionary* pages = GetPagesDict();
  const int num_pages_signed = pages ? pages->GetIntegerFor("Count") : 0;
  if (num_pages_signed <= 0) {
    return false;
  }
  const size_t num_pages = num_pages_signed;

  // Check the number of pages is in range.
  if (page_indices.empty() || page_indices.size() > num_pages) {
    return false;
  }

  // Check that destination page index is in range.
  if (dest_page_index < 0 ||
      static_cast<size_t>(dest_page_index) > num_pages - page_indices.size()) {
    return false;
  }

  // Check for if XFA is enabled.
  Extension* extension = GetExtension();
  if (extension && extension->ContainsExtensionFullForm()) {
    // Don't manipulate XFA-full PDFs.
    return false;
  }

  // Check for duplicate and out-of-range page indices
  std::set<int> unique_page_indices;
  // Store the pages that need to be moved. They'll be deleted then reinserted.
  std::vector<RetainPtr<CPDF_Dictionary>> pages_to_move;
  pages_to_move.reserve(page_indices.size());
  // Store the page indices that will be deleted (and moved).
  std::vector<int> page_indices_to_delete;
  page_indices_to_delete.reserve(page_indices.size());
  for (const int page_index : page_indices) {
    bool inserted = unique_page_indices.insert(page_index).second;
    if (!inserted) {
      // Duplicate page index found
      return false;
    }
    RetainPtr<CPDF_Dictionary> page = GetMutablePageDictionary(page_index);
    if (!page) {
      // Page not found, index might be out of range.
      return false;
    }
    pages_to_move.push_back(std::move(page));
    page_indices_to_delete.push_back(page_index);
  }

  // Sort the page indices to be deleted in descending order.
  std::sort(page_indices_to_delete.begin(), page_indices_to_delete.end(),
            std::greater<int>());
  // Delete the pages in descending order.
  if (extension) {
    for (int page_index : page_indices_to_delete) {
      extension->DeletePage(page_index);
    }
  } else {
    for (int page_index : page_indices_to_delete) {
      DeletePage(page_index);
    }
  }

  // Insert the deleted pages back into the document at the destination page
  // index.
  for (size_t i = 0; i < pages_to_move.size(); ++i) {
    if (!InsertNewPage(i + dest_page_index, pages_to_move[i])) {
      // Fail in an indeterminate state.
      return false;
    }
  }

  if (extension) {
    extension->PagesInserted(dest_page_index, pages_to_move.size());
  }

  return true;
}

void CPDF_Document::ResizePageListForTesting(size_t size) {
  page_list_.resize(size);
}

CPDF_Document::StockFontClearer::StockFontClearer(
    CPDF_Document::PageDataIface* pPageData)
    : page_data_(pPageData) {}

CPDF_Document::StockFontClearer::~StockFontClearer() {
  page_data_->ClearStockFont();
}

CPDF_Document::PageTreeData::PageTreeData(RetainPtr<CPDF_Dictionary> dict)
    : pages_dict(std::move(dict)) {}

CPDF_Document::PageTreeData::PageTreeData(PageTreeData&& that) noexcept =
    default;

CPDF_Document::PageTreeData& CPDF_Document::PageTreeData::operator=(
    PageTreeData&& that) noexcept = default;

CPDF_Document::PageTreeData::~PageTreeData() = default;

CPDF_Document::PageDataIface::PageDataIface() = default;

CPDF_Document::PageDataIface::~PageDataIface() = default;

CPDF_Document::RenderDataIface::RenderDataIface() = default;

CPDF_Document::RenderDataIface::~RenderDataIface() = default;
