private void WriteStructDefinition(IndentedStringBuilder builder, StructDefinition d) { var needsLifetime = NeedsLifetime(d); var name = MakeDefIdent(d.Name) + (needsLifetime ? "<'raw>" : ""); var isFixedSize = d.IsFixedSize(Schema); builder.Append("#[derive(Clone, Debug, PartialEq"); if (isFixedSize) { // this will allow us access it in a raw buffer without copying it. builder .AppendEnd(", Copy)]") .AppendLine("#[repr(packed)]"); } else { builder.AppendEnd(")]"); } builder .CodeBlock($"pub struct {name}", _tab, () => WriteStructDefinitionAttrs(builder, d)) .AppendLine(); if (isFixedSize) { builder .AppendLine($"impl ::bebop::FixedSized for {name} {{}}") .AppendLine(); } builder .CodeBlock($"impl<'raw> ::bebop::SubRecord<'raw> for {name}", _tab, () => { if (isFixedSize) { builder .AppendLine("const MIN_SERIALIZED_SIZE: usize = Self::SERIALIZED_SIZE;") .AppendLine("const EXACT_SERIALIZED_SIZE: Option<usize> = Some(Self::SERIALIZED_SIZE);") .AppendLine(); } else { // sum size of all fields at compile time builder.AppendLine("const MIN_SERIALIZED_SIZE: usize ="); var parts = d.Fields.Select(f => $"<{TypeName(f.Type)}>::MIN_SERIALIZED_SIZE"); builder.Indent(_tab).Append(string.Join(" +\n", parts)).AppendEnd(";").Dedent(_tab) .AppendLine(); } builder.AppendLine("#[inline]").CodeBlock("fn serialized_size(&self) -> usize", _tab, () => { if (isFixedSize) { builder.AppendLine("Self::SERIALIZED_SIZE"); } else { builder.AppendLine(string.Join(" +\n", d.Fields.Select( (f) => $"self.{MakeAttrIdent(f.Name)}.serialized_size()" ))); } }).AppendLine(); builder.CodeBlock( "fn _serialize_chained<W: ::std::io::Write>(&self, dest: &mut W) -> ::bebop::SeResult<usize>", _tab, () => { if (d.Fields.Count == 0) { builder.AppendLine("Ok(0)"); } else { // just serialize all fields and sum their bytes written builder.CodeBlock("Ok(", _tab, () => { builder.AppendLine(string.Join(" +\n", d.Fields.Select( (f) => $"self.{MakeAttrIdent(f.Name)}._serialize_chained(dest)?"))); }, "", ")"); } }).AppendLine(); builder.CodeBlock("fn _deserialize_chained(raw: &'raw [u8]) -> ::bebop::DeResult<(usize, Self)>", _tab, () => { WriteStructDeserialization(builder, d); }); }).AppendLine(); WriteRecordImpl(builder, name, d); }