Summarize PPI project bodies

This commit is contained in:
2026-06-01 12:44:49 +02:00
parent 2da247f0fb
commit f1ee1b28a1
9 changed files with 430 additions and 32 deletions

View File

@@ -2,11 +2,14 @@
#include "test_harness.h"
#include <array>
#include <bit>
#include <cstddef>
#include <cstdint>
#include <string_view>
#include <vector>
using pp::assets::parse_ppi_header;
using pp::assets::parse_ppi_project_summary;
using pp::assets::parse_ppi_project_layout;
using pp::assets::ppi_header_size;
using pp::assets::ppi_thumbnail_byte_size;
@@ -22,6 +25,18 @@ void append_u32(std::vector<std::byte>& bytes, std::uint32_t value)
bytes.push_back(static_cast<std::byte>((value >> 24U) & 0xffU));
}
void append_f32(std::vector<std::byte>& bytes, float value)
{
append_u32(bytes, std::bit_cast<std::uint32_t>(value));
}
void append_ascii(std::vector<std::byte>& bytes, std::string_view value)
{
for (const auto ch : value) {
bytes.push_back(static_cast<std::byte>(ch));
}
}
std::vector<std::byte> valid_header()
{
std::vector<std::byte> bytes {
@@ -42,6 +57,35 @@ std::vector<std::byte> valid_header()
return bytes;
}
void append_minimal_body(std::vector<std::byte>& bytes)
{
append_u32(bytes, 64);
append_u32(bytes, 32);
append_u32(bytes, 1);
append_u32(bytes, 1);
append_u32(bytes, 0);
append_f32(bytes, 1.0F);
append_u32(bytes, 3);
append_ascii(bytes, "Ink");
append_u32(bytes, 0);
bytes.push_back(std::byte { 0 });
bytes.push_back(std::byte { 1 });
append_u32(bytes, 1);
append_u32(bytes, 100);
for (std::uint32_t i = 0; i < 6U; ++i) {
append_u32(bytes, 0);
}
append_u32(bytes, 0);
}
std::vector<std::byte> minimal_project()
{
auto bytes = valid_header();
bytes.resize(ppi_header_size + (128U * 128U * 4U), std::byte { 0 });
append_minimal_body(bytes);
return bytes;
}
void parses_legacy_ppi_header(pp::tests::Harness& h)
{
const auto bytes = valid_header();
@@ -100,10 +144,7 @@ void rejects_unsupported_document_versions(pp::tests::Harness& h)
void parses_project_layout_with_thumbnail_and_body(pp::tests::Harness& h)
{
auto bytes = valid_header();
const auto thumbnail_size = ppi_thumbnail_byte_size(parse_ppi_header(bytes).value().thumbnail);
PP_EXPECT(h, thumbnail_size.ok());
bytes.resize(ppi_header_size + thumbnail_size.value() + 7U, std::byte { 0xaa });
const auto bytes = minimal_project();
const auto layout = parse_ppi_project_layout(bytes);
@@ -111,7 +152,7 @@ void parses_project_layout_with_thumbnail_and_body(pp::tests::Harness& h)
PP_EXPECT(h, layout.value().thumbnail_offset == ppi_header_size);
PP_EXPECT(h, layout.value().thumbnail_bytes == 128U * 128U * 4U);
PP_EXPECT(h, layout.value().body_offset == ppi_header_size + (128U * 128U * 4U));
PP_EXPECT(h, layout.value().body_bytes == 7U);
PP_EXPECT(h, layout.value().body_bytes == 73U);
}
void rejects_project_layout_with_truncated_thumbnail(pp::tests::Harness& h)
@@ -125,6 +166,45 @@ void rejects_project_layout_with_truncated_thumbnail(pp::tests::Harness& h)
PP_EXPECT(h, layout.status().code == StatusCode::out_of_range);
}
void parses_minimal_project_body_summary(pp::tests::Harness& h)
{
const auto project = minimal_project();
const auto summary = parse_ppi_project_summary(project);
PP_EXPECT(h, summary.ok());
PP_EXPECT(h, summary.value().body.width == 64U);
PP_EXPECT(h, summary.value().body.height == 32U);
PP_EXPECT(h, summary.value().body.layer_count == 1U);
PP_EXPECT(h, summary.value().body.declared_frame_count == 1U);
PP_EXPECT(h, summary.value().body.total_layer_frames == 1U);
PP_EXPECT(h, summary.value().body.dirty_face_count == 0U);
PP_EXPECT(h, summary.value().body.compressed_face_bytes == 0U);
PP_EXPECT(h, summary.value().body.info_bytes == 0U);
}
void rejects_invalid_project_body_summaries(pp::tests::Harness& h)
{
auto truncated = minimal_project();
truncated.pop_back();
auto mismatched_frames = minimal_project();
mismatched_frames[ppi_header_size + (128U * 128U * 4U) + 12U] = std::byte { 2 };
auto bad_layer_name = minimal_project();
bad_layer_name[ppi_header_size + (128U * 128U * 4U) + 24U] = std::byte { 255 };
const auto truncated_result = parse_ppi_project_summary(truncated);
const auto mismatched_frames_result = parse_ppi_project_summary(mismatched_frames);
const auto bad_layer_name_result = parse_ppi_project_summary(bad_layer_name);
PP_EXPECT(h, !truncated_result.ok());
PP_EXPECT(h, truncated_result.status().code == StatusCode::out_of_range);
PP_EXPECT(h, !mismatched_frames_result.ok());
PP_EXPECT(h, mismatched_frames_result.status().code == StatusCode::invalid_argument);
PP_EXPECT(h, !bad_layer_name_result.ok());
PP_EXPECT(h, bad_layer_name_result.status().code == StatusCode::out_of_range);
}
}
int main()
@@ -135,5 +215,7 @@ int main()
harness.run("rejects_unsupported_document_versions", rejects_unsupported_document_versions);
harness.run("parses_project_layout_with_thumbnail_and_body", parses_project_layout_with_thumbnail_and_body);
harness.run("rejects_project_layout_with_truncated_thumbnail", rejects_project_layout_with_truncated_thumbnail);
harness.run("parses_minimal_project_body_summary", parses_minimal_project_body_summary);
harness.run("rejects_invalid_project_body_summaries", rejects_invalid_project_body_summaries);
return harness.finish();
}