pub mod flag;
use std::collections::HashSet;
use serde::Deserialize;
use serde::Serialize;
use self::flag::Flag as SelectionFlag;
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct File {
#[serde(default, rename = "", skip_serializing_if = "HashSet::is_empty")]
pub per_file: HashSet<SelectionFlag>,
#[serde(default, rename = "*", skip_serializing_if = "HashSet::is_empty")]
pub per_contract: HashSet<SelectionFlag>,
}
impl File {
pub fn new(flags: Vec<SelectionFlag>) -> Self {
let mut per_file = HashSet::new();
let mut per_contract = HashSet::new();
for flag in flags.into_iter() {
match flag {
SelectionFlag::AST => {
per_file.insert(SelectionFlag::AST);
}
flag => {
per_contract.insert(flag);
}
}
}
Self {
per_file,
per_contract,
}
}
pub fn new_required_for_codegen() -> Self {
Self::new(SelectionFlag::codegen_requirements().into())
}
pub fn new_required_for_tests() -> Self {
Self {
per_file: HashSet::from_iter([SelectionFlag::AST]),
per_contract: HashSet::from_iter([
SelectionFlag::EVMBC,
SelectionFlag::EVMDBC,
SelectionFlag::MethodIdentifiers,
SelectionFlag::Metadata,
SelectionFlag::Yul,
]),
}
}
pub fn extend(&mut self, other: Self) -> &mut Self {
self.per_file.extend(other.per_file);
self.per_contract.extend(other.per_contract);
self
}
pub fn selection_to_prune(&self) -> Self {
let unset_per_file = SelectionFlag::all()
.iter()
.copied()
.filter(|flag| !self.per_file.contains(flag))
.collect();
let requests_evm_parent = self.contains(SelectionFlag::EVM);
let evm_children = SelectionFlag::evm_children();
let requests_evm_child = self.contains_any(evm_children);
let unset_per_contract: HashSet<_> = SelectionFlag::all()
.iter()
.copied()
.filter(|flag| {
if requests_evm_parent && evm_children.contains(flag) {
return false;
}
if requests_evm_child && *flag == SelectionFlag::EVM {
return false;
}
!self.per_contract.contains(flag)
})
.collect();
Self {
per_file: unset_per_file,
per_contract: unset_per_contract,
}
}
pub fn contains(&self, flag: SelectionFlag) -> bool {
match flag {
SelectionFlag::AST => self.per_file.contains(&flag),
_ => self.per_contract.contains(&flag),
}
}
pub fn contains_any(&self, flags: &[SelectionFlag]) -> bool {
flags.iter().any(|&flag| self.contains(flag))
}
pub fn requests_codegen(&self) -> bool {
self.contains_any(&[
SelectionFlag::EVM,
SelectionFlag::EVMBC,
SelectionFlag::EVMDBC,
SelectionFlag::Assembly,
])
}
pub fn is_empty(&self) -> bool {
self.per_file.is_empty() && self.per_contract.is_empty()
}
}