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))

Search Document