#include "deimos/core/status.h" #include "deimos/core/api_registry.h" #include "deimos/core/allocator.h" #include "deimos/core/atomic.h" static deimos::AllocatorApi* allocator_api; namespace deimos { StringView StatusCodeToString(StatusCode code) { switch (code) { case StatusCode::kOk: return StringView("OK"); case StatusCode::kUnknown: return StringView("Unknown error"); case StatusCode::kInvalidArgument: return StringView("Invalid argument"); case StatusCode::kUnimplemented: return StringView("Unimplemented"); case StatusCode::kInternal: return StringView("Internal error"); } } struct StatusRep { Atomic ref_count; StatusCode code{}; StringView message; }; Status::Status(StatusCode code, StringView message) { if (code == StatusCode::kOk || message.empty()) { m_rep = CodeToRep(code); } else { void* ptr = allocator_api->system->Allocate((int64_t)sizeof(StatusRep) + message.size() + 1); auto* rep = new(ptr) StatusRep; char* message_ptr = (char*)ptr + sizeof(StatusRep); // NOLINT MemoryCopy(message_ptr, message.data(), message.size()); message_ptr[message.size()] = '\0'; // NOLINT AtomicStore(&rep->ref_count, 1); rep->code = code; rep->message = StringView(message_ptr, message.size()); m_rep = std::bit_cast(rep); Ensures((m_rep & 1U) == 0); } } void Status::Ref() const { if (!IsInline()) { auto* rep = std::bit_cast(m_rep); Expects(AtomicLoad(&rep->ref_count) > 0); AtomicFetchIncrement(&rep->ref_count); } } StatusCode Status::RepCode() const { Expects(!IsInline()); return std::bit_cast(m_rep)->code; } void Status::Unref() const { if (!IsInline()) { auto* rep = std::bit_cast(m_rep); Expects(AtomicLoad(&rep->ref_count) > 0); if (AtomicFetchDecrement(&rep->ref_count, MemoryOrder::kRelease) == 1) { AtomicFence(MemoryOrder::kAcquire); deimos_StaticAssert(std::is_trivially_destructible_v); allocator_api->system->Free( rep, (int64_t)sizeof(StatusRep) + rep->message.size() + 1); } } } void DeimosFormat(IWriter* writer, const Status& status) { if (status.IsInline()) { Format(writer, "[$]", StatusCodeToString(status.code())); } else { auto* rep = std::bit_cast(status.m_rep); Format(writer, "[$: $]", StatusCodeToString(rep->code), rep->message); } } void InitializeStatus(ApiRegistry* api_registry) { allocator_api = api_registry->Get(); } } // namespace deimos