Skip to content

Support NifMap decoding when elixir map has missing fields#746

Open
DanielSidhion wants to merge 3 commits into
rusterlium:masterfrom
DanielSidhion:master
Open

Support NifMap decoding when elixir map has missing fields#746
DanielSidhion wants to merge 3 commits into
rusterlium:masterfrom
DanielSidhion:master

Conversation

@DanielSidhion

Copy link
Copy Markdown

Closes #745.

This PR currently only implements the behaviour for NifMap, but it could in theory support NifStruct as well, although the utility of that is way lower, since elixir structs will always have the fields - but in Rust they could map to a struct with more fields that will always become None.

It also only implements the decoding behaviour, but encoding could be done similarly: if the option is None, don't add that key to the elixir map. I could implement that for completeness.

The PR has 3 commits, it might be easier to review commit by commit to understand the changes faster.
The implementation is not ideal (e.g. the way I check whether a type is Option has false negatives and false positives, as explained in the comments), but given the alternative (explained later) and how the rest of the code behaves, I decided this was a good approach to take.

Instead of checking if the type of a field is Option, we could've done the entire implementation at runtime: when the elixir map doesn't have the field we're looking for, delegate the return value to a trait. This trait would return Ok(None) for Option<T> types, and and Err(_) value for all other types. However, this would require some sort of extra trait to gate the implementation specifically for Option<T>, because we can't just have an implementation for T and Option<T>. My idea here would be to add an extra "marker" trait for each type that implements rustler::Decoder except for Option<T>. This would be a lot of overhead compared to just checking the type at procgen time, so I opted for that approach instead.

This is done in preparation to add field attributes to
rustler, which will reuse some existing logic.

use syn::{Ident, Lit, Meta};

pub(crate) trait TryFromRustlerNestedAttr: Sized {

@DanielSidhion DanielSidhion Jun 12, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name for this trait should change to be a bit more global than just "rustler nested attributes", but I couldn't think of anything interesting. Appreciate any suggestions.

Since field attributes might change the behaviour of code
generated for a specific field, we introduce an extra struct
to hold information about the field and which attributes it
has to make it easier for future code to work with them.
This allows Elixir maps with missing keys to decode as None
variants for fields that are Options, as long as the attribute
is applied to them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support NifMap decoding when elixir map has missing fields

1 participant