contract_build/workspace/
profile.rs1use toml::value;
18
19#[derive(Default)]
24pub struct Profile {
25 pub opt_level: Option<OptLevel>,
26 pub lto: Option<Lto>,
27 pub codegen_units: Option<u32>,
29 pub panic: Option<PanicStrategy>,
30 pub overflow_checks: Option<bool>,
31}
32
33impl Profile {
34 pub fn default_contract_release() -> Profile {
36 Profile {
37 opt_level: Some(OptLevel::Z),
38 lto: Some(Lto::Fat),
39 codegen_units: Some(1),
40 panic: Some(PanicStrategy::Abort),
41 overflow_checks: Some(true),
42 }
43 }
44
45 pub(super) fn merge(&self, profile: &mut value::Table) {
53 fn set_value_if_vacant<T>(
54 key: &'static str,
55 value: Option<T>,
56 profile: &mut value::Table,
57 ) where
58 T: Into<value::Value>,
59 {
60 if let Some(value) = value
61 && !profile.contains_key(key)
62 {
63 profile.insert(key.into(), value.into());
64 }
65 }
66 set_value_if_vacant(
67 "opt-level",
68 self.opt_level.map(OptLevel::to_toml_value),
69 profile,
70 );
71 set_value_if_vacant("lto", self.lto.map(Lto::to_toml_value), profile);
72 set_value_if_vacant("codegen-units", self.codegen_units, profile);
73 set_value_if_vacant(
74 "panic",
75 self.panic.map(PanicStrategy::to_toml_value),
76 profile,
77 );
78 set_value_if_vacant("overflow-checks", self.overflow_checks, profile);
79 }
80}
81
82#[allow(unused)]
84#[derive(Clone, Copy)]
85pub enum OptLevel {
86 NoOptimizations,
87 O1,
88 O2,
89 O3,
90 S,
91 Z,
92}
93
94impl OptLevel {
95 fn to_toml_value(self) -> value::Value {
96 match self {
97 OptLevel::NoOptimizations => 0.into(),
98 OptLevel::O1 => 1.into(),
99 OptLevel::O2 => 2.into(),
100 OptLevel::O3 => 3.into(),
101 OptLevel::S => "s".into(),
102 OptLevel::Z => "z".into(),
103 }
104 }
105}
106
107#[derive(Clone, Copy)]
109#[allow(unused)]
110pub enum Lto {
111 ThinLocal,
113 Fat,
115 Thin,
117 Off,
119}
120
121impl Lto {
122 fn to_toml_value(self) -> value::Value {
123 match self {
124 Lto::ThinLocal => false.into(),
125 Lto::Fat => "fat".into(),
126 Lto::Thin => "thin".into(),
127 Lto::Off => "off".into(),
128 }
129 }
130}
131
132#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
134#[allow(unused)]
135pub enum PanicStrategy {
136 Unwind,
137 Abort,
138}
139
140impl PanicStrategy {
141 fn to_toml_value(self) -> value::Value {
142 match self {
143 PanicStrategy::Unwind => "unwind".into(),
144 PanicStrategy::Abort => "abort".into(),
145 }
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use pretty_assertions::assert_eq;
153
154 #[test]
155 fn merge_profile_inserts_preferred_defaults() {
156 let profile = Profile::default_contract_release();
157
158 let manifest_toml = "";
160 let mut expected = value::Table::new();
161 expected.insert("opt-level".into(), value::Value::String("z".into()));
162 expected.insert("lto".into(), value::Value::String("fat".into()));
163 expected.insert("codegen-units".into(), value::Value::Integer(1));
164 expected.insert("panic".into(), value::Value::String("abort".into()));
165 expected.insert("overflow-checks".into(), value::Value::Boolean(true));
166
167 let mut manifest_profile = toml::from_str(manifest_toml).unwrap();
168
169 profile.merge(&mut manifest_profile);
170
171 assert_eq!(expected, manifest_profile)
172 }
173
174 #[test]
175 fn merge_profile_preserves_user_defined_settings() {
176 let profile = Profile::default_contract_release();
177
178 let manifest_toml = r#"
179 panic = "unwind"
180 lto = false
181 opt-level = 3
182 codegen-units = 256
183 overflow-checks = false
184 "#;
185 let mut expected = value::Table::new();
186 expected.insert("opt-level".into(), value::Value::Integer(3));
187 expected.insert("lto".into(), value::Value::Boolean(false));
188 expected.insert("codegen-units".into(), value::Value::Integer(256));
189 expected.insert("panic".into(), value::Value::String("unwind".into()));
190 expected.insert("overflow-checks".into(), value::Value::Boolean(false));
191
192 let mut manifest_profile = toml::from_str(manifest_toml).unwrap();
193
194 profile.merge(&mut manifest_profile);
195
196 assert_eq!(expected, manifest_profile)
197 }
198}