How to impliment macros for a struct and use it from a varibale

how do i implement macro logic to use multiple "" brackets in front of variable name.

i have a struct that makes a json like data structure

{
	"one":"some",
	"two":{
		"one":"more"
	}
}

i wanna impliment a macro that can point to a path


let make = Object!{
	"one":{
		"two":{
			"three":"more"
		}
	}
}

//--------------------------------------
//how to implement this

let three = make["one"]["two"]["three"];

//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

So you are saying that you already have the Object macro, right?

Or are you saying that you want to make the Object macro?

i have the object macro

Ah, then you don't even need a macro for that. You can just implement the Index trait for your struct.

Also, in case you don't know already, you the serde_json crate does have that built-in. But you could have any number of reasons for having your own struct, so that could not be what you want:

use serde_json::json;

fn main() {
    let test = json!({
        "one": {
    		"two":{
    			"three":"more"
    		}
    	}  
    });
    
    assert_eq!("more", test["one"]["two"]["three"]);
}

If you want to implement Index you can do it something like this:

use std::collections::HashMap;

#[derive(Debug, Clone, Eq, PartialEq)]
enum MyData {
    Object(HashMap::<String, MyData>),
    String(String),
}

impl std::ops::Index<&str> for MyData {
    type Output = MyData;

    fn index(&self, key: &str) -> &Self::Output {
        match self {
            MyData::Object(map) => map.get(key).unwrap(),
            MyData::String(_) => panic!("Cannot index into string")
        }
    }
}

fn main() {
    let data = MyData::Object({
        let mut h = HashMap::new();
        
        h.insert("one".to_string(), MyData::Object({
            let mut h = HashMap::new();
            
            h.insert("two".to_string(), MyData::String("more".to_string()));
            
            h
        }));
        
        h
    });
    
    assert_eq!(data["one"]["two"], MyData::String("more".to_string()));
}
1 Like

thanks this works perfectly

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.