fn substitute<'a, 'b>(
  s: &'a str,
  vars: &'b HashMap<&'b str, &'b str>,
  used_vars: &mut HashSet<String>,
  max_recursion_depth: u8
) -> Option<String> {
  lazy_static! {
    static ref VAR: Regex = Regex::new(r"\$(?:([A-Za-z0-9_]+)|\{([A-Za-z0-9_]+)\})").unwrap();
  }

  // note: docker also allows defaults in FROMs, e.g.
  //   ARG tag
  //   FROM alpine:${tag:-3.12}
  // this isn't currently supported.

  let mut splicer = Splicer::from_str(s);

  for caps in VAR.captures_iter(s) {
    if max_recursion_depth == 0 {
      // can't substitute, so give up
      return None;
    }

    let full_range = caps.get(0)?.range();
    let var_name = caps.get(1).or_else(|| caps.get(2))?;
    let var_content = vars.get(var_name.as_str())?;
    let substituted_content = substitute(
      var_content,
      vars,
      used_vars,
      max_recursion_depth.saturating_sub(1)
    )?;
    used_vars.insert(var_name.as_str().to_string());

    // splice the substituted content back into the output string
    splicer.splice(&Span::new(full_range.start, full_range.end), &substituted_content);
  }

  Some(splicer.content)
}
/// Given a map of key/value pairs, perform variable substitution on a given
/// input string. `max_recursion_depth` controls the maximum allowed recursion
/// depth if variables refer to other strings themselves containing variable
/// references. A small number but reasonable is recommended by default, e.g.
/// 16.
/// If None is returned, substitution was impossible, either because a
/// referenced variable did not exist, or recursion depth was exceeded.
Given a map of key/value pairs, perform variable substitution on a given
input string. `max_recursion_depth` controls the maximum allowed recursion
depth if variables refer to other strings themselves containing variable
references. A small number but reasonable is recommended by default, e.g.
16.
If None is returned, substitution was impossible, either because a
referenced variable did not exist, or recursion depth was exceeded.
Given a map of key / value pairs perform variable substitution on a given input string . ` max_recursion_depth ` controls the maximum allowed recursion depth if variables refer to other strings themselves containing variable references . A small number but reasonable is recommended by default e . g . 16 . If None is returned substitution was impossible either because a referenced variable did not exist or recursion depth was exceeded .
fn substitute<'a, 'b>(
  s: &'a str,
  vars: &'b HashMap<&'b str, &'b str>,
  used_vars: &mut HashSet<String>,
  max_recursion_depth: u8
) -> Option<String> {
  lazy_static! {
    static ref VAR: Regex = Regex::new(r"\$(?:([A-Za-z0-9_]+)|\{([A-Za-z0-9_]+)\})").unwrap();
  }
  // note: docker also allows defaults in FROMs, e.g.
  //   ARG tag
  //   FROM alpine:${tag:-3.12}
  // this isn't currently supported.
  let mut splicer = Splicer::from_str(s);
  for caps in VAR.captures_iter(s) {
    if max_recursion_depth == 0 {
      // can't substitute, so give up
      return None;
    }
    let full_range = caps.get(0)?.range();
    let var_name = caps.get(1).or_else(|| caps.get(2))?;
    let var_content = vars.get(var_name.as_str())?;
    let substituted_content = substitute(
      var_content,
      vars,
      used_vars,
      max_recursion_depth.saturating_sub(1)
    )?;
    used_vars.insert(var_name.as_str().to_string());
    // splice the substituted content back into the output string
    splicer.splice(&Span::new(full_range.start, full_range.end), &substituted_content);
  }
  Some(splicer.content)
}
fn substitute < ' a , ' b > ( s : & ' a str , vars : & ' b HashMap < & ' b str , & ' b str > , used_vars : & mut HashSet < String > , max_recursion_depth : u8 ) -> Option < String > { lazy_static ! { static ref VAR Regex Regex new ( r"\$(?:([A-Za-z0-9_]+)|\{([A-Za-z0-9_]+)\})" ) unwrap ( ) } // note: docker also allows defaults in FROMs, e.g. //   ARG tag //   FROM alpine:${tag:-3.12} // this isn't currently supported. let mut splicer = Splicer :: from_str ( s ) ; for caps in VAR . captures_iter ( s ) { if max_recursion_depth == 0 { // can't substitute, so give up return None ; } let full_range = caps . get ( 0 ) ? . range ( ) ; let var_name = caps . get ( 1 ) . or_else ( | | caps . get ( 2 ) ) ? ; let var_content = vars . get ( var_name . as_str ( ) ) ? ; let substituted_content = substitute ( var_content , vars , used_vars , max_recursion_depth . saturating_sub ( 1 ) ) ? ; used_vars . insert ( var_name . as_str ( ) . to_string ( ) ) ; // splice the substituted content back into the output string splicer . splice ( & Span :: new ( full_range . start , full_range . end ) , & substituted_content ) ; } Some ( splicer . content ) }
Given a map of key/value pairs, perform variable substitution on a given
input string.
Given a map of key / value pairs perform variable substitution on a given input string .
s
&'a str
vars
&'b HashMap<&'b str, &'b str>
used_vars
&mut HashSet<String>
max_recursion_depth
u8