Hey, I am having an issue with borrowing an Arc in a for loop. I thought Arc had a shared ownership so I am confused on what the issue is. I read through other similar issues although most were solved by calling .to_string() to make a &str reference owned. Is there a way to do that with Arc? I tried to do a clone(), and I tried just changing input_element
to store an optional reference to an element, but both did not work as the value did not live long enough. Could anyone help with this issue?
Here is my code:
struct MyInfoQuestions {
question: String,
input_element: Option<Element<'static>>,
is_required: bool,
input_type: Option<InputType>,
}
fn submit_my_info(tab: Arc<Tab>) -> StepFuture {
Box::pin(async move {
/* Set Up - Prep Time */
let div_elem = match tab.wait_for_element("div[data-automation-id='applyFlowMyInfoPage']") {
Ok(div_elem) => div_elem,
Err(wait_err) => {
return Err(HttpResponse::BadRequest().body(format!("Wait Error: {}", wait_err)));
}
};
let labels = match div_elem.wait_for_elements("label") {
Ok(labels) => labels,
Err(wait_err) => {
return Err(HttpResponse::BadRequest().body(format!("Wait Error: {}", wait_err)));
}
};
// let mut is_radio = false;
// let mut radio_class = "".to_string();
let mut questions = Vec::new();
for label in labels {
let question_opt = label.get_inner_text().ok();
let for_label = if let Ok(label) = label.get_attribute_value("for") {
label
} else {
None
};
let question = if let Some(question) = question_opt {
question
} else {
continue;
};
let is_required = match question.chars().last() {
Some(last_char) => last_char == '*',
None => false,
};
if let Some(label) = for_label {
let input_elem: Element = match tab.find_element(format!("#{}", label).as_str()) {
Ok(elem) => elem,
Err(e) => {
return Err(HttpResponse::BadRequest()
.body(format!("Input For Label Error: {}", e)));
}
};
let input_type = match input_elem.get_attribute_value("type") {
Ok(inp_type) => inp_type,
Err(e) => {
return Err(HttpResponse::BadRequest()
.body(format!("Input Type Label Error: {}", e)));
}
};
match input_type {
Some(input_type) => match input_type.as_str() {
"text" => {
questions.push(MyInfoQuestions {
question,
input_element: Some(input_elem),
is_required,
input_type: Some(InputType::Text),
});
}
"radio" => {
questions.push(MyInfoQuestions {
question,
input_element: Some(input_elem),
is_required,
input_type: Some(InputType::Radio),
});
}
"checkbox" => {
questions.push(MyInfoQuestions {
question,
input_element: Some(input_elem),
is_required,
input_type: Some(InputType::CheckBox),
});
}
_ => {
questions.push(MyInfoQuestions {
question,
input_element: Some(input_elem),
is_required,
input_type: None,
});
}
},
None => {
questions.push(MyInfoQuestions {
question,
input_element: Some(input_elem),
is_required,
input_type: None,
});
}
}
}
}
// let question_and_input = match questions {
// Ok(question) => question,
// Err(err) => {
// return Err(err);
// }
// };
// if let Ok(Some(class)) = elem.get_attribute_value("class") {
// if is_radio {
// radio_class = class.clone();
// is_radio = false
// }
// if class != radio_class {
// radio_class = "".to_string();
// }
// }
// if radio_class != "".to_string() {
// return None;
// }
// if let Ok(Some(id)) = elem.get_attribute_value("id") {
// if id == "radio-label1" {
// is_radio = true;
// }
// }
/* Only Required */
let required_inputs: Vec<_> = questions
.into_iter()
.filter_map(|info| {
if info.is_required {
return Some(info.input_element);
}
None
})
.collect::<Vec<_>>();
println!("First: {:?}", required_inputs[0]);
// println!("Questions: {:?}", question_and_input);
Ok(())
})
}
Here is the error:
256 | fn submit_my_info(tab: Arc<Tab>) -> StepFuture {
| --- binding `tab` declared here
...
291 | let input_elem: Element = match tab.find_element(format!("#{}", label).as_str()) {
| ^^^ borrowed value does not live long enough
...
343 | input_element: Some(input_elem),
| ---------------- this usage requires that `tab` is borrowed for `'static`
...
392 | })
| - `tab` dropped here while still borrowed
Thank you for any help on this.
Edit: Sorry, I figured out the issue. I had to change to:
struct MyInfoQuestions {
question: String,
input_element: Option<Element<'static>>,
is_required: bool,
input_type: Option<InputType>,
}
to
struct MyInfoQuestions<'a> {
question: String,
input_element: Option<Element<'a>>,
is_required: bool,
input_type: Option<InputType>,
}
I get why this solved it because the vector can infer lifetime. Is there a way to pass in another lifetime except for static?