Add field attribute for Key derive to delegate encoding/decoding
I'm not sure the exact way this should work, but the goal is to allow specifying alternate key encoding and decoding implementations for a specific field.
For example, using a "fast" string from one of the various crates out there as a key should be easy, since the type in theory can be just encoded as a String with a small conversion wrapper when serializing/deserializing.
This would hopefully work similar to serde's helpers like serialize_with.
@ModProg: Mentioning you just so that you see the idea and you're looking for something to do someday. This was an idea from someone on Discord.
So should we have
#[derive(Attribute)]
#[attribute(ident = key)]
struct KeyFieldAttribute {
#[attribute(example = "String::from or |field| field.encode()")]
encode_with: Option<Expr>,
#[attribute(example = "From::from or |enc| enc.decode()")]
decode_with: Option<Expr>,
#[attribute(example = "path::module")]
with: Option<Expr>,
// This could make sense as shorthand, i.e. using `From::from` and `Into::into` for the
// conversion
from_into: bool,
}
Though we might have problems with type inference... We could make from_into: Option<Type> take the type to from and into to.
From our Discord conversation:
-
encode_withneeds to accept a reference to avoid cloning data and return a type that implements Key/KeyEncoding. The return type should be able to be borrowed from the parameter passed into the closure. -
decode_with's parameter is the composite key decoder, and it needs to return aResult<T, CompositeKeyError>. The field's value should be able to be constructed viaFieldType::from(T). - For now, we can skip
from_into. I think it's very useful too, but there are complications on how the API should actually work to avoid cloning data when possible.