protected String buildReadMethodBody() {
        resetStringBuilder();
        buildString("\n{\n");

        buildString("  if (!$3 && $1.trySkipNil()) {\n");
        buildString("    return null;\n");
        buildString("  }\n");

        buildString("  %s _$$_t;\n", origName);
        buildString("  if ($2 == null) {\n");
        buildString("    _$$_t = new %s();\n", origName);
        buildString("  } else {\n");
        buildString("    _$$_t = (%s) $2;\n", origName);
        buildString("  }\n");
        buildString("  $1.readArrayBegin();\n");

        int i;
        for (i = 0; i < entries.length; i++) {
            FieldEntry e = entries[i];
            if (!e.isAvailable()) {
                buildString("  $1.skip();\n");
                continue;
            }

            if (e.isOptional()) {
                buildString("  if ($1.trySkipNil()) {");
                // if Optional and nil, then keep default value
                buildString("  } else {\n");
            }

            DefaultFieldEntry de = (DefaultFieldEntry) e;
            boolean isPrivate = Modifier.isPrivate(de.getField().getModifiers());
            Class<?> type = de.getType();
            if (type.isPrimitive()) {
                if (!isPrivate) {
                    buildString("    _$$_t.%s = $1.%s();\n", de.getName(), primitiveReadName(type));
                } else {
                    buildString(
                            "    %s.readPrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n",
                            DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i);
                }
            } else {
                if (!isPrivate) {
                    buildString(
                            "    _$$_t.%s = (%s) this.templates[%d].read($1, _$$_t.%s);\n",
                            de.getName(), de.getJavaTypeName(), i, de.getName());
                } else {
                    buildString(
                            "    %s.readPrivateField($1, _$$_t, %s.class, \"%s\", templates[%d]);\n",
                            DefaultBuildContext.class.getName(), de.getField().getDeclaringClass().getName(), de.getName(), i);
                }
            }

            if (de.isOptional()) {
                buildString("  }\n");
            }
        }

        buildString("  $1.readArrayEnd();\n");
        buildString("  return _$$_t;\n");

        buildString("}\n");
        return getBuiltString();
    }