revive_solc_json_interface/standard_json/input/settings/selection/file/
mod.rs

1//! The `solc --standard-json` output file selection.
2
3pub mod flag;
4
5use std::collections::HashSet;
6
7use serde::Deserialize;
8use serde::Serialize;
9
10use self::flag::Flag as SelectionFlag;
11
12/// The `solc --standard-json` output file selection.
13#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
14pub struct File {
15    /// The per-file output selections.
16    #[serde(default, rename = "", skip_serializing_if = "HashSet::is_empty")]
17    pub per_file: HashSet<SelectionFlag>,
18    /// The per-contract output selections.
19    #[serde(default, rename = "*", skip_serializing_if = "HashSet::is_empty")]
20    pub per_contract: HashSet<SelectionFlag>,
21}
22
23impl File {
24    /// A shortcut constructor.
25    pub fn new(flags: Vec<SelectionFlag>) -> Self {
26        let mut per_file = HashSet::new();
27        let mut per_contract = HashSet::new();
28        for flag in flags.into_iter() {
29            match flag {
30                SelectionFlag::AST => {
31                    per_file.insert(SelectionFlag::AST);
32                }
33                flag => {
34                    per_contract.insert(flag);
35                }
36            }
37        }
38        Self {
39            per_file,
40            per_contract,
41        }
42    }
43    /// Creates the selection required for production compilation (excludes EVM bytecode).
44    pub fn new_required() -> Self {
45        Self {
46            per_file: HashSet::from_iter([SelectionFlag::AST]),
47            per_contract: HashSet::from_iter([
48                SelectionFlag::MethodIdentifiers,
49                SelectionFlag::Metadata,
50                SelectionFlag::Yul,
51            ]),
52        }
53    }
54
55    /// Creates the selection required for test compilation (includes EVM bytecode).
56    pub fn new_required_for_tests() -> Self {
57        Self {
58            per_file: HashSet::from_iter([SelectionFlag::AST]),
59            per_contract: HashSet::from_iter([
60                SelectionFlag::EVMBC,
61                SelectionFlag::EVMDBC,
62                SelectionFlag::MethodIdentifiers,
63                SelectionFlag::Metadata,
64                SelectionFlag::Yul,
65            ]),
66        }
67    }
68
69    /// Extends the user's output selection with flag required by our compilation process.
70    pub fn extend_with_required(&mut self) -> &mut Self {
71        let required = Self::new_required();
72
73        self.per_file.extend(required.per_file);
74        self.per_contract.extend(required.per_contract);
75
76        self
77    }
78
79    /// Extends the output selection with another one.
80    pub fn extend(&mut self, other: Self) -> &mut Self {
81        self.per_file.extend(other.per_file);
82        self.per_contract.extend(other.per_contract);
83        self
84    }
85
86    /// Returns flags that are going to be automatically added by the compiler,
87    /// but were not explicitly requested by the user.
88    ///
89    /// Afterwards, the flags are used to prune JSON output before returning it.
90    pub fn selection_to_prune(&self) -> Self {
91        let required_per_file = vec![SelectionFlag::AST];
92        let required_per_contract = vec![
93            SelectionFlag::MethodIdentifiers,
94            SelectionFlag::Metadata,
95            SelectionFlag::Yul,
96        ];
97
98        let mut unset_per_file = HashSet::with_capacity(required_per_file.len());
99        let mut unset_per_contract = HashSet::with_capacity(required_per_contract.len());
100
101        for flag in required_per_file {
102            if !self.per_file.contains(&flag) {
103                unset_per_file.insert(flag);
104            }
105        }
106        for flag in required_per_contract {
107            if !self.per_contract.contains(&flag) {
108                unset_per_contract.insert(flag);
109            }
110        }
111        Self {
112            per_file: unset_per_file,
113            per_contract: unset_per_contract,
114        }
115    }
116    /// Whether the flag is requested.
117    pub fn contains(&self, flag: &SelectionFlag) -> bool {
118        match flag {
119            flag @ SelectionFlag::AST => self.per_file.contains(flag),
120            flag => self.per_contract.contains(flag),
121        }
122    }
123
124    /// Checks whether the selection is empty.
125    pub fn is_empty(&self) -> bool {
126        self.per_file.is_empty() && self.per_contract.is_empty()
127    }
128}