pub(crate) fn generate(
mut writer: impl std::io::Write,
type_name: &str,
generics: super::Generics<'_>,
fields: &[super::Property<'_>],
map_namespace: &impl crate::MapNamespace,
resource_metadata: Option<&super::ResourceMetadata<'_>>,
) -> Result<(), crate::Error> {
use std::fmt::Write;
let local = crate::map_namespace_local_to_string(map_namespace)?;
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![];
let mut has_flattened_field = false;
if resource_metadata.is_some() {
writeln!(fields_string,
r#" {local}serde::ser::SerializeStruct::serialize_field(&mut state, "apiVersion", <Self as {local}Resource>::API_VERSION)?;"#)?;
writeln!(fields_string,
r#" {local}serde::ser::SerializeStruct::serialize_field(&mut state, "kind", <Self as {local}Resource>::KIND)?;"#)?;
required_fields_num += 2;
}
for super::Property { name, field_name, required, is_flattened, .. } in fields {
if *is_flattened {
writeln!(fields_string, " {local}serde::Serialize::serialize(&self.{field_name}, SerializerWrapper(&mut state))?;")?;
has_flattened_field = true;
}
else {
match required {
super::PropertyRequired::Required { is_default: _ } => {
writeln!(fields_string, " {local}serde::ser::SerializeStruct::serialize_field(&mut state, {name:?}, &self.{field_name})?;")?;
required_fields_num += 1;
},
super::PropertyRequired::Optional => {
writeln!(fields_string, " if let Some(value) = &self.{field_name} {{")?;
writeln!(fields_string, " {local}serde::ser::SerializeStruct::serialize_field(&mut state, {name:?}, value)?;")?;
writeln!(fields_string, " }}")?;
fields_num.push(format!("self.{field_name}.as_ref().map_or(0, |_| 1)"));
},
super::PropertyRequired::OptionalDefault => {
writeln!(fields_string, " if !self.{field_name}.is_empty() {{")?;
writeln!(fields_string, " {local}serde::ser::SerializeStruct::serialize_field(&mut state, {name:?}, &self.{field_name})?;")?;
writeln!(fields_string, " }}")?;
fields_num.push(format!("usize::from(!self.{field_name}.is_empty())"));
},
}
}
}
let fields_num: std::borrow::Cow<'_, str> = match (required_fields_num, fields_num.is_empty()) {
(0, true) => " 0".into(),
(0, false) => {
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) => {
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 {local}Resource>::KIND")
}
else {
format!("{type_name:?}")
};
let struct_serializer: std::borrow::Cow<'_, str> =
if has_flattened_field {
let mut out = String::new();
writeln!(out, " struct SerializerWrapper<'a, S>(&'a mut S);")?;
writeln!(out)?;
writeln!(out, " impl<'a, S> {local}serde::Serializer for SerializerWrapper<'a, S> where S: {local}serde::ser::SerializeStruct {{")?;
writeln!(out, " type Ok = ();")?;
writeln!(out, " type Error = <S as {local}serde::ser::SerializeStruct>::Error;")?;
writeln!(out)?;
writeln!(out, " type SerializeSeq = {local}serde::ser::Impossible<Self::Ok, Self::Error>;")?;
writeln!(out, " type SerializeTuple = {local}serde::ser::Impossible<Self::Ok, Self::Error>;")?;
writeln!(out, " type SerializeTupleStruct = {local}serde::ser::Impossible<Self::Ok, Self::Error>;")?;
writeln!(out, " type SerializeTupleVariant = {local}serde::ser::Impossible<Self::Ok, Self::Error>;")?;
writeln!(out, " type SerializeMap = {local}serde::ser::Impossible<Self::Ok, Self::Error>;")?;
writeln!(out, " type SerializeStruct = SerializerStructWrapper<'a, S>;")?;
writeln!(out, " type SerializeStructVariant = {local}serde::ser::Impossible<Self::Ok, Self::Error>;")?;
writeln!(out)?;
writeln!(out, " fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("bool is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("i8 is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom(" is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("i32 is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("i64 is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("u8 is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("u16 is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("u32 is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("u64 is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("f32 is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("f64 is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("char is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("str is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("bytes is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_none(self) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("none is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_some<T>(self, _: &T) -> Result<Self::Ok, Self::Error> where T: {local}serde::Serialize + ?Sized {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("some is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("unit is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("unit struct is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("unit variant is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_newtype_struct<T>(")?;
writeln!(out, " self,")?;
writeln!(out, " _: &'static str,")?;
writeln!(out, " _: &T,")?;
writeln!(out, " ) -> Result<Self::Ok, Self::Error> where T: {local}serde::Serialize + ?Sized {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("newtype struct is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_newtype_variant<T>(")?;
writeln!(out, " self,")?;
writeln!(out, " _: &'static str,")?;
writeln!(out, " _: u32,")?;
writeln!(out, " _: &'static str,")?;
writeln!(out, " _: &T,")?;
writeln!(out, " ) -> Result<Self::Ok, Self::Error> where T: {local}serde::Serialize + ?Sized {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("newtype variant is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("seq is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("tuple is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeTupleStruct, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("tuple struct is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_tuple_variant(")?;
writeln!(out, " self,")?;
writeln!(out, " _: &'static str,")?;
writeln!(out, " _: u32,")?;
writeln!(out, " _: &'static str,")?;
writeln!(out, " _: usize,")?;
writeln!(out, " ) -> Result<Self::SerializeTupleVariant, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("tuple variant is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("map is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct, Self::Error> {{")?;
writeln!(out, " Ok(SerializerStructWrapper(self.0))")?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn serialize_struct_variant(")?;
writeln!(out, " self,")?;
writeln!(out, " _: &'static str,")?;
writeln!(out, " _: u32,")?;
writeln!(out, " _: &'static str,")?;
writeln!(out, " _: usize,")?;
writeln!(out, " ) -> Result<Self::SerializeStructVariant, Self::Error> {{")?;
writeln!(out, r#" Err({local}serde::ser::Error::custom("struct variant is not supported"))"#)?;
writeln!(out, " }}")?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " struct SerializerStructWrapper<'a, S>(&'a mut S);")?;
writeln!(out)?;
writeln!(out, " impl<'a, S> {local}serde::ser::SerializeStruct for SerializerStructWrapper<'a, S> where S: {local}serde::ser::SerializeStruct {{")?;
writeln!(out, " type Ok = ();")?;
writeln!(out, " type Error = <S as {local}serde::ser::SerializeStruct>::Error;")?;
writeln!(out)?;
writeln!(out, " fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: {local}serde::Serialize + ?Sized {{")?;
writeln!(out, r#" self.0.serialize_field(key, value)"#)?;
writeln!(out, " }}")?;
writeln!(out)?;
writeln!(out, " fn end(self) -> Result<Self::Ok, Self::Error> {{")?;
writeln!(out, r#" Ok(())"#)?;
writeln!(out, " }}")?;
writeln!(out, " }}")?;
writeln!(out)?;
out.into()
}
else {
"".into()
};
writeln!(
writer,
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/impl_serialize.rs")),
local = local,
type_name = type_name,
type_generics_impl = type_generics_impl,
type_generics_type = type_generics_type,
type_generics_where = type_generics_where,
struct_serializer = struct_serializer,
fields_num = fields_num,
fields = fields_string,
serialize_type_name = serialize_type_name,
)?;
Ok(())
}