ecluse:ecluse-core
Safe HaskellNone
LanguageGHC2021

Ecluse.Core.Wire

Description

A table-driven codec for the small "named-enum" wire vocabularies the configuration boundary speaks: a queue or credential provider, the log format, the telemetry switch. Each is a fixed, finite set of wire names, historically hand-rolled as a parse \case, a render \case, and a separately maintained "(expected one of: …)" string -- three places kept in step by hand.

A WireVocab instance carries the vocabulary as one (value, name) table plus the human noun for the set. renderWire and parseWire are derived from it once and dispatched by type, so the rendered names, the parse, and the accepted-set message can no longer drift apart: there is a single list of names per type.

The vocabulary is keyed by type, which means one type speaks exactly one vocabulary. Where a type must be spoken two ways -- a credential provider is named differently as a mirror-target selector than as a per-mount field -- the second vocabulary is a newtype over the first with its own instance (see parseMirrorCredentialProvider).

The only contract is the round trip: for every value an instance's table names, parseWire (renderWire x) == Right x. It holds by construction, since both directions read the one wireTable. No algebraic laws are at stake, so this is deliberately not built on Ord, Semigroup, or Monoid.

Synopsis

Documentation

class WireVocab a where Source #

The wire vocabulary of a named-enum type: the (value, name) table that is the single source of truth for both renderWire and parseWire, and the human noun the rejected-input message names the set with.

Methods

wireKind :: Text Source #

The human noun for the vocabulary, e.g. "queue provider". Names the accepted set in parseWires failure message.

wireTable :: NonEmpty (a, Text) Source #

Every value paired with its wire name, listed in the order the accepted-set message names them. The table is expected to be complete (to list every inhabitant of a); renderWire relies on that.

renderWire :: (Eq a, WireVocab a) => a -> Text Source #

The wire name of a value, looked up in its instance's wireTable -- the inverse of parseWire.

A complete table (the contract every instance keeps) makes this total. A value the table omits -- an instance that has fallen behind its type -- renders as the first entry's name, which the instance's round-trip test surfaces rather than letting it pass silently.

parseWire :: WireVocab a => Text -> Either Text a Source #

Parse a wire name back to its value through the same wireTable, or report the accepted set on an unrecognised input. The failure message is unknown <kind> "<raw>" (expected one of: <names>), the names joined with a comma and a space in table order.