use std::collections::HashMap;
use serde::{ser::SerializeMap, Serialize};
use crate::core::{
logical_id::{LogicalId, LogicalIdentified},
parameter::Parameter,
resource::ManagedResource,
};
#[non_exhaustive]
#[derive(Debug, Clone, Copy)]
pub enum TemplateVersion {
V20100909,
}
impl TemplateVersion {
pub fn latest() -> TemplateVersion {
TemplateVersion::V20100909
}
}
impl Serialize for TemplateVersion {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
TemplateVersion::V20100909 => "2010-09-09".serialize(serializer),
}
}
}
pub struct Template {
format_version: TemplateVersion,
description: Option<String>,
resources: HashMap<LogicalId, Box<dyn ManagedResource>>,
string_parameters: Vec<Parameter<String>>,
number_parameters: Vec<Parameter<f64>>,
}
impl Template {
pub fn new() -> Self {
Self {
format_version: TemplateVersion::latest(),
description: None,
resources: HashMap::new(),
string_parameters: vec![],
number_parameters: vec![],
}
}
pub fn insert_string_param(&mut self, param: Parameter<String>) {
self.string_parameters.push(param);
}
pub fn insert_number_param(&mut self, param: Parameter<f64>) {
self.number_parameters.push(param);
}
pub fn insert_resource(
&mut self,
resource: Box<dyn ManagedResource>,
) -> Option<Box<dyn ManagedResource>> {
self.resources
.insert(resource.logical_id().clone(), resource)
}
}
impl Serialize for Template {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut map = serializer.serialize_map(None)?;
map.serialize_entry("AWSTemplateFormatVersion", &self.format_version)?;
if !self.string_parameters.is_empty() || !self.number_parameters.is_empty() {
let inner = SerParameter {
strings: &self.string_parameters,
numbers: &self.number_parameters,
};
map.serialize_entry("Parameters", &inner)?;
}
if let Some(description) = &self.description {
map.serialize_entry("Description", description)?;
}
map.serialize_entry("Resources", &self.resources)?;
map.end()
}
}
struct SerParameter<'a> {
strings: &'a [Parameter<String>],
numbers: &'a [Parameter<f64>],
}
impl Serialize for SerParameter<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let len = self.strings.len() + self.numbers.len();
let mut map = serializer.serialize_map(Some(len))?;
for e in self.strings {
map.serialize_entry(e.logical_id(), e)?;
}
for e in self.numbers {
map.serialize_entry(e.logical_id(), e)?;
}
map.end()
}
}