use super::*;
impl<A: Aleo> Future<A> {
pub fn find<A0: Into<Access<A>> + Clone + Debug>(&self, path: &[A0]) -> Result<Value<A>> {
ensure!(!path.is_empty(), "Attempted to find an argument with an empty path.");
enum ArgumentRefType<'a, A: Aleo> {
Plaintext(&'a Plaintext<A>),
Future(&'a Future<A>),
DynamicFuture(&'a DynamicFuture<A>),
}
let mut value = ArgumentRefType::Future(self);
for access in path.iter() {
let access = access.clone().into();
match (value, &access) {
(ArgumentRefType::Plaintext(Plaintext::Struct(members, ..)), Access::Member(identifier)) => {
match members.get(identifier) {
Some(member) => value = ArgumentRefType::Plaintext(member),
None => bail!("Failed to locate member '{identifier}''"),
}
}
(ArgumentRefType::Plaintext(Plaintext::Array(array, ..)), Access::Index(index)) => {
let index = match index.eject_mode() {
Mode::Constant => index.eject_value(),
_ => bail!("'{index}' must be a constant"),
};
match array.get(*index as usize) {
Some(element) => value = ArgumentRefType::Plaintext(element),
None => bail!("Index '{index}' is out of bounds"),
}
}
(ArgumentRefType::Future(future), Access::Index(index)) => {
let index = match index.eject_mode() {
Mode::Constant => index.eject_value(),
_ => bail!("'{index}' must be a constant"),
};
match future.arguments.get(*index as usize) {
Some(Argument::Future(future)) => value = ArgumentRefType::Future(future),
Some(Argument::Plaintext(plaintext)) => value = ArgumentRefType::Plaintext(plaintext),
Some(Argument::DynamicFuture(dynamic_future)) => {
value = ArgumentRefType::DynamicFuture(dynamic_future)
}
None => bail!("Index '{index}' is out of bounds"),
}
}
_ => bail!("Invalid access `{access}`"),
}
}
match value {
ArgumentRefType::Plaintext(plaintext) => Ok(Value::Plaintext(plaintext.clone())),
ArgumentRefType::Future(future) => Ok(Value::Future(future.clone())),
ArgumentRefType::DynamicFuture(dynamic_future) => Ok(Value::DynamicFuture(dynamic_future.clone())),
}
}
}