Add PPI header recognition tests

This commit is contained in:
2026-06-01 00:26:06 +02:00
parent 20b5dba41e
commit 126280ff7c
11 changed files with 316 additions and 8 deletions

73
src/assets/ppi_header.cpp Normal file
View File

@@ -0,0 +1,73 @@
#include "assets/ppi_header.h"
#include "foundation/binary_stream.h"
namespace pp::assets {
namespace {
[[nodiscard]] pp::foundation::Result<std::uint32_t> read_u32(pp::foundation::ByteReader& reader) noexcept
{
return reader.read_u32_le();
}
}
pp::foundation::Result<PpiHeaderInfo> parse_ppi_header(std::span<const std::byte> bytes) noexcept
{
if (bytes.size() < ppi_header_size) {
return pp::foundation::Result<PpiHeaderInfo>::failure(
pp::foundation::Status::out_of_range("PPI header is truncated"));
}
pp::foundation::ByteReader reader(bytes.subspan(0, ppi_header_size));
const auto magic = reader.read_bytes(4);
if (!magic || magic.value()[0] != std::byte { 'P' } || magic.value()[1] != std::byte { 'P' }
|| magic.value()[2] != std::byte { 'I' } || magic.value()[3] != std::byte { 0 }) {
return pp::foundation::Result<PpiHeaderInfo>::failure(
pp::foundation::Status::invalid_argument("PPI header magic is invalid"));
}
PpiHeaderInfo info;
const auto doc_major = read_u32(reader);
const auto doc_minor = read_u32(reader);
const auto soft_major = read_u32(reader);
const auto soft_minor = read_u32(reader);
const auto soft_fix = read_u32(reader);
const auto soft_build = read_u32(reader);
const auto thumb_width = read_u32(reader);
const auto thumb_height = read_u32(reader);
const auto thumb_components = read_u32(reader);
if (!doc_major || !doc_minor || !soft_major || !soft_minor || !soft_fix || !soft_build
|| !thumb_width || !thumb_height || !thumb_components) {
return pp::foundation::Result<PpiHeaderInfo>::failure(
pp::foundation::Status::out_of_range("PPI header is truncated"));
}
info.document_version = { doc_major.value(), doc_minor.value() };
info.software_version = {
soft_major.value(),
soft_minor.value(),
soft_fix.value(),
soft_build.value(),
};
info.thumbnail = {
thumb_width.value(),
thumb_height.value(),
thumb_components.value(),
};
if (info.document_version.major != 0 || info.document_version.minor < 1) {
return pp::foundation::Result<PpiHeaderInfo>::failure(
pp::foundation::Status::invalid_argument("PPI document version is unsupported"));
}
if (info.thumbnail.width != 128 || info.thumbnail.height != 128 || info.thumbnail.components != 4) {
return pp::foundation::Result<PpiHeaderInfo>::failure(
pp::foundation::Status::invalid_argument("PPI thumbnail descriptor is invalid"));
}
return pp::foundation::Result<PpiHeaderInfo>::success(info);
}
}