in serde-generate/src/dart.rs [609:889]
fn output_struct_or_variant_container(
&mut self,
variant_base: Option<&str>,
variant_index: Option<u32>,
name: &str,
fields: &[Named<Format>],
) -> Result<()> {
let field_count = fields.len();
// Beginning of class
writeln!(self.out)?;
self.output_comment(name)?;
if let Some(base) = variant_base {
writeln!(
self.out,
"@immutable\nclass {} extends {} {{",
self.quote_qualified_name(name),
base
)?;
} else {
writeln!(
self.out,
"@immutable\nclass {} {{",
self.quote_qualified_name(name)
)?;
}
self.enter_class(name);
// Constructor.
writeln!(
self.out,
"const {}({}",
self.quote_qualified_name(name),
if !fields.is_empty() { "{" } else { "" }
)?;
self.out.indent();
for field in fields.iter() {
let field_name = self.quote_field(&field.name.to_mixed_case());
match &field.value {
Format::Option(_) => writeln!(self.out, "this.{},", field_name)?,
_ => writeln!(self.out, "required this.{},", field_name)?,
}
}
self.out.unindent();
if variant_base.is_some() {
writeln!(
self.out,
"{}) : super();",
if !fields.is_empty() { "}" } else { "" }
)?;
} else {
writeln!(self.out, "{});", if !fields.is_empty() { "}" } else { "" })?;
}
if self.generator.config.serialization {
// a struct (UnitStruct) with zero fields
if variant_index.is_none() && fields.is_empty() {
writeln!(
self.out,
"\n{}.deserialize(BinaryDeserializer deserializer);",
self.quote_qualified_name(name)
)?;
// Deserialize (struct) or Load (variant)
} else if variant_index.is_none() {
writeln!(
self.out,
"\n{}.deserialize(BinaryDeserializer deserializer) :",
self.quote_qualified_name(name)
)?;
} else if !fields.is_empty() {
writeln!(
self.out,
"\n{}.load(BinaryDeserializer deserializer) :",
self.quote_qualified_name(name)
)?;
} else {
writeln!(
self.out,
"\n{}.load(BinaryDeserializer deserializer);",
self.quote_qualified_name(name)
)?;
}
self.out.indent();
for (index, field) in fields.iter().enumerate() {
if index == field_count - 1 {
writeln!(
self.out,
"{} = {};",
self.quote_field(&field.name.to_mixed_case()),
self.quote_deserialize(&field.value)
)?;
} else {
writeln!(
self.out,
"{} = {},",
self.quote_field(&field.name.to_mixed_case()),
self.quote_deserialize(&field.value)
)?;
}
}
self.out.unindent();
if variant_index.is_none() {
for encoding in &self.generator.config.encodings {
self.output_class_deserialize_for_encoding(name, *encoding)?;
}
}
}
// Fields
if !fields.is_empty() {
writeln!(self.out)?;
}
for field in fields {
writeln!(
self.out,
"final {} {};",
self.quote_type(&field.value),
self.quote_field(&field.name.to_mixed_case())
)?;
}
if !fields.is_empty() {
writeln!(self.out)?;
}
// Serialize
if self.generator.config.serialization {
writeln!(self.out, "\nvoid serialize(BinarySerializer serializer) {{",)?;
self.out.indent();
if let Some(index) = variant_index {
writeln!(self.out, "serializer.serializeVariantIndex({});", index)?;
}
for field in fields {
writeln!(
self.out,
"{}",
self.quote_serialize_value(
&self.quote_field(&field.name.to_mixed_case()),
&field.value
)
)?;
}
self.out.unindent();
writeln!(self.out, "}}")?;
if variant_index.is_none() {
for encoding in &self.generator.config.encodings {
self.output_class_serialize_for_encoding(*encoding)?;
}
}
}
// Equality
write!(self.out, "\n@override")?;
write!(self.out, "\nbool operator ==(Object other) {{")?;
self.out.indent();
writeln!(self.out, "\nif (identical(this, other)) return true;")?;
writeln!(
self.out,
"if (other.runtimeType != runtimeType) return false;"
)?;
writeln!(self.out, "\nreturn other is {}", name)?;
for field in fields.iter() {
let stmt = match &field.value {
Format::Seq(_) => {
format!(
" listEquals({0}, other.{0})",
self.quote_field(&field.name.to_mixed_case())
)
}
Format::TupleArray {
content: _,
size: _,
} => format!(
" listEquals({0}, other.{0})",
self.quote_field(&field.name.to_mixed_case())
),
Format::Map { .. } => {
format!(
" mapEquals({0}, other.{0})",
self.quote_field(&field.name.to_mixed_case())
)
}
_ => format!(
" {0} == other.{0}",
self.quote_field(&field.name.to_mixed_case())
),
};
writeln!(self.out, "&& {}", stmt)?;
}
write!(self.out, ";")?;
self.out.unindent();
writeln!(self.out, "}}")?;
// Hashing
if field_count > 0 {
write!(self.out, "\n@override")?;
if field_count == 1 {
writeln!(
self.out,
"\nint get hashCode => {}.hashCode;",
fields.first().unwrap().name.to_mixed_case()
)?;
} else {
let use_hash_all = field_count > 20;
if use_hash_all {
writeln!(self.out, "\nint get hashCode => Object.hashAll([")?;
} else {
writeln!(self.out, "\nint get hashCode => Object.hash(")?;
}
self.out.indent();
self.out.indent();
self.out.indent();
for field in fields {
writeln!(
self.out,
"{},",
self.quote_field(&field.name.to_mixed_case())
)?;
}
self.out.unindent();
if use_hash_all {
writeln!(self.out, "]);")?;
} else {
writeln!(self.out, ");")?;
}
self.out.unindent();
self.out.unindent();
}
}
// Generate a toString implementation in each class
writeln!(self.out, "\n@override\nString toString() {{")?;
self.out.indent();
writeln!(self.out, "String? fullString;")?;
writeln!(self.out, "\nassert(() {{")?;
self.out.indent();
writeln!(self.out, "fullString = '$runtimeType('")?;
self.out.indent();
for (index, field) in fields.iter().enumerate() {
if index == field_count - 1 {
writeln!(
self.out,
"'{0}: ${0}'",
self.quote_field(&field.name.to_mixed_case())
)?;
} else {
writeln!(
self.out,
"'{0}: ${0}, '",
self.quote_field(&field.name.to_mixed_case())
)?;
}
}
writeln!(self.out, "')';")?;
self.out.unindent();
writeln!(self.out, "return true;")?;
self.out.unindent();
writeln!(self.out, "}}());")?;
writeln!(self.out, "\nreturn fullString ?? '{}';", name)?;
self.out.unindent();
writeln!(self.out, "}}")?;
self.out.unindent();
// End of class
self.leave_class();
writeln!(self.out, "}}")
}