10 const std::byte*
bytes)
noexcept
15 static_cast<std::uint32_t
>(
16 std::to_integer<std::uint8_t>(
bytes[0])) |
17 (
static_cast<std::uint32_t
>(
18 std::to_integer<std::uint8_t>(
bytes[1])) << 8U) |
19 (
static_cast<std::uint32_t
>(
20 std::to_integer<std::uint8_t>(
bytes[2])) << 16U);
40 return "PositionOutOfRange";
43 return "InvalidChunkErrorCode";
51 levels_[0] = { 0, bytes_.size(), NullStandardId };
56 : owner_(std::move(
bytes)),
57 bytes_(owner_ ? std::span<const std::byte>(*owner_) :
60 levels_[0] = { 0, bytes_.size(), NullStandardId };
64 ChunkError LegacyChunkReader::error(
69 return { code,
offset, std::move(detail) };
78 return std::unexpected(
error(
80 "legacy chunk nesting cannot exceed seven child levels",
84 const std::size_t
parentEnd = levels_[level_].end;
93 return std::unexpected(
error(
95 "fewer than four bytes remain for a chunk header",
101 const std::uint8_t
id =
102 std::to_integer<std::uint8_t>(
header[3]);
106 return std::unexpected(
error(
108 "chunk size includes its header and cannot be below four",
114 return std::unexpected(
error(
116 "chunk extends beyond its parent boundary",
128 if ((
id & 0x7FU) == 0)
130 return std::unexpected(
error(
132 "selected chunk ID 0 or 128 is a null sentinel",
137 const std::size_t dataStart =
139 levels_[level_] = { dataStart,
chunkEnd,
id };
140 currentOffset_ = dataStart;
157 return std::unexpected(
error(
162 "no next child chunk remains" :
163 "requested chunk ID was not found among remaining siblings",
172 return std::unexpected(
error(
174 "cannot ascend above the root byte container",
178 currentOffset_ = levels_[level_].end;
184 std::expected<std::span<const std::byte>,
ChunkError>
188 const auto mapped = bytes_.subspan(currentOffset_, amount);
189 currentOffset_ += amount;
201 return std::unexpected(
mapped.error());
217 return std::unexpected(
error(
219 "position must remain inside current chunk data",
230 return currentOffset_;
241 std::size_t level)
const noexcept
243 return level <= level_ ? levels_[level].id : NullStandardId;
248 std::size_t level)
const noexcept
250 return level <= level_ ?
251 levels_[level].end - levels_[level].dataStart : 0;
256 std::size_t level)
const noexcept
258 return level <= level_ ? levels_[level].dataStart : 0;
264 return levels_[level_].end - currentOffset_;
276 return std::unexpected(
metadata.error());
286 "LE_CHUNK_ReadFromDataID requires a DataChunky item"
294 return std::unexpected(
bytes.error());
LegacyBitmapMetadata metadata
std::vector< std::byte > bytes
std::shared_ptr< const data::HmdTextureImage > source
std::expected< std::size_t, ChunkError > read(std::span< std::byte > destination)
std::uint8_t idForLevel(std::size_t level) const noexcept
std::size_t level() const noexcept
static constexpr std::uint8_t NullStandardId
std::expected< std::span< const std::byte >, ChunkError > map(std::size_t requestedBytes)
static constexpr std::size_t PhysicalHeaderSize
std::size_t dataSizeForLevel(std::size_t level) const noexcept
LegacyChunkReader(std::span< const std::byte > bytes) noexcept
std::size_t dataStartForLevel(std::size_t level) const noexcept
std::expected< void, ChunkError > ascend()
std::expected< ChunkInfo, ChunkError > descend(std::uint8_t findId=NullStandardId)
std::expected< void, ChunkError > seek(std::size_t absoluteOffset)
std::size_t remaining() const noexcept
static constexpr std::size_t MaximumLevels
std::size_t currentOffset() const noexcept
constexpr DataTag dataTag(DataId id) noexcept
std::string_view chunkErrorCodeName(ChunkErrorCode code) noexcept
std::shared_ptr< const DataBytes > SharedDataBytes
std::expected< LegacyChunkReader, DataError > openLegacyChunkReader(const DataSource &source, DataId id)