-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
any chance to get a trait tagged to the struct as well that exposes the "FIELD_NAMES_AS_ARRAY" #24
Comments
Thanks for the great feature request. I actually was working on this when I was trying to implement a |
yes, would definitely be helpful, as a way to deal with generics that are deriving this. I don't understand the blackmagic of procmacros enough to guess, in standard macro_rules it seems it would be simple but procmacros are a whole different world lol |
I've been trying to find the right interface and I think I have a solution that I'm okay with. The thing is, having an associated array requires our trait to have a const generic parameter like this: trait FieldNamesAsArray<const N: usize> {
const FIELD_NAMES_AS_ARRAY: [&'static str; N];
} Now that makes it really cumbersome to use it as a bound on a generic type, because we always have to provide struct X {
y: u8,
z: u8,
}
impl FieldNamesAsArray<2> for X {
const FIELD_NAMES_AS_ARRAY: [&'static str; 2] = ["y", "z"];
}
fn foo<const N: usize, T: FieldNamesAsArray<N>>() {
println!("{:?}", T::FIELD_NAMES_AS_ARRAY);
}
// not really an elegant call
foo::<{X::FIELD_NAMES_AS_ARRAY.len()}, X>(); There is a primitive type that behaves enough like an array, without requiring the additional constant size parameter: a slice. Working with a trait that has an associated slice, rather than an associated array, is a lot smoother: trait FieldNamesAsSlice {
const FIELD_NAMES_AS_SLICE: &'static [&'static str];
}
impl FieldNamesAsSlice for X {
const FIELD_NAMES_AS_SLICE: &'static [&'static str] = &X::FIELD_NAMES_AS_ARRAY;
}
fn bar<T: FieldNamesAsSlice>() {
println!("{:?}", T::FIELD_NAMES_AS_SLICE);
}
// a lot better!
bar::<X>(); Unfortunately we are unable to combine both traits (which would've been really cool) in the sense that we have only one trait ( impl<T, const N: usize> FieldNamesAsSlice for T where T: FieldNamesAsArray<N> {
const FIELD_NAMES_AS_SLICE: &'static [&'static str] = &T::FIELD_NAMES_AS_ARRAY;
} This does not work, because nothing stops us from implementing both So since we can't meaningfully combine both traits, we should keep them separated (I want to keep the array variant because of the crate name). That way users can decide if they want to implement use struct_field_names_as_array::{FieldNamesAsArray, FieldNamesAsSlice};
#[derive(FieldNamesAsArray, FieldNamesAsSlice)]
struct Foo {
bar: String,
baz: String,
bat: String,
}
assert_eq!(Foo::FIELD_NAMES_AS_ARRAY, ["bar", "baz", "bat"]);
assert_eq!(Foo::FIELD_NAMES_AS_ARRAY, Foo::FIELD_NAMES_AS_SLICE); Any thoughts on the proposed API? I feel like a |
Holy crap I, really sent you down a rabbit hole LOL... API is definitely nicer looking to work with on the slice, I'm pretty sure you've covered the edge cases, and having it accessible as a slice to be able to work with the generics is definitely an improvement to usability. Honestly if it wasn't for the name of the crate the slice feels nicer in general to me, but that might just be me. One question though you mentioned ... My question is i don't see how this occurs unless someones purposefully trying to manually implement it on purpose to break it, since the crates designed to be used as a derive, I can't really derive the same struct with different amounts of properties, unless i'm missing something. |
Yeah. Originally I published
Yes sorry for this convoluted description. What I wanted to say is that the compiler doesn't know that there will only ever be a single |
Ya that clears things up, and makes sense lol, adding an AsSlice with the trait would be great, and solve most of the hang ups... Guess that the one good thing for when people name crates obscure words instead of what they do because it gives flexibility XD. Any chance you'll release a version with the FielNamesAsSlice+Trait available? |
Yes, definitely. Would've already started but had a chaotic schedule lately. This week or maybe next I should be ready with the |
Released |
I'm using generics and based on the generic type i need the field names, but right now i can't do a T::FIELD_NAMES_AS_ARRAY because there's no way for me to say the T implements that.
The text was updated successfully, but these errors were encountered: