tadpole/model/decode
Shared plumbing for the model JSON decoders: snowflake ID fields and the wrapper that turns gleam/json parse errors into DecodeFailed. Nothing here knows about specific models. Gateway and REST wiring call these with the event name they know; the model-level from_json helpers leave the event empty.
from_json takes either a bare event object or a full gateway frame
envelope with the event object under d, because both shapes arrive
in practice: the shard decodes dispatch frames as the envelope, the
REST paths decode bare response objects.
Internals: snowflake_id validates Discord’s string ids inside the
decoder pipeline (a non-snowflake string fails with the offending
text in got), and from_json reports the first failure with a
JSON path — fields joined by dots, list indices in brackets. See
also tadpole/types/ids for the constructors
and tadpole/error for the DecodeFailed shape.
Values
pub fn from_json(
event: option.Option(String),
payload: String,
decoder: decode.Decoder(t),
) -> Result(t, error.TadpoleError)
Parse payload with decoder, folding every failure into
error.DecodeFailed. event is the gateway event name when known, for
example Some(“MESSAGE_CREATE”); None suits REST responses.
The payload may be a bare event object (what the model from_json
helpers and the REST paths get) or a full gateway frame envelope with
the event object under d (what frame.parse hands the shard). When
the parsed JSON carries a d field, the decoder runs on that inner
value; otherwise it runs on the payload as-is.
The reported path is relative to the event object: fields join with
dots, list indices go in brackets (author.id, mentions[0].username),
and a payload that is not JSON at all reports $. Only the first
problem found is reported — fix it and re-run to see the next one.
pub fn snowflake_id(
constructor: fn(String) -> Result(id, ids.InvalidId),
) -> decode.Decoder(id)
A decoder for one Discord ID field. Discord sends snowflakes as JSON
strings, so the raw string is validated with constructor (ids.user_id
and friends) inside the decoder pipeline. A non-string fails as an
ordinary type mismatch; a string that is not a snowflake fails with the
offending text in the error’s got.
e.g. use id <- d.field("id", decode.snowflake_id(ids.user_id))