Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,25 +155,30 @@ using namespace dross;
number big_num{"99999999999999999999999999999999999999"};
number result = big_num * big_num; // No overflow!

// Dynamic typing
value data = dictionary{
{"name", string{"Dross"}},
{"version", number{"0.0.1"}},
{"features", array{string{"fast"}, string{"safe"}}},
{"release_date", timestamp{2024, 1, 21, 15, 30, 0, timezone::utc()}}
};

// Platform utilities
auto config_dir = xdg::config_home();
auto app_config = config_dir / "myapp" / "config.toml";
// Dynamic typing. dictionary has no initializer-list constructor, so
// entries are assigned after construction.
dictionary config;
config["name"] = string("Dross");
config["version"] = number("0.0.1");
config["features"] = array{string{"fast"}, string{"safe"}};
config["release_date"] = timestamp{2024, 1, 21, 15, 30, 0, timezone::utc()};

value data = config;

// Platform utilities. The XDG accessors are instance methods, and the
// application name is already part of what they return.
xdg app{"myapp"};
if (auto config_dir = app.config_home()) {
path app_config = path{*config_dir}.append("config.toml");
}
```

## 📚 Core Modules

### Type System
- **`boolean`** - Type-safe boolean operations with logical operators
- **`number`** - Arbitrary precision arithmetic with string-based storage
- **`string`** - Unicode-aware string handling
- **`string`** - UTF-8 text held as bytes, with byte-oriented operations
- **`timestamp`** - Date and time handling with timezone support
- **`timezone`** - Type-safe timezone representation with ISO 8601 support
- **`array`** - Dynamic arrays with value semantics
Expand Down Expand Up @@ -201,8 +206,8 @@ Complete documentation including:
Dross follows modern C++ best practices:

- **Pimpl Idiom** - ABI stability through opaque pointers
- **Value Semantics** - All types are copyable and assignable
- **Error Handling** - `std::expected` and `std::optional` instead of exceptions
- **Value Semantics** - The value types are copyable and assignable; `environment` exposes only static members
- **Error Handling** - `std::expected` and `std::optional` for failures, apart from the bounds-checked accessors and the `path` calls that let `std::filesystem` exceptions through
- **Type Safety** - Concepts for compile-time constraints
- **Zero-Cost Abstractions** - Performance without compromise

Expand Down
33 changes: 26 additions & 7 deletions docs/sphinx/source/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,33 +41,52 @@ The dross library follows consistent naming conventions:
Error Handling
--------------

dross does not use exceptions. All operations that may fail return either:
Operations that may fail report it through the return type rather than by
throwing:

- ``std::optional<T>`` for operations that may not produce a value
- ``std::expected<T, error>`` for operations that may fail with error information

Some operations are exceptions to that rule:

- The bounds-checked accessors — the const ``dictionary::operator[]``,
``array::operator[]`` and ``array::value_at()`` — throw
``std::out_of_range`` when the key or index is not present. Ask
``dictionary::contains()`` or ``array::length()`` before indexing.
- ``path::expand()``, despite returning ``std::expected``, lets a
``std::filesystem::filesystem_error`` escape for any canonicalisation
failure on a ``~`` path. ``path::resolve()`` catches those and returns
them.
- ``path``'s ``exists()`` calls the throwing form of
``std::filesystem::exists``, so an error while querying the path — as
opposed to the path simply being absent — escapes as a
``std::filesystem::filesystem_error``.
- The default ``path`` constructor resolves ``"."`` with the throwing form of
``std::filesystem::absolute``.

Example:

.. code-block:: cpp

// Using std::optional
auto env_value = environment::get("MY_VAR");
auto env_value = environment::value("MY_VAR");
if (env_value) {
std::cout << "Value: " << *env_value << std::endl;
}

// Using std::expected
auto result = path::read_file("/path/to/file");
auto result = path::mkdir(std::string{"/path/to/dir"});
if (result) {
process_content(*result);
process_path(result->string());
} else {
handle_error(result.error());
}

Memory Management
-----------------

All types in dross provide value semantics:
The value types provide value semantics, apart from ``environment``, which
exposes only static members:

- Types are copyable and movable
- No manual memory management required
Expand All @@ -81,4 +100,4 @@ Unless otherwise documented:

- Types are not thread-safe for modification
- Const operations are thread-safe
- Copy construction and assignment create independent instances
- Copy construction and assignment create independent instances
Loading
Loading