feat: encode structs via optional Torque.Encoder protocol - #51
Open
gilbertwong96 wants to merge 1 commit into
Open
feat: encode structs via optional Torque.Encoder protocol#51gilbertwong96 wants to merge 1 commit into
gilbertwong96 wants to merge 1 commit into
Conversation
gilbertwong96
force-pushed
the
feat/encoder-protocol
branch
2 times, most recently
from
August 12, 2026 10:19
752b4f3 to
297cb84
Compare
Structs (maps with an atom __struct__ key) are rejected by the NIF
encoder with {:error, :unhandled_struct}; the Elixir layer then runs
the term through the Torque.Encoder protocol and retries once.
- NIF detects structs while encoding maps (zero cost when absent)
- Torque.Encoder protocol with Any fallback (opt-in per struct type)
- normalize/1 recursively encodes protocol output
- consolidation deferred to the host project so it can implement
the protocol for its own structs (e.g. Decimal)
A struct without an implementation still fails with
:unhandled_struct — never silently dropped.
gilbertwong96
force-pushed
the
feat/encoder-protocol
branch
from
August 12, 2026 10:24
297cb84 to
0b9a19f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Structs currently serialize as raw maps (
{"__struct__":"Elixir.Decimal",...}), so there's no way to customize how a struct encodes — e.g.Decimalvalues lose precision as JSON floats past 2^53.This adds an optional
Torque.Encoderprotocol:__struct__key) with{:error, :unhandled_struct}— a single map lookup, so the no-struct fast path stays at zero cost:unhandled_struct— never silently droppedStructs can also derive the implementation with
:only/:except, matching Jason and Elixir's built-inJSON.Encoder:Consolidation is deferred to the host project (
consolidate_protocols: Mix.env() != :test), so apps implement the protocol for their own structs at build time.Breaking change: structs previously encoded as raw maps now error. Happy to add a
structs: :rawopt-out if that's a concern.Nested structs are handled recursively: a protocol implementation may return a term containing other structs, which are normalized in turn. A struct without an implementation fails the whole encode — implement the protocol for each struct type you want to serialize. Structs nested inside jiffy-style
{proplist}tuples are normalized too.