コード例 #1
0
        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);
        }