Closed ta32 closed 3 years ago
Do you think this crate might be of use? https://github.com/vityafx/introspection
I should have mentioned that the function in serde-rs/serde#1110, will get the field names as they are serialized - including the effect of macros. Eg
#[macro_use] extern crate serde;
#[macro_use] extern crate serde_derive;
use serde::de::{self, Deserialize, Deserializer, Visitor};
#[derive(Deserialize)]
#[serde(rename_all = "lowercase")]
enum Setting { On, Off }
fn enum_variants<'de, T>() -> &'static [&'static str]
where T: Deserialize<'de>
{
struct EnumVariantsDeserializer<'a> {
variants: &'a mut Option<&'static [&'static str]>,
}
impl<'de, 'a> Deserializer<'de> for EnumVariantsDeserializer<'a> {
type Error = serde::de::value::Error;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor<'de>
{
Err(de::Error::custom("I'm just here for the variants"))
}
fn deserialize_enum<V>(
self,
_name: &'static str,
variants: &'static [&'static str],
visitor: V
) -> Result<V::Value, Self::Error>
where V: Visitor<'de>
{
*self.variants = Some(variants);
self.deserialize_any(visitor)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct identifier ignored_any
}
}
let mut variants = None;
let _ = T::deserialize(EnumVariantsDeserializer { variants: &mut variants });
variants.unwrap()
}
fn main() {
// prints ["on", "off"]
println!("{:?}", enum_variants::<Setting>());
}
Where as introspection gets the field names generically. Eg because the Setting enum has "#[serde(rename_all = "lowercase")]" the field names will be different.
I am still struggling with understanding the use-case, but that is something you could answer, I guess. If you think it helps, then yes, let's go add it. Would you like to do this or would you like me to do that myself?
I was basically querying an API and de-serializing the results into a vector of structs.
The API needs a query selecting all the field names of the struct, matching how they would be serialized.
For some of the fields I used directives like #[serde(rename = "FIELDNAME")] As the struct member would be field_name.
I created a method for the struct which calls:
let fields = struct_fields::<Self>().to_vec();
This returns a list of field names as they would be serialized/de-serialized by serde.
I can have ago at creating a PR if you want. I guess I would need to create some tests and some usage comments?
Thanks for clarifying the intent and the use case. Yes please, go ahead if you have time. And yes, please, try to provide such doc-comments with tests and usage.
@vityafx I checked out your repo and created a branch where I implemented the changes, but I cant push my branch to remote.
This is my first time contributing to open source so I am not sure about the correct procedure. Do I need to fork the project and merge the code there?
@ta32 Yes, this is how it works. First, you fork a repository so that GitHub knows the connection between a fork and the upstream repository. Then you work with the fork by cloning it and making changes there, and then you open a pull request proposing your changes to be merged to the upstream.
Hi
Would a function implemented in this issue, be useful in this crate? https://github.com/serde-rs/serde/issues/1110
A function like this would eliminate a lot of boiler plate code in my app. I copied and pasted the implementation into my application and it works but I think it would be useful as apart of this library. The original issue was closed.
Note: link has implementation for enum and struct