I am facing an error that I have failed to understand properly, maybe I have insufficient knowledge on closure and there proper use. The error is can't capture dynamic environment in a fn item use the `|| { ... }` closure form instead
I have defined closures for the handle_app_add_new_app
in the AppParams
impl as well. All code has been shared below.
main.rs
use std::collections::HashMap;
use std::fs::OpenOptions;
use std::{str, io::Write as write};
use std::env;
mod utils;
use utils::*;
fn main() {
let args: Vec<String> = env::args().collect();
let chain_id = args[0];
let chain_address = args[1];
let appname = args[2];
let abi_endpoint = args[3];
let app_address = args[4];
let token_name = args[5];
let token_address = args[6];
let new_token = &TokenParams::new(&token_name, &token_address);
let mut chain_tokens = HashMap::new();
// Add new tokens to chain.
chain_tokens.insert(
new_token.token_name,
new_token.token_address,
);
let app = AppParams::new(
&appname, &abi_endpoint, &app_address, &chain_tokens
);
pub unsafe fn convert_to_u8<T: Sized>(p: &T) -> &[u8] {
::std::slice::from_raw_parts(
(p as *const T) as *const u8,
::std::mem::size_of::<T>(),
)
}
//add new application(dex,payments...etc)
pub async fn handle_add_new_app(chain_id: &str, chain_address: &str,) -> Box<dyn Fn(ChainParams) -> ChainParams>{
let new_app= Box::new(|x| ChainParams::new(
&chain_id,
&chain_address,
app,
));
let bytes: &[u8] = unsafe {convert_to_u8(&new_app) };
let mut updated_file = OpenOptions::new().append(true).open("config.json").expect("Unable to open file");
updated_file.write_all(bytes).expect("adding app to config failed");
new_app
}
}
The utils file
use std::{error::Error, collections::HashMap};
use serde_json::Value;
#[derive(serde::Deserialize)]
pub struct Addresses{
pub to_address: String,
pub from_address: String,
}
impl Addresses{}
#[derive(serde::Deserialize)]
pub struct TokenParams {
pub token_name: String,
pub token_address: String,
}
impl TokenParams{
/// create a new token instance
pub fn new(token_name: &str, token_address: &str) -> Self {
let token_name = token_name;
let token_address = token_address;
TokenParams {
token_address: token_address.to_string(),
token_name: token_name.to_string(),
}
}
pub fn get_token(chain: &str, app: &str) -> Result<Vec<Value>, Box<dyn Error>>{
let token_getter = {
// Load the first file into a string.
let config = std::fs::read_to_string("Config.json").unwrap();
// Parse the string into a dynamically-typed JSON structure.
serde_json::from_str::<Value>(&config).unwrap()
};
// Get the get tokens with chain and app(eg dex)
let chain_elements = token_getter[chain][app].as_array().unwrap();
Ok(chain_elements.to_vec())
}
}
#[derive(serde::Deserialize)]
pub struct AppParams {
pub appname: String,
pub abi_endpoint: String,
pub app_address: String,
#[serde(flatten)]
pub tokens: HashMap<String, String>
}
impl AppParams{
/// create a new App(dex, marketplace...etc) instance
pub fn new(appname: &str, abi_endpoint: &str, address: &str, tokens: &HashMap<String, String>) -> Box<dyn Fn(AppParams) -> AppParams> {
let appname = appname;
let abi_endpoint = abi_endpoint;
let address = address;
let mut app_tokens = HashMap::new();
Box::new(|x| AppParams {
appname: appname.to_string(),
abi_endpoint: abi_endpoint.to_string(),
tokens: app_tokens,
app_address: address.to_string(),
})
}
pub fn get_app_params(self, chain: &str) -> Result<Vec<Value>, Box<dyn Error>>{
let app_getter = {
// Load the first file into a string.
let config = std::fs::read_to_string("Config.json").unwrap();
// Parse the string into a dynamically-typed JSON structure.
serde_json::from_str::<Value>(&config).unwrap()
};
// Get the get tokens with chain and app(eg dex)
let chain_elements = app_getter[chain][self.appname].as_array().unwrap();
Ok(chain_elements.to_vec())
}
}
#[derive(serde::Deserialize)]
pub struct ChainParams {
pub chain_id: String,
pub chain_address: String,
#[serde(flatten)]
pub chain_application: Vec<AppParams>,
}
impl ChainParams{
/// get an App(dex, marketplace...etc) instance
pub fn new(chain_id: &str, chain_address: &str, chain_application: AppParams ) -> Self {
let chain_id = chain_id;
let chain_address = chain_address;
let new_tokens = HashMap::new();
let new_application = AppParams::new(
&chain_application.appname,
&chain_application.abi_endpoint,
&chain_application.app_address,
&new_tokens,
);
ChainParams {
chain_id: chain_id.to_string(),
chain_address: chain_address.to_string(),
chain_application: vec![new_application(chain_application)],
}
}
//get chain params
pub fn get_chain_params(self) -> Result<Vec<Value>, Box<dyn Error>>{
let app_getter = {
// Load the first file into a string.
let config = std::fs::read_to_string("Config.json").unwrap();
// Parse the string into a dynamically-typed JSON structure.
serde_json::from_str::<Value>(&config).unwrap()
};
// Get the get tokens with chain and app(eg dex)
let chain_elements = app_getter[self.chain_id].as_array().unwrap();
Ok(chain_elements.to_vec())
}
}
A detailed explanation of your answer will be highly appreciated.