# Utilities and logging
Oxiland provides focused application helpers under
[`oxiland::utility`](https://docs.rs/oxiland/latest/oxiland/utility/) plus
logging on [`World`](https://docs.rs/oxiland/latest/oxiland/struct.World.html)
(optional `tracing` feature).
These helpers use the same `oxiland::Result` and typed error categories as the
model, I/O, and SPARQL APIs. They do not configure global process logging or
silently accept unknown algorithms and malformed IRIs.
## Digests
```rust
use oxiland::utility::{DigestAlgorithm, digest_hex};
assert_eq!(
digest_hex(DigestAlgorithm::Sha256, b"abc"),
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
);
```
Supported names: `md5`, `sha1`, `sha256`. Others return `Error::Unsupported`.
MD5 and SHA-1 are provided for compatibility workflows; do not select them for
new security-sensitive integrity or authentication designs.
## URI and file helpers
- `join_iri` / `relativize_iri` / `resolve_iri`
- `path_to_file_uri` / `file_uri_to_path`
`join_iri` is a path-append helper (not a full RFC 3986 resolver). Prefer
[`Namespace`](https://docs.rs/oxiland/latest/oxiland/utility/struct.Namespace.html)
for `#`-terminated vocabulary bases. Query and fragment on `file://` IRIs are
stripped by `file_uri_to_path`.
Malformed input returns `Error::InvalidRdf` or `Error::Unsupported`—utilities
do not panic.
## Unicode
`normalize_nfc` and `normalize_nfkc` wrap Unicode normalization forms.
## Namespaces and vocabulary
Namespace bases must end with `/`, `#`, or `:` (for example
`https://example.com/` or `http://example.org/ns#`).
```rust
use oxiland::utility::vocab::rdf;
use oxiland::utility::Namespace;
# fn main() -> oxiland::Result<()> {
let ex = Namespace::new("ex", "https://example.com/")?;
assert_eq!(ex.expand("alice")?.as_str(), "https://example.com/alice");
assert_eq!(
rdf::type_().as_str(),
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
);
# Ok(())
# }
```
Curated vocab modules: `rdf`, `rdfs`, `xsd`, `owl`, and `dc` (Dublin Core
Terms `http://purl.org/dc/terms/`, not the older `elements/1.1/` namespace).
## Logging
```rust
use oxiland::{LogFacility, LogLevel, World};
let world = World::new();
world.set_log_level(LogLevel::Info);
```
Enable the Cargo feature `tracing` to also emit `tracing` events. Cloned
`World` values share the same handler and minimum log level.
The handler executes in the calling process. Keep it bounded, avoid re-entering
expensive RDF operations from a log callback, and redact query text, paths, and
literal values according to the application's data policy. Oxiland does not
install a subscriber or choose log destinations for the application.
## Hashes and lists
Redland hash/list types are replaced by `HashMap`, `Vec`, and Rust iterators.
See [migration from Redland](../evaluators/migration-from-redland.md) and
`cargo run --example std_replacements`.
## Production guidance
- Validate external algorithm names, IRIs, and paths at the application edge.
- Use `path_to_file_uri` and `file_uri_to_path` for conversion, not authorization;
authorize the resolved path separately.
- Record digest algorithm names alongside stored digests.
- Treat vocabulary constants as IRIs, not schema validation.
- Keep logging callbacks non-blocking and free of sensitive payloads.
See [Rust production operations](rust-production.md) and the
[security policy](../security.md).