tf_bindgen/model/
config.rs

1use std::collections::HashMap;
2
3use semver::{Comparator, Op, VersionReq};
4use serde::{Deserialize, Serialize};
5
6#[derive(Default, Debug, Deserialize, Serialize)]
7pub struct Terraform {
8    required_providers: HashMap<String, Provider>,
9}
10
11#[derive(Debug, Deserialize, Serialize)]
12pub struct Provider {
13    source: String,
14    version: String,
15}
16
17impl Terraform {
18    /// Add provider from specified dependency.
19    pub fn add_provider(&mut self, provider_name: &str, constraint: VersionReq) {
20        let segments: Vec<_> = provider_name.split('/').collect();
21        let name = segments.last().unwrap();
22        let provider = Provider {
23            source: if segments.len() == 2 {
24                provider_name.to_string()
25            } else {
26                format!("hashicorp/{}", name)
27            },
28            version: constraint
29                .comparators
30                .into_iter()
31                .map(cargo_simplify_version)
32                .fold(String::from(">=0.0.0"), |text, constraint| {
33                    text + "," + &constraint
34                }),
35        };
36        self.required_providers.insert(name.to_string(), provider);
37    }
38
39    /// Returns an iterator other all registered provider.
40    pub fn provider(&self) -> impl Iterator<Item = (&String, &Provider)> {
41        self.required_providers.iter()
42    }
43}
44
45fn cargo_simplify_version(constraint: Comparator) -> String {
46    let major = constraint.major;
47    let minor = constraint.minor.unwrap_or(0);
48    let patch = constraint.patch.unwrap_or(0);
49    assert!(
50        constraint.pre.is_empty(),
51        "pre release constraints are not supported"
52    );
53    match constraint.op {
54        Op::Tilde if constraint.minor.is_some() => {
55            format!(">={major}{minor}{patch},<{major}{}.0", minor + 1)
56        }
57        Op::Caret if major == 0 && constraint.minor.is_none() => ">=0.0.0,<1.0.0".to_string(),
58        Op::Caret if major == 0 && minor == 0 && constraint.patch.is_some() => {
59            format!(">=0.0.{patch},<0.0.{}", patch + 1)
60        }
61        Op::Caret if major == 0 => {
62            format!(">=0.{minor}.0,<0.{}.0", minor + 1)
63        }
64        Op::Wildcard if constraint.minor.is_some() => {
65            format!(">={major}.{minor}.0,<{major}.{}.0", minor + 1)
66        }
67        Op::Tilde | Op::Caret | Op::Wildcard => {
68            format!(">={major}.{minor}.{patch},<{}.0.0", major + 1)
69        }
70        Op::Exact => format!("={major}.{minor}.{patch}"),
71        Op::Greater => format!(">{major}.{minor}.{patch}"),
72        Op::GreaterEq => format!(">={major}.{minor}.{patch}"),
73        Op::Less => format!("<{major}.{minor}.{patch}"),
74        Op::LessEq => format!("<={major}.{minor}.{patch}"),
75        _ => unimplemented!(),
76    }
77}