four/core/
template.rs

1use std::collections::HashMap;
2
3use serde::{ser::SerializeMap, Serialize};
4
5use crate::core::{
6    logical_id::{LogicalId, LogicalIdentified},
7    parameter::Parameter,
8    resource::ManagedResource,
9};
10
11#[non_exhaustive]
12#[derive(Debug, Clone, Copy)]
13pub enum TemplateVersion {
14    V20100909,
15}
16
17impl TemplateVersion {
18    pub fn latest() -> TemplateVersion {
19        TemplateVersion::V20100909
20    }
21}
22
23impl Serialize for TemplateVersion {
24    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
25    where
26        S: serde::Serializer,
27    {
28        match self {
29            TemplateVersion::V20100909 => "2010-09-09".serialize(serializer),
30        }
31    }
32}
33
34/// Serialized to be
35pub struct Template {
36    format_version: TemplateVersion,
37    description: Option<String>,
38    resources: HashMap<LogicalId, Box<dyn ManagedResource>>,
39    string_parameters: Vec<Parameter<String>>,
40    number_parameters: Vec<Parameter<f64>>,
41}
42
43impl Template {
44    pub fn new() -> Self {
45        Self {
46            format_version: TemplateVersion::latest(),
47            description: None,
48            resources: HashMap::new(),
49            string_parameters: vec![],
50            number_parameters: vec![],
51        }
52    }
53
54    pub fn insert_string_param(&mut self, param: Parameter<String>) {
55        self.string_parameters.push(param);
56    }
57
58    pub fn insert_number_param(&mut self, param: Parameter<f64>) {
59        self.number_parameters.push(param);
60    }
61
62    pub fn insert_resource(
63        &mut self,
64        resource: Box<dyn ManagedResource>,
65    ) -> Option<Box<dyn ManagedResource>> {
66        self.resources
67            .insert(resource.logical_id().clone(), resource)
68    }
69}
70
71impl Serialize for Template {
72    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73    where
74        S: serde::Serializer,
75    {
76        let mut map = serializer.serialize_map(None)?;
77        map.serialize_entry("AWSTemplateFormatVersion", &self.format_version)?;
78        if !self.string_parameters.is_empty() || !self.number_parameters.is_empty() {
79            let inner = SerParameter {
80                strings: &self.string_parameters,
81                numbers: &self.number_parameters,
82            };
83
84            map.serialize_entry("Parameters", &inner)?;
85        }
86        if let Some(description) = &self.description {
87            map.serialize_entry("Description", description)?;
88        }
89        map.serialize_entry("Resources", &self.resources)?;
90
91        map.end()
92    }
93}
94
95struct SerParameter<'a> {
96    strings: &'a [Parameter<String>],
97    numbers: &'a [Parameter<f64>],
98}
99
100impl Serialize for SerParameter<'_> {
101    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
102    where
103        S: serde::Serializer,
104    {
105        let len = self.strings.len() + self.numbers.len();
106        let mut map = serializer.serialize_map(Some(len))?;
107        for e in self.strings {
108            map.serialize_entry(e.logical_id(), e)?;
109        }
110        for e in self.numbers {
111            map.serialize_entry(e.logical_id(), e)?;
112        }
113        map.end()
114    }
115}