diff options
Diffstat (limited to 'src/makefile/macro.rs')
-rw-r--r-- | src/makefile/macro.rs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/makefile/macro.rs b/src/makefile/macro.rs index 2c8747c..5e7ea9c 100644 --- a/src/makefile/macro.rs +++ b/src/makefile/macro.rs @@ -1,6 +1,8 @@ #[cfg(feature = "full")] use std::cell::RefCell; use std::collections::HashMap; +#[cfg(feature = "full")] +use std::collections::HashSet; use std::env; use std::fmt; #[cfg(feature = "full")] @@ -33,6 +35,64 @@ pub trait LookupInternal: for<'a> Fn(&'a str) -> Result<String> {} impl<F: for<'a> Fn(&'a str) -> Result<String>> LookupInternal for F {} +#[cfg(feature = "full")] +#[derive(Clone)] +pub enum ExportConfig { + Only(HashSet<String>), + AllBut(HashSet<String>), +} + +#[cfg(feature = "full")] +impl ExportConfig { + pub fn all_but() -> Self { + Self::AllBut(HashSet::new()) + } + + pub fn only() -> Self { + Self::Only(HashSet::new()) + } + + pub fn add_all<'a, I: IntoIterator<Item = &'a str>>(&mut self, iter: I) { + match self { + Self::Only(exported) => { + exported.extend(iter.into_iter().map(|x| x.to_owned())); + } + Self::AllBut(not_exported) => { + for added in iter { + not_exported.remove(added); + } + } + } + } + + pub fn remove_all<'a, I: IntoIterator<Item = &'a str>>(&mut self, iter: I) { + match self { + Self::Only(exported) => { + for removed in iter { + exported.remove(removed); + } + } + Self::AllBut(not_exported) => { + not_exported.extend(iter.into_iter().map(|x| x.into())); + } + } + } + + fn same_type(&self) -> Self { + match self { + Self::Only(_) => Self::only(), + Self::AllBut(_) => Self::all_but(), + } + } + + fn should_export(&self, x: &str) -> bool { + match self { + Self::Only(exported) => exported.contains(x), + Self::AllBut(not_exported) => !not_exported.contains(x), + } + } +} + #[derive(Clone)] pub struct Set<'parent, 'lookup> { parent: Option<&'parent Set<'parent, 'lookup>>, @@ -40,6 +100,8 @@ pub struct Set<'parent, 'lookup> { lookup_internal: Option<&'lookup dyn LookupInternal>, #[cfg(feature = "full")] pub to_eval: Rc<RefCell<Vec<String>>>, + #[cfg(feature = "full")] + pub exported: ExportConfig, } impl<'parent, 'lookup> Set<'parent, 'lookup> { @@ -50,6 +112,8 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> { lookup_internal: None, #[cfg(feature = "full")] to_eval: Rc::new(RefCell::new(Vec::new())), + #[cfg(feature = "full")] + exported: ExportConfig::only(), } } @@ -209,6 +273,8 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> { lookup_internal: Some(lookup), #[cfg(feature = "full")] to_eval: Rc::clone(&self.to_eval), + #[cfg(feature = "full")] + exported: self.exported.same_type(), } } @@ -219,8 +285,27 @@ impl<'parent, 'lookup> Set<'parent, 'lookup> { lookup_internal: None, #[cfg(feature = "full")] to_eval: Rc::clone(&self.to_eval), + #[cfg(feature = "full")] + exported: self.exported.same_type(), } } + + #[cfg(feature = "full")] + pub fn resolve_exports(&self) -> Result<Vec<(&str, String)>> { + let own_exports = self + .data + .iter() + .filter(|(name, _)| self.exported.should_export(name)) + .map(|(name, value)| self.expand(&value.text).map(|text| (name.as_ref(), text))) + .collect::<Result<Vec<_>>>()?; + Ok(if let Some(parent) = self.parent { + let mut parent_exports = parent.resolve_exports()?; + parent_exports.extend(own_exports); + parent_exports + } else { + own_exports + }) + } } impl fmt::Display for Set<'_, '_> { |