Skip to content

Commit a4bb5fa

Browse files
authored
Merge pull request #89 from bboczula/codex/issue-45-diagnostics-helpers
[AS2-E2-S6] Add diagnostics helpers for probe and decode failures
2 parents 4a8e9f2 + 49302b4 commit a4bb5fa

6 files changed

Lines changed: 233 additions & 16 deletions

File tree

source/common/AssetSuite.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "AssetSuiteContext.h"
55

66
#include "../runtime/AssetSuiteRuntime.h"
7+
#include "../runtime/AssetSuiteRuntimeDiagnostics.h"
78
#include "../runtime/AssetSuiteRuntimeState.h"
89
#include "../wavefront/ModelLoader.h"
910
#include "../bmp/BmpDecoder.h"
@@ -182,7 +183,10 @@ AssetSuite::Result AssetSuite::LoadFile(ContextHandle context, const char* fileP
182183
const Result mappedResult = MapFileLoadResult(loadResult);
183184
if (mappedResult != Result::Success)
184185
{
185-
context->Runtime().Diagnostics().Add(loadResult, "Failed to load blob source file.");
186+
context->Runtime().EmitDiagnostic(
187+
loadResult,
188+
LogLevel::Error,
189+
Internal::Diagnostics::BlobLoadFailed);
186190
return mappedResult;
187191
}
188192

@@ -246,13 +250,17 @@ AssetSuite::Result AssetSuite::DecodeImageFromFile(ContextHandle context, const
246250
const Result mappedResult = MapFileLoadResult(loadResult);
247251
if (mappedResult != Result::Success)
248252
{
249-
context->Runtime().Diagnostics().Add(loadResult, "Failed to load image source file.");
253+
context->Runtime().EmitDiagnostic(
254+
loadResult,
255+
LogLevel::Error,
256+
Internal::Diagnostics::ImageLoadFailed);
250257
return mappedResult;
251258
}
252259

253260
try
254261
{
255262
Internal::Blob blob(std::move(rawBytes), Internal::MakeBlobSourceMetadata(filePath));
263+
// DecodeImageBlob owns probe/decode diagnostics so this wrapper does not duplicate them.
256264
return context->Runtime().DecodeImageBlob(blob, outImage);
257265
}
258266
catch (const std::bad_alloc&)
@@ -308,13 +316,17 @@ AssetSuite::Result AssetSuite::DecodeMeshFromFile(ContextHandle context, const c
308316
const Result mappedResult = MapFileLoadResult(loadResult);
309317
if (mappedResult != Result::Success)
310318
{
311-
context->Runtime().Diagnostics().Add(loadResult, "Failed to load mesh source file.");
319+
context->Runtime().EmitDiagnostic(
320+
loadResult,
321+
LogLevel::Error,
322+
Internal::Diagnostics::MeshLoadFailed);
312323
return mappedResult;
313324
}
314325

315326
try
316327
{
317328
Internal::Blob blob(std::move(rawBytes), Internal::MakeBlobSourceMetadata(filePath));
329+
// DecodeMeshBlob owns probe/decode diagnostics so this wrapper does not duplicate them.
318330
return context->Runtime().DecodeMeshBlob(blob, outMesh);
319331
}
320332
catch (const std::bad_alloc&)

source/runtime/AssetSuiteRuntime.cpp

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "AssetSuiteRuntime.h"
2+
#include "AssetSuiteRuntimeDiagnostics.h"
23

34
#include <new>
45
#include <utility>
@@ -158,28 +159,40 @@ AssetSuite::Result AssetSuite::Internal::RuntimeContext::DecodeImageBlob(
158159
static_cast<size_t>(blob.ByteSize()));
159160
if (decoder == ImageDecoders::Auto)
160161
{
161-
Diagnostics().Add(ErrorCode::FileTypeNotSupported, "Image blob format is not supported.");
162+
EmitDiagnostic(
163+
ErrorCode::FileTypeNotSupported,
164+
LogLevel::Warning,
165+
Diagnostics::UnsupportedImageFormat);
162166
return Result::ErrorUnsupportedFormat;
163167
}
164168

165169
if (!HasMinimumImageDecodeBytes(decoder, blob))
166170
{
167-
Diagnostics().Add(ErrorCode::Undefined, "Image blob is too small for the selected decoder.");
171+
EmitDiagnostic(
172+
ErrorCode::Undefined,
173+
LogLevel::Error,
174+
Diagnostics::ImageBlobTooSmall);
168175
return Result::ErrorMalformedData;
169176
}
170177

171178
ImageDecoder* imageDecoder = CodecRegistry().FindImageDecoder(decoder);
172179
if (!imageDecoder)
173180
{
174-
Diagnostics().Add(ErrorCode::FileTypeNotSupported, "Image decoder is not registered.");
181+
EmitDiagnostic(
182+
ErrorCode::FileTypeNotSupported,
183+
LogLevel::Warning,
184+
Diagnostics::ImageDecoderMissing);
175185
return Result::ErrorUnsupportedFormat;
176186
}
177187

178188
std::vector<BYTE> decodedBytes;
179189
ImageDescriptor descriptor = {};
180190
if (!imageDecoder->Decode(decodedBytes, const_cast<BYTE*>(reinterpret_cast<const BYTE*>(blob.Data())), descriptor))
181191
{
182-
Diagnostics().Add(ErrorCode::Undefined, "Image decoder rejected malformed data.");
192+
EmitDiagnostic(
193+
ErrorCode::Undefined,
194+
LogLevel::Error,
195+
Diagnostics::ImageDecodeRejected);
183196
return MapSelectedDecoderFailure();
184197
}
185198

@@ -218,20 +231,29 @@ AssetSuite::Result AssetSuite::Internal::RuntimeContext::DecodeMeshBlob(
218231
static_cast<size_t>(blob.ByteSize()));
219232
if (decoder == MeshDecoders::Auto)
220233
{
221-
Diagnostics().Add(ErrorCode::FileTypeNotSupported, "Mesh blob format is not supported.");
234+
EmitDiagnostic(
235+
ErrorCode::FileTypeNotSupported,
236+
LogLevel::Warning,
237+
Diagnostics::UnsupportedMeshFormat);
222238
return Result::ErrorUnsupportedFormat;
223239
}
224240

225241
if (!HasMinimumMeshDecodeBytes(decoder, blob))
226242
{
227-
Diagnostics().Add(ErrorCode::Undefined, "Mesh blob is too small for the selected decoder.");
243+
EmitDiagnostic(
244+
ErrorCode::Undefined,
245+
LogLevel::Error,
246+
Diagnostics::MeshBlobTooSmall);
228247
return Result::ErrorMalformedData;
229248
}
230249

231250
MeshDecoder* meshDecoder = CodecRegistry().FindMeshDecoder(decoder);
232251
if (!meshDecoder)
233252
{
234-
Diagnostics().Add(ErrorCode::FileTypeNotSupported, "Mesh decoder is not registered.");
253+
EmitDiagnostic(
254+
ErrorCode::FileTypeNotSupported,
255+
LogLevel::Warning,
256+
Diagnostics::MeshDecoderMissing);
235257
return Result::ErrorUnsupportedFormat;
236258
}
237259

@@ -242,7 +264,10 @@ AssetSuite::Result AssetSuite::Internal::RuntimeContext::DecodeMeshBlob(
242264
MeshDescriptor descriptor = {};
243265
if (!meshDecoder->Decode(decodedBytes, decodeBuffer.data(), descriptor))
244266
{
245-
Diagnostics().Add(ErrorCode::Undefined, "Mesh decoder rejected malformed data.");
267+
EmitDiagnostic(
268+
ErrorCode::Undefined,
269+
LogLevel::Error,
270+
Diagnostics::MeshDecodeRejected);
246271
return MapSelectedDecoderFailure();
247272
}
248273

@@ -294,3 +319,12 @@ void AssetSuite::Internal::RuntimeContext::DispatchLogEvent(LogLevel level, cons
294319

295320
logging.callback(level, message, logging.userData);
296321
}
322+
323+
void AssetSuite::Internal::RuntimeContext::EmitDiagnostic(
324+
ErrorCode code,
325+
LogLevel level,
326+
const char* message)
327+
{
328+
Diagnostics().Add(code, message);
329+
DispatchLogEvent(level, message);
330+
}

source/runtime/AssetSuiteRuntime.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace AssetSuite::Internal
3636

3737
void SetLoggingCallback(LoggingCallback callback, LogLevel minimumLevel, void* userData) noexcept;
3838
void DispatchLogEvent(LogLevel level, const char* message) const;
39+
void EmitDiagnostic(ErrorCode code, LogLevel level, const char* message);
3940

4041
private:
4142
struct LoggingState
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
3+
namespace AssetSuite::Internal::Diagnostics
4+
{
5+
inline constexpr const char* UnsupportedImageFormat =
6+
"ASSET_UNSUPPORTED_FORMAT: Image blob format is not supported.";
7+
inline constexpr const char* ImageBlobTooSmall =
8+
"ASSET_MALFORMED_DATA: Image blob is too small for the selected decoder.";
9+
inline constexpr const char* ImageDecoderMissing =
10+
"ASSET_UNSUPPORTED_FORMAT: Image decoder is not registered.";
11+
inline constexpr const char* ImageDecodeRejected =
12+
"ASSET_MALFORMED_DATA: Image decoder rejected malformed data.";
13+
14+
inline constexpr const char* UnsupportedMeshFormat =
15+
"ASSET_UNSUPPORTED_FORMAT: Mesh blob format is not supported.";
16+
inline constexpr const char* MeshBlobTooSmall =
17+
"ASSET_MALFORMED_DATA: Mesh blob is too small for the selected decoder.";
18+
inline constexpr const char* MeshDecoderMissing =
19+
"ASSET_UNSUPPORTED_FORMAT: Mesh decoder is not registered.";
20+
inline constexpr const char* MeshDecodeRejected =
21+
"ASSET_MALFORMED_DATA: Mesh decoder rejected malformed data.";
22+
23+
inline constexpr const char* BlobLoadFailed =
24+
"ASSET_FILE_LOAD_FAILED: Failed to load blob source file.";
25+
inline constexpr const char* ImageLoadFailed =
26+
"ASSET_FILE_LOAD_FAILED: Failed to load image source file.";
27+
inline constexpr const char* MeshLoadFailed =
28+
"ASSET_FILE_LOAD_FAILED: Failed to load mesh source file.";
29+
}

source/runtime/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ persistent public `BlobHandle`.
6767

6868
The public SDK adapter maps `NonExistingFile` to `Result::ErrorFileNotFound` and `IoFailure` to `Result::ErrorIoFailure`. Text-mode loads append a null terminator after successful reads; binary loads preserve the exact file bytes.
6969

70+
## Diagnostics And Logging
71+
72+
Runtime probe, decode, and file-load failures record private diagnostics and may emit one callback log event through the registered logging callback. Callback messages use stable internal `ASSET_*` prefixes, but diagnostic storage and runtime error details remain private implementation state.
73+
74+
Decode-from-file wrappers own file-load diagnostics only. Once bytes are wrapped in a temporary blob, `DecodeImageBlob` and `DecodeMeshBlob` own probe/decode diagnostics so a single public failure path does not log the same failure twice.
75+
76+
This story keeps cleanup scope limited to cleanup that occurs inside failed file/decode wrapper flows. Explicit invalid cleanup API calls such as failed `ReleaseBlob`, `ReleaseImage`, `ReleaseMesh`, and repeated `DestroyContext` validation remain non-logging paths unless a later story expands that behavior.
77+
7078
## Deferred Scope
7179

7280
This runtime layer is intentionally foundational. The following work is deferred to later stories:

0 commit comments

Comments
 (0)