Start assets component image signature tests

This commit is contained in:
2026-05-31 23:55:20 +02:00
parent ec5ecbdb54
commit 99eda95cee
12 changed files with 315 additions and 10 deletions

View File

@@ -0,0 +1,94 @@
#include "assets/image_format.h"
#include <array>
#include <cstdint>
namespace pp::assets {
namespace {
constexpr std::array png_signature {
std::byte { 0x89 },
std::byte { 0x50 },
std::byte { 0x4e },
std::byte { 0x47 },
std::byte { 0x0d },
std::byte { 0x0a },
std::byte { 0x1a },
std::byte { 0x0a },
};
[[nodiscard]] bool starts_with(std::span<const std::byte> bytes, std::span<const std::byte> prefix) noexcept
{
if (bytes.size() < prefix.size()) {
return false;
}
for (std::size_t i = 0; i < prefix.size(); ++i) {
if (bytes[i] != prefix[i]) {
return false;
}
}
return true;
}
[[nodiscard]] bool is_prefix_of(std::span<const std::byte> bytes, std::span<const std::byte> signature) noexcept
{
if (bytes.size() >= signature.size()) {
return false;
}
for (std::size_t i = 0; i < bytes.size(); ++i) {
if (bytes[i] != signature[i]) {
return false;
}
}
return true;
}
}
pp::foundation::Result<ImageFormat> detect_image_format(std::span<const std::byte> bytes) noexcept
{
if (bytes.empty()) {
return pp::foundation::Result<ImageFormat>::failure(
pp::foundation::Status::invalid_argument("image data must not be empty"));
}
if (starts_with(bytes, png_signature)) {
return pp::foundation::Result<ImageFormat>::success(ImageFormat::png);
}
if (is_prefix_of(bytes, png_signature)) {
return pp::foundation::Result<ImageFormat>::failure(
pp::foundation::Status::out_of_range("image data is a truncated PNG signature"));
}
if (bytes.size() < 3U) {
return pp::foundation::Result<ImageFormat>::failure(
pp::foundation::Status::out_of_range("image data is too short to identify"));
}
if (bytes[0] == std::byte { 0xff } && bytes[1] == std::byte { 0xd8 } && bytes[2] == std::byte { 0xff }) {
return pp::foundation::Result<ImageFormat>::success(ImageFormat::jpeg);
}
return pp::foundation::Result<ImageFormat>::failure(
pp::foundation::Status::invalid_argument("unsupported image signature"));
}
const char* image_format_name(ImageFormat format) noexcept
{
switch (format) {
case ImageFormat::png:
return "png";
case ImageFormat::jpeg:
return "jpeg";
}
return "unknown";
}
}

20
src/assets/image_format.h Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include "foundation/result.h"
#include <cstddef>
#include <span>
namespace pp::assets {
enum class ImageFormat {
png,
jpeg,
};
[[nodiscard]] pp::foundation::Result<ImageFormat> detect_image_format(
std::span<const std::byte> bytes) noexcept;
[[nodiscard]] const char* image_format_name(ImageFormat format) noexcept;
}