Problem
Every variant of DbError (aimdb-core/src/error.rs) carries different fields per target:
RecordKeyNotFound {
#[cfg(feature = "std")]
key: String,
#[cfg(not(feature = "std"))]
_key: (),
},
This design multiplies cost across the whole codebase:
- Every construction site needs a dual
#[cfg] branch. builder.rs alone has ~8 of these blocks; typed_record.rs, typed_api.rs, and the adapters repeat the pattern. Helper constructors (DbError::runtime_error, record_key_not_found, …) exist but only cover some paths, so both styles coexist.
- Error context is silently discarded on embedded targets — exactly where debugging is hardest. The
no_std Display impl can only print a numeric code.
- The
no_std shape cannot be tested from a std build — the enum is literally a different type per target.
The kicker: aimdb-core always requires alloc (extern crate alloc is unconditional, and every feature builds on the alloc feature). alloc::string::String is available on every supported target, and thiserror 2.x supports no_std. The dual-field design solves a problem the crate does not have.
Proposal
- Give every
DbError variant one shape, using alloc::string::String for context fields unconditionally.
- Derive
thiserror::Error + #[error(...)] unconditionally (thiserror 2.x is no_std-capable); delete the hand-written no_std Display impl with its numeric-code table.
- Delete every dual construction branch at call sites (
builder.rs, typed_record.rs, typed_api.rs, connectors, adapters) — each collapses to a single expression.
- Keep the
#[cfg(feature = "std")]-only variants that genuinely wrap std types (Io, Json, sync-API timeouts) — those gates are legitimate.
- Keep (and prefer) the existing helper constructors so future call sites stay one-liners.
If String formatting cost on MCU ever becomes a measured concern, the answer is still one shape (e.g. &'static str context), not two enums behind cfg.
Affected files (non-exhaustive)
aimdb-core/src/error.rs — variant definitions, Display impl, helpers
aimdb-core/src/builder.rs, typed_record.rs, typed_api.rs — dual construction sites
aimdb-tokio-adapter, aimdb-embassy-adapter, connectors — error mapping sites (e.g. the #[cfg] branches in aimdb-knx-connector/src/tokio_client.rs)
Acceptance criteria
Estimated effect
−400 to −600 lines of pure noise; every future error site is one branch instead of two.
See docs/design/034-technical-debt-review.md §3.1.1 and Phase 1 of the remediation roadmap for full context.
Problem
Every variant of
DbError(aimdb-core/src/error.rs) carries different fields per target:This design multiplies cost across the whole codebase:
#[cfg]branch.builder.rsalone has ~8 of these blocks;typed_record.rs,typed_api.rs, and the adapters repeat the pattern. Helper constructors (DbError::runtime_error,record_key_not_found, …) exist but only cover some paths, so both styles coexist.no_stdDisplayimpl can only print a numeric code.no_stdshape cannot be tested from a std build — the enum is literally a different type per target.The kicker:
aimdb-corealways requiresalloc(extern crate allocis unconditional, and every feature builds on theallocfeature).alloc::string::Stringis available on every supported target, andthiserror2.x supportsno_std. The dual-field design solves a problem the crate does not have.Proposal
DbErrorvariant one shape, usingalloc::string::Stringfor context fields unconditionally.thiserror::Error+#[error(...)]unconditionally (thiserror 2.x isno_std-capable); delete the hand-writtenno_stdDisplayimpl with its numeric-code table.builder.rs,typed_record.rs,typed_api.rs, connectors, adapters) — each collapses to a single expression.#[cfg(feature = "std")]-only variants that genuinely wrap std types (Io,Json, sync-API timeouts) — those gates are legitimate.If
Stringformatting cost on MCU ever becomes a measured concern, the answer is still one shape (e.g.&'static strcontext), not two enums behindcfg.Affected files (non-exhaustive)
aimdb-core/src/error.rs— variant definitions,Displayimpl, helpersaimdb-core/src/builder.rs,typed_record.rs,typed_api.rs— dual construction sitesaimdb-tokio-adapter,aimdb-embassy-adapter, connectors — error mapping sites (e.g. the#[cfg]branches inaimdb-knx-connector/src/tokio_client.rs)Acceptance criteria
DbErrorvariant has#[cfg]-gated fields; no_field: ()placeholders remain#[cfg(feature = "std")]/#[cfg(not(feature = "std"))]pairs exist purely to construct aDbErrorno_stdbuilds produce the same error messages as std builds (modulo std-only variants)cargo build -p aimdb-core --no-default-features --features allocand the embedded targets (make test-embedded) still pass_key: ()→key: String) noted in the changelog as a no_std-only breaking changeEstimated effect
−400 to −600 lines of pure noise; every future error site is one branch instead of two.
See
docs/design/034-technical-debt-review.md§3.1.1 and Phase 1 of the remediation roadmap for full context.