Rix is the official package layer for Vix.cpp Browse packages
Skip to content

Debug API

This page documents the public rix/debug API.

Use debug through the unified Rix facade:

cpp
#include <rix.hpp>

Then access debug helpers with:

cpp
rix.debug

The debug API provides helpers for:

txt
printing values
printing to stderr
debug-only printing
formatting strings
appending formatted strings
inspecting values
small example output

rix/debug is designed for examples, local development, quick checks, tests, and small tools.

For real Vix application logs, prefer the Vix logging system:

cpp
vix::log

Package

The debug package is:

txt
rix/debug

For facade usage, install:

bash
vix add rix/rix
vix install

In vix.app:

txt
deps = [
  "rix/rix",
]

For independent package usage, install:

bash
vix add rix/debug
vix install

In vix.app:

txt
deps = [
  "rix/debug",
]

Facade usage:

cpp
#include <rix.hpp>

Independent usage:

cpp
#include <rix/debug.hpp>

Most application examples should use the facade.

Facade member

The debug facade member is:

cpp
rix.debug

Example:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello", "Rix");
  return 0;
}

Main helpers

Common debug helpers are:

cpp
rix.debug.print(...)
rix.debug.eprint(...)
rix.debug.dprint(...)
rix.debug.sprint(...)
rix.debug.format(...)
rix.debug.format.append(...)
rix.debug.format.to(...)
rix.debug.inspect(...)

Use:

cpp
rix.debug.print(...)

Example:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello", "Rix");
  rix.debug.print("count:", 3);
  return 0;
}

print writes values separated by spaces and adds a newline.

Use:

cpp
rix.debug.eprint(...)

Example:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.eprint("error:", "something failed");
  return 0;
}

Use eprint for example errors, diagnostics, and test output.

For production logs in a Vix app, prefer:

cpp
vix::log

Debug-only print

Use:

cpp
rix.debug.dprint(...)

Example:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.dprint("debug value:", 42);
  return 0;
}

Use dprint for temporary debug messages.

Format values into a string

Use:

cpp
const auto text = rix.debug.format(
    "Package: {}",
    "rix/debug");

Example:

cpp
#include <rix.hpp>

int main()
{
  const auto text = rix.debug.format(
      "Package: {}, version: {}",
      "rix/debug",
      1);

  rix.debug.print(text);
  return 0;
}

Placeholder syntax

The formatter supports simple placeholders.

Automatic indexing:

cpp
rix.debug.format("Hello, {}", "Rix");

Explicit positional indexing:

cpp
rix.debug.format("{0} uses {1}", "Rix", "C++");

Escaped braces:

cpp
rix.debug.format("{{ package }} = {}", "ready");

Supported placeholder forms:

txt
{}
{0}
{1}
{2}
{{
}}

Format specifiers are intentionally not supported:

txt
{:>10}
{:.2f}
{:04d}

The formatter is small on purpose.

Automatic placeholders

cpp
const auto message = rix.debug.format(
    "Hello, {}",
    "Ada");

Output shape:

txt
Hello, Ada

Explicit placeholders

cpp
const auto message = rix.debug.format(
    "{0} writes {1}",
    "Ada",
    "C++");

Output shape:

txt
Ada writes C++

Do not mix automatic and explicit indexing in the same format string.

Wrong:

cpp
rix.debug.format("{} {0}", "Ada");

Use one style:

cpp
rix.debug.format("{} {}", "Ada", "C++");

or:

cpp
rix.debug.format("{0} {1}", "Ada", "C++");

Append formatted output

Use:

cpp
rix.debug.format.append(out, "Hello {}", "Rix");

Example:

cpp
#include <rix.hpp>

#include <string>

int main()
{
  std::string out = "message: ";

  rix.debug.format.append(
      out,
      "{}",
      "ready");

  rix.debug.print(out);
  return 0;
}

This appends formatted output to an existing string.

Replace a string with formatted output

Use:

cpp
rix.debug.format.to(out, "Package: {}", "rix/debug");

Example:

cpp
#include <rix.hpp>

#include <string>

int main()
{
  std::string out = "old value";

  rix.debug.format.to(
      out,
      "Package: {}",
      "rix/debug");

  rix.debug.print(out);
  return 0;
}

This clears the string and writes the formatted output into it.

Format errors

Invalid format strings can throw rixlib::format_error.

Examples of invalid format strings:

cpp
rix.debug.format("{", "value");
rix.debug.format("}", "value");
rix.debug.format("{:>10}", "value");

Handle format errors when formatting user-controlled format strings.

cpp
#include <rix.hpp>

int main()
{
  try
  {
    const auto text = rix.debug.format("{", "value");
    rix.debug.print(text);
  }
  catch (const rixlib::format_error &error)
  {
    rix.debug.eprint("format error:", error.what());
    return 1;
  }

  return 0;
}

For fixed application format strings, this is usually not necessary.

Inspect values

Use:

cpp
rix.debug.inspect(value);

Example:

cpp
#include <rix.hpp>

#include <string>
#include <vector>

int main()
{
  std::vector<std::string> values = {
      "Ada",
      "C++",
      "Rix"};

  rix.debug.inspect(values);

  return 0;
}

inspect is useful for examples, tests, and quick diagnostics.

Sprint values into a string

Use:

cpp
const auto text = rix.debug.sprint("Hello", "Rix");

Example:

cpp
#include <rix.hpp>

int main()
{
  const auto text = rix.debug.sprint(
      "Hello",
      "Rix",
      2026);

  rix.debug.print(text);
  return 0;
}

sprint uses the debug rendering pipeline and returns a string.

Complete debug example

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello", "Rix");

  const std::string package = rix.debug.format(
      "Package: {}",
      "rix/rix");

  rix.debug.print(package);

  rix.debug.eprint("stderr:", "diagnostic message");

  rix.debug.inspect(package);

  return 0;
}

Run:

bash
vix run debug.cpp

CSV debug example

cpp
#include <rix.hpp>

int main()
{
  const auto table = rix.csv.parse(
      "name,language\n"
      "Ada,C++\n"
      "Gaspard,Vix\n");

  rix.debug.print("rows:", table.size());
  rix.debug.inspect(table);

  return 0;
}

This uses:

txt
rix.csv
rix.debug

so the unified facade is the right dependency.

PDF debug example

cpp
#include <rix.hpp>

int main()
{
  auto doc = rix.pdf.document();

  auto &page = doc.add_page();

  page.text(
      page.x_left(),
      page.y_top(),
      "Hello from rix.pdf");

  auto saved = rix.pdf.save(doc, "debug-pdf.pdf");

  if (saved.failed())
  {
    rix.debug.eprint(
        "pdf error:",
        rix.pdf.error.to_string(saved.error()),
        saved.error().message());

    return 1;
  }

  rix.debug.print("created:", "debug-pdf.pdf");
  return 0;
}

Auth debug example

cpp
#include <rix.hpp>

int main()
{
  auto auth = rix.auth.memory();

  auto registered = auth.register_user({
      "ada@example.com",
      "correct-password"});

  if (registered.failed())
  {
    rix.debug.eprint(
        "auth error:",
        rix.auth.error.to_string(registered.error()),
        registered.error().message());

    return 1;
  }

  rix.debug.print("registered:", registered.value().email());
  return 0;
}

Do not print passwords, password hashes, raw tokens, or session ids in production output.

Logging note

rix.debug includes a small debug logging helper for simple development output.

Example shape:

cpp
rix.debug.log("loaded {} rows", table.size());
rix.debug.log.warn("slow path: {}", "csv parse");
rix.debug.log.error("failed: {}", "invalid input");

This is useful for examples and local tools.

For real Vix application logging, prefer:

cpp
vix::log

Do not design production Vix apps around rix.debug.log.

Production logging

In a Vix application, prefer Vix logging for application logs.

Use rix.debug for:

txt
examples
tests
small tools
temporary diagnostics
formatting helpers
inspection helpers

Use vix::log for:

txt
production logs
HTTP request logs
service logs
deployment diagnostics
runtime events

Use in a Vix project

Create a Vix app:

bash
vix new rix-debug-api --app
cd rix-debug-api

Add Rix:

bash
vix add rix/rix
vix install

Make sure vix.app contains:

txt
deps = [
  "rix/rix",
]

Use in src/main.cpp:

cpp
#include <rix.hpp>

Build and run:

bash
vix build
vix run

Single-file usage

Create a file:

bash
mkdir -p ~/rix-debug-api
cd ~/rix-debug-api
touch debug.cpp

Add:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello from rix.debug");
  return 0;
}

Run:

bash
vix run debug.cpp

If Rix is not available globally:

bash
vix install -g rix/rix
vix run debug.cpp

Independent usage

Install only debug:

bash
vix add rix/debug
vix install

In vix.app:

txt
deps = [
  "rix/debug",
]

Then include:

cpp
#include <rix/debug.hpp>

Example:

cpp
#include <rix/debug.hpp>

int main()
{
  auto debug = rixlib::debug::module();

  debug.print("Hello from independent rix/debug");

  const auto text = debug.format(
      "Package: {}",
      "rix/debug");

  debug.print(text);

  return 0;
}

Use independent package APIs when you intentionally do not want the unified facade.

For most documentation and application examples, prefer:

cpp
#include <rix.hpp>

and:

cpp
rix.debug

Enable only debug in the facade

Use feature macros when you want the facade style but only want debug mounted:

cpp
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello from debug-only facade");
  return 0;
}

When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.

Enable debug with another package

CSV and debug:

cpp
#define RIX_ENABLE_CSV
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  const auto table = rix.csv.parse(
      "name\n"
      "Ada\n");

  rix.debug.print("rows:", table.size());

  return 0;
}

PDF and debug:

cpp
#define RIX_ENABLE_PDF
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  auto doc = rix.pdf.document();

  rix.debug.print("PDF ready");

  return 0;
}

Auth and debug:

cpp
#define RIX_ENABLE_AUTH
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  auto auth = rix.auth.memory();

  rix.debug.print("auth ready");

  return 0;
}

Format API reference

rix.debug.format supports:

cpp
operator()(std::string_view fmt, const Args &...args)
append(std::string &out, std::string_view fmt, const Args &...args)
to(std::string &out, std::string_view fmt, const Args &...args)

Usage:

cpp
const auto text = rix.debug.format("Hello {}", "Rix");

std::string out;

rix.debug.format.append(out, "A {}", "B");

rix.debug.format.to(out, "C {}", "D");

Debug facade API reference

rix.debug exposes:

cpp
format
log
inspect
print(...)
eprint(...)
dprint(...)
sprint(...)

Use:

cpp
rix.debug.print("Hello", "Rix");
rix.debug.eprint("error:", "failed");
rix.debug.dprint("debug:", 42);
auto text = rix.debug.sprint("Hello", "Rix");

Common mistakes

Forgetting to install Rix

If your code uses:

cpp
#include <rix.hpp>

install:

bash
vix add rix/rix
vix install

If your code uses:

cpp
#include <rix/debug.hpp>

install:

bash
vix add rix/debug
vix install

Putting Rix in packages

Wrong:

txt
packages = [
  "rix/debug",
]

Correct:

txt
deps = [
  "rix/debug",
]

deps is for Vix Registry packages.

packages is for CMake package discovery.

Installing rix/debug but including <rix.hpp>

If your code uses:

cpp
#include <rix.hpp>

then install:

bash
vix add rix/rix
vix install

If your code uses:

cpp
#include <rix/debug.hpp>

then install:

bash
vix add rix/debug
vix install

Using format specifiers

This is not supported:

cpp
rix.debug.format("{:.2f}", 3.14);

Use simple placeholders:

cpp
rix.debug.format("value: {}", 3.14);

Mixing automatic and explicit indexes

Wrong:

cpp
rix.debug.format("{} {0}", "Ada");

Correct:

cpp
rix.debug.format("{} {}", "Ada", "C++");

or:

cpp
rix.debug.format("{0} {1}", "Ada", "C++");

Using rix.debug.log for production logs

rix.debug.log is a small development helper.

For Vix application logs, prefer:

cpp
vix::log

Printing sensitive values

Avoid printing:

txt
passwords
password hashes
raw tokens
session ids
private keys
secrets

This matters especially when using rix.auth.

Mixing facade and independent usage

Avoid this without a clear reason:

cpp
#include <rix.hpp>
#include <rix/debug.hpp>

Use one style per file.

Facade:

cpp
#include <rix.hpp>

Independent:

cpp
#include <rix/debug.hpp>

What you should remember

Print:

cpp
rix.debug.print("Hello", "Rix");

Print errors:

cpp
rix.debug.eprint("error:", "failed");

Format:

cpp
const auto text = rix.debug.format(
    "Package: {}",
    "rix/debug");

Inspect:

cpp
rix.debug.inspect(value);

Use the facade for most examples:

cpp
#include <rix.hpp>

and:

cpp
rix.debug

For project usage:

bash
vix add rix/rix
vix install

and keep:

txt
deps = [
  "rix/rix",
]

For production Vix application logs, prefer:

cpp
vix::log

Next step

Continue with the PDF API.

Next: PDF API

Released under the MIT License.