Factor out reusable parts regarding blueprints from lib/project

So we can re-apply the same logic for applying arguments.
This commit is contained in:
KtorZ 2023-02-04 10:21:45 +01:00
parent 55ecc199d1
commit 9c71aab3db
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
2 changed files with 70 additions and 37 deletions

View File

@ -7,12 +7,12 @@ use aiken_lang::uplc::CodeGenerator;
use error::Error; use error::Error;
use schema::Schema; use schema::Schema;
use std::fmt::{self, Debug, Display}; use std::fmt::{self, Debug, Display};
use validator::Validator; use validator::{Purpose, Validator};
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub struct Blueprint<T> { pub struct Blueprint<T> {
pub preamble: Preamble, pub preamble: Preamble,
pub validators: Vec<validator::Validator<T>>, pub validators: Vec<Validator<T>>,
} }
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
@ -25,6 +25,12 @@ pub struct Preamble {
pub license: Option<String>, pub license: Option<String>,
} }
#[derive(Debug, PartialEq, Clone)]
pub enum LookupResult<'a, T> {
One(&'a T),
Many,
}
impl Blueprint<Schema> { impl Blueprint<Schema> {
pub fn new( pub fn new(
config: &Config, config: &Config,
@ -47,6 +53,56 @@ impl Blueprint<Schema> {
} }
} }
impl<T> Blueprint<T> {
pub fn lookup(
&self,
title: Option<&String>,
purpose: Option<&Purpose>,
) -> Option<LookupResult<Validator<T>>> {
let mut validator = None;
for v in self.validators.iter() {
let match_title = Some(&v.title) == title.or(Some(&v.title));
let match_purpose = Some(&v.purpose) == purpose.or(Some(&v.purpose));
if match_title && match_purpose {
validator = Some(if validator.is_none() {
LookupResult::One(v)
} else {
LookupResult::Many
})
}
}
validator
}
pub fn with_validator<F, A, E>(
&self,
title: Option<&String>,
purpose: Option<&Purpose>,
when_missing: fn(Vec<(String, Purpose)>) -> E,
when_too_many: fn(Vec<(String, Purpose)>) -> E,
action: F,
) -> Result<A, E>
where
F: Fn(&Validator<T>) -> Result<A, E>,
{
match self.lookup(title, purpose) {
Some(LookupResult::One(validator)) => action(validator),
Some(LookupResult::Many) => Err(when_too_many(
self.validators
.iter()
.map(|v| (v.title.clone(), v.purpose.clone()))
.collect(),
)),
None => Err(when_missing(
self.validators
.iter()
.map(|v| (v.title.clone(), v.purpose.clone()))
.collect(),
)),
}
}
}
impl Display for Blueprint<Schema> { impl Display for Blueprint<Schema> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = serde_json::to_string_pretty(self).map_err(|_| fmt::Error)?; let s = serde_json::to_string_pretty(self).map_err(|_| fmt::Error)?;

View File

@ -12,7 +12,7 @@ pub mod pretty;
pub mod script; pub mod script;
pub mod telemetry; pub mod telemetry;
use crate::blueprint::{schema::Schema, validator, Blueprint}; use crate::blueprint::{schema::Schema, validator, Blueprint, LookupResult};
use aiken_lang::{ use aiken_lang::{
ast::{Definition, Function, ModuleKind, TypedDataType, TypedFunction}, ast::{Definition, Function, ModuleKind, TypedDataType, TypedFunction},
builder::{DataTypeKey, FunctionAccessKey}, builder::{DataTypeKey, FunctionAccessKey},
@ -283,8 +283,8 @@ where
pub fn address( pub fn address(
&self, &self,
with_title: Option<&String>, title: Option<&String>,
with_purpose: Option<&validator::Purpose>, purpose: Option<&validator::Purpose>,
stake_address: Option<&String>, stake_address: Option<&String>,
) -> Result<ShelleyAddress, Error> { ) -> Result<ShelleyAddress, Error> {
// Parse stake address // Parse stake address
@ -312,38 +312,15 @@ where
let blueprint: Blueprint<serde_json::Value> = let blueprint: Blueprint<serde_json::Value> =
serde_json::from_reader(BufReader::new(blueprint))?; serde_json::from_reader(BufReader::new(blueprint))?;
// Find validator's program // Calculate the address
let mut program = None; let when_too_many =
for v in blueprint.validators.iter() { |known_validators| Error::MoreThanOneValidatorFound { known_validators };
if Some(&v.title) == with_title.or(Some(&v.title)) let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators };
&& Some(&v.purpose) == with_purpose.or(Some(&v.purpose)) blueprint.with_validator(title, purpose, when_too_many, when_missing, |validator| {
{ Ok(validator
program = Some(if program.is_none() { .program
Ok(v.program.clone()) .address(Network::Testnet, delegation_part.to_owned()))
} else { })
Err(Error::MoreThanOneValidatorFound {
known_validators: blueprint
.validators
.iter()
.map(|v| (v.title.clone(), v.purpose.clone()))
.collect(),
})
})
}
}
// Print the address
match program {
Some(Ok(program)) => Ok(program.address(Network::Testnet, delegation_part)),
Some(Err(e)) => Err(e),
None => Err(Error::NoValidatorNotFound {
known_validators: blueprint
.validators
.iter()
.map(|v| (v.title.clone(), v.purpose.clone()))
.collect(),
}),
}
} }
fn compile_deps(&mut self) -> Result<(), Error> { fn compile_deps(&mut self) -> Result<(), Error> {