aboutsummaryrefslogtreecommitdiff
path: root/src/makefile/macro.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/makefile/macro.rs')
-rw-r--r--src/makefile/macro.rs85
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<'_, '_> {