1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
pub(crate) fn generate(
	mut writer: impl std::io::Write,
	type_name: &str,
	generics: super::Generics<'_>,
	fields: &[super::Property<'_>],
	crate_root: &str,
	resource_metadata: Option<&super::ResourceMetadata<'_>>,
) -> Result<(), crate::Error> {
	let type_generics_impl = generics.type_part.map(|part| format!("<{}>", part)).unwrap_or_default();
	let type_generics_type = generics.type_part.map(|part| format!("<{}>", part)).unwrap_or_default();
	let type_generics_where = generics.where_part.map(|part| format!(" where {}", part)).unwrap_or_default();

	let mut fields_string = String::new();
	let mut required_fields_num = 0_usize;
	let mut fields_num = vec![];

	if resource_metadata.is_some() {
		use std::fmt::Write;

		writeln!(fields_string, r#"        serde::ser::SerializeStruct::serialize_field(&mut state, "apiVersion", <Self as {}::Resource>::API_VERSION)?;"#, crate_root)?;
		writeln!(fields_string, r#"        serde::ser::SerializeStruct::serialize_field(&mut state, "kind", <Self as {}::Resource>::KIND)?;"#, crate_root)?;

		required_fields_num += 2;

	}
	for super::Property { name, field_name, required, .. } in fields {
		use std::fmt::Write;

		if *required {
			writeln!(fields_string, "        serde::ser::SerializeStruct::serialize_field(&mut state, {:?}, &self.{})?;", name, field_name)?;

			required_fields_num += 1;
		}
		else {
			writeln!(fields_string, "        if let Some(value) = &self.{} {{", field_name)?;
			writeln!(fields_string, "            serde::ser::SerializeStruct::serialize_field(&mut state, {:?}, value)?;", name)?;
			writeln!(fields_string, "        }}")?;

			fields_num.push(format!("self.{}.as_ref().map_or(0, |_| 1)", field_name));
		}
	}

	let fields_num: std::borrow::Cow<'_, str> = match (required_fields_num, fields_num.is_empty()) {
		(0, true) => "            0".into(),

		(0, false) => {
			use std::fmt::Write;

			let mut fields_num_str = String::new();
			let mut first = true;
			for field_num in fields_num {
				if first {
					first = false;
				}
				else {
					writeln!(fields_num_str, " +")?;
				}

				write!(fields_num_str, "            {}", field_num)?;
			}

			fields_num_str.into()
		},

		(required_fields_num, true) => format!("            {}", required_fields_num).into(),

		(required_fields_num, false) => {
			use std::fmt::Write;

			let mut fields_num_str = format!("            {}", required_fields_num);
			for field_num in fields_num {
				writeln!(fields_num_str, " +")?;
				write!(fields_num_str, "            {}", field_num)?;
			}

			fields_num_str.into()
		},
	};

	let serialize_type_name =
		if resource_metadata.is_some() {
			format!("<Self as {}::Resource>::KIND", crate_root)
		}
		else {
			format!("{:?}", type_name)
		};

	writeln!(
		writer,
		include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/impl_serialize.rs")),
		type_name = type_name,
		type_generics_impl = type_generics_impl,
		type_generics_type = type_generics_type,
		type_generics_where = type_generics_where,
		fields_num = fields_num,
		fields = fields_string,
		serialize_type_name = serialize_type_name,
	)?;

	Ok(())
}