ArchiveTOCView.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <AzCore/base.h>
  10. #include <AzCore/std/containers/map.h>
  11. #include <AzCore/std/containers/set.h>
  12. #include <AzCore/std/containers/vector.h>
  13. #include <AzCore/std/function/function_fwd.h>
  14. #include <Archive/Clients/ArchiveInterfaceStructs.h>
  15. namespace Archive
  16. {
  17. //! Stores the error code resulting from the validation of the table of contents
  18. //! against the ArchiveHeader
  19. enum class ArchiveTocErrorCode
  20. {
  21. InvalidMagicBytes = 1,
  22. FileMetadataTableSizeMismatch,
  23. FileIndexTableSizeMismatch,
  24. BlockOffsetTableCountMismatch
  25. };
  26. //! Stores the error code and any error messages related to failing
  27. //! to validate the archive table of contents against its header
  28. struct ArchiveTocValidationResult
  29. {
  30. explicit constexpr operator bool() const;
  31. ArchiveTocErrorCode m_errorCode{};
  32. using ErrorString = AZStd::basic_fixed_string<char, 512, AZStd::char_traits<char>>;
  33. ErrorString m_errorMessage;
  34. };
  35. //! View Structure for viewing the Table of Contents at the end of the archive file
  36. //! This structure does not own the table of contents data in memory
  37. struct ArchiveTableOfContentsView
  38. {
  39. ArchiveTableOfContentsView();
  40. //! Initializes a Table of Contents view using the archive header
  41. //! and a buffer containing the uncompressed table of contents data from storage
  42. using CreateTOCViewOutcome = AZStd::expected<ArchiveTableOfContentsView, ArchiveTocValidationResult>;
  43. static CreateTOCViewOutcome CreateFromArchiveHeaderAndBuffer(const ArchiveHeader& archiveHeader,
  44. AZStd::span<AZStd::byte> tocBuffer);
  45. //! 8-byte magic bytes entry used to indicate that the read table of contents is valid
  46. AZ::u64 m_magicBytes = ArchiveTocMagicBytes;
  47. //! pointer to the beginning of the Archive File Metadata Table
  48. //! It's length is based on the file count value in the Archive Header Section
  49. AZStd::span<ArchiveTocFileMetadata const> m_fileMetadataTable{};
  50. //! pointer to the beginning of the Archive File Path Index Table
  51. //! It's length is based on the file count value in the Archive Header Section
  52. AZStd::span<ArchiveTocFilePathIndex const> m_filePathIndexTable{};
  53. //! ArchiveFilePathTable is a view into the start of the blob for file paths
  54. using ArchiveFilePathTable = AZStd::string_view;
  55. ArchiveFilePathTable m_filePathBlob{};
  56. //! pointer to block offset table which stores the compressed size of all blocks within the archive
  57. AZStd::span<ArchiveBlockLineUnion const> m_blockOffsetTable{};
  58. };
  59. //! Options which allows configuring which sections of the table of contents
  60. //! should be validated.
  61. //! NOTE: The Block Offset table takes the longest time to validate
  62. //! as it verifies the number of block lines in the table of contents
  63. //! is equivalent to the number of block lines each file should have
  64. //! It does this by calculating the number of block lines a file should
  65. //! have by examining each file uncompressed size
  66. struct ArchiveTocValidationOptions
  67. {
  68. bool m_validateFileMetadataTable{ true };
  69. bool m_validateFileIndexTable{ true };
  70. bool m_validateBlockOffsetTable{ true };
  71. };
  72. //! Validates the Table of Contents data
  73. //! This is a potentially lengthy operation as it verifies
  74. //! That the each archived file in the Table of Contents
  75. //! has the correct number of blocks based on whether it is
  76. //! uncompressed(file is stored contiguously with no entry in the block table)
  77. //! or compressed(the number of blocks stored is based on the uncompressed size of the file split into 2 MiB chunks);
  78. ArchiveTocValidationResult ValidateTableOfContents(const ArchiveTableOfContentsView& tocView,
  79. const ArchiveHeader& archiveHeader,
  80. const ArchiveTocValidationOptions& validationOptions = {});
  81. //! Visitor invoked for each deleted file path index entry
  82. //! It gets passed in the offset within the file path blob table where the deleted file path resides
  83. //! and the length of that file path
  84. //! @param filePathBlobOffset Offset into the raw archive TOC file path blob table where the deleted file path starts
  85. //! @param filePathSize length of the deleted file path. The value is guaranteed to be >0
  86. using FilePathIndexEntryVisitor = AZStd::function<void(AZ::u64 filePathBlobOffset, AZ::u16 filePathSize)>;
  87. //! Enumerates each file path index found in the TOC View
  88. //! @param callback to invoke when a deleted path index entry is found
  89. //! @param tocView view structure overlaying the raw table of contents data
  90. //! @return the number of file path index entries visited
  91. size_t EnumerateFilePathIndexOffsets(FilePathIndexEntryVisitor callback,
  92. const ArchiveTableOfContentsView& tocView);
  93. } // namespace Archive
  94. // Separate namespace block to create visual spacing around utility functions
  95. // for querying the the Table of Contents View
  96. namespace Archive
  97. {
  98. //! Retrieves a subspan from the archive TOC BlockLine Offset Table
  99. //! that contains the block lines associated with a specific file
  100. //! @param tocView readonly view into the Archive TOC
  101. //! The file metadata table and block offset table is accessed using the TOC view
  102. //! @param fileMetadataTableIndex index into the file metadata table
  103. //! This is used to lookup the uncompressed size and the first block line offset entry
  104. //! for a file
  105. //! @return On success return a span over a view of each block line associated with the file
  106. //! at the provided file metadata table index.
  107. //! On failure returns an error message providing the reason the span could not be created
  108. using FileBlockLineOutcome = AZStd::expected<AZStd::span<const ArchiveBlockLineUnion>, ResultString>;
  109. FileBlockLineOutcome GetBlockLineSpanForFile(const ArchiveTableOfContentsView& tocView,
  110. size_t fileMetadataTableIndex);
  111. //! Queries the compressed size at the block index in the block line span for the compressed file
  112. //! @param fileBlockLineSpan span of the block lines associated with a single file
  113. //! The entire TOC block line span should NOT be passed to this function
  114. //! The span that is passed in should be from a call of GetBlockLineSpanForFile()
  115. //! @param blockCount The number of 2-MiB blocks for the file
  116. //! @param blockIndex index of block entry in the block line span to read the compressed size
  117. //! @return the compressed size value for the block if block index corresponds to a block in the file
  118. //! otherwise 0 is returned
  119. AZ::u64 GetCompressedSizeForBlock(AZStd::span<const ArchiveBlockLineUnion> fileBlockLineSpan,
  120. AZ::u64 blockCount, AZ::u64 blockIndex);
  121. //! Gets the raw size for the file in the archive
  122. //! If the file is uncompressed then the uncompressed size is returned from the file metadata
  123. //! If the file is compressed, then this returns the size needed to read the contiguous
  124. //! sequence of compressed blocks exact
  125. //!
  126. //! @param fileMetadata reference to the TOC file metadata entry which contains the start offset into
  127. //! the block offset table for the file.
  128. //! The TOC file metadata structure m_uncompressedSize member is used to determine
  129. //! @param tocBlockOffsetTable span for the entire TOC block line offset table
  130. //! @return On success return the exact size for the file as stored in the archive
  131. //! On failure returns an error message with the failure reason
  132. using GetRawFileSizeOutcome = AZStd::expected<AZ::u64, ResultString>;
  133. GetRawFileSizeOutcome GetRawFileSize(const ArchiveTocFileMetadata& fileMetadata,
  134. AZStd::span<const ArchiveBlockLineUnion> tocBlockOffsetTable);
  135. }
  136. // Implementation for any struct functions
  137. #include "ArchiveTOCView.inl"