Skip to content

[FEAT] Per-link codec selection for a single record type #178

Description

@lxsaah

Background

A record type T: Linkable has exactly one codec pair —
T::from_bytes / T::to_bytes (aimdb-data-contracts/src/lib.rs:252) — and every
link uses it. The .linked_from(url) / .linked_to(url) verbs
(aimdb-data-contracts/src/linkable.rs:21) default both directions onto that one
pair, which is the right 80% behaviour.

But the mesh templates will want the same record mirrored over two links with
different wire formats — postcard toward a constrained MCU peer and JSON
toward the cloud/dashboard
. Today the only way to do that is to bypass the
one-line verbs and hand-write the raw .with_serializer() / .with_deserializer()
builders per link (aimdb-data-contracts/src/linkable.rs:37,43), which drops the
ergonomics and re-introduces exactly the codec boilerplate the Linkable verbs
exist to remove.

Proposal

Let the codec be chosen per link while keeping the default intact. Sketch:

// Default (unchanged): uses T::from_bytes / T::to_bytes
reg.linked_to("mqtt://cloud/telemetry");

// Per-link override: same T, different codec toward the MCU
reg.linked_to_with("serial://mcu", Codec::Postcard);

Shape TBD — a codec selector argument on a *_with variant, or a codec marker
threaded into the link builder that dispatches to the matching (de)serializer.
.linked_from / .linked_to keep defaulting to T::from_bytes / T::to_bytes.

Why it's interesting

  • Composes with the existing byte seam — the codecs already exist
    (emit_linkable_postcard at aimdb-codegen/src/rust.rs:996, JSON via
    linkable-json); this is about selecting one per link, not adding formats.

Constraints / risks

  • A record's Linkable impl is a single trait impl, so "a different codec per
    link" cannot live on the type — it has to be expressed at link-wiring time
    (builder/registrar level), which is the design question to settle.
  • Must not regress the one-line default path or the raw-builder escape hatch.

Scope

Registrar/builder ergonomics only. No change to the self-describing
(AimX/MCP/CLI) paths.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions