configbuilder_pattern_substitution/
composite_policy.rs1use crate::{SubstitutionError, SubstitutionPolicy};
2
3pub struct CompositePolicy {
5 policies: Vec<Box<dyn SubstitutionPolicy>>,
6}
7
8impl CompositePolicy {
9 pub fn new(policies: Vec<Box<dyn SubstitutionPolicy>>) -> Self {
11 Self { policies }
12 }
13}
14
15impl std::fmt::Debug for CompositePolicy {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 f.debug_struct("CompositePolicy")
18 .field("policy_count", &self.policies.len())
19 .finish()
20 }
21}
22
23impl SubstitutionPolicy for CompositePolicy {
24 fn validate(&self, var_name: &str) -> Result<(), SubstitutionError> {
25 let mut reasons = Vec::new();
26 for policy in &self.policies {
27 if let Err(SubstitutionError::VariableRejected { reason, .. }) =
28 policy.validate(var_name)
29 {
30 reasons.push(reason);
31 }
32 }
33 if reasons.is_empty() {
34 Ok(())
35 } else {
36 Err(SubstitutionError::VariableRejected {
37 var_name: var_name.to_string(),
38 reason: reasons.join(" AND "),
39 policy: self.description(),
40 })
41 }
42 }
43
44 fn description(&self) -> String {
45 format!(
46 "Composite({})",
47 self.policies
48 .iter()
49 .map(|p| p.description())
50 .collect::<Vec<_>>()
51 .join(" AND ")
52 )
53 }
54}