public override void PrettyWrite(IPrettyWriter pw)
        {
            int tmp = pw.LastLineLength;

            pw.Append(FProp.TypeString());
            pw.PadLastLine(tmp + 12, ' ');
            pw.Append($"{FProp.Name}: ");
            pw.Append(PropToString());
        }
        public static void WriteDataTableDump(StreamWriter sw, SourceDemo demo, DataTableDumpMode mode)
        {
            PrettyStreamWriter pw = new PrettyStreamWriter(sw.BaseStream);
            int datatablesCount   = 0;           // spliced demos have more than one datatables packet

            foreach (DataTables dataTables in demo.FilterForPacket <DataTables>())
            {
                if (datatablesCount++ > 0)
                {
                    pw.Append("\n\n\n");
                }
                if (mode != DataTableDumpMode.TreeOnly)
                {
                    switch (mode)
                    {
                    case DataTableDumpMode.PacketAndTree:
                        dataTables.PrettyWrite(pw);
                        break;

                    case DataTableDumpMode.Flattened:
                        var tableParser = new DataTableParser(demo, dataTables);
                        tableParser.FlattenClasses(false);
                        foreach ((ServerClass sClass, List <FlattenedProp> fProps) in tableParser.FlattenedProps !)
                        {
                            pw.AppendLine($"{sClass.ClassName} ({sClass.DataTableName}) ({fProps.Count} props):");
                            for (var i = 0; i < fProps.Count; i++)
                            {
                                FlattenedProp fProp = fProps[i];
                                pw.Append($"\t({i}): ");
                                pw.Append(fProp.TypeString().PadRight(12));
                                pw.AppendLine(fProp.ArrayElementPropInfo == null
                                                                                ? fProp.PropInfo.ToStringNoType()
                                                                                : fProp.ArrayElementPropInfo.ToStringNoType());
                            }
                        }
                        break;

                    default:
                        throw new ArgProcessProgrammerException($"invalid data table dump mode: \"{mode}\"");
                    }
                }
                if (mode != DataTableDumpMode.TreeOnly)
                {
                    pw.Append("\n\n\n");
                }
                pw.Append("Datatable hierarchy:\n\n\n");
                new DataTableTree(dataTables, true).PrettyWrite(pw);
            }
            // see note at PrettyStreamWriter
            pw.Flush();
        }