use super::*;
impl<N: Network> Future<N> {
pub fn find<A: Into<Access<N>> + Copy + Debug>(&self, path: &[A]) -> Result<Value<N>> {
ensure!(!path.is_empty(), "Attempted to find an argument with an empty path.");
enum ArgumentRefType<'a, N: Network> {
Plaintext(&'a Plaintext<N>),
Future(&'a Future<N>),
}
let mut value = ArgumentRefType::Future(self);
for access in path.iter() {
let access = (*access).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)) => {
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)) => {
match future.arguments.get(*index as usize) {
Some(Argument::Future(future)) => value = ArgumentRefType::Future(future),
Some(Argument::Plaintext(plaintext)) => value = ArgumentRefType::Plaintext(plaintext),
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())),
}
}
}