These are chat archives for rust-lang/rust

24th
Jul 2018
trsh
@trsh
Jul 24 2018 09:05
Can I check in macro, if a some identifier is in scope?
hI!
trsh
@trsh
Jul 24 2018 09:23
Like let x = format!("n1__{}", some_str); let daa: x = something;
trsh
@trsh
Jul 24 2018 09:37
Ot the question cold be, I I can create ty(type) from string
?
Dmitriy
@dpogretskiy
Jul 24 2018 09:39
nope, names are not composable inside of macros if i got you right
Ash
@ashthespy
Jul 24 2018 09:43
Hi ho, How does one tell cargo to use a local git repo?
When I give it the path to the local repo, cargo complains about failing to resolve the network address.
trsh
@trsh
Jul 24 2018 09:53
@dpogretskiy sucks
I have that JSON (value), that I want to load in a Struct. The struct is Generated by bindgen, and has slightly different namings, so I can do it traditional way, as well I need some processing in between.
Dmitriy
@dpogretskiy
Jul 24 2018 09:56
@trsh i just use same names in this case
trsh
@trsh
Jul 24 2018 09:56
json_srde somhave manages to load Json into a struct (and complains if some field is mssing), so sure is some way
@dpogretskiy well as I said I can't arrange same names, and also need some processing and checks
Dmitriy
@dpogretskiy
Jul 24 2018 10:05
then write a mapper that take one thing processes & validates it and spits another, make De/Serializers for both of them and viola
trsh
@trsh
Jul 24 2018 10:06
@dpogretskiy if you have 10 min or so, can you show some example, or pseudo code, as I have no idea what u are talking about? :D
Dmitriy
@dpogretskiy
Jul 24 2018 10:09
fn validate_and_map(struct_one: StructOne) -> StructTwo like this?
read struct one, put it in there, get struct two
with appropriate field names and so on
then serialize struct two and get json you need
trsh
@trsh
Jul 24 2018 11:15
yeah but this hell of manual work
As you see the names differ only by "n1__" something, and I will need some processing for Pointers/cnversations
This just small example, The data IS HUGE
So i still wonder, how serde dynamically can load values in to struct.. So it does's check fields on runtime, and it's possible
Denis Lisov
@tanriol
Jul 24 2018 11:19
@trsh Are the naming differences in struct names only?
Michal 'vorner' Vaner
@vorner
Jul 24 2018 11:19
You can read the generated code, something like cargo expand will show you the code (after you install cargo-expand`)
trsh
@trsh
Jul 24 2018 11:21
@tanriol yes
@vorner for what?
Michal 'vorner' Vaner
@vorner
Jul 24 2018 11:21
So i still wonder, how serde dynamically can load values in to struct..
Denis Lisov
@tanriol
Jul 24 2018 11:22
AFAIK, struct names are not usually used in serialization (unlike field and variant names), or am I wrong?
trsh
@trsh
Jul 24 2018 11:22
@tanriol is still need to convert String to c_char
I twill not work with in-the-box solutions
@vorner but its not Via macro
expand is to see what macro does
Michal 'vorner' Vaner
@vorner
Jul 24 2018 11:23
#[derive(Serialize, Deserialize)] is also a macro and it just generates bunch of code.
trsh
@trsh
Jul 24 2018 11:24
@vorner aaaah, gotcha. It wont work without those
Denis Lisov
@tanriol
Jul 24 2018 11:24
@trsh Ideally I'd try to hook into bindgen and generate the serde attributes needed.
However, note that you've got bigger problems than just deserializing.
trsh
@trsh
Jul 24 2018 11:26
Yes. For example to fill a arr pointer code like unsafe { libc::malloc(std::mem::size_of::<$y>() * $x.len()) as *mut $y }
Is required
Denis Lisov
@tanriol
Jul 24 2018 11:26
Have you already thought about the way you're going to free this memory?
trsh
@trsh
Jul 24 2018 11:27
I could try to create a special derive, that generates code (some special setters, getters), that would be able to handle this conversion. That could be a start point.
@tanriol the end result is one big pointer
That I feed to extern C fn
And then I forget it
Seems to work
Anyways, if someone can show some intersecting solution for my problem.. the link is here https://play.rust-lang.org/?gist=323e02a1df22203b878977f44dc4b4f4&version=stable&mode=debug&edition=2015, Greatly appreciated!
Denis Lisov
@tanriol
Jul 24 2018 11:32
So you expect the function to free it for you... well, that's ok if it's documented to do so...
trsh
@trsh
Jul 24 2018 14:55
In procedual Macro, can I get a field type StuctX, and then get the fields of that (like nested) ?
trsh
@trsh
Jul 24 2018 15:04
Or is what u get is what u see?
trsh
@trsh
Jul 24 2018 15:35
It somehave now written > https://doc.rust-lang.org/book/first-edition/procedural-macros.html > how to read HelloWorldName attribute. Can someone help out?
Ingvar Stepanyan
@RReverser
Jul 24 2018 15:36
syn will pass it as part of the struct
trsh
@trsh
Jul 24 2018 15:36
struct_item.attrs[0] ?
Ingvar Stepanyan
@RReverser
Jul 24 2018 15:37
You need to start from https://docs.rs/syn/0.14/syn/struct.DeriveInput.html which is what you get when you parse input to your derive
You can see attrs field which is attributes on the item itself
Then you search through that vector to find attribute with the name that interests you
trsh
@trsh
Jul 24 2018 15:38
@RReverser ok im there, but how to I get it as str > https://docs.rs/syn/0.14/syn/struct.Attribute.html
Seems like a different thing, like for ! and not ! #
And what stands for name?
Ingvar Stepanyan
@RReverser
Jul 24 2018 15:40
Nope, as it says, it matches all the attributes
You need to check manually which style you're interested in (based on style)
From there, the simplest is to do interpret_meta - most of attributes correspond to that style, and if your attribute is going to correspond to it to, you can just match it

So you'll end up with something like

input.attrs.iter().filter_map(|attr| attr.interpret_meta()).filter(|meta| meta.name() == "my_attr")...

And then you match the actual Meta
trsh
@trsh
Jul 24 2018 15:46
@RReverser so im down to Right attribute. How can I get value from it
?
The Grand question
Ingvar Stepanyan
@RReverser
Jul 24 2018 15:46
match Meta
And extract what you need from corresponding style
(and panic on non-compliant style)
trsh
@trsh
Jul 24 2018 15:56
Holly macaroni
let gg = struct_item.attrs.iter().filter_map(|attr| attr.interpret_meta()).find(|meta| meta.name() == "schema").unwrap();

            match gg {
                syn::Meta::NameValue(v) => {
                    match v.lit {
                        syn::Lit::Str(v) => {
                            println!("{:?}", v.value());
                        }
                        _ => {
                            panic!("kaka");        
                        }
                    }
                }
                _ => {
                    panic!("kaka");
                }
            };
tnx @RReverser
Ingvar Stepanyan
@RReverser
Jul 24 2018 15:57
np
you can merge matches btw
match gg {
    syn::Meta::NameValue(syn::Lit::Str(v)) => {
        println!("{:?}", v.value());
    }
    _ => {
        panic!("kaka");
    }
};
err
well you'll need one more to match .lit
match gg {
    syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(v), .. }) => {
        println!("{:?}", v.value());
    }
    _ => {
        panic!("kaka");
    }
};
I think
but also in proc macro libs it's usually worth adding use syn::*; at the top to reduce noise
most of your imports will come from it anyway
trsh
@trsh
Jul 24 2018 16:01
@RReverser one more q
let output = quote!{  
        impl HelloWorld2 for #name {
            fn hello_world() {
                println!("Hello, World! My name is {}", stringify!(#name));
            }
        }
    };
What if I need hello_world1, and hello_world2 etc. Like generate In loop. Can I do that?
Ingvar Stepanyan
@RReverser
Jul 24 2018 16:02
What do you mean?
Like a list of functions?
trsh
@trsh
Jul 24 2018 16:03
let output = quote!{  
        impl HelloWorld2 for #name {
            // These fn's are generated in loop, dependent one some value
            fn hello_world() {
                println!("Hello, World! My name is {}", stringify!(#name));
            }
 fn hello_world2() {
                println!("Hello, World! My name is {}", stringify!(#name));
            }
        }
    };
Ingvar Stepanyan
@RReverser
Jul 24 2018 16:04
you need to use an iterable variable
simple lazy iterator would work
I don't know where your list is coming from, but basically you'll have something like
let funcs =
  inputs
  .iter()
  .map(|input| quote!(/*... generated code for that particular function ...*/));

let output = quote! {
  impl HelloWorld2 for #name {
    #(#funcs)*
  }
};
trsh
@trsh
Jul 24 2018 16:06
Ahh ok
Cool
tnx
Ingvar Stepanyan
@RReverser
Jul 24 2018 16:06
Sure :)
trsh
@trsh
Jul 24 2018 16:18
@RReverser ok very last q :D ! How do I generate some, for example, fn name from string.. So I can use like fn #fn_name ... ?
Sylwester Rąpała
@xoac
Jul 24 2018 16:48
Any lifetime experts here?
Is possible to create sth like this:
#[derive(Default)]
struct Node<'a> {
    pub parent: Option<&'a Node<'a>>,
}

#[derive(Default)]
struct Holder<'a> {
    main_node: Node<'a>,
    nodes: Vec<Node<'a>>
}

impl<'a> Holder<'a> {
    // `node` need life as long or longer than Holder
    pub fn insert_node(&mut self, node: Node<'a>) -> &mut Self {
        node.parent = Some(&self.main_node); // every `node` in `self.nodes` point to `self.main_mode`
        self.nodes.push(node);
        self
    }
}

fn main() {
    let mut holder: Holder = Default::default();
    let node: Node = Default::default();
    holder.insert_node(node);
}
and link
Ingvar Stepanyan
@RReverser
Jul 24 2018 17:06
@trsh Yeah, Ident it is
@xoac You can't do that as-is because you will end up returning a mutable borrow while still holding an immutable one to the same Holder
Ingvar Stepanyan
@RReverser
Jul 24 2018 17:11
But if you drop the return type and add appropriate lifetime to &mut itself, it becomes possible: https://play.rust-lang.org/?gist=72aea6283c23008dc91ce9bd415dd60a&version=stable&mode=debug&edition=2015
Sylwester Rąpała
@xoac
Jul 24 2018 17:15
where I holding immutable borrow? (In node?)
Ingvar Stepanyan
@RReverser
Jul 24 2018 17:15
yeah
Sylwester Rąpała
@xoac
Jul 24 2018 17:18
So it's a problem
so the solution is to allocate this on Heap with smart pointer?