# Result Library

## Purpose

<span style="white-space: pre-wrap;">The </span>`<span class="editor-theme-code">result</span>`<span style="white-space: pre-wrap;"> module defines a </span>**shared result code system**<span style="white-space: pre-wrap;"> for the codebase.</span>

Its job is to give functions a consistent way to report success and failure without inventing random local conventions like:

- `<span class="editor-theme-code">0</span>`<span style="white-space: pre-wrap;"> means success here</span>
- `<span class="editor-theme-code">1</span>`<span style="white-space: pre-wrap;"> means success there</span>
- negative values somewhere else
- <span style="white-space: pre-wrap;">and one cursed module returning </span>`<span class="editor-theme-code">true</span>`<span style="white-space: pre-wrap;"> for failure because someone was feeling creative</span>

<span style="white-space: pre-wrap;">Instead, functions return a </span>`<span class="editor-theme-code">result_t</span>`, which makes error handling:

- consistent
- readable
- easier to propagate upward
- easier to log
- easier to document

This module also provides:

- string conversion helpers for result codes
- helper macros for early-return error propagation
- optional logging-aware propagation macros when the logging module is included

## What files belong to this module

This module consists of:

- `<span class="editor-theme-code">result.h</span>`
- `<span class="editor-theme-code">result.c</span>`

### `<span class="editor-theme-code">result.h</span>`

Defines:

- <span style="white-space: pre-wrap;">the </span>`<span class="editor-theme-code">result_t</span>`<span style="white-space: pre-wrap;"> enum</span>
- the public string conversion functions
- the helper macros:
    - `<span class="editor-theme-code">TRY</span>`
    - `<span class="editor-theme-code">TRY_CLEAN</span>`
    - `<span class="editor-theme-code">TRY_LOG</span>`
    - `<span class="editor-theme-code">TRY_LOG_CLEAN</span>`

### `<span class="editor-theme-code">result.c</span>`

Implements:

- `<span class="editor-theme-code">result_to_short_str()</span>`
- `<span class="editor-theme-code">result_to_desc_str()</span>`

## What problem this solves

In an embedded system, functions fail for many reasons:

- invalid arguments
- timeouts
- communication issues
- bad packet formats
- state machine misuse
- lack of memory
- busy resources
- and the usual parade of avoidable pain

<p class="callout info">Without a shared result type, every module ends up inventing its own error style. This library creates one common language for reporting outcomes across modules.</p>

That gives the codebase several benefits:

- function contracts are clearer
- errors can be passed up the call chain without translation
- logs can use the same human-readable error text
- helper macros reduce repetitive boilerplate

## Core design

The design is intentionally simple:

- `<span class="editor-theme-code">RESULT_OK</span>`<span style="white-space: pre-wrap;"> means success</span>
- <span style="white-space: pre-wrap;">every other </span>`<span class="editor-theme-code">result_t</span>`<span style="white-space: pre-wrap;"> value represents a failure or exceptional condition</span>
- functions return a single enum value
- callers decide whether to:
    - handle the error locally
    - return it upward
    - clean up before returning
    - log it before returning

<span style="white-space: pre-wrap;">This makes </span>`<span class="editor-theme-code">result_t</span>`<span style="white-space: pre-wrap;"> a lightweight, shared error protocol.</span>

## Public API overview

The public API consists of:

- `<span class="editor-theme-code">result_t</span>`
- `<span class="editor-theme-code">result_to_short_str()</span>`
- `<span class="editor-theme-code">result_to_desc_str()</span>`
- `<span class="editor-theme-code">TRY(expr)</span>`
- `<span class="editor-theme-code">TRY_CLEAN(expr)</span>`
- `<span class="editor-theme-code">TRY_LOG(expr)</span>`
- `<span class="editor-theme-code">TRY_LOG_CLEAN(expr)</span>`

## String conversion functions

The module provides two functions for converting result codes into human-readable text.

These are useful for:

- logs
- diagnostics
- debug output
- CLI or terminal status messages
- test failure reporting

### `<span class="editor-theme-code">result_to_short_str()</span>`

```c
const char *result_to_short_str(result_t code);
```

#### Purpose

Returns a short label for a result code.

#### Examples

- `<span class="editor-theme-code">RESULT_OK</span>`<span style="white-space: pre-wrap;"> -&gt; </span>`<span class="editor-theme-code">"OK"</span>`
- `<span class="editor-theme-code">RESULT_ERR_TIMEOUT</span>`<span style="white-space: pre-wrap;"> -&gt; </span>`<span class="editor-theme-code">"Timeout"</span>`
- `<span class="editor-theme-code">RESULT_ERR_INVALID_ARG</span>`<span style="white-space: pre-wrap;"> -&gt; </span>`<span class="editor-theme-code">"Invalid Argument"</span>`

#### Default behavior

If the result code is unknown or unsupported, it returns:

```
"Unknown Error"
```

#### Intended use

This is best for compact output such as:

```
ERROR: Timeout
ERROR: Invalid Packet
ERROR: Buffer too small
```

---

### `<span class="editor-theme-code">result_to_desc_str()</span>`

```c
const char *result_to_desc_str(result_t code);
```

#### Purpose

Returns a longer descriptive explanation of a result code.

#### Examples

- `<span class="editor-theme-code">RESULT_OK</span>`<span style="white-space: pre-wrap;"> -&gt; </span>`<span class="editor-theme-code">"The operation completed successfully."</span>`
- `<span class="editor-theme-code">RESULT_ERR_TIMEOUT</span>`<span style="white-space: pre-wrap;"> -&gt; </span>`<span class="editor-theme-code">"An operation failed to complete within the allotted time."</span>`
- `<span class="editor-theme-code">RESULT_ERR_INVALID_ARG</span>`<span style="white-space: pre-wrap;"> -&gt; </span>`<span class="editor-theme-code">"A provided argument is null, out of range, or otherwise invalid."</span>`

#### Default behavior

If the code is unknown or unsupported, it returns:

```
"An unknown error code was encountered."
```

#### Intended use

This is useful when more context is needed, especially in logs:

```
Invalid Argument: A provided argument is null, out of range, or otherwise invalid.
```

---

## Important implementation detail: mapping must stay synchronized

<span style="white-space: pre-wrap;">The enum in </span>`<span class="editor-theme-code">result.h</span>`<span style="white-space: pre-wrap;"> and the switch statements in </span>`<span class="editor-theme-code">result.c</span>`<span style="white-space: pre-wrap;"> must stay synchronized.</span>

<p class="callout warning"><span style="white-space: pre-wrap;">At the moment, they are </span>**not fully synchronized**.</p>

### Why this matters

This causes:

- misleading logs
- incomplete diagnostics
- confusion for anyone trying to use those result codes

### Maintenance rule

<span style="white-space: pre-wrap;">Whenever a new </span>`<span class="editor-theme-code">result_t</span>`<span style="white-space: pre-wrap;"> value is added, both conversion functions must be updated in the same change.</span>

<p class="callout danger">**This should be treated as mandatory.**</p>

## Error propagation macros

<span style="white-space: pre-wrap;">The module provides a set of helper macros that reduce repetitive boilerplate when working with </span>`<span class="editor-theme-code">result_t</span>`.

These macros assume the common pattern:

- <span style="white-space: pre-wrap;">call a function returning </span>`<span class="editor-theme-code">result_t</span>`
- if it failed, stop current flow
- either return immediately or jump to cleanup

---

### `<span class="editor-theme-code">TRY(expr)</span>`

```c
#define TRY(expr) \
  do { \
    result_t _try_status = (expr); \
    if (_try_status != RESULT_OK) { \
      return _try_status; \
    } \
  } while (0)
```

#### Purpose

<span style="white-space: pre-wrap;">Evaluates an expression returning </span>`<span class="editor-theme-code">result_t</span>`.

<span style="white-space: pre-wrap;">If the result is not </span>`<span class="editor-theme-code">RESULT_OK</span>`, the current function immediately returns that result.

#### Example

```c
result_t motor_start(void) {
  TRY(motor_check_ready());
  TRY(motor_enable_power());
  TRY(motor_configure_pwm());

  return RESULT_OK;
}
```

### Expanded behavior

This behaves roughly like:

```c
result_t status = motor_check_ready();
if (status != RESULT_OK) {
  return status;
}
```

for each call.

### When to use it

<span style="white-space: pre-wrap;">Use </span>`<span class="editor-theme-code">TRY()</span>`<span style="white-space: pre-wrap;"> when:</span>

- <span style="white-space: pre-wrap;">the current function also returns </span>`<span class="editor-theme-code">result_t</span>`
- no local cleanup is needed before returning
- you want simple upward propagation

### `<span class="editor-theme-code">TRY_CLEAN(expr)</span>`

```c
#define TRY_CLEAN(expr) \
  do { \
    result_t _try_status = (expr); \
    if (_try_status != RESULT_OK) { \
      goto cleanup; \
    } \
  } while (0)
```

#### Purpose

<span style="white-space: pre-wrap;">Evaluates an expression returning </span>`<span class="editor-theme-code">result_t</span>`.

<span style="white-space: pre-wrap;">If the result is not </span>`<span class="editor-theme-code">RESULT_OK</span>`<span style="white-space: pre-wrap;">, execution jumps to a </span>`<span class="editor-theme-code">cleanup:</span>`<span style="white-space: pre-wrap;"> label.</span>

#### Example

```c
result_t process_frame(void) {
  result_t status = RESULT_OK;
  void *buffer = NULL;

  buffer = malloc(128);
  if (buffer == NULL) {
    return RESULT_ERR_NO_MEM;
  }

  TRY_CLEAN(step_one());
  TRY_CLEAN(step_two());
  TRY_CLEAN(step_three());

  return RESULT_OK;

cleanup:
  free(buffer);
  return RESULT_ERR;
}
```

### `<span class="editor-theme-code">TRY_LOG(expr)</span>`

<span style="white-space: pre-wrap;">When </span>`<span class="editor-theme-code">LOGGING_H</span>`<span style="white-space: pre-wrap;"> is defined, this macro becomes:</span>

```c
#define TRY_LOG(expr) \
  do { \
    result_t _try_status = (expr); \
    if (_try_status != RESULT_OK) { \
      LOGE(TAG, "%s: %s", result_to_short_str(_try_status), \
           result_to_desc_str(_try_status)); \
      return _try_status; \
    } \
  } while (0)
```

#### Purpose

<span style="white-space: pre-wrap;">Like </span>`<span class="editor-theme-code">TRY()</span>`, but also emits a log message before returning.

#### Required assumption

<span style="white-space: pre-wrap;">The surrounding scope must define </span>`<span class="editor-theme-code">TAG</span>`, because the macro calls:

```c
LOGE(TAG, ...)
```

<span style="white-space: pre-wrap;">If </span>`<span class="editor-theme-code">TAG</span>`<span style="white-space: pre-wrap;"> is not defined, compilation will fail.</span>

#### Example

```c
#define TAG "NET"

result_t net_start(void) {
  TRY_LOG(net_hw_init());
  TRY_LOG(net_link_up());

  return RESULT_OK;
}
```

<span style="white-space: pre-wrap;">If </span>`<span class="editor-theme-code">net_link_up()</span>`<span style="white-space: pre-wrap;"> returns </span>`<span class="editor-theme-code">RESULT_ERR_TIMEOUT</span>`, the log might look like:

```
[ERROR] NET: Timeout: An operation failed to complete within the allotted time.
```

and then the function returns that result.

### `<span class="editor-theme-code">TRY_LOG_CLEAN(expr)</span>`

<span style="white-space: pre-wrap;">When </span>`<span class="editor-theme-code">LOGGING_H</span>`<span style="white-space: pre-wrap;"> is defined, this macro becomes:</span>

```c
#define TRY_LOG_CLEAN(expr) \
  do { \
    result_t _try_status = (expr); \
    if (_try_status != RESULT_OK) { \
      LOGE(TAG, "%s: %s", result_to_short_str(_try_status), \
           result_to_desc_str(_try_status)); \
      goto cleanup; \
    } \
  } while (0)
```

#### Purpose

<span style="white-space: pre-wrap;">Like </span>`<span class="editor-theme-code">TRY_CLEAN()</span>`<span style="white-space: pre-wrap;">, but logs before jumping to </span>`<span class="editor-theme-code">cleanup</span>`.

## Behavior when logging is not available

<span style="white-space: pre-wrap;">The logging-aware macros depend on whether </span>`<span class="editor-theme-code">LOGGING_H</span>`<span style="white-space: pre-wrap;"> is defined.</span>

<span style="white-space: pre-wrap;">This means they behave differently depending on whether the logging header has been included before </span>`<span class="editor-theme-code">result.h</span>`.

That is an important design detail.

### <span style="white-space: pre-wrap;">When </span>`<span class="editor-theme-code">LOGGING_H</span>`<span style="white-space: pre-wrap;"> is defined</span>

<span style="white-space: pre-wrap;">If the logging header has already been included, </span>`<span class="editor-theme-code">TRY_LOG</span>`<span style="white-space: pre-wrap;"> and </span>`<span class="editor-theme-code">TRY_LOG_CLEAN</span>`<span style="white-space: pre-wrap;"> perform logging through </span>`<span class="editor-theme-code">LOGE</span>`.

<span style="white-space: pre-wrap;">This couples the macros to the logging module without hard-including it from </span>`<span class="editor-theme-code">result.h</span>`.

<span style="white-space: pre-wrap;">That keeps </span>`<span class="editor-theme-code">result.h</span>`<span style="white-space: pre-wrap;"> lightweight, but also makes behavior depend on include order.</span>

### <span style="white-space: pre-wrap;">When </span>`<span class="editor-theme-code">LOGGING_H</span>`<span style="white-space: pre-wrap;"> is not defined</span>

The code falls back to compiler-specific warning behavior.

#### GCC / Clang

<span style="white-space: pre-wrap;">The macros emit a compile-time warning via </span>`<span class="editor-theme-code">_Pragma(...)</span>`<span style="white-space: pre-wrap;"> and then degrade to:</span>

- `<span class="editor-theme-code">TRY(expr)</span>`
- `<span class="editor-theme-code">TRY_CLEAN(expr)</span>`

#### MSVC

They emit a compiler message and also degrade to the non-logging versions.

#### Other compilers

<span style="white-space: pre-wrap;">A general </span>`<span class="editor-theme-code">#warning</span>`<span style="white-space: pre-wrap;"> is emitted and the macros degrade to the non-logging versions.</span>

#### Practical meaning

If logging is not available, the macros still work for flow control. They just do not log.

## Recommended usage guidelines

### Prefer specific result codes

<span style="white-space: pre-wrap;">Use the most precise </span>`<span class="editor-theme-code">result_t</span>`<span style="white-space: pre-wrap;"> value that matches the failure.</span>

Prefer:

- `<span class="editor-theme-code">RESULT_ERR_INVALID_ARG</span>`
- `<span class="editor-theme-code">RESULT_ERR_TIMEOUT</span>`
- `<span class="editor-theme-code">RESULT_ERR_NOT_INITIALIZED</span>`

over generic:

- `<span class="editor-theme-code">RESULT_FAIL</span>`

when possible.

### <span style="white-space: pre-wrap;">Keep </span>`<span class="editor-theme-code">RESULT_FAIL</span>`<span style="white-space: pre-wrap;"> as fallback only</span>

`<span class="editor-theme-code">RESULT_FAIL</span>`<span style="white-space: pre-wrap;"> should mean:</span>

> “something failed, but no existing specific code fits cleanly.”

It should not become the default.

### <span style="white-space: pre-wrap;">Use </span>`<span class="editor-theme-code">TRY()</span>`<span style="white-space: pre-wrap;"> only in functions returning </span>`<span class="editor-theme-code">result_t</span>`

<span style="white-space: pre-wrap;">Otherwise the generated </span>`<span class="editor-theme-code">return _try_status;</span>`<span style="white-space: pre-wrap;"> is wrong.</span>

### <span style="white-space: pre-wrap;">Use </span>`<span class="editor-theme-code">TRY_CLEAN()</span>`<span style="white-space: pre-wrap;"> only when a cleanup label exists</span>

And only when you understand whether the error code is preserved.

### <span style="white-space: pre-wrap;">Define </span>`<span class="editor-theme-code">TAG</span>`<span style="white-space: pre-wrap;"> before using logging-aware macros</span>

<span style="white-space: pre-wrap;">Without it, </span>`<span class="editor-theme-code">TRY_LOG</span>`<span style="white-space: pre-wrap;"> and </span>`<span class="editor-theme-code">TRY_LOG_CLEAN</span>`<span style="white-space: pre-wrap;"> are not valid.</span>

### Keep conversion functions updated

Whenever a new enum value is added, update:

- `<span class="editor-theme-code">result_to_short_str()</span>`
- `<span class="editor-theme-code">result_to_desc_str()</span>`

in the same commit.

This should be treated as mandatory maintenance.

## Suggested mental model

Think of this module as:

> “The project-wide language for function outcomes.”

It is not just a list of enum values.

<p class="callout info">It defines how modules communicate success and failure to each other, and the helper macros define the common patterns for passing those outcomes upward through the call stack.</p>

That makes it foundational infrastructure, even if the code itself is small and visually innocent.