1use alloc::string::ToString;
2use core::borrow::Borrow;
3
4use miden_assembly_syntax::debuginfo::Spanned;
5
6use crate::*;
7
8#[derive(Debug, Clone)]
10pub struct Profile {
11 name: Span<Arc<str>>,
13 debug: bool,
15 trim_paths: bool,
18 metadata: Metadata,
23}
24
25impl Default for Profile {
26 fn default() -> Self {
28 Self {
29 name: Span::unknown("dev".to_string().into_boxed_str().into()),
30 debug: true,
31 trim_paths: false,
32 metadata: Default::default(),
33 }
34 }
35}
36
37impl Profile {
39 pub fn new(name: Span<Arc<str>>) -> Self {
41 Self { name, ..Default::default() }
42 }
43
44 pub fn inherit(name: Span<Arc<str>>, parent: &Self) -> Self {
50 Self { name, ..parent.clone() }
51 }
52
53 pub fn release() -> Self {
55 Self {
56 name: Span::unknown("release".to_string().into_boxed_str().into()),
57 debug: false,
58 trim_paths: true,
59 metadata: Default::default(),
60 }
61 }
62
63 #[cfg(feature = "serde")]
64 pub fn from_ast(
65 ast: &ast::Profile,
66 source: Arc<SourceFile>,
67 inheritable: &[Profile],
68 ) -> Result<Self, Report> {
69 use crate::ast::ProjectFileError;
70
71 let ast::Profile {
72 inherits,
73 name,
74 debug,
75 trim_paths,
76 metadata,
77 } = ast;
78
79 let mut profile = match inherits.as_ref() {
80 Some(parent) => {
81 if let Some(parent) = inheritable.iter().find(|p| p.name() == parent.inner()) {
82 Profile::inherit(name.clone(), parent)
83 } else {
84 return Err(ProjectFileError::UnknownProfile {
85 name: parent.inner().clone(),
86 source_file: source,
87 span: parent.span(),
88 }
89 .into());
90 }
91 },
92 None => Profile::new(name.clone()),
93 };
94
95 if let Some(debug) = *debug {
96 profile.enable_debug_info(debug);
97 }
98
99 if let Some(trim_paths) = *trim_paths {
100 profile.enable_trim_paths(trim_paths);
101 }
102
103 if !metadata.is_empty() {
104 profile.extend(metadata.iter().map(|(k, v)| (k.clone(), v.clone())));
105 }
106
107 Ok(profile)
108 }
109
110 pub fn merge(&mut self, other: &Self) {
115 let Self { name: _, debug, trim_paths, metadata } = self;
116
117 *debug = other.debug;
118 *trim_paths = other.trim_paths;
119 for (k, v2) in other.metadata.iter() {
120 if let Some(v) = metadata.get_mut(k) {
121 match &mut **v {
122 Value::Table(table) => {
123 if let Value::Table(table2) = v2.inner() {
124 table.extend(table2.iter().map(|(k, v)| (k.clone(), v.clone())));
125 } else {
126 *v = v2.clone();
127 }
128 },
129 _ => {
130 *v = v2.clone();
131 },
132 }
133 } else {
134 metadata.insert(k.clone(), v2.clone());
135 }
136 }
137 }
138}
139
140impl Profile {
142 pub fn enable_debug_info(&mut self, yes: bool) -> &mut Self {
144 self.debug = yes;
145 self
146 }
147
148 pub fn enable_trim_paths(&mut self, yes: bool) -> &mut Self {
150 self.trim_paths = yes;
151 self
152 }
153}
154
155impl Profile {
157 pub fn name(&self) -> &Arc<str> {
159 &self.name
160 }
161
162 pub const fn should_emit_debug_info(&self) -> bool {
164 self.debug
165 }
166
167 pub const fn should_trim_paths(&self) -> bool {
170 self.trim_paths
171 }
172
173 #[inline]
175 pub fn contains_key<Q>(&self, key: &Q) -> bool
176 where
177 Q: ?Sized + Ord,
178 Span<Arc<str>>: Borrow<Q> + Ord,
179 {
180 self.metadata.contains_key(key)
181 }
182
183 #[inline]
187 pub fn get<Q>(&self, key: &Q) -> Option<&Span<Value>>
188 where
189 Q: ?Sized + Ord,
190 Span<Arc<str>>: Borrow<Q> + Ord,
191 {
192 self.metadata.get(key)
193 }
194}
195
196impl Extend<(Span<Arc<str>>, Span<Value>)> for Profile {
197 fn extend<T: IntoIterator<Item = (Span<Arc<str>>, Span<Value>)>>(&mut self, iter: T) {
198 self.metadata.extend(iter);
199 }
200}
201
202impl Spanned for Profile {
203 fn span(&self) -> SourceSpan {
204 self.name.span()
205 }
206}